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