ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/prefs_editor_gtk.cpp
(Generate patch)

Comparing SheepShaver/src/Unix/prefs_editor_gtk.cpp (file contents):
Revision 1.16 by gbeauche, 2005-11-29T23:59:36Z vs.
Revision 1.17 by gbeauche, 2006-05-01T22:33:34Z

# Line 35 | Line 35
35   #include "prefs.h"
36   #include "prefs_editor.h"
37  
38 + #define DEBUG 0
39 + #include "debug.h"
40 +
41  
42   // Global variables
43   static GtkWidget *win;                          // Preferences window
44 < static bool start_clicked = true;       // Return value of PrefsEditor() function
44 > static bool start_clicked = false;      // Return value of PrefsEditor() function
45   static int screen_width, screen_height; // Screen dimensions
46  
47  
# Line 1291 | Line 1294 | static void read_settings(void)
1294   {
1295          read_volumes_settings();
1296          read_graphics_settings();
1297 +        read_input_settings();
1298          read_serial_settings();
1299          read_memory_settings();
1300          read_jit_settings();
1301   }
1302 +
1303 +
1304 + #ifdef STANDALONE_GUI
1305 + #include <errno.h>
1306 + #include <sys/wait.h>
1307 + #include "rpc.h"
1308 +
1309 + /*
1310 + *  Fake unused data and functions
1311 + */
1312 +
1313 + uint8 XPRAM[XPRAM_SIZE];
1314 + void MountVolume(void *fh) { }
1315 + void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1316 +
1317 + #if defined __APPLE__ && defined __MACH__
1318 + void DarwinAddCDROMPrefs(void) { }
1319 + void DarwinAddFloppyPrefs(void) { }
1320 + void DarwinAddSerialPrefs(void) { }
1321 + bool DarwinCDReadTOC(char *, uint8 *) { }
1322 + #endif
1323 +
1324 +
1325 + /*
1326 + *  Display alert
1327 + */
1328 +
1329 + static void dl_destroyed(void)
1330 + {
1331 +        gtk_main_quit();
1332 + }
1333 +
1334 + static void display_alert(int title_id, int prefix_id, int button_id, const char *text)
1335 + {
1336 +        char str[256];
1337 +        sprintf(str, GetString(prefix_id), text);
1338 +
1339 +        GtkWidget *dialog = gtk_dialog_new();
1340 +        gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
1341 +        gtk_container_border_width(GTK_CONTAINER(dialog), 5);
1342 +        gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
1343 +        gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
1344 +
1345 +        GtkWidget *label = gtk_label_new(str);
1346 +        gtk_widget_show(label);
1347 +        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
1348 +
1349 +        GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
1350 +        gtk_widget_show(button);
1351 +        gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
1352 +        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
1353 +        GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1354 +        gtk_widget_grab_default(button);
1355 +        gtk_widget_show(dialog);
1356 +
1357 +        gtk_main();
1358 + }
1359 +
1360 +
1361 + /*
1362 + *  Display error alert
1363 + */
1364 +
1365 + void ErrorAlert(const char *text)
1366 + {
1367 +        display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
1368 + }
1369 +
1370 +
1371 + /*
1372 + *  Display warning alert
1373 + */
1374 +
1375 + void WarningAlert(const char *text)
1376 + {
1377 +        display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
1378 + }
1379 +
1380 +
1381 + /*
1382 + *  RPC handlers
1383 + */
1384 +
1385 + static GMainLoop *g_gui_loop;
1386 +
1387 + static int handle_ErrorAlert(rpc_connection_t *connection)
1388 + {
1389 +        D(bug("handle_ErrorAlert\n"));
1390 +
1391 +        int error;
1392 +        char *str;
1393 +        if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1394 +                return error;
1395 +
1396 +        ErrorAlert(str);
1397 +        free(str);
1398 +        return RPC_ERROR_NO_ERROR;
1399 + }
1400 +
1401 + static int handle_WarningAlert(rpc_connection_t *connection)
1402 + {
1403 +        D(bug("handle_WarningAlert\n"));
1404 +
1405 +        int error;
1406 +        char *str;
1407 +        if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1408 +                return error;
1409 +
1410 +        WarningAlert(str);
1411 +        free(str);
1412 +        return RPC_ERROR_NO_ERROR;
1413 + }
1414 +
1415 + static int handle_Exit(rpc_connection_t *connection)
1416 + {
1417 +        D(bug("handle_Exit\n"));
1418 +
1419 +        g_main_quit(g_gui_loop);
1420 +        return RPC_ERROR_NO_ERROR;
1421 + }
1422 +
1423 +
1424 + /*
1425 + *  SIGCHLD handler
1426 + */
1427 +
1428 + static char g_app_path[PATH_MAX];
1429 + static rpc_connection_t *g_gui_connection = NULL;
1430 +
1431 + static void sigchld_handler(int sig, siginfo_t *sip, void *)
1432 + {
1433 +        D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status));
1434 +
1435 +        // XXX perform a new wait because sip->si_status is sometimes not
1436 +        // the exit _value_ on MacOS X but rather the usual status field
1437 +        // from waitpid() -- we could arrange this code in some other way...
1438 +        int status;
1439 +        if (waitpid(sip->si_pid, &status, 0) < 0)
1440 +                status = sip->si_status;
1441 +        if (WIFEXITED(status))
1442 +                status = WEXITSTATUS(status);
1443 +        if (status & 0x80)
1444 +                status |= -1 ^0xff;
1445 +
1446 +        if (status < 0) {       // negative -> execlp/-errno
1447 +                char str[256];
1448 +                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status));
1449 +                ErrorAlert(str);
1450 +                status = 1;
1451 +        }
1452 +
1453 +        if (status != 0) {
1454 +                if (g_gui_connection)
1455 +                        rpc_exit(g_gui_connection);
1456 +                exit(status);
1457 +        }
1458 + }
1459 +
1460 +
1461 + /*
1462 + *  Start standalone GUI
1463 + */
1464 +
1465 + int main(int argc, char *argv[])
1466 + {
1467 +        // Init GTK
1468 +        gtk_set_locale();
1469 +        gtk_init(&argc, &argv);
1470 +
1471 +        // Read preferences
1472 +        PrefsInit(argc, argv);
1473 +
1474 +        // Show preferences editor
1475 +        bool start = PrefsEditor();
1476 +
1477 +        // Exit preferences
1478 +        PrefsExit();
1479 +
1480 +        // Transfer control to the executable
1481 +        if (start) {
1482 +                char gui_connection_path[64];
1483 +                sprintf(gui_connection_path, "/org/SheepShaver/GUI/%d", getpid());
1484 +
1485 +                // Catch exits from the child process
1486 +                struct sigaction sigchld_sa, old_sigchld_sa;
1487 +                sigemptyset(&sigchld_sa.sa_mask);
1488 +                sigchld_sa.sa_sigaction = sigchld_handler;
1489 +                sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
1490 +                if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) {
1491 +                        char str[256];
1492 +                        sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno));
1493 +                        ErrorAlert(str);
1494 +                        return 1;
1495 +                }
1496 +
1497 +                // Search and run the SheepShaver executable
1498 +                char *p;
1499 +                strcpy(g_app_path, argv[0]);
1500 +                if ((p = strstr(g_app_path, "SheepShaverGUI.app/Contents/MacOS")) != NULL) {
1501 +                    strcpy(p, "SheepShaver.app/Contents/MacOS/SheepShaver");
1502 +                        if (access(g_app_path, X_OK) < 0) {
1503 +                                char str[256];
1504 +                                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(errno));
1505 +                                WarningAlert(str);
1506 +                                strcpy(g_app_path, "/Applications/SheepShaver.app/Contents/MacOS/SheepShaver");
1507 +                        }
1508 +                } else {
1509 +                        p = strrchr(g_app_path, '/');
1510 +                        p = p ? p + 1 : g_app_path;
1511 +                        strcpy(p, "SheepShaver");
1512 +                }
1513 +
1514 +                int pid = fork();
1515 +                if (pid == 0) {
1516 +                        D(bug("Trying to execute %s\n", g_app_path));
1517 +                        execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL);
1518 + #ifdef _POSIX_PRIORITY_SCHEDULING
1519 +                        // XXX get a chance to run the parent process so that to not confuse/upset GTK...
1520 +                        sched_yield();
1521 + #endif
1522 +                        _exit(-errno);
1523 +                }
1524 +
1525 +                // Establish a connection to Basilisk II
1526 +                if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) {
1527 +                        printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1528 +                        return 1;
1529 +                }
1530 +                static const rpc_method_descriptor_t vtable[] = {
1531 +                        { RPC_METHOD_ERROR_ALERT,                       handle_ErrorAlert },
1532 +                        { RPC_METHOD_WARNING_ALERT,                     handle_WarningAlert },
1533 +                        { RPC_METHOD_EXIT,                                      handle_Exit }
1534 +                };
1535 +                if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1536 +                        printf("ERROR: failed to setup GUI method callbacks\n");
1537 +                        return 1;
1538 +                }
1539 +                int socket;
1540 +                if ((socket = rpc_listen_socket(g_gui_connection)) < 0) {
1541 +                        printf("ERROR: failed to initialize RPC server thread\n");
1542 +                        return 1;
1543 +                }
1544 +
1545 +                g_gui_loop = g_main_new(TRUE);
1546 +                while (g_main_is_running(g_gui_loop)) {
1547 +
1548 +                        // Process a few events pending
1549 +                        const int N_EVENTS_DISPATCH = 10;
1550 +                        for (int i = 0; i < N_EVENTS_DISPATCH; i++) {
1551 +                                if (!g_main_iteration(FALSE))
1552 +                                        break;
1553 +                        }
1554 +
1555 +                        // Check for RPC events (100 ms timeout)
1556 +                        int ret = rpc_wait_dispatch(g_gui_connection, 100000);
1557 +                        if (ret == 0)
1558 +                                continue;
1559 +                        if (ret < 0)
1560 +                                break;
1561 +                        rpc_dispatch(g_gui_connection);
1562 +                }
1563 +
1564 +                rpc_exit(g_gui_connection);
1565 +                return 0;
1566 +        }
1567 +
1568 +        return 0;
1569 + }
1570 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines