mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-24 10:32:32 +00:00
Port --enable-standalone-gui support to SheepShaver
Others changes include: - Factor out STR_SIG_INSTALL_ERR messages - Process command line arguments early (prior to calling PrefsInit()) - GUI: set start_clicked only if the "Start" button was clicked - GUI: save changes to the "Input" pane when the "Start" button was clicked
This commit is contained in:
parent
daa0af4da6
commit
9b60acb2da
@ -67,6 +67,7 @@ links:
|
||||
Unix/video_blit.cpp Unix/config.sub Unix/config.guess Unix/m4 \
|
||||
Unix/keycodes Unix/tunconfig Unix/clip_unix.cpp Unix/Irix/audio_irix.cpp \
|
||||
Unix/Linux/scsi_linux.cpp Unix/Linux/NetDriver Unix/ether_unix.cpp \
|
||||
Unix/rpc.h Unix/rpc_unix.cpp Unix/Darwin/mkstandalone \
|
||||
Unix/Darwin/lowmem.c Unix/Darwin/pagezero.c Unix/Darwin/testlmem.sh \
|
||||
dummy/audio_dummy.cpp dummy/clip_dummy.cpp dummy/serial_dummy.cpp \
|
||||
dummy/prefs_editor_dummy.cpp dummy/scsi_dummy.cpp SDL slirp \
|
||||
|
@ -42,6 +42,12 @@ SLIRP_CFLAGS = @SLIRP_CFLAGS@
|
||||
SLIRP_SRCS = @SLIRP_SRCS@
|
||||
SLIRP_OBJS = $(SLIRP_SRCS:../slirp/%.c=obj/%.o)
|
||||
|
||||
STANDALONE_GUI = @STANDALONE_GUI@
|
||||
GUI_CFLAGS = @GUI_CFLAGS@
|
||||
GUI_LIBS = @GUI_LIBS@
|
||||
GUI_SRCS = ../prefs.cpp prefs_unix.cpp prefs_editor_gtk.cpp ../prefs_items.cpp \
|
||||
../user_strings.cpp user_strings_unix.cpp xpram_unix.cpp sys_unix.cpp rpc_unix.cpp
|
||||
|
||||
# Append disassembler to dyngen, if available
|
||||
ifneq (:no,$(MONSRCS):$(USE_DYNGEN))
|
||||
DYNGENSRCS += $(filter %i386-dis.c,$(MONSRCS))
|
||||
@ -55,18 +61,29 @@ SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp
|
||||
../gfxaccel.cpp ../video.cpp video_blit.cpp ../audio.cpp ../ether.cpp ../thunks.cpp \
|
||||
../serial.cpp ../extfs.cpp \
|
||||
about_window_unix.cpp ../user_strings.cpp user_strings_unix.cpp \
|
||||
vm_alloc.cpp sigsegv.cpp \
|
||||
vm_alloc.cpp sigsegv.cpp rpc_unix.cpp \
|
||||
sshpty.c strlcpy.c $(SYSSRCS) $(CPUSRCS) $(MONSRCS) $(SLIRP_SRCS)
|
||||
APP = SheepShaver
|
||||
APP_EXE = $(APP)$(EXEEXT)
|
||||
APP_APP = $(APP).app
|
||||
|
||||
PROGS = $(APP_EXE)
|
||||
ifeq ($(STANDALONE_GUI),yes)
|
||||
GUI_APP = SheepShaverGUI
|
||||
GUI_APP_EXE = $(GUI_APP)$(EXEEXT)
|
||||
GUI_APP_APP = $(GUI_APP).app
|
||||
PROGS += $(GUI_APP_EXE)
|
||||
endif
|
||||
|
||||
CXXFLAGS += $(GUI_CFLAGS)
|
||||
LIBS += $(GUI_LIBS)
|
||||
|
||||
## Rules
|
||||
.PHONY: modules install uninstall clean distclean depend dep
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .S .o .h
|
||||
|
||||
all: $(APP_EXE)
|
||||
all: $(PROGS)
|
||||
|
||||
OBJ_DIR = obj
|
||||
$(OBJ_DIR)::
|
||||
@ -78,6 +95,12 @@ define SRCS_LIST_TO_OBJS
|
||||
endef
|
||||
OBJS = $(SRCS_LIST_TO_OBJS)
|
||||
|
||||
define GUI_SRCS_LIST_TO_OBJS
|
||||
$(addprefix $(OBJ_DIR)/, $(addsuffix .go, $(foreach file, $(GUI_SRCS), \
|
||||
$(basename $(notdir $(file))))))
|
||||
endef
|
||||
GUI_OBJS = $(GUI_SRCS_LIST_TO_OBJS)
|
||||
|
||||
define DYNGENSRCS_LIST_TO_OBJS
|
||||
$(addprefix $(OBJ_DIR)/, $(addsuffix .dgo, $(foreach file, $(DYNGENSRCS), \
|
||||
$(basename $(notdir $(file))))))
|
||||
@ -89,10 +112,13 @@ VPATH :=
|
||||
VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS))))
|
||||
|
||||
$(APP_EXE): $(OBJ_DIR) $(OBJS)
|
||||
$(CXX) -o $(APP_EXE) $(LDFLAGS) $(OBJS) $(LIBS)
|
||||
$(CXX) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
|
||||
$(BLESS) $(APP_EXE)
|
||||
|
||||
$(APP)_app: $(APP) ../MacOSX/Info.plist ../MacOSX/SheepShaver.icns
|
||||
$(GUI_APP_EXE): $(OBJ_DIR) $(GUI_OBJS)
|
||||
$(CXX) -o $@ $(LDFLAGS) $(GUI_OBJS) $(GUI_LIBS)
|
||||
|
||||
$(APP)_app: $(APP) ../MacOSX/Info.plist ../MacOSX/$(APP).icns
|
||||
mkdir -p $(APP_APP)/Contents
|
||||
cp -f ../MacOSX/Info.plist $(APP_APP)/Contents/
|
||||
echo -n 'APPL????' > $(APP_APP)/Contents/PkgInfo
|
||||
@ -102,11 +128,24 @@ $(APP)_app: $(APP) ../MacOSX/Info.plist ../MacOSX/SheepShaver.icns
|
||||
mkdir -p $(APP_APP)/Contents/Resources
|
||||
cp -f ../MacOSX/SheepShaver.icns $(APP_APP)/Contents/Resources/
|
||||
|
||||
$(GUI_APP)_app: $(GUI_APP) ../MacOSX/Info.plist ../MacOSX/$(APP).icns
|
||||
mkdir -p $(GUI_APP_APP)/Contents
|
||||
sed -e "s/$(APP)/$(GUI_APP)/" < ../MacOSX/Info.plist > $(GUI_APP_APP)/Contents/Info.plist
|
||||
echo -n 'APPL????' > $(GUI_APP_APP)/Contents/PkgInfo
|
||||
mkdir -p $(GUI_APP_APP)/Contents/MacOS
|
||||
cp -f $(GUI_APP) $(GUI_APP_APP)/Contents/MacOS/
|
||||
strip $(GUI_APP_APP)/Contents/MacOS/$(GUI_APP)
|
||||
mkdir -p $(GUI_APP_APP)/Contents/Resources
|
||||
cp -f ../MacOSX/$(APP).icns $(GUI_APP_APP)/Contents/Resources/$(GUI_APP).icns
|
||||
|
||||
modules:
|
||||
cd Linux/NetDriver; make
|
||||
|
||||
install: $(APP_EXE) installdirs
|
||||
install: $(PROGS) installdirs
|
||||
$(INSTALL_PROGRAM) $(APP_EXE) $(DESTDIR)$(bindir)/$(APP_EXE)
|
||||
if test -f "$(GUI_APP_EXE)"; then \
|
||||
$(INSTALL_PROGRAM) $(GUI_APP_EXE) $(DESTDIR)$(bindir)/$(GUI_APP_EXE); \
|
||||
fi
|
||||
-$(INSTALL_DATA) $(APP).1 $(DESTDIR)$(man1dir)/$(APP).1
|
||||
$(INSTALL_DATA) $(KEYCODES) $(DESTDIR)$(datadir)/$(APP)/keycodes
|
||||
$(INSTALL_DATA) tunconfig $(DESTDIR)$(datadir)/$(APP)/tunconfig
|
||||
@ -117,6 +156,7 @@ installdirs:
|
||||
|
||||
uninstall:
|
||||
rm -f $(DESTDIR)$(bindir)/$(APP_EXE)
|
||||
rm -f $(DESTDIR)$(bindir)/$(GUI_APP_EXE)
|
||||
rm -f $(DESTDIR)$(man1dir)/$(APP).1
|
||||
rm -f $(DESTDIR)$(datadir)/$(APP)/keycodes
|
||||
rm -f $(DESTDIR)$(datadir)/$(APP)/tunconfig
|
||||
@ -148,6 +188,8 @@ $(OBJ_DIR)/%.o : %.S
|
||||
$(CPP) $(CPPFLAGS) -D__ASSEMBLY__ $< -o $*.out.s
|
||||
$(AS) $(ASFLAGS) -o $@ $*.out.s
|
||||
rm $*.out.s
|
||||
$(OBJ_DIR)/%.go : %.cpp
|
||||
$(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) $(GUI_CFLAGS) -DSTANDALONE_GUI -c $< -o $@
|
||||
|
||||
# Kheperix CPU emulator
|
||||
kpxsrcdir = ../kpx_cpu/src
|
||||
|
@ -28,6 +28,7 @@ AC_ARG_ENABLE(fbdev-dga, [ --enable-fbdev-dga use direct frame buffer a
|
||||
AC_ARG_ENABLE(xf86-dga, [ --enable-xf86-dga use the XFree86 DGA extension [default=yes]], [WANT_XF86_DGA=$enableval], [WANT_XF86_DGA=yes])
|
||||
AC_ARG_ENABLE(xf86-vidmode, [ --enable-xf86-vidmode use the XFree86 VidMode extension [default=yes]], [WANT_XF86_VIDMODE=$enableval], [WANT_XF86_VIDMODE=yes])
|
||||
AC_ARG_ENABLE(vosf, [ --enable-vosf enable video on SEGV signals [default=yes]], [WANT_VOSF=$enableval], [WANT_VOSF=yes])
|
||||
AC_ARG_ENABLE(standalone-gui,[ --enable-standalone-gui enable a standalone GUI prefs editor [default=no]], [WANT_STANDALONE_GUI=$enableval], [WANT_STANDALONE_GUI=no])
|
||||
AC_ARG_WITH(esd, [ --with-esd support ESD for sound under Linux/FreeBSD [default=yes]], [WANT_ESD=$withval], [WANT_ESD=yes])
|
||||
AC_ARG_WITH(gtk, [ --with-gtk use GTK user interface [default=yes]],
|
||||
[case "$withval" in
|
||||
@ -246,9 +247,8 @@ case "x$WANT_GTK" in
|
||||
xgtk2*)
|
||||
AM_PATH_GTK_2_0(1.3.15, [
|
||||
AC_DEFINE(ENABLE_GTK, 1, [Define if using GTK.])
|
||||
CFLAGS="$CFLAGS $GTK_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $GTK_CFLAGS"
|
||||
LIBS="$LIBS $GTK_LIBS"
|
||||
GUI_CFLAGS="$GTK_CFLAGS"
|
||||
GUI_LIBS="$GTK_LIBS"
|
||||
UISRCS=prefs_editor_gtk.cpp
|
||||
WANT_GTK=gtk2
|
||||
], [
|
||||
@ -268,15 +268,25 @@ esac
|
||||
if [[ "x$WANT_GTK" = "xgtk" ]]; then
|
||||
AM_PATH_GTK(1.2.0, [
|
||||
AC_DEFINE(ENABLE_GTK, 1, [Define if using GTK.])
|
||||
CFLAGS="$CFLAGS $GTK_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $GTK_CFLAGS"
|
||||
LIBS="$LIBS $GTK_LIBS"
|
||||
GUI_CFLAGS="$GTK_CFLAGS"
|
||||
GUI_LIBS="$GTK_LIBS"
|
||||
UISRCS=prefs_editor_gtk.cpp
|
||||
], [
|
||||
AC_MSG_WARN([Could not find GTK+, disabling user interface.])
|
||||
WANT_GTK=no
|
||||
])
|
||||
fi
|
||||
AC_SUBST(GUI_CFLAGS)
|
||||
AC_SUBST(GUI_LIBS)
|
||||
|
||||
dnl Build external GUI if requested.
|
||||
if [[ "$WANT_STANDALONE_GUI" != "yes" ]]; then
|
||||
WANT_STANDALONE_GUI=no
|
||||
fi
|
||||
if [[ "$WANT_GTK" = "no" ]]; then
|
||||
WANT_STANDALONE_GUI=no
|
||||
fi
|
||||
AC_SUBST(STANDALONE_GUI, [$WANT_STANDALONE_GUI])
|
||||
|
||||
dnl We use ESD if possible.
|
||||
if [[ "x$WANT_ESD" = "xyes" ]]; then
|
||||
|
@ -110,6 +110,7 @@
|
||||
#include "vm_alloc.h"
|
||||
#include "sigsegv.h"
|
||||
#include "sigregs.h"
|
||||
#include "rpc.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -231,6 +232,9 @@ static sigregs sigsegv_regs; // Register dump when crashed
|
||||
static const char *crash_reason = NULL; // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
|
||||
#endif
|
||||
|
||||
static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI
|
||||
static const char *gui_connection_path = NULL; // GUI connection identifier
|
||||
|
||||
uint32 SheepMem::page_size; // Size of a native page
|
||||
uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros
|
||||
uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data
|
||||
@ -385,15 +389,6 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_GTK
|
||||
// Init GTK
|
||||
gtk_set_locale();
|
||||
gtk_init(&argc, &argv);
|
||||
#endif
|
||||
|
||||
// Read preferences
|
||||
PrefsInit(argc, argv);
|
||||
|
||||
// Parse command line arguments
|
||||
for (int i=1; i<argc; i++) {
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
@ -404,7 +399,51 @@ int main(int argc, char **argv)
|
||||
if (i < argc)
|
||||
x_display_name = strdup(argv[i]);
|
||||
#endif
|
||||
} else if (argv[i][0] == '-') {
|
||||
} else if (strcmp(argv[i], "--gui-connection") == 0) {
|
||||
argv[i++] = NULL;
|
||||
if (i < argc) {
|
||||
gui_connection_path = argv[i];
|
||||
argv[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove processed arguments
|
||||
for (int i=1; i<argc; i++) {
|
||||
int k;
|
||||
for (k=i; k<argc; k++)
|
||||
if (argv[k] != NULL)
|
||||
break;
|
||||
if (k > i) {
|
||||
k -= i;
|
||||
for (int j=i+k; j<argc; j++)
|
||||
argv[j-k] = argv[j];
|
||||
argc -= k;
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to the external GUI
|
||||
if (gui_connection_path) {
|
||||
if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) {
|
||||
fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_GTK
|
||||
if (!gui_connection) {
|
||||
// Init GTK
|
||||
gtk_set_locale();
|
||||
gtk_init(&argc, &argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Read preferences
|
||||
PrefsInit(argc, argv);
|
||||
|
||||
// Any command line arguments left?
|
||||
for (int i=1; i<argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
|
||||
usage(argv[0]);
|
||||
}
|
||||
@ -485,19 +524,19 @@ int main(int argc, char **argv)
|
||||
sigsegv_action.sa_restorer = NULL;
|
||||
#endif
|
||||
if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
|
||||
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
|
||||
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
if (sigaction(SIGBUS, &sigsegv_action, NULL) < 0) {
|
||||
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
|
||||
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGBUS", strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
#else
|
||||
// Install SIGSEGV handler for CPU emulator
|
||||
if (!sigsegv_install_handler(sigsegv_handler)) {
|
||||
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
|
||||
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
@ -860,7 +899,7 @@ int main(int argc, char **argv)
|
||||
sigill_action.sa_restorer = NULL;
|
||||
#endif
|
||||
if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
|
||||
sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno));
|
||||
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
@ -875,7 +914,7 @@ int main(int argc, char **argv)
|
||||
sigusr2_action.sa_restorer = NULL;
|
||||
#endif
|
||||
if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
|
||||
sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
|
||||
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
@ -986,6 +1025,12 @@ static void Quit(void)
|
||||
XCloseDisplay(x_display);
|
||||
#endif
|
||||
|
||||
// Notify GUI we are about to leave
|
||||
if (gui_connection) {
|
||||
if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
||||
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -2078,6 +2123,11 @@ void display_alert(int title_id, int prefix_id, int button_id, const char *text)
|
||||
|
||||
void ErrorAlert(const char *text)
|
||||
{
|
||||
if (gui_connection) {
|
||||
if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
|
||||
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
||||
return;
|
||||
}
|
||||
#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
|
||||
if (PrefsFindBool("nogui") || x_display == NULL) {
|
||||
printf(GetString(STR_SHELL_ERROR_PREFIX), text);
|
||||
@ -2097,6 +2147,11 @@ void ErrorAlert(const char *text)
|
||||
|
||||
void WarningAlert(const char *text)
|
||||
{
|
||||
if (gui_connection) {
|
||||
if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
|
||||
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
||||
return;
|
||||
}
|
||||
#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
|
||||
if (PrefsFindBool("nogui") || x_display == NULL) {
|
||||
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
|
||||
|
@ -35,10 +35,13 @@
|
||||
#include "prefs.h"
|
||||
#include "prefs_editor.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static GtkWidget *win; // Preferences window
|
||||
static bool start_clicked = true; // Return value of PrefsEditor() function
|
||||
static bool start_clicked = false; // Return value of PrefsEditor() function
|
||||
static int screen_width, screen_height; // Screen dimensions
|
||||
|
||||
|
||||
@ -1291,7 +1294,277 @@ static void read_settings(void)
|
||||
{
|
||||
read_volumes_settings();
|
||||
read_graphics_settings();
|
||||
read_input_settings();
|
||||
read_serial_settings();
|
||||
read_memory_settings();
|
||||
read_jit_settings();
|
||||
}
|
||||
|
||||
|
||||
#ifdef STANDALONE_GUI
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include "rpc.h"
|
||||
|
||||
/*
|
||||
* Fake unused data and functions
|
||||
*/
|
||||
|
||||
uint8 XPRAM[XPRAM_SIZE];
|
||||
void MountVolume(void *fh) { }
|
||||
void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
|
||||
|
||||
#if defined __APPLE__ && defined __MACH__
|
||||
void DarwinAddCDROMPrefs(void) { }
|
||||
void DarwinAddFloppyPrefs(void) { }
|
||||
void DarwinAddSerialPrefs(void) { }
|
||||
bool DarwinCDReadTOC(char *, uint8 *) { }
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Display alert
|
||||
*/
|
||||
|
||||
static void dl_destroyed(void)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void display_alert(int title_id, int prefix_id, int button_id, const char *text)
|
||||
{
|
||||
char str[256];
|
||||
sprintf(str, GetString(prefix_id), text);
|
||||
|
||||
GtkWidget *dialog = gtk_dialog_new();
|
||||
gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
|
||||
gtk_container_border_width(GTK_CONTAINER(dialog), 5);
|
||||
gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
|
||||
gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
|
||||
|
||||
GtkWidget *label = gtk_label_new(str);
|
||||
gtk_widget_show(label);
|
||||
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
|
||||
|
||||
GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
|
||||
gtk_widget_show(button);
|
||||
gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
|
||||
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
|
||||
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
|
||||
gtk_widget_grab_default(button);
|
||||
gtk_widget_show(dialog);
|
||||
|
||||
gtk_main();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display error alert
|
||||
*/
|
||||
|
||||
void ErrorAlert(const char *text)
|
||||
{
|
||||
display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display warning alert
|
||||
*/
|
||||
|
||||
void WarningAlert(const char *text)
|
||||
{
|
||||
display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RPC handlers
|
||||
*/
|
||||
|
||||
static GMainLoop *g_gui_loop;
|
||||
|
||||
static int handle_ErrorAlert(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_ErrorAlert\n"));
|
||||
|
||||
int error;
|
||||
char *str;
|
||||
if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
|
||||
return error;
|
||||
|
||||
ErrorAlert(str);
|
||||
free(str);
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static int handle_WarningAlert(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_WarningAlert\n"));
|
||||
|
||||
int error;
|
||||
char *str;
|
||||
if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
|
||||
return error;
|
||||
|
||||
WarningAlert(str);
|
||||
free(str);
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static int handle_Exit(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_Exit\n"));
|
||||
|
||||
g_main_quit(g_gui_loop);
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SIGCHLD handler
|
||||
*/
|
||||
|
||||
static char g_app_path[PATH_MAX];
|
||||
static rpc_connection_t *g_gui_connection = NULL;
|
||||
|
||||
static void sigchld_handler(int sig, siginfo_t *sip, void *)
|
||||
{
|
||||
D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status));
|
||||
|
||||
// XXX perform a new wait because sip->si_status is sometimes not
|
||||
// the exit _value_ on MacOS X but rather the usual status field
|
||||
// from waitpid() -- we could arrange this code in some other way...
|
||||
int status;
|
||||
if (waitpid(sip->si_pid, &status, 0) < 0)
|
||||
status = sip->si_status;
|
||||
if (WIFEXITED(status))
|
||||
status = WEXITSTATUS(status);
|
||||
if (status & 0x80)
|
||||
status |= -1 ^0xff;
|
||||
|
||||
if (status < 0) { // negative -> execlp/-errno
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status));
|
||||
ErrorAlert(str);
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (status != 0) {
|
||||
if (g_gui_connection)
|
||||
rpc_exit(g_gui_connection);
|
||||
exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start standalone GUI
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Init GTK
|
||||
gtk_set_locale();
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// Read preferences
|
||||
PrefsInit(argc, argv);
|
||||
|
||||
// Show preferences editor
|
||||
bool start = PrefsEditor();
|
||||
|
||||
// Exit preferences
|
||||
PrefsExit();
|
||||
|
||||
// Transfer control to the executable
|
||||
if (start) {
|
||||
char gui_connection_path[64];
|
||||
sprintf(gui_connection_path, "/org/SheepShaver/GUI/%d", getpid());
|
||||
|
||||
// Catch exits from the child process
|
||||
struct sigaction sigchld_sa, old_sigchld_sa;
|
||||
sigemptyset(&sigchld_sa.sa_mask);
|
||||
sigchld_sa.sa_sigaction = sigchld_handler;
|
||||
sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
|
||||
if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) {
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno));
|
||||
ErrorAlert(str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Search and run the SheepShaver executable
|
||||
char *p;
|
||||
strcpy(g_app_path, argv[0]);
|
||||
if ((p = strstr(g_app_path, "SheepShaverGUI.app/Contents/MacOS")) != NULL) {
|
||||
strcpy(p, "SheepShaver.app/Contents/MacOS/SheepShaver");
|
||||
if (access(g_app_path, X_OK) < 0) {
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(errno));
|
||||
WarningAlert(str);
|
||||
strcpy(g_app_path, "/Applications/SheepShaver.app/Contents/MacOS/SheepShaver");
|
||||
}
|
||||
} else {
|
||||
p = strrchr(g_app_path, '/');
|
||||
p = p ? p + 1 : g_app_path;
|
||||
strcpy(p, "SheepShaver");
|
||||
}
|
||||
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
D(bug("Trying to execute %s\n", g_app_path));
|
||||
execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL);
|
||||
#ifdef _POSIX_PRIORITY_SCHEDULING
|
||||
// XXX get a chance to run the parent process so that to not confuse/upset GTK...
|
||||
sched_yield();
|
||||
#endif
|
||||
_exit(-errno);
|
||||
}
|
||||
|
||||
// Establish a connection to Basilisk II
|
||||
if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) {
|
||||
printf("ERROR: failed to initialize GUI-side RPC server connection\n");
|
||||
return 1;
|
||||
}
|
||||
static const rpc_method_descriptor_t vtable[] = {
|
||||
{ RPC_METHOD_ERROR_ALERT, handle_ErrorAlert },
|
||||
{ RPC_METHOD_WARNING_ALERT, handle_WarningAlert },
|
||||
{ RPC_METHOD_EXIT, handle_Exit }
|
||||
};
|
||||
if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
|
||||
printf("ERROR: failed to setup GUI method callbacks\n");
|
||||
return 1;
|
||||
}
|
||||
int socket;
|
||||
if ((socket = rpc_listen_socket(g_gui_connection)) < 0) {
|
||||
printf("ERROR: failed to initialize RPC server thread\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_gui_loop = g_main_new(TRUE);
|
||||
while (g_main_is_running(g_gui_loop)) {
|
||||
|
||||
// Process a few events pending
|
||||
const int N_EVENTS_DISPATCH = 10;
|
||||
for (int i = 0; i < N_EVENTS_DISPATCH; i++) {
|
||||
if (!g_main_iteration(FALSE))
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for RPC events (100 ms timeout)
|
||||
int ret = rpc_wait_dispatch(g_gui_connection, 100000);
|
||||
if (ret == 0)
|
||||
continue;
|
||||
if (ret < 0)
|
||||
break;
|
||||
rpc_dispatch(g_gui_connection);
|
||||
}
|
||||
|
||||
rpc_exit(g_gui_connection);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -42,9 +42,7 @@ user_string_def platform_strings[] = {
|
||||
{STR_DR_EMULATOR_MMAP_ERR, "Cannot map DR Emulator: %s."},
|
||||
{STR_SHEEP_MEM_MMAP_ERR, "Cannot map SheepShaver Data area: %s."},
|
||||
{STR_SIGALTSTACK_ERR, "Cannot install alternate signal stack (%s). It seems that you need a newer kernel."},
|
||||
{STR_SIGSEGV_INSTALL_ERR, "Cannot install SIGSEGV handler: %s."},
|
||||
{STR_SIGILL_INSTALL_ERR, "Cannot install SIGILL handler: %s."},
|
||||
{STR_SIGUSR2_INSTALL_ERR, "Cannot install SIGUSR2 handler (%s). It seems that you need a newer libc."},
|
||||
{STR_SIG_INSTALL_ERR, "Cannot install %s handler (%s)."},
|
||||
{STR_NO_XSERVER_ERR, "Cannot connect to X server %s."},
|
||||
{STR_NO_XVISUAL_ERR, "Cannot obtain appropriate X visual."},
|
||||
{STR_UNSUPP_DEPTH_ERR, "Unsupported color depth of screen."},
|
||||
@ -86,6 +84,8 @@ user_string_def platform_strings[] = {
|
||||
{STR_OPEN_WINDOW_ERR, "Cannot open Mac window."},
|
||||
{STR_WINDOW_TITLE_GRABBED, "SheepShaver (mouse grabbed, press Ctrl-F5 to release)"},
|
||||
|
||||
{STR_NO_B2_EXE_FOUND, "Could not start %s (%s)."},
|
||||
|
||||
{-1, NULL} // End marker
|
||||
};
|
||||
|
||||
|
@ -33,9 +33,7 @@ enum {
|
||||
STR_DR_EMULATOR_MMAP_ERR,
|
||||
STR_SHEEP_MEM_MMAP_ERR,
|
||||
STR_SIGALTSTACK_ERR,
|
||||
STR_SIGSEGV_INSTALL_ERR,
|
||||
STR_SIGILL_INSTALL_ERR,
|
||||
STR_SIGUSR2_INSTALL_ERR,
|
||||
STR_SIG_INSTALL_ERR,
|
||||
STR_NO_XSERVER_ERR,
|
||||
STR_NO_XVISUAL_ERR,
|
||||
STR_UNSUPP_DEPTH_ERR,
|
||||
@ -78,7 +76,9 @@ enum {
|
||||
STR_MOUSEWHEELLINES_CTRL,
|
||||
|
||||
STR_OPEN_WINDOW_ERR,
|
||||
STR_WINDOW_TITLE_GRABBED
|
||||
STR_WINDOW_TITLE_GRABBED,
|
||||
|
||||
STR_NO_B2_EXE_FOUND
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user