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>
52 * SECTION:x_interaction
53 * @Short_description: X backend-specific functions
54 * @Title: X Window System Interaction
56 * The functions in this section are specific to the GDK X11 backend.
57 * To use them, you need to include the <literal><gdk/gdkx.h></literal>
58 * header and use the X11-specific pkg-config files to build your
59 * application (either <literal>gdk-x11-3.0</literal> or
60 * <literal>gtk+-x11-3.0</literal>).
62 * To make your code compile with other GDK backends, guard backend-specific
63 * calls by an ifdef as follows. Since GDK may be built with multiple
64 * backends, you should also check for the backend that is in use (e.g. by
65 * using the GDK_IS_X11_DISPLAY() macro).
67 * #ifdef GDK_WINDOWING_X11
68 * if (GDK_IS_X11_DISPLAY (display))
70 * /* make X11-specific calls here */
74 * #ifdef GDK_WINDOWING_QUARTZ
75 * if (GDK_IS_QUARTZ_DISPLAY (display))
77 * /* make Quartz-specific calls here &ast/
81 * g_error ("Unsupported GDK backend");
85 typedef struct _GdkPredicate GdkPredicate;
93 /* non-GDK previous error handler */
94 typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
95 static GdkXErrorHandler _gdk_old_error_handler;
96 /* number of times we've pushed the GDK error handler */
97 static int _gdk_error_handler_push_count = 0;
100 * Private function declarations
103 #ifndef HAVE_XCONVERTCASE
104 static void gdkx_XConvertCase (KeySym symbol,
107 #define XConvertCase gdkx_XConvertCase
110 static int gdk_x_error (Display *display,
112 static int gdk_x_io_error (Display *display);
115 _gdk_x11_windowing_init (void)
117 XSetErrorHandler (gdk_x_error);
118 XSetIOErrorHandler (gdk_x_io_error);
120 gdk_window_add_filter (NULL,
121 _gdk_wm_protocols_filter,
123 gdk_window_add_filter (NULL,
129 _gdk_x11_convert_grab_status (gint status)
134 return GDK_GRAB_SUCCESS;
136 return GDK_GRAB_ALREADY_GRABBED;
137 case GrabInvalidTime:
138 return GDK_GRAB_INVALID_TIME;
139 case GrabNotViewable:
140 return GDK_GRAB_NOT_VIEWABLE;
142 return GDK_GRAB_FROZEN;
145 g_assert_not_reached();
151 * _gdk_x11_window_grab_check_unmap:
152 * @window: a #GdkWindow
153 * @serial: serial from Unmap event (or from NextRequest(display)
154 * if the unmap is being done by this client.)
156 * Checks to see if an unmap request or event causes the current
157 * grab window to become not viewable, and if so, clear the
158 * the pointer we keep to it.
161 _gdk_x11_window_grab_check_unmap (GdkWindow *window,
164 GdkDisplay *display = gdk_window_get_display (window);
165 GdkDeviceManager *device_manager;
168 device_manager = gdk_display_get_device_manager (display);
170 /* Get all devices */
171 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
172 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
173 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
175 /* End all grabs on the newly hidden window */
176 for (d = devices; d; d = d->next)
177 _gdk_display_end_device_grab (display, d->data, serial, window, TRUE);
179 g_list_free (devices);
183 * _gdk_x11_window_grab_check_destroy:
184 * @window: a #GdkWindow
186 * Checks to see if window is the current grab window, and if
187 * so, clear the current grab window.
190 _gdk_x11_window_grab_check_destroy (GdkWindow *window)
192 GdkDisplay *display = gdk_window_get_display (window);
193 GdkDeviceManager *device_manager;
194 GdkDeviceGrabInfo *grab;
197 device_manager = gdk_display_get_device_manager (display);
199 /* Get all devices */
200 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
201 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
202 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
204 for (d = devices; d; d = d->next)
206 /* Make sure there is no lasting grab in this native window */
207 grab = _gdk_display_get_last_device_grab (display, d->data);
209 if (grab && grab->native_window == window)
211 /* We don't know the actual serial to end, but it
212 doesn't really matter as this only happens
213 after we get told of the destroy from the
214 server so we know its ended in the server,
215 just make sure its ended. */
216 grab->serial_end = grab->serial_start;
217 grab->implicit_ungrab = TRUE;
221 g_list_free (devices);
225 *--------------------------------------------------------------
228 * The X I/O error handling routine.
231 * "display" is the X display the error orignated from.
234 * An X I/O error basically means we lost our connection
235 * to the X server. There is not much we can do to
236 * continue, so simply print an error message and exit.
240 *--------------------------------------------------------------
244 gdk_x_io_error (Display *display)
246 /* This is basically modelled after the code in XLib. We need
247 * an explicit error handler here, so we can disable our atexit()
248 * which would otherwise cause a nice segfault.
249 * We fprintf(stderr, instead of g_warning() because g_warning()
250 * could possibly be redirected to a dialog
254 g_warning ("The application '%s' lost its connection to the display %s;\n"
255 "most likely the X server was shut down or you killed/destroyed\n"
256 "the application.\n",
258 display ? DisplayString (display) : gdk_get_display_arg_name ());
262 g_warning ("%s: Fatal IO error %d (%s) on X server %s.\n",
264 errno, g_strerror (errno),
265 display ? DisplayString (display) : gdk_get_display_arg_name ());
271 /* X error handler. Keep the name the same because people are used to
272 * breaking on it in the debugger.
275 gdk_x_error (Display *xdisplay,
278 if (error->error_code)
280 GdkDisplay *error_display;
281 GdkDisplayManager *manager;
284 /* Figure out which GdkDisplay if any got the error. */
285 error_display = NULL;
286 manager = gdk_display_manager_get ();
287 displays = gdk_display_manager_list_displays (manager);
288 while (displays != NULL)
290 GdkX11Display *gdk_display = displays->data;
292 if (xdisplay == gdk_display->xdisplay)
294 error_display = GDK_DISPLAY (gdk_display);
295 g_slist_free (displays);
300 displays = g_slist_delete_link (displays, displays);
304 if (error_display == NULL)
306 /* Error on an X display not opened by GDK. Ignore. */
312 _gdk_x11_display_error_event (error_display, error);
320 _gdk_x11_error_handler_push (void)
322 GdkXErrorHandler previous;
324 previous = XSetErrorHandler (gdk_x_error);
326 if (_gdk_error_handler_push_count > 0)
328 if (previous != gdk_x_error)
329 g_warning ("XSetErrorHandler() called with a GDK error trap pushed. Don't do that.");
333 _gdk_old_error_handler = previous;
336 _gdk_error_handler_push_count += 1;
340 _gdk_x11_error_handler_pop (void)
342 g_return_if_fail (_gdk_error_handler_push_count > 0);
344 _gdk_error_handler_push_count -= 1;
346 if (_gdk_error_handler_push_count == 0)
348 XSetErrorHandler (_gdk_old_error_handler);
349 _gdk_old_error_handler = NULL;
354 _gdk_x11_display_send_xevent (GdkDisplay *display,
362 if (gdk_display_is_closed (display))
365 gdk_x11_display_error_trap_push (display);
366 result = XSendEvent (GDK_DISPLAY_XDISPLAY (display), window,
367 propagate, event_mask, event_send);
368 XSync (GDK_DISPLAY_XDISPLAY (display), False);
370 if (gdk_x11_display_error_trap_pop (display))
377 _gdk_x11_region_get_xrectangles (const cairo_region_t *region,
383 XRectangle *rectangles;
384 cairo_rectangle_int_t box;
387 n = cairo_region_num_rectangles (region);
388 rectangles = g_new (XRectangle, n);
390 for (i = 0; i < n; i++)
392 cairo_region_get_rectangle (region, i, &box);
393 rectangles[i].x = CLAMP (box.x + x_offset, G_MINSHORT, G_MAXSHORT);
394 rectangles[i].y = CLAMP (box.y + y_offset, G_MINSHORT, G_MAXSHORT);
395 rectangles[i].width = CLAMP (box.width, G_MINSHORT, G_MAXSHORT);
396 rectangles[i].height = CLAMP (box.height, G_MINSHORT, G_MAXSHORT);
404 * gdk_x11_grab_server:
406 * Call gdk_x11_display_grab() on the default display.
407 * To ungrab the server again, use gdk_x11_ungrab_server().
409 * gdk_x11_grab_server()/gdk_x11_ungrab_server() calls can be nested.
412 gdk_x11_grab_server (void)
414 gdk_x11_display_grab (gdk_display_get_default ());
418 * gdk_x11_ungrab_server:
420 * Ungrab the default display after it has been grabbed with
421 * gdk_x11_grab_server().
424 gdk_x11_ungrab_server (void)
426 gdk_x11_display_ungrab (gdk_display_get_default ());
430 * gdk_x11_get_default_screen:
432 * Gets the default GTK+ screen number.
434 * Return value: returns the screen number specified by
435 * the --display command line option or the DISPLAY environment
436 * variable when gdk_init() calls XOpenDisplay().
439 gdk_x11_get_default_screen (void)
441 return gdk_screen_get_number (gdk_screen_get_default ());
445 * gdk_x11_get_default_root_xwindow:
447 * Gets the root window of the default screen
448 * (see gdk_x11_get_default_screen()).
450 * Return value: an Xlib <type>Window</type>.
453 gdk_x11_get_default_root_xwindow (void)
455 return GDK_SCREEN_XROOTWIN (gdk_screen_get_default ());
459 * gdk_x11_get_default_xdisplay:
461 * Gets the default GTK+ display.
463 * Return value: (transfer none): the Xlib <type>Display*</type> for
464 * the display specified in the <option>--display</option> command
465 * line option or the <envar>DISPLAY</envar> environment variable.
468 gdk_x11_get_default_xdisplay (void)
470 return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());