/* simple.c * Copyright (C) 1997 Red Hat, Inc * Author: Elliot Lee * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library. If not, see . */ #include #include #include jmp_buf jmp_ret; void gdk_display_closed_callback(GdkDisplay *display, gboolean is_error, gpointer data) { fprintf(stderr, "gdk_display_closed_callback %p is_error=%d data=%p\n", display, is_error, data); } void register_closed_callback() { Display *dpy = gdk_x11_display_get_xdisplay (gdk_display_get_default ()); GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy); int closed_callback_tag = g_signal_connect (G_OBJECT (gdpy), "closed", G_CALLBACK (gdk_display_closed_callback), NULL); if (!closed_callback_tag) { fprintf(stderr, "failed to register a callback on gdk display ::closed\n"); } else { fprintf(stderr, "registered \"closed\" callback on gdk display %p dpy %s\n", gdpy, DisplayString(dpy)); } } void hello (void) { g_print ("hello world\n"); } void x_error_quitter (Display *display, XErrorEvent *event) { if (event->error_code == BadName) return; char buf[256]; XGetErrorText (display, event->error_code, buf, sizeof (buf)); fprintf(stderr, "x_error_quitter on %s: error %s on protocol request %d\n", DisplayString(display), buf, event->request_code); longjmp(jmp_ret, 1); } static int x_io_error_quitter (Display *display) { fprintf(stderr, "Connection lost to X Server%s\n", DisplayString (display)); longjmp(jmp_ret, 2); } static int x_error_handler (Display *display, XErrorEvent *event) { fprintf(stderr, "x_error_handler %p %p\n", display, event); if ((event->error_code == BadMatch || event->error_code == BadWindow) /* && event->request_code == X_SetInputFocus */) { return 0; } x_error_quitter (display, event); return 0; } void my_gtk_main_quit(GtkWidget *window, gboolean *kill_switch) { fprintf(stderr, "my_gtk_main_quit()\n"); *kill_switch = True; } int main (int argc, char *argv[]) { GtkWidget *window; gtk_init (&argc, &argv); register_closed_callback(); XSetErrorHandler (x_error_handler); XSetIOErrorHandler (x_io_error_quitter); gboolean kill_switch = False; window = g_object_connect (g_object_new (gtk_window_get_type (), "type", GTK_WINDOW_TOPLEVEL, "title", "hello world", "resizable", FALSE, "border_width", 10, NULL), "signal::destroy", my_gtk_main_quit, &kill_switch, NULL); g_object_connect (g_object_new (gtk_button_get_type (), "GtkButton::label", "hello world", "GtkWidget::parent", window, "GtkWidget::visible", TRUE, NULL), "signal::clicked", hello, NULL, NULL); gtk_widget_show (window); GMainContext *default_context = g_main_context_default(); guint64 n_iter = 0; int ret; if ((ret = setjmp(jmp_ret)) != 0) { fprintf(stderr, "handled longjmp from %squitter\n", (ret == 2) ? "io" : ""); } while(1) { if (kill_switch) break; gboolean ret = g_main_context_iteration(default_context, True); n_iter++; if (n_iter % 10 == 0) fprintf(stderr, "."); if (n_iter % 1000 == 0) { fprintf(stderr, "\n"); n_iter = 0; } } fprintf(stderr, "\nquitting: %d\n", kill_switch); return 0; } /* gcc simple.c -Wno-deprecated -Wno-deprecated-declarations -g3 $(pkg-config gtk+-3.0 --cflags --libs ) -lX11 $ DISPLAY=:0 Xephyr :1 $ DISPLAY=:1 G_DEBUG=fatal-warnings ./a.out */