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