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/.
37 #ifdef HAVE_SYS_SELECT_H
38 #include <sys/select.h>
39 #endif /* HAVE_SYS_SELECT_H_ */
41 #define XLIB_ILLEGAL_ACCESS
42 #include <X11/Xatom.h>
45 #include <X11/Xutil.h>
46 #include <X11/cursorfont.h>
49 #include <X11/XKBlib.h>
54 #include "gdkprivate-x11.h"
55 #include "gdkinternals.h"
56 #include "gdkinputprivate.h"
58 #include <pango/pangox.h>
60 typedef struct _GdkPredicate GdkPredicate;
61 typedef struct _GdkErrorTrap GdkErrorTrap;
76 * Private function declarations
79 #ifndef HAVE_XCONVERTCASE
80 static void gdkx_XConvertCase (KeySym symbol,
83 #define XConvertCase gdkx_XConvertCase
86 static int gdk_x_error (Display *display,
88 static int gdk_x_io_error (Display *display);
90 /* Private variable declarations
92 static int gdk_initialized = 0; /* 1 if the library is initialized,
96 static gint autorepeat;
97 static gboolean gdk_synchronize = FALSE;
100 static const GDebugKey gdk_debug_keys[] = {
101 {"events", GDK_DEBUG_EVENTS},
102 {"misc", GDK_DEBUG_MISC},
103 {"dnd", GDK_DEBUG_DND},
104 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
105 {"xim", GDK_DEBUG_XIM}
108 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
110 #endif /* G_ENABLE_DEBUG */
113 gdk_arg_xim_preedit_cb (const gchar *arg, const gchar *value, gpointer cb_data)
115 if (strcmp ("none", value) == 0)
116 gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
117 else if (strcmp ("nothing", value) == 0)
118 gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
119 else if (strcmp ("area", value) == 0)
120 gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
121 else if (strcmp ("position", value) == 0)
122 gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
123 else if (strcmp ("callbacks", value) == 0)
124 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
128 gdk_arg_xim_status_cb (const gchar *arg, const gchar *value, gpointer cb_data)
130 if (strcmp ("none", value) == 0)
131 gdk_im_set_best_style (GDK_IM_STATUS_NONE);
132 else if (strcmp ("nothing", value) == 0)
133 gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
134 else if (strcmp ("area", value) == 0)
135 gdk_im_set_best_style (GDK_IM_STATUS_AREA);
136 else if (strcmp ("callbacks", value) == 0)
137 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
140 GdkArgDesc _gdk_windowing_args[] = {
141 { "display", GDK_ARG_STRING, &gdk_display_name, (GdkArgFunc)NULL },
142 { "sync", GDK_ARG_BOOL, &gdk_synchronize, (GdkArgFunc)NULL },
143 { "no-xshm", GDK_ARG_NOBOOL, &gdk_use_xshm, (GdkArgFunc)NULL },
144 { "class", GDK_ARG_STRING, &gdk_progclass, (GdkArgFunc)NULL },
145 { "gxid-host", GDK_ARG_STRING, &gdk_input_gxid_host, (GdkArgFunc)NULL },
146 { "gxid-port", GDK_ARG_INT, &gdk_input_gxid_port, (GdkArgFunc)NULL },
147 { "xim-preedit", GDK_ARG_CALLBACK, NULL, gdk_arg_xim_preedit_cb },
148 { "xim-status", GDK_ARG_CALLBACK, NULL, gdk_arg_xim_status_cb },
153 _gdk_windowing_init_check (int argc, char **argv)
155 XKeyboardState keyboard_state;
156 XClassHint *class_hint;
159 XSetErrorHandler (gdk_x_error);
160 XSetIOErrorHandler (gdk_x_io_error);
162 gdk_display = XOpenDisplay (gdk_display_name);
167 XSynchronize (gdk_display, True);
169 gdk_screen = DefaultScreen (gdk_display);
170 gdk_root_window = RootWindow (gdk_display, gdk_screen);
172 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
173 10, 10, 10, 10, 0, 0 , 0);
174 class_hint = XAllocClassHint();
175 class_hint->res_name = g_get_prgname ();
176 if (gdk_progclass == NULL)
178 gdk_progclass = g_strdup (g_get_prgname ());
179 gdk_progclass[0] = toupper (gdk_progclass[0]);
181 class_hint->res_class = gdk_progclass;
182 XmbSetWMProperties (gdk_display, gdk_leader_window,
183 NULL, NULL, argv, argc,
184 NULL, NULL, class_hint);
188 XChangeProperty (gdk_display, gdk_leader_window,
189 gdk_atom_intern ("_NET_WM_PID", FALSE),
194 gdk_wm_delete_window = gdk_atom_intern ("WM_DELETE_WINDOW", FALSE);
195 gdk_wm_take_focus = gdk_atom_intern ("WM_TAKE_FOCUS", FALSE);
196 gdk_wm_protocols = gdk_atom_intern ("WM_PROTOCOLS", FALSE);
197 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
198 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
199 gdk_wm_window_protocols[2] = gdk_atom_intern ("_NET_WM_PING", FALSE);
200 gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
202 XGetKeyboardControl (gdk_display, &keyboard_state);
203 autorepeat = keyboard_state.global_auto_repeat;
207 gint xkb_major = XkbMajorVersion;
208 gint xkb_minor = XkbMinorVersion;
209 if (XkbLibraryVersion (&xkb_major, &xkb_minor))
211 xkb_major = XkbMajorVersion;
212 xkb_minor = XkbMinorVersion;
213 if (XkbQueryExtension (gdk_display, NULL, NULL, NULL,
214 &xkb_major, &xkb_minor))
218 XkbSelectEvents (gdk_display,
231 gdk_set_use_xshm (gboolean use_xshm)
233 gdk_use_xshm = use_xshm;
237 gdk_get_use_xshm (void)
243 gdk_x11_convert_grab_status (gint status)
248 return GDK_GRAB_SUCCESS;
250 return GDK_GRAB_ALREADY_GRABBED;
251 case GrabInvalidTime:
252 return GDK_GRAB_INVALID_TIME;
253 case GrabNotViewable:
254 return GDK_GRAB_NOT_VIEWABLE;
256 return GDK_GRAB_FROZEN;
259 g_assert_not_reached();
265 *--------------------------------------------------------------
268 * Grabs the pointer to a specific window
271 * "window" is the window which will receive the grab
272 * "owner_events" specifies whether events will be reported as is,
273 * or relative to "window"
274 * "event_mask" masks only interesting events
275 * "confine_to" limits the cursor movement to the specified window
276 * "cursor" changes the cursor for the duration of the grab
277 * "time" specifies the time
282 * requires a corresponding call to gdk_pointer_ungrab
284 *--------------------------------------------------------------
288 gdk_pointer_grab (GdkWindow * window,
289 gboolean owner_events,
290 GdkEventMask event_mask,
291 GdkWindow * confine_to,
296 GdkCursorPrivate *cursor_private;
303 g_return_val_if_fail (window != NULL, 0);
304 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
305 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
307 cursor_private = (GdkCursorPrivate*) cursor;
309 xwindow = GDK_WINDOW_XID (window);
311 if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
314 xconfine_to = GDK_WINDOW_XID (confine_to);
319 xcursor = cursor_private->xcursor;
323 for (i = 0; i < gdk_nevent_masks; i++)
325 if (event_mask & (1 << (i + 1)))
326 xevent_mask |= gdk_event_mask_table[i];
329 return_val = _gdk_input_grab_pointer (window,
335 if (return_val == GrabSuccess)
337 if (!GDK_WINDOW_DESTROYED (window))
338 return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
342 GrabModeAsync, GrabModeAsync,
347 return_val = AlreadyGrabbed;
350 if (return_val == GrabSuccess)
351 gdk_xgrab_window = (GdkWindowObject *)window;
353 return gdk_x11_convert_grab_status (return_val);
357 *--------------------------------------------------------------
360 * Releases any pointer grab
368 *--------------------------------------------------------------
372 gdk_pointer_ungrab (guint32 time)
374 _gdk_input_ungrab_pointer (time);
376 XUngrabPointer (gdk_display, time);
377 gdk_xgrab_window = NULL;
381 *--------------------------------------------------------------
382 * gdk_pointer_is_grabbed
384 * Tell wether there is an active x pointer grab in effect
392 *--------------------------------------------------------------
396 gdk_pointer_is_grabbed (void)
398 return gdk_xgrab_window != NULL;
402 *--------------------------------------------------------------
405 * Grabs the keyboard to a specific window
408 * "window" is the window which will receive the grab
409 * "owner_events" specifies whether events will be reported as is,
410 * or relative to "window"
411 * "time" specifies the time
416 * requires a corresponding call to gdk_keyboard_ungrab
418 *--------------------------------------------------------------
422 gdk_keyboard_grab (GdkWindow * window,
423 gboolean owner_events,
428 g_return_val_if_fail (window != NULL, 0);
429 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
431 if (!GDK_WINDOW_DESTROYED (window))
432 return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (window),
433 GDK_WINDOW_XID (window),
435 GrabModeAsync, GrabModeAsync,
438 return_val = AlreadyGrabbed;
440 return gdk_x11_convert_grab_status (return_val);
444 *--------------------------------------------------------------
445 * gdk_keyboard_ungrab
447 * Releases any keyboard grab
455 *--------------------------------------------------------------
459 gdk_keyboard_ungrab (guint32 time)
461 XUngrabKeyboard (gdk_display, time);
465 *--------------------------------------------------------------
468 * Return the width of the screen.
476 *--------------------------------------------------------------
480 gdk_screen_width (void)
484 return_val = DisplayWidth (gdk_display, gdk_screen);
490 *--------------------------------------------------------------
493 * Return the height of the screen.
501 *--------------------------------------------------------------
505 gdk_screen_height (void)
509 return_val = DisplayHeight (gdk_display, gdk_screen);
515 *--------------------------------------------------------------
516 * gdk_screen_width_mm
518 * Return the width of the screen in millimeters.
526 *--------------------------------------------------------------
530 gdk_screen_width_mm (void)
534 return_val = DisplayWidthMM (gdk_display, gdk_screen);
540 *--------------------------------------------------------------
543 * Return the height of the screen in millimeters.
551 *--------------------------------------------------------------
555 gdk_screen_height_mm (void)
559 return_val = DisplayHeightMM (gdk_display, gdk_screen);
565 *--------------------------------------------------------------
566 * gdk_set_sm_client_id
568 * Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window
569 * so that the window manager can save our state using the
570 * X11R6 ICCCM session management protocol. A NULL value should
571 * be set following disconnection from the session manager to
572 * remove the SM_CLIENT_ID property.
576 * "sm_client_id" specifies the client id assigned to us by the
577 * session manager or NULL to remove the property.
583 *--------------------------------------------------------------
587 gdk_set_sm_client_id (const gchar* sm_client_id)
589 if (sm_client_id && strcmp (sm_client_id, ""))
591 XChangeProperty (gdk_display, gdk_leader_window,
592 gdk_atom_intern ("SM_CLIENT_ID", FALSE),
593 XA_STRING, 8, PropModeReplace,
594 sm_client_id, strlen(sm_client_id));
597 XDeleteProperty (gdk_display, gdk_leader_window,
598 gdk_atom_intern ("SM_CLIENT_ID", FALSE));
604 XBell(gdk_display, 0);
608 gdk_windowing_exit (void)
610 pango_x_shutdown_display (gdk_display);
612 XCloseDisplay (gdk_display);
616 *--------------------------------------------------------------
619 * The X error handling routine.
622 * "display" is the X display the error orignated from.
623 * "error" is the XErrorEvent that we are handling.
626 * Either we were expecting some sort of error to occur,
627 * in which case we set the "gdk_error_code" flag, or this
628 * error was unexpected, in which case we will print an
629 * error message and exit. (Since trying to continue will
630 * most likely simply lead to more errors).
634 *--------------------------------------------------------------
638 gdk_x_error (Display *display,
641 if (error->error_code)
643 if (gdk_error_warnings)
647 XGetErrorText (display, error->error_code, buf, 63);
649 #ifdef G_ENABLE_DEBUG
650 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
656 #else /* !G_ENABLE_DEBUG */
657 fprintf (stderr, "Gdk-ERROR **: %s\n serial %ld error_code %d request_code %d minor_code %d\n",
665 #endif /* G_ENABLE_DEBUG */
667 gdk_error_code = error->error_code;
674 *--------------------------------------------------------------
677 * The X I/O error handling routine.
680 * "display" is the X display the error orignated from.
683 * An X I/O error basically means we lost our connection
684 * to the X server. There is not much we can do to
685 * continue, so simply print an error message and exit.
689 *--------------------------------------------------------------
693 gdk_x_io_error (Display *display)
695 /* This is basically modelled after the code in XLib. We need
696 * an explicit error handler here, so we can disable our atexit()
697 * which would otherwise cause a nice segfault.
698 * We fprintf(stderr, instead of g_warning() because g_warning()
699 * could possibly be redirected to a dialog
703 fprintf (stderr, "Gdk-ERROR **: X connection to %s broken (explicit kill or server shutdown).\n", gdk_display ? DisplayString (gdk_display) : gdk_get_display());
707 fprintf (stderr, "Gdk-ERROR **: Fatal IO error %d (%s) on X server %s.\n",
708 errno, g_strerror (errno),
709 gdk_display ? DisplayString (gdk_display) : gdk_get_display());
712 /* Disable the atexit shutdown for GDK */
719 gdk_get_display (void)
721 return (gchar *)XDisplayName (gdk_display_name);
725 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
729 gint old_warnings = gdk_error_warnings;
733 gdk_error_warnings = 0;
734 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
735 XSync (gdk_display, False);
736 gdk_error_warnings = old_warnings;
738 return result && !gdk_error_code;