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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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-1999. 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/.
36 #ifdef HAVE_SYS_SELECT_H
37 #include <sys/select.h>
38 #endif /* HAVE_SYS_SELECT_H_ */
40 #define XLIB_ILLEGAL_ACCESS
41 #include <X11/Xatom.h>
44 #include <X11/Xutil.h>
45 #include <X11/cursorfont.h>
49 #include "gdkprivate-x11.h"
50 #include "gdkinternals.h"
51 #include "gdkinputprivate.h"
53 typedef struct _GdkPredicate GdkPredicate;
54 typedef struct _GdkErrorTrap GdkErrorTrap;
69 * Private function declarations
72 #ifndef HAVE_XCONVERTCASE
73 static void gdkx_XConvertCase (KeySym symbol,
76 #define XConvertCase gdkx_XConvertCase
79 static int gdk_x_error (Display *display,
81 static int gdk_x_io_error (Display *display);
83 /* Private variable declarations
85 static int gdk_initialized = 0; /* 1 if the library is initialized,
89 static gint autorepeat;
90 static gboolean gdk_synchronize = FALSE;
93 static const GDebugKey gdk_debug_keys[] = {
94 {"events", GDK_DEBUG_EVENTS},
95 {"misc", GDK_DEBUG_MISC},
96 {"dnd", GDK_DEBUG_DND},
97 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
98 {"xim", GDK_DEBUG_XIM}
101 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
103 #endif /* G_ENABLE_DEBUG */
106 gdk_arg_xim_preedit_cb (const gchar *arg, const gchar *value, gpointer cb_data)
108 if (strcmp ("none", value) == 0)
109 gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
110 else if (strcmp ("nothing", value) == 0)
111 gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
112 else if (strcmp ("area", value) == 0)
113 gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
114 else if (strcmp ("position", value) == 0)
115 gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
116 else if (strcmp ("callbacks", value) == 0)
117 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
121 gdk_arg_xim_status_cb (const gchar *arg, const gchar *value, gpointer cb_data)
123 if (strcmp ("none", value) == 0)
124 gdk_im_set_best_style (GDK_IM_STATUS_NONE);
125 else if (strcmp ("nothing", value) == 0)
126 gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
127 else if (strcmp ("area", value) == 0)
128 gdk_im_set_best_style (GDK_IM_STATUS_AREA);
129 else if (strcmp ("callbacks", value) == 0)
130 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
133 GdkArgDesc _gdk_windowing_args[] = {
134 { "display", GDK_ARG_STRING, &gdk_display_name, (GdkArgFunc)NULL },
135 { "sync", GDK_ARG_BOOL, &gdk_synchronize, (GdkArgFunc)NULL },
136 { "no-xshm", GDK_ARG_NOBOOL, &gdk_use_xshm, (GdkArgFunc)NULL },
137 { "class", GDK_ARG_STRING, &gdk_progclass, (GdkArgFunc)NULL },
138 { "gxid-host", GDK_ARG_STRING, &gdk_input_gxid_host, (GdkArgFunc)NULL },
139 { "gxid-port", GDK_ARG_INT, &gdk_input_gxid_port, (GdkArgFunc)NULL },
140 { "xim-preedit", GDK_ARG_CALLBACK, NULL, gdk_arg_xim_preedit_cb },
141 { "xim-status", GDK_ARG_CALLBACK, NULL, gdk_arg_xim_status_cb },
146 _gdk_windowing_init_check (int argc, char **argv)
148 XKeyboardState keyboard_state;
149 XClassHint *class_hint;
151 XSetErrorHandler (gdk_x_error);
152 XSetIOErrorHandler (gdk_x_io_error);
154 gdk_display = XOpenDisplay (gdk_display_name);
159 XSynchronize (gdk_display, True);
161 gdk_screen = DefaultScreen (gdk_display);
162 gdk_root_window = RootWindow (gdk_display, gdk_screen);
164 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
165 10, 10, 10, 10, 0, 0 , 0);
166 class_hint = XAllocClassHint();
167 class_hint->res_name = g_get_prgname ();
168 if (gdk_progclass == NULL)
170 gdk_progclass = g_strdup (g_get_prgname ());
171 gdk_progclass[0] = toupper (gdk_progclass[0]);
173 class_hint->res_class = gdk_progclass;
174 XmbSetWMProperties (gdk_display, gdk_leader_window,
175 NULL, NULL, argv, argc,
176 NULL, NULL, class_hint);
179 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", False);
180 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", False);
181 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", False);
182 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
183 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
184 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
186 XGetKeyboardControl (gdk_display, &keyboard_state);
187 autorepeat = keyboard_state.global_auto_repeat;
193 gdk_set_use_xshm (gboolean use_xshm)
195 gdk_use_xshm = use_xshm;
199 gdk_get_use_xshm (void)
205 *--------------------------------------------------------------
208 * Grabs the pointer to a specific window
211 * "window" is the window which will receive the grab
212 * "owner_events" specifies whether events will be reported as is,
213 * or relative to "window"
214 * "event_mask" masks only interesting events
215 * "confine_to" limits the cursor movement to the specified window
216 * "cursor" changes the cursor for the duration of the grab
217 * "time" specifies the time
222 * requires a corresponding call to gdk_pointer_ungrab
224 *--------------------------------------------------------------
228 gdk_pointer_grab (GdkWindow * window,
229 gboolean owner_events,
230 GdkEventMask event_mask,
231 GdkWindow * confine_to,
236 GdkCursorPrivate *cursor_private;
243 g_return_val_if_fail (window != NULL, 0);
244 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
245 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
247 cursor_private = (GdkCursorPrivate*) cursor;
249 xwindow = GDK_DRAWABLE_XID (window);
251 if (!confine_to || GDK_DRAWABLE_DESTROYED (confine_to))
254 xconfine_to = GDK_DRAWABLE_XID (confine_to);
259 xcursor = cursor_private->xcursor;
263 for (i = 0; i < gdk_nevent_masks; i++)
265 if (event_mask & (1 << (i + 1)))
266 xevent_mask |= gdk_event_mask_table[i];
269 if (gdk_input_vtable.grab_pointer)
270 return_val = gdk_input_vtable.grab_pointer (window,
276 return_val = Success;
278 if (return_val == Success)
280 if (!GDK_DRAWABLE_DESTROYED (window))
281 return_val = XGrabPointer (GDK_DRAWABLE_XDISPLAY (window),
285 GrabModeAsync, GrabModeAsync,
290 return_val = AlreadyGrabbed;
293 if (return_val == GrabSuccess)
294 gdk_xgrab_window = (GdkWindowPrivate *)window;
300 *--------------------------------------------------------------
303 * Releases any pointer grab
311 *--------------------------------------------------------------
315 gdk_pointer_ungrab (guint32 time)
317 if (gdk_input_vtable.ungrab_pointer)
318 gdk_input_vtable.ungrab_pointer (time);
320 XUngrabPointer (gdk_display, time);
321 gdk_xgrab_window = NULL;
325 *--------------------------------------------------------------
326 * gdk_pointer_is_grabbed
328 * Tell wether there is an active x pointer grab in effect
336 *--------------------------------------------------------------
340 gdk_pointer_is_grabbed (void)
342 return gdk_xgrab_window != NULL;
346 *--------------------------------------------------------------
349 * Grabs the keyboard to a specific window
352 * "window" is the window which will receive the grab
353 * "owner_events" specifies whether events will be reported as is,
354 * or relative to "window"
355 * "time" specifies the time
360 * requires a corresponding call to gdk_keyboard_ungrab
362 *--------------------------------------------------------------
366 gdk_keyboard_grab (GdkWindow * window,
367 gboolean owner_events,
370 g_return_val_if_fail (window != NULL, 0);
371 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
373 if (!GDK_DRAWABLE_DESTROYED (window))
374 return XGrabKeyboard (GDK_DRAWABLE_XDISPLAY (window),
375 GDK_DRAWABLE_XID (window),
377 GrabModeAsync, GrabModeAsync,
380 return AlreadyGrabbed;
384 *--------------------------------------------------------------
385 * gdk_keyboard_ungrab
387 * Releases any keyboard grab
395 *--------------------------------------------------------------
399 gdk_keyboard_ungrab (guint32 time)
401 XUngrabKeyboard (gdk_display, time);
405 *--------------------------------------------------------------
408 * Return the width of the screen.
416 *--------------------------------------------------------------
420 gdk_screen_width (void)
424 return_val = DisplayWidth (gdk_display, gdk_screen);
430 *--------------------------------------------------------------
433 * Return the height of the screen.
441 *--------------------------------------------------------------
445 gdk_screen_height (void)
449 return_val = DisplayHeight (gdk_display, gdk_screen);
455 *--------------------------------------------------------------
456 * gdk_screen_width_mm
458 * Return the width of the screen in millimeters.
466 *--------------------------------------------------------------
470 gdk_screen_width_mm (void)
474 return_val = DisplayWidthMM (gdk_display, gdk_screen);
480 *--------------------------------------------------------------
483 * Return the height of the screen in millimeters.
491 *--------------------------------------------------------------
495 gdk_screen_height_mm (void)
499 return_val = DisplayHeightMM (gdk_display, gdk_screen);
505 *--------------------------------------------------------------
506 * gdk_set_sm_client_id
508 * Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window
509 * so that the window manager can save our state using the
510 * X11R6 ICCCM session management protocol. A NULL value should
511 * be set following disconnection from the session manager to
512 * remove the SM_CLIENT_ID property.
516 * "sm_client_id" specifies the client id assigned to us by the
517 * session manager or NULL to remove the property.
523 *--------------------------------------------------------------
527 gdk_set_sm_client_id (const gchar* sm_client_id)
529 if (sm_client_id && strcmp (sm_client_id, ""))
531 XChangeProperty (gdk_display, gdk_leader_window,
532 gdk_atom_intern ("SM_CLIENT_ID", FALSE),
533 XA_STRING, 8, PropModeReplace,
534 sm_client_id, strlen(sm_client_id));
537 XDeleteProperty (gdk_display, gdk_leader_window,
538 gdk_atom_intern ("SM_CLIENT_ID", FALSE));
542 gdk_key_repeat_disable (void)
544 XAutoRepeatOff (gdk_display);
548 gdk_key_repeat_restore (void)
551 XAutoRepeatOn (gdk_display);
553 XAutoRepeatOff (gdk_display);
560 XBell(gdk_display, 0);
564 gdk_windowing_exit (void)
566 pango_x_shutdown_display (gdk_display);
568 XCloseDisplay (gdk_display);
572 *--------------------------------------------------------------
575 * The X error handling routine.
578 * "display" is the X display the error orignated from.
579 * "error" is the XErrorEvent that we are handling.
582 * Either we were expecting some sort of error to occur,
583 * in which case we set the "gdk_error_code" flag, or this
584 * error was unexpected, in which case we will print an
585 * error message and exit. (Since trying to continue will
586 * most likely simply lead to more errors).
590 *--------------------------------------------------------------
594 gdk_x_error (Display *display,
597 if (error->error_code)
599 if (gdk_error_warnings)
603 XGetErrorText (display, error->error_code, buf, 63);
605 #ifdef G_ENABLE_DEBUG
606 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
612 #else /* !G_ENABLE_DEBUG */
613 fprintf (stderr, "Gdk-ERROR **: %s\n serial %ld error_code %d request_code %d minor_code %d\n",
621 #endif /* G_ENABLE_DEBUG */
623 gdk_error_code = error->error_code;
630 *--------------------------------------------------------------
633 * The X I/O error handling routine.
636 * "display" is the X display the error orignated from.
639 * An X I/O error basically means we lost our connection
640 * to the X server. There is not much we can do to
641 * continue, so simply print an error message and exit.
645 *--------------------------------------------------------------
649 gdk_x_io_error (Display *display)
651 /* This is basically modelled after the code in XLib. We need
652 * an explicit error handler here, so we can disable our atexit()
653 * which would otherwise cause a nice segfault.
654 * We fprintf(stderr, instead of g_warning() because g_warning()
655 * could possibly be redirected to a dialog
659 fprintf (stderr, "Gdk-ERROR **: X connection to %s broken (explicit kill or server shutdown).\n", gdk_display ? DisplayString (gdk_display) : gdk_get_display());
663 fprintf (stderr, "Gdk-ERROR **: Fatal IO error %d (%s) on X server %s.\n",
664 errno, g_strerror (errno),
665 gdk_display ? DisplayString (gdk_display) : gdk_get_display());
668 /* Disable the atexit shutdown for GDK */
675 gdk_get_display (void)
677 return (gchar *)XDisplayName (gdk_display_name);
681 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
685 gint old_warnings = gdk_error_warnings;
689 gdk_error_warnings = 0;
690 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
691 XSync (gdk_display, False);
692 gdk_error_warnings = old_warnings;
694 return result && !gdk_error_code;
698 gdk_keyval_name (guint keyval)
700 return XKeysymToString (keyval);
704 gdk_keyval_from_name (const gchar *keyval_name)
706 g_return_val_if_fail (keyval_name != NULL, 0);
708 return XStringToKeysym (keyval_name);
711 #ifdef HAVE_XCONVERTCASE
713 gdk_keyval_convert_case (guint symbol,
721 XConvertCase (symbol, &xlower, &xupper);
728 #endif HAVE_XCONVERTCASE