]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkmain-x11.c
Initial client-side-windows work
[~andy/gtk] / gdk / x11 / gdkmain-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #include <glib/gprintf.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <limits.h>
34 #include <errno.h>
35
36 #include <X11/Xatom.h>
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39
40 #ifdef HAVE_XKB
41 #include <X11/XKBlib.h>
42 #endif
43
44 #include "gdk.h"
45
46 #include "gdkx.h"
47 #include "gdkdisplay-x11.h"
48 #include "gdkinternals.h"
49 #include "gdkintl.h"
50 #include "gdkregion-generic.h"
51 #include "gdkinputprivate.h"
52 #include "gdkalias.h"
53
54 typedef struct _GdkPredicate  GdkPredicate;
55 typedef struct _GdkErrorTrap  GdkErrorTrap;
56
57 struct _GdkPredicate
58 {
59   GdkEventFunc func;
60   gpointer data;
61 };
62
63 struct _GdkErrorTrap
64 {
65   int (*old_handler) (Display *, XErrorEvent *);
66   gint error_warnings;
67   gint error_code;
68 };
69
70 /* 
71  * Private function declarations
72  */
73
74 #ifndef HAVE_XCONVERTCASE
75 static void      gdkx_XConvertCase      (KeySym        symbol,
76                                          KeySym       *lower,
77                                          KeySym       *upper);
78 #define XConvertCase gdkx_XConvertCase
79 #endif
80
81 static int          gdk_x_error                  (Display     *display, 
82                                                   XErrorEvent *error);
83 static int          gdk_x_io_error               (Display     *display);
84
85 /* Private variable declarations
86  */
87 static GSList *gdk_error_traps = NULL;               /* List of error traps */
88 static GSList *gdk_error_trap_free_list = NULL;      /* Free list */
89
90 const GOptionEntry _gdk_windowing_args[] = {
91   { "sync", 0, 0, G_OPTION_ARG_NONE, &_gdk_synchronize, 
92     /* Description of --sync in --help output */ N_("Make X calls synchronous"), NULL },
93   { NULL }
94 };
95
96 void
97 _gdk_windowing_init (void)
98 {
99   _gdk_x11_initialize_locale ();
100   
101   XSetErrorHandler (gdk_x_error);
102   XSetIOErrorHandler (gdk_x_io_error);
103
104   _gdk_selection_property = gdk_atom_intern_static_string ("GDK_SELECTION");
105 }
106
107 void
108 gdk_set_use_xshm (gboolean use_xshm)
109 {
110 }
111
112 gboolean
113 gdk_get_use_xshm (void)
114 {
115   return GDK_DISPLAY_X11 (gdk_display_get_default ())->use_xshm;
116 }
117
118 static GdkGrabStatus
119 gdk_x11_convert_grab_status (gint status)
120 {
121   switch (status)
122     {
123     case GrabSuccess:
124       return GDK_GRAB_SUCCESS;
125     case AlreadyGrabbed:
126       return GDK_GRAB_ALREADY_GRABBED;
127     case GrabInvalidTime:
128       return GDK_GRAB_INVALID_TIME;
129     case GrabNotViewable:
130       return GDK_GRAB_NOT_VIEWABLE;
131     case GrabFrozen:
132       return GDK_GRAB_FROZEN;
133     }
134
135   g_assert_not_reached();
136
137   return 0;
138 }
139
140 static void
141 generate_grab_broken_event (GdkWindow *window,
142                             gboolean   keyboard,
143                             gboolean   implicit,
144                             GdkWindow *grab_window)
145 {
146   g_return_if_fail (window != NULL);
147
148   if (!GDK_WINDOW_DESTROYED (window))
149     {
150       GdkEvent event;
151       event.type = GDK_GRAB_BROKEN;
152       event.grab_broken.window = window;
153       event.grab_broken.send_event = 0;
154       event.grab_broken.keyboard = keyboard;
155       event.grab_broken.implicit = implicit;
156       event.grab_broken.grab_window = grab_window;
157       gdk_event_put (&event);
158     }
159 }
160
161 /*
162  *--------------------------------------------------------------
163  * gdk_pointer_grab
164  *
165  *   Grabs the pointer to a specific window
166  *
167  * Arguments:
168  *   "window" is the window which will receive the grab
169  *   "owner_events" specifies whether events will be reported as is,
170  *     or relative to "window"
171  *   "event_mask" masks only interesting events
172  *   "confine_to" limits the cursor movement to the specified window
173  *   "cursor" changes the cursor for the duration of the grab
174  *   "time" specifies the time
175  *
176  * Results:
177  *
178  * Side effects:
179  *   requires a corresponding call to gdk_pointer_ungrab
180  *
181  *--------------------------------------------------------------
182  */
183
184 GdkGrabStatus
185 gdk_pointer_grab (GdkWindow *     window,
186                   gboolean        owner_events,
187                   GdkEventMask    event_mask,
188                   GdkWindow *     confine_to,
189                   GdkCursor *     cursor,
190                   guint32         time)
191 {
192   gint return_val;
193   GdkCursorPrivate *cursor_private;
194   GdkWindow *native;
195   GdkDisplayX11 *display_x11;
196   guint xevent_mask;
197   Window xwindow;
198   Window xconfine_to;
199   Cursor xcursor;
200   unsigned long serial;
201   int i;
202   
203   g_return_val_if_fail (window != NULL, 0);
204   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
205   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
206
207   native = _gdk_window_get_impl_window (window);
208
209   if (confine_to)
210     confine_to = _gdk_window_get_impl_window (confine_to);
211
212   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
213
214   cursor_private = (GdkCursorPrivate*) cursor;
215   
216   xwindow = GDK_WINDOW_XID (native);
217   serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
218   
219   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
220     xconfine_to = None;
221   else
222     xconfine_to = GDK_WINDOW_XID (confine_to);
223   
224   if (!cursor)
225     xcursor = None;
226   else
227     {
228       _gdk_x11_cursor_update_theme (cursor);
229       xcursor = cursor_private->xcursor;
230     }
231   
232   xevent_mask = 0;
233   for (i = 0; i < _gdk_nenvent_masks; i++)
234     {
235       if (event_mask & (1 << (i + 1)))
236         xevent_mask |= _gdk_event_mask_table[i];
237     }
238   
239   return_val = _gdk_input_grab_pointer (native,
240                                         owner_events,
241                                         event_mask,
242                                         confine_to,
243                                         time);
244
245   if (return_val == GrabSuccess || 
246       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
247     {
248       if (!GDK_WINDOW_DESTROYED (native))
249         {
250 #ifdef G_ENABLE_DEBUG
251           if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
252             return_val = GrabSuccess;
253           else
254 #endif
255             return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
256                                        xwindow,
257                                        owner_events,
258                                        xevent_mask,
259                                        GrabModeAsync, GrabModeAsync,
260                                        xconfine_to,
261                                        xcursor,
262                                        time);
263         }
264       else
265         return_val = AlreadyGrabbed;
266     }
267   
268   if (return_val == GrabSuccess)
269     {
270       _gdk_display_set_has_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
271                                          window,
272                                          native,
273                                          owner_events,
274                                          event_mask,
275                                          serial,
276                                          time,
277                                          FALSE);
278     }
279
280   return gdk_x11_convert_grab_status (return_val);
281 }
282
283 /*
284  *--------------------------------------------------------------
285  * gdk_keyboard_grab
286  *
287  *   Grabs the keyboard to a specific window
288  *
289  * Arguments:
290  *   "window" is the window which will receive the grab
291  *   "owner_events" specifies whether events will be reported as is,
292  *     or relative to "window"
293  *   "time" specifies the time
294  *
295  * Results:
296  *
297  * Side effects:
298  *   requires a corresponding call to gdk_keyboard_ungrab
299  *
300  *--------------------------------------------------------------
301  */
302
303 GdkGrabStatus
304 gdk_keyboard_grab (GdkWindow *     window,
305                    gboolean        owner_events,
306                    guint32         time)
307 {
308   gint return_val;
309   unsigned long serial;
310   GdkDisplayX11 *display_x11;
311   GdkWindow *native;
312
313   if (1) return 0; /* TODO: fix */
314   
315   g_return_val_if_fail (window != NULL, 0);
316   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
317
318   native = _gdk_window_get_impl_window (window);
319
320   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
321
322   serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
323
324   if (!GDK_WINDOW_DESTROYED (native))
325     {
326 #ifdef G_ENABLE_DEBUG
327       if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
328         return_val = GrabSuccess;
329       else
330 #endif
331         return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (native),
332                                     GDK_WINDOW_XID (native),
333                                     owner_events,
334                                     GrabModeAsync, GrabModeAsync,
335                                     time);
336         if (G_UNLIKELY (!display_x11->trusted_client && 
337                         return_val == AlreadyGrabbed))
338           /* we can't grab the keyboard, but we can do a GTK-local grab */
339           return_val = GrabSuccess;
340     }
341   else
342     return_val = AlreadyGrabbed;
343
344   if (return_val == GrabSuccess)
345     {
346       if (display_x11->keyboard_xgrab_window != NULL &&
347           display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
348         generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
349                                     TRUE, FALSE, window);
350       
351       display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
352       display_x11->keyboard_xgrab_native_window = (GdkWindowObject *)native;
353       display_x11->keyboard_xgrab_serial = serial;
354       display_x11->keyboard_xgrab_owner_events = owner_events;
355       display_x11->keyboard_xgrab_time = time;      
356     }
357
358   return gdk_x11_convert_grab_status (return_val);
359 }
360
361 void
362 _gdk_windowing_grab_broken (GdkDisplay *display)
363 {
364   /* TODO: Move to common code */
365 #if 0
366   GdkDisplayX11 *display_x11;
367
368   g_return_if_fail (display != NULL);
369
370   display_x11 = GDK_DISPLAY_X11 (display);
371   generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_grab.window),
372                               FALSE,
373                               display_x11->pointer_grab.implicit,
374                               NULL);
375   display_x11->pointer_grab.window = NULL;
376 #endif
377 }
378
379 /**
380  * gdk_keyboard_grab_info_libgtk_only:
381  * @display: the display for which to get the grab information
382  * @grab_window: location to store current grab window
383  * @owner_events: location to store boolean indicating whether
384  *   the @owner_events flag to gdk_keyboard_grab() was %TRUE.
385  * 
386  * Determines information about the current keyboard grab.
387  * This is not public API and must not be used by applications.
388  * 
389  * Return value: %TRUE if this application currently has the
390  *  keyboard grabbed.
391  **/
392 gboolean
393 gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
394                                     GdkWindow **grab_window,
395                                     gboolean   *owner_events)
396 {
397   GdkDisplayX11 *display_x11;
398   
399   g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
400
401   display_x11 = GDK_DISPLAY_X11 (display);
402
403   if (display_x11->keyboard_xgrab_window)
404     {
405       if (grab_window)
406         *grab_window = (GdkWindow *)display_x11->keyboard_xgrab_window;
407       if (owner_events)
408         *owner_events = display_x11->keyboard_xgrab_owner_events;
409
410       return TRUE;
411     }
412   else
413     return FALSE;
414 }
415
416 /**
417  * _gdk_xgrab_check_unmap:
418  * @window: a #GdkWindow
419  * @serial: serial from Unmap event (or from NextRequest(display)
420  *   if the unmap is being done by this client.)
421  * 
422  * Checks to see if an unmap request or event causes the current
423  * grab window to become not viewable, and if so, clear the
424  * the pointer we keep to it.
425  **/
426 void
427 _gdk_xgrab_check_unmap (GdkWindow *window,
428                         gulong     serial)
429 {
430   GdkDisplay *display = gdk_drawable_get_display (window);
431   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
432   
433   if (display->pointer_grab.window && 
434       serial >= display->pointer_grab.serial)
435     {
436       GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
437       GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->pointer_grab.native_window);
438
439       while (tmp && tmp != private)
440         tmp = tmp->parent;
441
442       if (tmp)
443         _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
444     }
445
446   if (display_x11->keyboard_xgrab_window &&
447       serial >= display_x11->keyboard_xgrab_serial)
448     {
449       GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
450       GdkWindowObject *tmp = display_x11->keyboard_xgrab_window;
451       
452
453       while (tmp && tmp != private)
454         tmp = tmp->parent;
455
456       if (tmp)
457         {
458           generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
459                                       TRUE, FALSE, NULL);
460           display_x11->keyboard_xgrab_window = NULL;  
461         }
462     }
463 }
464
465 /**
466  * _gdk_xgrab_check_destroy:
467  * @window: a #GdkWindow
468  * 
469  * Checks to see if window is the current grab window, and if
470  * so, clear the current grab window.
471  **/
472 void
473 _gdk_xgrab_check_destroy (GdkWindow *window)
474 {
475   GdkDisplay *display = gdk_drawable_get_display (window);
476   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
477   
478   if (window == display->pointer_grab.native_window &&
479       display->pointer_grab.window != NULL)
480     _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
481
482   if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_native_window &&
483       display_x11->keyboard_xgrab_window != NULL)
484     {
485       generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
486                                   TRUE, FALSE, NULL);
487       display_x11->keyboard_xgrab_window = NULL;
488     }
489 }
490
491 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
492                              GDK_BUTTON2_MASK | \
493                              GDK_BUTTON3_MASK | \
494                              GDK_BUTTON4_MASK | \
495                              GDK_BUTTON5_MASK)
496
497 /**
498  * _gdk_xgrab_check_button_event:
499  * @window: a #GdkWindow
500  * @event: an XEvent of type ButtonPress or ButtonRelease
501  * 
502  * Checks to see if a button event starts or ends an implicit grab.
503  **/
504 void
505 _gdk_xgrab_check_button_event (GdkWindow *window, 
506                                XEvent *xevent)
507 {
508   GdkDisplay *display = gdk_drawable_get_display (window);
509   
510   /* track implicit grabs for button presses */
511   switch (xevent->type)
512     {
513     case ButtonPress:
514       if (!display->pointer_grab.window)
515         {
516           _gdk_display_set_has_pointer_grab (display,
517                                              window,
518                                              window,
519                                              FALSE,
520                                              gdk_window_get_events (window),
521                                              xevent->xany.serial,
522                                              xevent->xbutton.time,
523                                              TRUE);
524         }
525       break;
526     case ButtonRelease:
527       if (display->pointer_grab.window &&
528           display->pointer_grab.implicit &&
529           (xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
530         {
531           _gdk_display_unset_has_pointer_grab (display, TRUE, TRUE,
532                                                xevent->xbutton.time);
533         }
534       break;
535     default:
536       g_assert_not_reached ();
537     }
538 }
539
540 void
541 _gdk_windowing_display_set_sm_client_id (GdkDisplay  *display,
542                                          const gchar *sm_client_id)
543 {
544   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
545
546   if (display->closed)
547     return;
548
549   if (sm_client_id && strcmp (sm_client_id, ""))
550     {
551       XChangeProperty (display_x11->xdisplay, display_x11->leader_window,
552                        gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"),
553                        XA_STRING, 8, PropModeReplace, (guchar *)sm_client_id,
554                        strlen (sm_client_id));
555     }
556   else
557     XDeleteProperty (display_x11->xdisplay, display_x11->leader_window,
558                      gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"));
559 }
560
561 /* Close all open displays
562  */
563 void
564 _gdk_windowing_exit (void)
565 {
566   GSList *tmp_list = _gdk_displays;
567     
568   while (tmp_list)
569     {
570       XCloseDisplay (GDK_DISPLAY_XDISPLAY (tmp_list->data));
571       
572       tmp_list = tmp_list->next;
573   }
574 }
575
576 /*
577  *--------------------------------------------------------------
578  * gdk_x_error
579  *
580  *   The X error handling routine.
581  *
582  * Arguments:
583  *   "display" is the X display the error orignated from.
584  *   "error" is the XErrorEvent that we are handling.
585  *
586  * Results:
587  *   Either we were expecting some sort of error to occur,
588  *   in which case we set the "_gdk_error_code" flag, or this
589  *   error was unexpected, in which case we will print an
590  *   error message and exit. (Since trying to continue will
591  *   most likely simply lead to more errors).
592  *
593  * Side effects:
594  *
595  *--------------------------------------------------------------
596  */
597
598 static int
599 gdk_x_error (Display     *display,
600              XErrorEvent *error)
601 {
602   if (error->error_code)
603     {
604       if (_gdk_error_warnings)
605         {
606           gchar buf[64];
607           gchar *msg;
608           
609           XGetErrorText (display, error->error_code, buf, 63);
610
611           msg =
612             g_strdup_printf ("The program '%s' received an X Window System error.\n"
613                              "This probably reflects a bug in the program.\n"
614                              "The error was '%s'.\n"
615                              "  (Details: serial %ld error_code %d request_code %d minor_code %d)\n"
616                              "  (Note to programmers: normally, X errors are reported asynchronously;\n"
617                              "   that is, you will receive the error a while after causing it.\n"
618                              "   To debug your program, run it with the --sync command line\n"
619                              "   option to change this behavior. You can then get a meaningful\n"
620                              "   backtrace from your debugger if you break on the gdk_x_error() function.)",
621                              g_get_prgname (),
622                              buf,
623                              error->serial, 
624                              error->error_code, 
625                              error->request_code,
626                              error->minor_code);
627           
628 #ifdef G_ENABLE_DEBUG     
629           g_error ("%s", msg);
630 #else /* !G_ENABLE_DEBUG */
631           g_fprintf (stderr, "%s\n", msg);
632
633           exit (1);
634 #endif /* G_ENABLE_DEBUG */
635         }
636       _gdk_error_code = error->error_code;
637     }
638   
639   return 0;
640 }
641
642 /*
643  *--------------------------------------------------------------
644  * gdk_x_io_error
645  *
646  *   The X I/O error handling routine.
647  *
648  * Arguments:
649  *   "display" is the X display the error orignated from.
650  *
651  * Results:
652  *   An X I/O error basically means we lost our connection
653  *   to the X server. There is not much we can do to
654  *   continue, so simply print an error message and exit.
655  *
656  * Side effects:
657  *
658  *--------------------------------------------------------------
659  */
660
661 static int
662 gdk_x_io_error (Display *display)
663 {
664   /* This is basically modelled after the code in XLib. We need
665    * an explicit error handler here, so we can disable our atexit()
666    * which would otherwise cause a nice segfault.
667    * We fprintf(stderr, instead of g_warning() because g_warning()
668    * could possibly be redirected to a dialog
669    */
670   if (errno == EPIPE)
671     {
672       g_fprintf (stderr,
673                "The application '%s' lost its connection to the display %s;\n"
674                "most likely the X server was shut down or you killed/destroyed\n"
675                "the application.\n",
676                g_get_prgname (),
677                display ? DisplayString (display) : gdk_get_display_arg_name ());
678     }
679   else
680     {
681       g_fprintf (stderr, "%s: Fatal IO error %d (%s) on X server %s.\n",
682                g_get_prgname (),
683                errno, g_strerror (errno),
684                display ? DisplayString (display) : gdk_get_display_arg_name ());
685     }
686
687   exit(1);
688 }
689
690 /*************************************************************
691  * gdk_error_trap_push:
692  *     Push an error trap. X errors will be trapped until
693  *     the corresponding gdk_error_pop(), which will return
694  *     the error code, if any.
695  *   arguments:
696  *     
697  *   results:
698  *************************************************************/
699
700 void
701 gdk_error_trap_push (void)
702 {
703   GSList *node;
704   GdkErrorTrap *trap;
705
706   if (gdk_error_trap_free_list)
707     {
708       node = gdk_error_trap_free_list;
709       gdk_error_trap_free_list = gdk_error_trap_free_list->next;
710     }
711   else
712     {
713       node = g_slist_alloc ();
714       node->data = g_new (GdkErrorTrap, 1);
715     }
716
717   node->next = gdk_error_traps;
718   gdk_error_traps = node;
719   
720   trap = node->data;
721   trap->old_handler = XSetErrorHandler (gdk_x_error);
722   trap->error_code = _gdk_error_code;
723   trap->error_warnings = _gdk_error_warnings;
724
725   _gdk_error_code = 0;
726   _gdk_error_warnings = 0;
727 }
728
729 /*************************************************************
730  * gdk_error_trap_pop:
731  *     Pop an error trap added with gdk_error_push()
732  *   arguments:
733  *     
734  *   results:
735  *     0, if no error occured, otherwise the error code.
736  *************************************************************/
737
738 gint
739 gdk_error_trap_pop (void)
740 {
741   GSList *node;
742   GdkErrorTrap *trap;
743   gint result;
744
745   g_return_val_if_fail (gdk_error_traps != NULL, 0);
746
747   node = gdk_error_traps;
748   gdk_error_traps = gdk_error_traps->next;
749
750   node->next = gdk_error_trap_free_list;
751   gdk_error_trap_free_list = node;
752   
753   result = _gdk_error_code;
754   
755   trap = node->data;
756   _gdk_error_code = trap->error_code;
757   _gdk_error_warnings = trap->error_warnings;
758   XSetErrorHandler (trap->old_handler);
759   
760   return result;
761 }
762
763 gchar *
764 gdk_get_display (void)
765 {
766   return g_strdup (gdk_display_get_name (gdk_display_get_default ()));
767 }
768
769 /**
770  * _gdk_send_xevent:
771  * @display: #GdkDisplay which @window is on
772  * @window: window ID to which to send the event
773  * @propagate: %TRUE if the event should be propagated if the target window
774  *             doesn't handle it.
775  * @event_mask: event mask to match against, or 0 to send it to @window
776  *              without regard to event masks.
777  * @event_send: #XEvent to send
778  * 
779  * Send an event, like XSendEvent(), but trap errors and check
780  * the result.
781  * 
782  * Return value: %TRUE if sending the event succeeded.
783  **/
784 gint 
785 _gdk_send_xevent (GdkDisplay *display,
786                   Window      window, 
787                   gboolean    propagate, 
788                   glong       event_mask,
789                   XEvent     *event_send)
790 {
791   gboolean result;
792
793   if (display->closed)
794     return FALSE;
795
796   gdk_error_trap_push ();
797   result = XSendEvent (GDK_DISPLAY_XDISPLAY (display), window, 
798                        propagate, event_mask, event_send);
799   XSync (GDK_DISPLAY_XDISPLAY (display), False);
800   
801   if (gdk_error_trap_pop ())
802     return FALSE;
803  
804   return result;
805 }
806
807 void
808 _gdk_region_get_xrectangles (const GdkRegion *region,
809                              gint             x_offset,
810                              gint             y_offset,
811                              XRectangle     **rects,
812                              gint            *n_rects)
813 {
814   XRectangle *rectangles = g_new (XRectangle, region->numRects);
815   GdkRegionBox *boxes = region->rects;
816   gint i;
817   
818   for (i = 0; i < region->numRects; i++)
819     {
820       rectangles[i].x = CLAMP (boxes[i].x1 + x_offset, G_MINSHORT, G_MAXSHORT);
821       rectangles[i].y = CLAMP (boxes[i].y1 + y_offset, G_MINSHORT, G_MAXSHORT);
822       rectangles[i].width = CLAMP (boxes[i].x2 + x_offset, G_MINSHORT, G_MAXSHORT) - rectangles[i].x;
823       rectangles[i].height = CLAMP (boxes[i].y2 + y_offset, G_MINSHORT, G_MAXSHORT) - rectangles[i].y;
824     }
825
826   *rects = rectangles;
827   *n_rects = region->numRects;
828 }
829
830 /**
831  * gdk_x11_grab_server:
832  * 
833  * Call gdk_x11_display_grab() on the default display. 
834  * To ungrab the server again, use gdk_x11_ungrab_server(). 
835  *
836  * gdk_x11_grab_server()/gdk_x11_ungrab_server() calls can be nested.
837  **/ 
838 void
839 gdk_x11_grab_server (void)
840 {
841   gdk_x11_display_grab (gdk_display_get_default ());
842 }
843
844 /**
845  * gdk_x11_ungrab_server:
846  *
847  * Ungrab the default display after it has been grabbed with 
848  * gdk_x11_grab_server(). 
849  **/
850 void
851 gdk_x11_ungrab_server (void)
852 {
853   gdk_x11_display_ungrab (gdk_display_get_default ());
854 }
855
856 /**
857  * gdk_x11_get_default_screen:
858  * 
859  * Gets the default GTK+ screen number.
860  * 
861  * Return value: returns the screen number specified by
862  *   the --display command line option or the DISPLAY environment
863  *   variable when gdk_init() calls XOpenDisplay().
864  **/
865 gint
866 gdk_x11_get_default_screen (void)
867 {
868   return gdk_screen_get_number (gdk_screen_get_default ());
869 }
870
871 /**
872  * gdk_x11_get_default_root_xwindow:
873  * 
874  * Gets the root window of the default screen 
875  * (see gdk_x11_get_default_screen()).  
876  * 
877  * Return value: an Xlib <type>Window</type>.
878  **/
879 Window
880 gdk_x11_get_default_root_xwindow (void)
881 {
882   return GDK_SCREEN_XROOTWIN (gdk_screen_get_default ());
883 }
884
885 /**
886  * gdk_x11_get_default_xdisplay:
887  * 
888  * Gets the default GTK+ display.
889  * 
890  * Return value: the Xlib <type>Display*</type> for the display
891  * specified in the <option>--display</option> command line option 
892  * or the <envar>DISPLAY</envar> environment variable.
893  **/
894 Display *
895 gdk_x11_get_default_xdisplay (void)
896 {
897   return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
898 }
899
900 #define __GDK_MAIN_X11_C__
901 #include "gdkaliasdef.c"