/* 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
*/