1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
29 #include "gdkdeviceprivate.h"
30 #include "gdkinternals.h"
33 #include "gdkdisplay-x11.h"
34 #include "gdkprivate-x11.h"
36 #include <glib/gprintf.h>
43 #include <X11/Xatom.h>
45 #include <X11/Xutil.h>
48 #include <X11/XKBlib.h>
51 typedef struct _GdkPredicate GdkPredicate;
59 /* non-GDK previous error handler */
60 typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
61 static GdkXErrorHandler _gdk_old_error_handler;
62 /* number of times we've pushed the GDK error handler */
63 static int _gdk_error_handler_push_count = 0;
66 * Private function declarations
69 #ifndef HAVE_XCONVERTCASE
70 static void gdkx_XConvertCase (KeySym symbol,
73 #define XConvertCase gdkx_XConvertCase
76 static int gdk_x_error (Display *display,
78 static int gdk_x_io_error (Display *display);
81 _gdk_x11_windowing_init (void)
83 XSetErrorHandler (gdk_x_error);
84 XSetIOErrorHandler (gdk_x_io_error);
88 _gdk_x11_convert_grab_status (gint status)
93 return GDK_GRAB_SUCCESS;
95 return GDK_GRAB_ALREADY_GRABBED;
97 return GDK_GRAB_INVALID_TIME;
99 return GDK_GRAB_NOT_VIEWABLE;
101 return GDK_GRAB_FROZEN;
104 g_assert_not_reached();
110 * _gdk_x11_window_grab_check_unmap:
111 * @window: a #GdkWindow
112 * @serial: serial from Unmap event (or from NextRequest(display)
113 * if the unmap is being done by this client.)
115 * Checks to see if an unmap request or event causes the current
116 * grab window to become not viewable, and if so, clear the
117 * the pointer we keep to it.
120 _gdk_x11_window_grab_check_unmap (GdkWindow *window,
123 GdkDisplay *display = gdk_window_get_display (window);
124 GdkDeviceManager *device_manager;
127 device_manager = gdk_display_get_device_manager (display);
129 /* Get all devices */
130 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
131 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
132 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
134 /* End all grabs on the newly hidden window */
135 for (d = devices; d; d = d->next)
136 _gdk_display_end_device_grab (display, d->data, serial, window, TRUE);
138 g_list_free (devices);
142 * _gdk_x11_window_grab_check_destroy:
143 * @window: a #GdkWindow
145 * Checks to see if window is the current grab window, and if
146 * so, clear the current grab window.
149 _gdk_x11_window_grab_check_destroy (GdkWindow *window)
151 GdkDisplay *display = gdk_window_get_display (window);
152 GdkDeviceManager *device_manager;
153 GdkDeviceGrabInfo *grab;
156 device_manager = gdk_display_get_device_manager (display);
158 /* Get all devices */
159 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
160 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
161 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
163 for (d = devices; d; d = d->next)
165 /* Make sure there is no lasting grab in this native window */
166 grab = _gdk_display_get_last_device_grab (display, d->data);
168 if (grab && grab->native_window == window)
170 /* We don't know the actual serial to end, but it
171 doesn't really matter as this only happens
172 after we get told of the destroy from the
173 server so we know its ended in the server,
174 just make sure its ended. */
175 grab->serial_end = grab->serial_start;
176 grab->implicit_ungrab = TRUE;
180 g_list_free (devices);
184 *--------------------------------------------------------------
187 * The X I/O error handling routine.
190 * "display" is the X display the error orignated from.
193 * An X I/O error basically means we lost our connection
194 * to the X server. There is not much we can do to
195 * continue, so simply print an error message and exit.
199 *--------------------------------------------------------------
203 gdk_x_io_error (Display *display)
205 /* This is basically modelled after the code in XLib. We need
206 * an explicit error handler here, so we can disable our atexit()
207 * which would otherwise cause a nice segfault.
208 * We fprintf(stderr, instead of g_warning() because g_warning()
209 * could possibly be redirected to a dialog
213 g_warning ("The application '%s' lost its connection to the display %s;\n"
214 "most likely the X server was shut down or you killed/destroyed\n"
215 "the application.\n",
217 display ? DisplayString (display) : gdk_get_display_arg_name ());
221 g_warning ("%s: Fatal IO error %d (%s) on X server %s.\n",
223 errno, g_strerror (errno),
224 display ? DisplayString (display) : gdk_get_display_arg_name ());
230 /* X error handler. Keep the name the same because people are used to
231 * breaking on it in the debugger.
234 gdk_x_error (Display *xdisplay,
237 if (error->error_code)
239 GdkDisplay *error_display;
240 GdkDisplayManager *manager;
243 /* Figure out which GdkDisplay if any got the error. */
244 error_display = NULL;
245 manager = gdk_display_manager_get ();
246 displays = gdk_display_manager_list_displays (manager);
247 while (displays != NULL)
249 GdkDisplayX11 *gdk_display = displays->data;
251 if (xdisplay == gdk_display->xdisplay)
253 error_display = GDK_DISPLAY_OBJECT (gdk_display);
254 g_slist_free (displays);
259 displays = g_slist_delete_link (displays, displays);
263 if (error_display == NULL)
265 /* Error on an X display not opened by GDK. Ignore. */
271 _gdk_x11_display_error_event (error_display, error);
279 _gdk_x11_error_handler_push (void)
281 GdkXErrorHandler previous;
283 previous = XSetErrorHandler (gdk_x_error);
285 if (_gdk_error_handler_push_count > 0)
287 if (previous != gdk_x_error)
288 g_warning ("XSetErrorHandler() called with a GDK error trap pushed. Don't do that.");
292 _gdk_old_error_handler = previous;
295 _gdk_error_handler_push_count += 1;
299 _gdk_x11_error_handler_pop (void)
301 g_return_if_fail (_gdk_error_handler_push_count > 0);
303 _gdk_error_handler_push_count -= 1;
305 if (_gdk_error_handler_push_count == 0)
307 XSetErrorHandler (_gdk_old_error_handler);
308 _gdk_old_error_handler = NULL;
313 _gdk_x11_display_send_xevent (GdkDisplay *display,
321 if (gdk_display_is_closed (display))
324 gdk_x11_display_error_trap_push (display);
325 result = XSendEvent (GDK_DISPLAY_XDISPLAY (display), window,
326 propagate, event_mask, event_send);
327 XSync (GDK_DISPLAY_XDISPLAY (display), False);
329 if (gdk_x11_display_error_trap_pop (display))
336 _gdk_x11_region_get_xrectangles (const cairo_region_t *region,
342 XRectangle *rectangles;
343 cairo_rectangle_int_t box;
346 n = cairo_region_num_rectangles (region);
347 rectangles = g_new (XRectangle, n);
349 for (i = 0; i < n; i++)
351 cairo_region_get_rectangle (region, i, &box);
352 rectangles[i].x = CLAMP (box.x + x_offset, G_MINSHORT, G_MAXSHORT);
353 rectangles[i].y = CLAMP (box.y + y_offset, G_MINSHORT, G_MAXSHORT);
354 rectangles[i].width = CLAMP (box.width, G_MINSHORT, G_MAXSHORT);
355 rectangles[i].height = CLAMP (box.height, G_MINSHORT, G_MAXSHORT);
363 * gdk_x11_grab_server:
365 * Call gdk_x11_display_grab() on the default display.
366 * To ungrab the server again, use gdk_x11_ungrab_server().
368 * gdk_x11_grab_server()/gdk_x11_ungrab_server() calls can be nested.
371 gdk_x11_grab_server (void)
373 gdk_x11_display_grab (gdk_display_get_default ());
377 * gdk_x11_ungrab_server:
379 * Ungrab the default display after it has been grabbed with
380 * gdk_x11_grab_server().
383 gdk_x11_ungrab_server (void)
385 gdk_x11_display_ungrab (gdk_display_get_default ());
389 * gdk_x11_get_default_screen:
391 * Gets the default GTK+ screen number.
393 * Return value: returns the screen number specified by
394 * the --display command line option or the DISPLAY environment
395 * variable when gdk_init() calls XOpenDisplay().
398 gdk_x11_get_default_screen (void)
400 return gdk_screen_get_number (gdk_screen_get_default ());
404 * gdk_x11_get_default_root_xwindow:
406 * Gets the root window of the default screen
407 * (see gdk_x11_get_default_screen()).
409 * Return value: an Xlib <type>Window</type>.
412 gdk_x11_get_default_root_xwindow (void)
414 return GDK_SCREEN_XROOTWIN (gdk_screen_get_default ());
418 * gdk_x11_get_default_xdisplay:
420 * Gets the default GTK+ display.
422 * Return value: the Xlib <type>Display*</type> for the display
423 * specified in the <option>--display</option> command line option
424 * or the <envar>DISPLAY</envar> environment variable.
427 gdk_x11_get_default_xdisplay (void)
429 return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());