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 /* If you don't want to use gdk's signal handlers define this */
22 /* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */
24 #include <X11/Xlocale.h>
32 #ifdef HAVE_SYS_SELECT_H
33 #include <sys/select.h>
34 #endif /* HAVE_SYS_SELECT_H_ */
36 #define XLIB_ILLEGAL_ACCESS
37 #include <X11/Xatom.h>
40 #include <X11/Xutil.h>
41 #include <X11/Xmu/WinUtil.h>
42 #include <X11/cursorfont.h>
44 #include "gdkprivate.h"
48 #include "gdkkeysyms.h"
50 #ifndef X_GETTIMEOFDAY
51 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
52 #endif /* X_GETTIMEOFDAY */
55 #define DOUBLE_CLICK_TIME 250
56 #define TRIPLE_CLICK_TIME 500
57 #define DOUBLE_CLICK_DIST 5
58 #define TRIPLE_CLICK_DIST 5
62 # define SELECT_MASK fd_set
68 # define SELECT_MASK void
70 # define SELECT_MASK int
75 typedef struct _GdkInput GdkInput;
76 typedef struct _GdkPredicate GdkPredicate;
82 GdkInputCondition condition;
83 GdkInputFunction function;
85 GdkDestroyNotify destroy;
95 * Private function declarations
98 static GdkEvent *gdk_event_new (void);
99 static gint gdk_event_wait (void);
100 static gint gdk_event_apply_filters (XEvent *xevent,
103 static gint gdk_event_translate (GdkEvent *event,
106 static Bool gdk_event_get_type (Display *display,
110 static void gdk_synthesize_click (GdkEvent *event,
113 #ifndef HAVE_XCONVERTCASE
114 static void gdkx_XConvertCase (KeySym symbol,
117 #define XConvertCase gdkx_XConvertCase
121 * old junk from offix, we might use it though so leave it
123 Window gdk_get_client_window (Display *dpy,
125 #ifdef WE_HAVE_MOTIF_DROPS_DONE
126 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
130 static void gdk_exit_func (void);
131 static int gdk_x_error (Display *display,
133 static int gdk_x_io_error (Display *display);
134 static RETSIGTYPE gdk_signal (int signum);
136 GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
140 /* Private variable declarations
142 static int gdk_initialized = 0; /* 1 if the library is initialized,
145 static int connection_number = 0; /* The file descriptor number of our
146 * connection to the X server. This
147 * is used so that we may determine
148 * when events are pending by using
149 * the "select" system call.
153 static struct timeval start; /* The time at which the library was
156 static struct timeval timer; /* Timeout interval to use in the call
157 * to "select". This is used in
158 * conjunction with "timerp" to create
159 * a maximum time to wait for an event
162 static struct timeval *timerp; /* The actual timer passed to "select"
163 * This may be NULL, in which case
164 * "select" will block until an event
167 static guint32 timer_val; /* The timeout length as specified by
168 * the user in milliseconds.
170 static GList *inputs; /* A list of the input file descriptors
171 * that we care about. Each list node
172 * contains a GdkInput struct that describes
173 * when we are interested in the specified
174 * file descriptor. That is, when it is
175 * available for read, write or has an
178 static guint32 button_click_time[2]; /* The last 2 button click times. Used
179 * to determine if the latest button click
180 * is part of a double or triple click.
182 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
183 * Also used to determine if the latest button
184 * click is part of a double or triple click.
186 static guint button_number[2]; /* The last 2 buttons to be pressed.
188 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
192 static GList *client_filters; /* Filters for client messages */
194 static GList *putback_events = NULL;
196 static gulong base_id;
197 static gint autorepeat;
199 #ifdef G_ENABLE_DEBUG
200 static const GDebugKey gdk_debug_keys[] = {
201 {"events", GDK_DEBUG_EVENTS},
202 {"misc", GDK_DEBUG_MISC},
203 {"dnd", GDK_DEBUG_DND},
204 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
205 {"xim", GDK_DEBUG_XIM}
208 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
210 #endif /* G_ENABLE_DEBUG */
213 *--------------------------------------------------------------
216 * Initialize the library for use.
219 * "argc" is the number of arguments.
220 * "argv" is an array of strings.
223 * "argc" and "argv" are modified to reflect any arguments
224 * which were not handled. (Such arguments should either
225 * be handled by the application or dismissed).
228 * The library is initialized.
230 *--------------------------------------------------------------
237 XKeyboardState keyboard_state;
240 XClassHint *class_hint;
241 gchar **argv_orig = NULL;
251 argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
252 for (i = 0; i < argc_orig; i++)
253 argv_orig[i] = g_strdup ((*argv)[i]);
254 argv_orig[argc_orig] = NULL;
257 X_GETTIMEOFDAY (&start);
259 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
260 signal (SIGHUP, gdk_signal);
261 signal (SIGINT, gdk_signal);
262 signal (SIGQUIT, gdk_signal);
263 signal (SIGBUS, gdk_signal);
264 signal (SIGSEGV, gdk_signal);
265 signal (SIGPIPE, gdk_signal);
266 signal (SIGTERM, gdk_signal);
269 gdk_display_name = NULL;
271 XSetErrorHandler (gdk_x_error);
272 XSetIOErrorHandler (gdk_x_io_error);
276 #ifdef G_ENABLE_DEBUG
278 gchar *debug_string = getenv("GDK_DEBUG");
279 if (debug_string != NULL)
280 gdk_debug_flags = g_parse_debug_string (debug_string,
284 #endif /* G_ENABLE_DEBUG */
292 d = strrchr((*argv)[0],'/');
294 g_set_prgname (d + 1);
296 g_set_prgname ((*argv)[0]);
299 for (i = 1; i < *argc;)
301 #ifdef G_ENABLE_DEBUG
302 if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
303 (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
305 gchar *equal_pos = strchr ((*argv)[i], '=');
307 if (equal_pos != NULL)
309 gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
313 else if ((i + 1) < *argc && (*argv)[i + 1])
315 gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
323 else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
324 (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
326 gchar *equal_pos = strchr ((*argv)[i], '=');
328 if (equal_pos != NULL)
330 gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
334 else if ((i + 1) < *argc && (*argv)[i + 1])
336 gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
345 #endif /* G_ENABLE_DEBUG */
346 if (strcmp ("--display", (*argv)[i]) == 0)
350 if ((i + 1) < *argc && (*argv)[i + 1])
352 gdk_display_name = g_strdup ((*argv)[i + 1]);
353 (*argv)[i + 1] = NULL;
357 else if (strcmp ("--sync", (*argv)[i]) == 0)
362 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
365 gdk_use_xshm = FALSE;
367 else if (strcmp ("--name", (*argv)[i]) == 0)
369 if ((i + 1) < *argc && (*argv)[i + 1])
372 g_set_prgname ((*argv)[i]);
376 else if (strcmp ("--class", (*argv)[i]) == 0)
378 if ((i + 1) < *argc && (*argv)[i + 1])
381 gdk_progclass = (*argv)[i];
386 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
388 if ((i + 1) < *argc && (*argv)[i + 1])
391 gdk_input_gxid_host = ((*argv)[i]);
395 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
397 if ((i + 1) < *argc && (*argv)[i + 1])
400 gdk_input_gxid_port = atoi ((*argv)[i]);
406 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
408 if ((i + 1) < *argc && (*argv)[i + 1])
411 if (strcmp ("none", (*argv)[i]) == 0)
412 gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
413 else if (strcmp ("nothing", (*argv)[i]) == 0)
414 gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
415 else if (strcmp ("area", (*argv)[i]) == 0)
416 gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
417 else if (strcmp ("position", (*argv)[i]) == 0)
418 gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
419 else if (strcmp ("callbacks", (*argv)[i]) == 0)
420 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
423 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
425 if ((i + 1) < *argc && (*argv)[i + 1])
428 if (strcmp ("none", (*argv)[i]) == 0)
429 gdk_im_set_best_style (GDK_IM_STATUS_NONE);
430 else if (strcmp ("nothing", (*argv)[i]) == 0)
431 gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
432 else if (strcmp ("area", (*argv)[i]) == 0)
433 gdk_im_set_best_style (GDK_IM_STATUS_AREA);
434 else if (strcmp ("callbacks", (*argv)[i]) == 0)
435 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
443 for (i = 1; i < *argc; i++)
445 for (k = i; k < *argc; k++)
446 if ((*argv)[k] != NULL)
452 for (j = i + k; j < *argc; j++)
453 (*argv)[j-k] = (*argv)[j];
460 g_set_prgname ("<unknown>");
463 GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));
465 gdk_display = XOpenDisplay (gdk_display_name);
468 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
472 /* This is really crappy. We have to look into the display structure
473 * to find the base resource id. This is only needed for recording
474 * and playback of events.
476 /* base_id = RESOURCE_BASE; */
478 GDK_NOTE (EVENTS, g_message ("base id: %lu", base_id));
480 connection_number = ConnectionNumber (gdk_display);
482 g_message ("connection number: %d", connection_number));
485 XSynchronize (gdk_display, True);
487 gdk_screen = DefaultScreen (gdk_display);
488 gdk_root_window = RootWindow (gdk_display, gdk_screen);
490 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
491 10, 10, 10, 10, 0, 0 , 0);
492 class_hint = XAllocClassHint();
493 class_hint->res_name = g_get_prgname ();
494 if (gdk_progclass == NULL)
496 gdk_progclass = g_strdup (g_get_prgname ());
497 gdk_progclass[0] = toupper (gdk_progclass[0]);
499 class_hint->res_class = gdk_progclass;
500 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
501 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
504 for (i = 0; i < argc_orig; i++)
505 g_free(argv_orig[i]);
508 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
509 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
510 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
511 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
512 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
513 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
515 XGetKeyboardControl (gdk_display, &keyboard_state);
516 autorepeat = keyboard_state.global_auto_repeat;
522 button_click_time[0] = 0;
523 button_click_time[1] = 0;
524 button_window[0] = NULL;
525 button_window[1] = NULL;
526 button_number[0] = -1;
527 button_number[1] = -1;
529 g_atexit (gdk_exit_func);
537 gdk_add_client_message_filter (gdk_wm_protocols,
538 gdk_wm_protocols_filter, NULL);
548 *--------------------------------------------------------------
551 * Restores the library to an un-itialized state and exits
552 * the program using the "exit" system call.
555 * "errorcode" is the error value to pass to "exit".
558 * Allocated structures are freed and the program exits
563 *--------------------------------------------------------------
567 gdk_exit (int errorcode)
569 /* de-initialisation is done by the gdk_exit_funct(),
570 no need to do this here (Alex J.) */
575 *--------------------------------------------------------------
584 *--------------------------------------------------------------
588 gdk_set_locale (void)
590 if (!setlocale (LC_ALL,""))
591 g_message ("locale not supported by C library");
593 if (!XSupportsLocale ())
595 g_message ("locale not supported by Xlib, locale set to C");
596 setlocale (LC_ALL, "C");
599 if (!XSetLocaleModifiers (""))
601 g_message ("can not set locale modifiers");
604 return setlocale (LC_ALL,NULL);
608 *--------------------------------------------------------------
611 * Returns the number of events pending on the queue.
612 * These events have already been read from the server
618 * Returns the number of events on XLib's event queue.
622 *--------------------------------------------------------------
626 gdk_events_pending (void)
631 result = XPending (gdk_display);
633 tmp_list = putback_events;
637 tmp_list = tmp_list->next;
644 *--------------------------------------------------------------
645 * gdk_event_get_graphics_expose
647 * Waits for a GraphicsExpose or NoExpose event
652 * For GraphicsExpose events, returns a pointer to the event
653 * converted into a GdkEvent Otherwise, returns NULL.
657 *-------------------------------------------------------------- */
660 graphics_expose_predicate (Display *display,
664 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
666 g_return_val_if_fail (private != NULL, False);
668 if ((xevent->xany.window == private->xwindow) &&
669 ((xevent->xany.type == GraphicsExpose) ||
670 (xevent->xany.type == NoExpose)))
677 gdk_event_get_graphics_expose (GdkWindow *window)
682 g_return_val_if_fail (window != NULL, NULL);
684 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
686 if (xevent.xany.type == GraphicsExpose)
688 event = gdk_event_new ();
690 if (gdk_event_translate (event, &xevent))
693 gdk_event_free (event);
699 /************************
700 * Exposure compression *
701 ************************/
704 * The following implements simple exposure compression. It is
705 * modelled after the way Xt does exposure compression - in
706 * particular compress_expose = XtExposeCompressMultiple.
707 * It compress consecutive sequences of exposure events,
708 * but not sequences that cross other events. (This is because
709 * if it crosses a ConfigureNotify, we could screw up and
710 * mistakenly compress the exposures generated for the new
711 * size - could we just check for ConfigureNotify?)
713 * Xt compresses to a region / bounding rectangle, we compress
714 * to two rectangles, and try find the two rectangles of minimal
715 * area for this - this is supposed to handle the typical
716 * L-shaped regions generated by OpaqueMove.
719 /* Given three rectangles, find the two rectangles that cover
720 * them with the smallest area.
723 gdk_add_rect_to_rects (GdkRectangle *rect1,
725 GdkRectangle *new_rect)
727 GdkRectangle t1, t2, t3;
728 gint size1, size2, size3;
730 gdk_rectangle_union (rect1, rect2, &t1);
731 gdk_rectangle_union (rect1, new_rect, &t2);
732 gdk_rectangle_union (rect2, new_rect, &t3);
734 size1 = t1.width * t1.height + new_rect->width * new_rect->height;
735 size2 = t2.width * t2.height + rect2->width * rect2->height;
736 size3 = t1.width * t1.height + rect1->width * rect1->height;
757 typedef struct _GdkExposeInfo GdkExposeInfo;
759 struct _GdkExposeInfo {
761 gboolean seen_nonmatching;
765 expose_predicate (Display *display, XEvent *xevent, XPointer arg)
767 GdkExposeInfo *info = (GdkExposeInfo *)arg;
769 if (xevent->xany.type != Expose)
771 info->seen_nonmatching = TRUE;
774 if (info->seen_nonmatching || (xevent->xany.window != info->window))
781 gdk_compress_exposures (XEvent *xevent, GdkWindow *window)
787 GdkRectangle tmp_rect;
789 GdkFilterReturn result;
793 info.window = xevent->xany.window;
794 info.seen_nonmatching = FALSE;
796 rect1.x = xevent->xexpose.x;
797 rect1.y = xevent->xexpose.y;
798 rect1.width = xevent->xexpose.width;
799 rect1.height = xevent->xexpose.height;
805 if (!XCheckIfEvent (gdk_display,
812 XIfEvent (gdk_display,
817 /* We apply filters here, and if it was filtered, completely
820 result = gdk_event_apply_filters (xevent, &event,
822 ((GdkWindowPrivate *)window)->filters
823 : gdk_default_filters);
825 if (result != GDK_FILTER_CONTINUE)
827 if (result == GDK_FILTER_TRANSLATE)
828 gdk_event_put (&event);
834 rect2.x = tmp_event.xexpose.x;
835 rect2.y = tmp_event.xexpose.y;
836 rect2.width = tmp_event.xexpose.width;
837 rect2.height = tmp_event.xexpose.height;
843 tmp_rect.x = tmp_event.xexpose.x;
844 tmp_rect.y = tmp_event.xexpose.y;
845 tmp_rect.width = tmp_event.xexpose.width;
846 tmp_rect.height = tmp_event.xexpose.height;
848 gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
851 count = tmp_event.xexpose.count;
856 gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
858 if ((tmp_rect.width * tmp_rect.height) <
859 2 * (rect1.height * rect1.width +
860 rect2.height * rect2.width))
869 event.expose.type = GDK_EXPOSE;
870 event.expose.window = window;
871 event.expose.area.x = rect2.x;
872 event.expose.area.y = rect2.y;
873 event.expose.area.width = rect2.width;
874 event.expose.area.height = rect2.height;
875 event.expose.count = 0;
877 gdk_event_put (&event);
880 xevent->xexpose.count = nrects - 1;
881 xevent->xexpose.x = rect1.x;
882 xevent->xexpose.y = rect1.y;
883 xevent->xexpose.width = rect1.width;
884 xevent->xexpose.height = rect1.height;
888 *--------------------------------------------------------------
891 * Gets the next event.
896 * If an event was received that we care about, returns
897 * a pointer to that event, to be freed with gdk_event_free.
898 * Otherwise, returns NULL. This function will also return
899 * before an event is received if the timeout interval
904 *--------------------------------------------------------------
917 temp_list = putback_events;
920 temp_event = temp_list->data;
922 if ((* pred) (temp_event, data))
925 *event = *temp_event;
926 putback_events = g_list_remove_link (putback_events, temp_list);
927 g_list_free (temp_list);
931 temp_list = temp_list->next;
934 event_pred.func = pred;
935 event_pred.data = data;
937 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
939 return gdk_event_translate (event, &xevent);
945 event = putback_events->data;
947 temp_list = putback_events;
948 putback_events = g_list_remove_link (putback_events, temp_list);
949 g_list_free_1 (temp_list);
954 /* Wait for an event to occur or the timeout to elapse.
955 * If an event occurs "gdk_event_wait" will return TRUE.
956 * If the timeout elapses "gdk_event_wait" will return
959 if (gdk_event_wait ())
961 /* If we get here we can rest assurred that an event
962 * has occurred. Read it.
967 XNextEvent (gdk_display, &xevent);
975 w = GDK_WINDOW_XWINDOW (gdk_xim_window);
979 if (XFilterEvent (&xevent, w))
982 XNextEvent (gdk_display, &xevent);
985 event = gdk_event_new ();
987 event->any.type = GDK_NOTHING;
988 event->any.window = NULL;
989 event->any.send_event = FALSE;
990 event->any.send_event = xevent.xany.send_event;
992 if (gdk_event_translate (event, &xevent))
995 gdk_event_free (event);
1002 gdk_event_put (GdkEvent *event)
1004 GdkEvent *new_event;
1006 g_return_if_fail (event != NULL);
1008 new_event = gdk_event_copy (event);
1010 putback_events = g_list_prepend (putback_events, new_event);
1014 *--------------------------------------------------------------
1017 * Copy a event structure into new storage.
1020 * "event" is the event struct to copy.
1023 * A new event structure. Free it with gdk_event_free.
1026 * The reference count of the window in the event is increased.
1028 *--------------------------------------------------------------
1031 static GMemChunk *event_chunk;
1034 gdk_event_new (void)
1036 GdkEvent *new_event;
1038 if (event_chunk == NULL)
1039 event_chunk = g_mem_chunk_new ("events",
1044 new_event = g_chunk_new (GdkEvent, event_chunk);
1050 gdk_event_copy (GdkEvent *event)
1052 GdkEvent *new_event;
1054 g_return_val_if_fail (event != NULL, NULL);
1056 new_event = gdk_event_new ();
1058 *new_event = *event;
1059 gdk_window_ref (new_event->any.window);
1061 switch (event->any.type)
1064 case GDK_KEY_RELEASE:
1065 new_event->key.string = g_strdup (event->key.string);
1068 case GDK_ENTER_NOTIFY:
1069 case GDK_LEAVE_NOTIFY:
1070 if (event->crossing.subwindow != NULL)
1071 gdk_window_ref (event->crossing.subwindow);
1074 case GDK_DRAG_ENTER:
1075 case GDK_DRAG_LEAVE:
1076 case GDK_DRAG_MOTION:
1077 case GDK_DRAG_STATUS:
1078 case GDK_DROP_START:
1079 case GDK_DROP_FINISHED:
1080 gdk_drag_context_ref (event->dnd.context);
1092 *--------------------------------------------------------------
1095 * Free a event structure obtained from gdk_event_copy. Do not use
1096 * with other event structures.
1099 * "event" is the event struct to free.
1104 * The reference count of the window in the event is decreased and
1105 * might be freed, too.
1107 *-------------------------------------------------------------- */
1110 gdk_event_free (GdkEvent *event)
1112 g_assert (event_chunk != NULL);
1113 g_return_if_fail (event != NULL);
1115 if (event->any.window)
1116 gdk_window_unref (event->any.window);
1118 switch (event->any.type)
1121 case GDK_KEY_RELEASE:
1122 g_free (event->key.string);
1125 case GDK_ENTER_NOTIFY:
1126 case GDK_LEAVE_NOTIFY:
1127 if (event->crossing.subwindow != NULL)
1128 gdk_window_unref (event->crossing.subwindow);
1131 case GDK_DRAG_ENTER:
1132 case GDK_DRAG_LEAVE:
1133 case GDK_DRAG_MOTION:
1134 case GDK_DRAG_STATUS:
1135 case GDK_DROP_START:
1136 case GDK_DROP_FINISHED:
1137 gdk_drag_context_unref (event->dnd.context);
1145 g_mem_chunk_free (event_chunk, event);
1149 *--------------------------------------------------------------
1150 * gdk_set_show_events
1152 * Turns on/off the showing of events.
1155 * "show_events" is a boolean describing whether or
1156 * not to show the events gdk receives.
1161 * When "show_events" is TRUE, calls to "gdk_event_get"
1162 * will output debugging informatin regarding the event
1163 * received to stdout.
1165 *--------------------------------------------------------------
1169 *--------------------------------------------------------------
1170 * gdk_event_get_time:
1171 * Get the timestamp from an event.
1175 * The event's time stamp, if it has one, otherwise
1177 *--------------------------------------------------------------
1181 gdk_event_get_time (GdkEvent *event)
1184 switch (event->type)
1186 case GDK_MOTION_NOTIFY:
1187 return event->motion.time;
1188 case GDK_BUTTON_PRESS:
1189 case GDK_2BUTTON_PRESS:
1190 case GDK_3BUTTON_PRESS:
1191 case GDK_BUTTON_RELEASE:
1192 return event->button.time;
1194 case GDK_KEY_RELEASE:
1195 return event->key.time;
1196 case GDK_ENTER_NOTIFY:
1197 case GDK_LEAVE_NOTIFY:
1198 return event->crossing.time;
1199 case GDK_PROPERTY_NOTIFY:
1200 return event->property.time;
1201 case GDK_SELECTION_CLEAR:
1202 case GDK_SELECTION_REQUEST:
1203 case GDK_SELECTION_NOTIFY:
1204 return event->selection.time;
1205 case GDK_PROXIMITY_IN:
1206 case GDK_PROXIMITY_OUT:
1207 return event->proximity.time;
1208 case GDK_DRAG_ENTER:
1209 case GDK_DRAG_LEAVE:
1210 case GDK_DRAG_MOTION:
1211 case GDK_DRAG_STATUS:
1212 case GDK_DROP_START:
1213 case GDK_DROP_FINISHED:
1214 return event->dnd.time;
1215 default: /* use current time */
1219 return GDK_CURRENT_TIME;
1223 gdk_set_show_events (int show_events)
1226 gdk_debug_flags |= GDK_DEBUG_EVENTS;
1228 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1232 gdk_set_use_xshm (gint use_xshm)
1234 gdk_use_xshm = use_xshm;
1238 gdk_get_show_events (void)
1240 return gdk_debug_flags & GDK_DEBUG_EVENTS;
1244 gdk_get_use_xshm (void)
1246 return gdk_use_xshm;
1250 *--------------------------------------------------------------
1253 * Get the number of milliseconds since the library was
1259 * The time since the library was initialized is returned.
1260 * This time value is accurate to milliseconds even though
1261 * a more accurate time down to the microsecond could be
1266 *--------------------------------------------------------------
1273 struct timeval elapsed;
1274 guint32 milliseconds;
1276 X_GETTIMEOFDAY (&end);
1278 if (start.tv_usec > end.tv_usec)
1280 end.tv_usec += 1000000;
1283 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1284 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1286 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1288 return milliseconds;
1292 *--------------------------------------------------------------
1295 * Returns the current timer.
1300 * Returns the current timer interval. This interval is
1301 * in units of milliseconds.
1305 *--------------------------------------------------------------
1309 gdk_timer_get (void)
1315 *--------------------------------------------------------------
1318 * Sets the timer interval.
1321 * "milliseconds" is the new value for the timer.
1326 * Calls to "gdk_event_get" will last for a maximum
1327 * of time of "milliseconds". However, a value of 0
1328 * milliseconds will cause "gdk_event_get" to block
1329 * indefinately until an event is received.
1331 *--------------------------------------------------------------
1335 gdk_timer_set (guint32 milliseconds)
1337 timer_val = milliseconds;
1338 timer.tv_sec = milliseconds / 1000;
1339 timer.tv_usec = (milliseconds % 1000) * 1000;
1344 gdk_timer_enable (void)
1350 gdk_timer_disable (void)
1356 gdk_input_add_full (gint source,
1357 GdkInputCondition condition,
1358 GdkInputFunction function,
1360 GdkDestroyNotify destroy)
1362 static gint next_tag = 1;
1375 if ((input->source == source) && (input->condition == condition))
1378 (input->destroy) (input->data);
1379 input->function = function;
1381 input->destroy = destroy;
1388 input = g_new (GdkInput, 1);
1389 input->tag = next_tag++;
1390 input->source = source;
1391 input->condition = condition;
1392 input->function = function;
1394 input->destroy = destroy;
1397 inputs = g_list_prepend (inputs, input);
1404 gdk_input_add (gint source,
1405 GdkInputCondition condition,
1406 GdkInputFunction function,
1409 return gdk_input_add_interp (source, condition, function, data, NULL);
1413 gdk_input_remove (gint tag)
1423 if (input->tag == tag)
1426 (input->destroy) (input->data);
1428 input->tag = 0; /* do not free it here */
1429 input->condition = 0; /* it's done in gdk_event_wait */
1439 *--------------------------------------------------------------
1442 * Grabs the pointer to a specific window
1445 * "window" is the window which will receive the grab
1446 * "owner_events" specifies whether events will be reported as is,
1447 * or relative to "window"
1448 * "event_mask" masks only interesting events
1449 * "confine_to" limits the cursor movement to the specified window
1450 * "cursor" changes the cursor for the duration of the grab
1451 * "time" specifies the time
1456 * requires a corresponding call to gdk_pointer_ungrab
1458 *--------------------------------------------------------------
1462 gdk_pointer_grab (GdkWindow * window,
1464 GdkEventMask event_mask,
1465 GdkWindow * confine_to,
1469 /* From gdkwindow.c */
1470 extern const int nevent_masks;
1471 extern const int event_mask_table[];
1474 GdkWindowPrivate *window_private;
1475 GdkWindowPrivate *confine_to_private;
1476 GdkCursorPrivate *cursor_private;
1483 g_return_val_if_fail (window != NULL, 0);
1485 window_private = (GdkWindowPrivate*) window;
1486 confine_to_private = (GdkWindowPrivate*) confine_to;
1487 cursor_private = (GdkCursorPrivate*) cursor;
1489 xwindow = window_private->xwindow;
1491 if (!confine_to || confine_to_private->destroyed)
1494 xconfine_to = confine_to_private->xwindow;
1499 xcursor = cursor_private->xcursor;
1503 for (i = 0; i < nevent_masks; i++)
1505 if (event_mask & (1 << (i + 1)))
1506 xevent_mask |= event_mask_table[i];
1509 if (gdk_input_vtable.grab_pointer)
1510 return_val = gdk_input_vtable.grab_pointer (window,
1516 return_val = Success;
1518 if (return_val == Success)
1520 if (!window_private->destroyed)
1521 return_val = XGrabPointer (window_private->xdisplay,
1525 GrabModeAsync, GrabModeAsync,
1530 return_val = AlreadyGrabbed;
1533 if (return_val == GrabSuccess)
1534 xgrab_window = window_private;
1540 *--------------------------------------------------------------
1541 * gdk_pointer_ungrab
1543 * Releases any pointer grab
1551 *--------------------------------------------------------------
1555 gdk_pointer_ungrab (guint32 time)
1557 if (gdk_input_vtable.ungrab_pointer)
1558 gdk_input_vtable.ungrab_pointer (time);
1560 XUngrabPointer (gdk_display, time);
1561 xgrab_window = NULL;
1565 *--------------------------------------------------------------
1566 * gdk_pointer_is_grabbed
1568 * Tell wether there is an active x pointer grab in effect
1576 *--------------------------------------------------------------
1580 gdk_pointer_is_grabbed (void)
1582 return xgrab_window != NULL;
1586 *--------------------------------------------------------------
1589 * Grabs the keyboard to a specific window
1592 * "window" is the window which will receive the grab
1593 * "owner_events" specifies whether events will be reported as is,
1594 * or relative to "window"
1595 * "time" specifies the time
1600 * requires a corresponding call to gdk_keyboard_ungrab
1602 *--------------------------------------------------------------
1606 gdk_keyboard_grab (GdkWindow * window,
1610 GdkWindowPrivate *window_private;
1613 g_return_val_if_fail (window != NULL, 0);
1615 window_private = (GdkWindowPrivate*) window;
1616 xwindow = window_private->xwindow;
1618 if (!window_private->destroyed)
1619 return XGrabKeyboard (window_private->xdisplay,
1622 GrabModeAsync, GrabModeAsync,
1625 return AlreadyGrabbed;
1629 *--------------------------------------------------------------
1630 * gdk_keyboard_ungrab
1632 * Releases any keyboard grab
1640 *--------------------------------------------------------------
1644 gdk_keyboard_ungrab (guint32 time)
1646 XUngrabKeyboard (gdk_display, time);
1650 *--------------------------------------------------------------
1653 * Return the width of the screen.
1661 *--------------------------------------------------------------
1665 gdk_screen_width (void)
1669 return_val = DisplayWidth (gdk_display, gdk_screen);
1675 *--------------------------------------------------------------
1678 * Return the height of the screen.
1686 *--------------------------------------------------------------
1690 gdk_screen_height (void)
1694 return_val = DisplayHeight (gdk_display, gdk_screen);
1700 *--------------------------------------------------------------
1701 * gdk_screen_width_mm
1703 * Return the width of the screen in millimeters.
1711 *--------------------------------------------------------------
1715 gdk_screen_width_mm (void)
1719 return_val = DisplayWidthMM (gdk_display, gdk_screen);
1725 *--------------------------------------------------------------
1728 * Return the height of the screen in millimeters.
1736 *--------------------------------------------------------------
1740 gdk_screen_height_mm (void)
1744 return_val = DisplayHeightMM (gdk_display, gdk_screen);
1750 gdk_key_repeat_disable (void)
1752 XAutoRepeatOff (gdk_display);
1756 gdk_key_repeat_restore (void)
1759 XAutoRepeatOn (gdk_display);
1761 XAutoRepeatOff (gdk_display);
1766 *--------------------------------------------------------------
1769 * Flushes the Xlib output buffer and then waits
1770 * until all requests have been received and processed
1771 * by the X server. The only real use for this function
1772 * is in dealing with XShm.
1780 *--------------------------------------------------------------
1783 void gdk_flush (void)
1785 XSync (gdk_display, False);
1792 XBell(gdk_display, 100);
1797 *--------------------------------------------------------------
1800 * Waits until an event occurs or the timer runs out.
1805 * Returns TRUE if an event is ready to be read and FALSE
1806 * if the timer ran out.
1810 *--------------------------------------------------------------
1814 gdk_event_wait (void)
1819 GdkInputCondition condition;
1820 SELECT_MASK readfds;
1821 SELECT_MASK writefds;
1822 SELECT_MASK exceptfds;
1826 /* If there are no events pending we will wait for an event.
1827 * The time we wait is dependant on the "timer". If no timer
1828 * has been specified then we'll block until an event arrives.
1829 * If a timer has been specified we'll block until an event
1830 * arrives or the timer expires. (This is all done using the
1831 * "select" system call).
1834 if (XPending (gdk_display) == 0)
1837 FD_ZERO (&writefds);
1838 FD_ZERO (&exceptfds);
1840 FD_SET (connection_number, &readfds);
1841 max_input = connection_number;
1850 if (input->condition & GDK_INPUT_READ)
1851 FD_SET (input->source, &readfds);
1852 if (input->condition & GDK_INPUT_WRITE)
1853 FD_SET (input->source, &writefds);
1854 if (input->condition & GDK_INPUT_EXCEPTION)
1855 FD_SET (input->source, &exceptfds);
1857 max_input = MAX (max_input, input->source);
1860 else /* free removed inputs */
1865 list->next->prev = list->prev;
1867 list->prev->next = list->next;
1869 inputs = list->next;
1873 temp_list->next = NULL;
1874 temp_list->prev = NULL;
1876 g_free (temp_list->data);
1877 g_list_free (temp_list);
1882 if (gdk_using_threads)
1884 gdk_select_waiting = TRUE;
1886 FD_SET (gdk_threads_pipe[0], &readfds);
1887 max_input = MAX (max_input, gdk_threads_pipe[0]);
1888 gdk_threads_leave ();
1892 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1895 if (gdk_using_threads)
1898 gdk_threads_enter ();
1899 gdk_select_waiting = FALSE;
1901 if (FD_ISSET (gdk_threads_pipe[0], &readfds))
1902 read (gdk_threads_pipe[0], &c, 1);
1911 if (FD_ISSET (connection_number, &readfds))
1913 if (XPending (gdk_display) == 0)
1917 XNoOp (gdk_display);
1918 XFlush (gdk_display);
1933 if (FD_ISSET (input->source, &readfds))
1934 condition |= GDK_INPUT_READ;
1935 if (FD_ISSET (input->source, &writefds))
1936 condition |= GDK_INPUT_WRITE;
1937 if (FD_ISSET (input->source, &exceptfds))
1938 condition |= GDK_INPUT_EXCEPTION;
1940 if (condition && input->function)
1941 (* input->function) (input->data, input->source, condition);
1952 gdk_event_apply_filters (XEvent *xevent,
1956 GdkEventFilter *filter;
1958 GdkFilterReturn result;
1964 filter = (GdkEventFilter *)tmp_list->data;
1966 result = (*filter->function)(xevent, event, filter->data);
1967 if (result != GDK_FILTER_CONTINUE)
1970 tmp_list = tmp_list->next;
1973 return GDK_FILTER_CONTINUE;
1977 gdk_add_client_message_filter (GdkAtom message_type,
1981 GdkClientFilter *filter = g_new (GdkClientFilter, 1);
1983 filter->type = message_type;
1984 filter->function = func;
1985 filter->data = data;
1987 client_filters = g_list_prepend (client_filters, filter);
1991 gdk_event_translate (GdkEvent *event,
1996 GdkWindowPrivate *window_private;
1997 static XComposeStatus compose;
2001 static gchar* buf = NULL;
2002 static gint buf_len= 0;
2010 /* Find the GdkWindow that this event occurred in.
2012 * We handle events with window=None
2013 * specially - they are generated by XFree86's XInput under
2014 * some circumstances.
2017 if ((xevent->xany.window == None) &&
2018 gdk_input_vtable.window_none_event)
2020 return_val = gdk_input_vtable.window_none_event (event,xevent);
2022 if (return_val >= 0) /* was handled */
2028 window = gdk_window_lookup (xevent->xany.window);
2029 window_private = (GdkWindowPrivate *) window;
2032 gdk_window_ref (window);
2034 event->any.window = window;
2035 event->any.send_event = xevent->xany.send_event;
2037 if (window_private && window_private->destroyed)
2039 if (xevent->type != DestroyNotify)
2044 /* Check for filters for this window */
2046 GdkFilterReturn result;
2049 if (window == NULL &&
2050 xevent->type == KeyPress &&
2052 !((GdkWindowPrivate *) gdk_xim_window)->destroyed)
2055 * If user presses a key in Preedit or Status window, keypress event
2056 * is sometimes sent to these windows. These windows are not managed
2057 * by GDK, so we redirect KeyPress event to gdk_xim_window.
2059 * If someone want to use the window whitch is not managed by GDK
2060 * and want to get KeyPress event, he/she must register the filter
2061 * function to gdk_default_filters to intercept the event.
2064 window = gdk_xim_window;
2065 window_private = (GdkWindowPrivate *) window;
2066 gdk_window_ref (window);
2067 event->any.window = window;
2070 g_message ("KeyPress event is redirected to gdk_xim_window: %#lx",
2071 xevent->xany.window));
2073 #endif /* USE_XIM */
2075 result = gdk_event_apply_filters (xevent, event,
2077 ?window_private->filters
2078 :gdk_default_filters);
2080 if (result != GDK_FILTER_CONTINUE)
2081 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2085 g_message ("Got event for unknown window: %#lx\n", xevent->xany.window);
2087 /* We do a "manual" conversion of the XEvent to a
2088 * GdkEvent. The structures are mostly the same so
2089 * the conversion is fairly straightforward. We also
2090 * optionally print debugging info regarding events
2096 switch (xevent->type)
2099 /* Lookup the string corresponding to the given keysym.
2105 buf = g_new (gchar, buf_len);
2107 keysym = GDK_VoidSymbol;
2109 if (gdk_xim_ic && gdk_xim_ic->xic)
2113 /* Clear keyval. Depending on status, may not be set */
2114 charcount = XmbLookupString(gdk_xim_ic->xic,
2115 &xevent->xkey, buf, buf_len-1,
2117 if (status == XBufferOverflow)
2119 /* alloc adequate size of buffer */
2121 g_message("XIM: overflow (required %i)", charcount));
2123 while (buf_len <= charcount)
2125 buf = (gchar *) g_realloc (buf, buf_len);
2127 charcount = XmbLookupString (gdk_xim_ic->xic,
2128 &xevent->xkey, buf, buf_len-1,
2131 if (status == XLookupNone)
2138 charcount = XLookupString (&xevent->xkey, buf, buf_len,
2141 charcount = XLookupString (&xevent->xkey, buf, 16,
2144 event->key.keyval = keysym;
2146 if (charcount > 0 && buf[charcount-1] == '\0')
2149 buf[charcount] = '\0';
2151 /* Print debugging info.
2153 #ifdef G_ENABLE_DEBUG
2154 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2156 g_message ("key press:\twindow: %ld key: %12s %d",
2157 xevent->xkey.window - base_id,
2158 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
2161 g_message ("\t\tlength: %4d string: \"%s\"",
2164 #endif /* G_ENABLE_DEBUG */
2166 event->key.type = GDK_KEY_PRESS;
2167 event->key.window = window;
2168 event->key.time = xevent->xkey.time;
2169 event->key.state = (GdkModifierType) xevent->xkey.state;
2170 event->key.string = g_strdup (buf);
2171 event->key.length = charcount;
2176 /* Lookup the string corresponding to the given keysym.
2182 buf = g_new (gchar, buf_len);
2185 keysym = GDK_VoidSymbol;
2186 charcount = XLookupString (&xevent->xkey, buf, 16,
2188 event->key.keyval = keysym;
2190 /* Print debugging info.
2193 g_message ("key release:\t\twindow: %ld key: %12s %d",
2194 xevent->xkey.window - base_id,
2195 XKeysymToString (event->key.keyval),
2196 event->key.keyval));
2198 event->key.type = GDK_KEY_RELEASE;
2199 event->key.window = window;
2200 event->key.time = xevent->xkey.time;
2201 event->key.state = (GdkModifierType) xevent->xkey.state;
2202 event->key.length = 0;
2203 event->key.string = NULL;
2208 /* Print debugging info.
2211 g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
2212 xevent->xbutton.window - base_id,
2213 xevent->xbutton.x, xevent->xbutton.y,
2214 xevent->xbutton.button));
2216 if (window_private &&
2217 (window_private->extension_events != 0) &&
2218 gdk_input_ignore_core)
2224 event->button.type = GDK_BUTTON_PRESS;
2225 event->button.window = window;
2226 event->button.time = xevent->xbutton.time;
2227 event->button.x = xevent->xbutton.x;
2228 event->button.y = xevent->xbutton.y;
2229 event->button.x_root = (gfloat)xevent->xbutton.x_root;
2230 event->button.y_root = (gfloat)xevent->xbutton.y_root;
2231 event->button.pressure = 0.5;
2232 event->button.xtilt = 0;
2233 event->button.ytilt = 0;
2234 event->button.state = (GdkModifierType) xevent->xbutton.state;
2235 event->button.button = xevent->xbutton.button;
2236 event->button.source = GDK_SOURCE_MOUSE;
2237 event->button.deviceid = GDK_CORE_POINTER;
2239 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
2240 (event->button.window == button_window[1]) &&
2241 (event->button.button == button_number[1]))
2243 gdk_synthesize_click (event, 3);
2245 button_click_time[1] = 0;
2246 button_click_time[0] = 0;
2247 button_window[1] = NULL;
2248 button_window[0] = 0;
2249 button_number[1] = -1;
2250 button_number[0] = -1;
2252 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
2253 (event->button.window == button_window[0]) &&
2254 (event->button.button == button_number[0]))
2256 gdk_synthesize_click (event, 2);
2258 button_click_time[1] = button_click_time[0];
2259 button_click_time[0] = event->button.time;
2260 button_window[1] = button_window[0];
2261 button_window[0] = event->button.window;
2262 button_number[1] = button_number[0];
2263 button_number[0] = event->button.button;
2267 button_click_time[1] = 0;
2268 button_click_time[0] = event->button.time;
2269 button_window[1] = NULL;
2270 button_window[0] = event->button.window;
2271 button_number[1] = -1;
2272 button_number[0] = event->button.button;
2278 /* Print debugging info.
2281 g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
2282 xevent->xbutton.window - base_id,
2283 xevent->xbutton.x, xevent->xbutton.y,
2284 xevent->xbutton.button));
2286 if (window_private &&
2287 (window_private->extension_events != 0) &&
2288 gdk_input_ignore_core)
2294 event->button.type = GDK_BUTTON_RELEASE;
2295 event->button.window = window;
2296 event->button.time = xevent->xbutton.time;
2297 event->button.x = xevent->xbutton.x;
2298 event->button.y = xevent->xbutton.y;
2299 event->button.x_root = (gfloat)xevent->xbutton.x_root;
2300 event->button.y_root = (gfloat)xevent->xbutton.y_root;
2301 event->button.pressure = 0.5;
2302 event->button.xtilt = 0;
2303 event->button.ytilt = 0;
2304 event->button.state = (GdkModifierType) xevent->xbutton.state;
2305 event->button.button = xevent->xbutton.button;
2306 event->button.source = GDK_SOURCE_MOUSE;
2307 event->button.deviceid = GDK_CORE_POINTER;
2312 /* Print debugging info.
2315 g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
2316 xevent->xmotion.window - base_id,
2317 xevent->xmotion.x, xevent->xmotion.y,
2318 (xevent->xmotion.is_hint) ? "true" : "false"));
2320 if (window_private &&
2321 (window_private->extension_events != 0) &&
2322 gdk_input_ignore_core)
2328 event->motion.type = GDK_MOTION_NOTIFY;
2329 event->motion.window = window;
2330 event->motion.time = xevent->xmotion.time;
2331 event->motion.x = xevent->xmotion.x;
2332 event->motion.y = xevent->xmotion.y;
2333 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2334 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2335 event->motion.pressure = 0.5;
2336 event->motion.xtilt = 0;
2337 event->motion.ytilt = 0;
2338 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2339 event->motion.is_hint = xevent->xmotion.is_hint;
2340 event->motion.source = GDK_SOURCE_MOUSE;
2341 event->motion.deviceid = GDK_CORE_POINTER;
2346 /* Print debugging info.
2349 g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
2350 xevent->xcrossing.window - base_id,
2351 xevent->xcrossing.detail,
2352 xevent->xcrossing.subwindow - base_id));
2354 /* Tell XInput stuff about it if appropriate */
2355 if (window_private &&
2356 !window_private->destroyed &&
2357 (window_private->extension_events != 0) &&
2358 gdk_input_vtable.enter_event)
2359 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2361 event->crossing.type = GDK_ENTER_NOTIFY;
2362 event->crossing.window = window;
2364 /* If the subwindow field of the XEvent is non-NULL, then
2365 * lookup the corresponding GdkWindow.
2367 if (xevent->xcrossing.subwindow != None)
2368 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2370 event->crossing.subwindow = NULL;
2372 event->crossing.time = xevent->xcrossing.time;
2373 event->crossing.x = xevent->xcrossing.x;
2374 event->crossing.y = xevent->xcrossing.y;
2375 event->crossing.x_root = xevent->xcrossing.x_root;
2376 event->crossing.y_root = xevent->xcrossing.y_root;
2378 /* Translate the crossing mode into Gdk terms.
2380 switch (xevent->xcrossing.mode)
2383 event->crossing.mode = GDK_CROSSING_NORMAL;
2386 event->crossing.mode = GDK_CROSSING_GRAB;
2389 event->crossing.mode = GDK_CROSSING_UNGRAB;
2393 /* Translate the crossing detail into Gdk terms.
2395 switch (xevent->xcrossing.detail)
2397 case NotifyInferior:
2398 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2400 case NotifyAncestor:
2401 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2404 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2406 case NotifyNonlinear:
2407 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2409 case NotifyNonlinearVirtual:
2410 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2413 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2417 event->crossing.focus = xevent->xcrossing.focus;
2418 event->crossing.state = xevent->xcrossing.state;
2423 /* Print debugging info.
2426 g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
2427 xevent->xcrossing.window - base_id,
2428 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2430 event->crossing.type = GDK_LEAVE_NOTIFY;
2431 event->crossing.window = window;
2433 /* If the subwindow field of the XEvent is non-NULL, then
2434 * lookup the corresponding GdkWindow.
2436 if (xevent->xcrossing.subwindow != None)
2437 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2439 event->crossing.subwindow = NULL;
2441 event->crossing.time = xevent->xcrossing.time;
2442 event->crossing.x = xevent->xcrossing.x;
2443 event->crossing.y = xevent->xcrossing.y;
2444 event->crossing.x_root = xevent->xcrossing.x_root;
2445 event->crossing.y_root = xevent->xcrossing.y_root;
2447 /* Translate the crossing mode into Gdk terms.
2449 switch (xevent->xcrossing.mode)
2452 event->crossing.mode = GDK_CROSSING_NORMAL;
2455 event->crossing.mode = GDK_CROSSING_GRAB;
2458 event->crossing.mode = GDK_CROSSING_UNGRAB;
2462 /* Translate the crossing detail into Gdk terms.
2464 switch (xevent->xcrossing.detail)
2466 case NotifyInferior:
2467 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2469 case NotifyAncestor:
2470 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2473 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2475 case NotifyNonlinear:
2476 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2478 case NotifyNonlinearVirtual:
2479 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2482 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2486 event->crossing.focus = xevent->xcrossing.focus;
2487 event->crossing.state = xevent->xcrossing.state;
2493 /* We only care about focus events that indicate that _this_
2494 * window (not a ancestor or child) got or lost the focus
2496 switch (xevent->xfocus.detail)
2498 case NotifyAncestor:
2499 case NotifyInferior:
2500 case NotifyNonlinear:
2501 /* Print debugging info.
2504 g_message ("focus %s:\t\twindow: %ld",
2505 (xevent->xany.type == FocusIn) ? "in" : "out",
2506 xevent->xfocus.window - base_id));
2508 /* gdk_keyboard_grab() causes following events. These events confuse
2509 * the XIM focus, so ignore them.
2511 if (xevent->xfocus.mode == NotifyGrab ||
2512 xevent->xfocus.mode == NotifyUngrab)
2515 event->focus_change.type = GDK_FOCUS_CHANGE;
2516 event->focus_change.window = window;
2517 event->focus_change.in = (xevent->xany.type == FocusIn);
2526 /* Print debugging info.
2529 g_message ("keymap notify"));
2531 /* Not currently handled */
2536 /* Print debugging info.
2539 g_message ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d",
2540 xevent->xexpose.window - base_id, xevent->xexpose.count,
2541 xevent->xexpose.x, xevent->xexpose.y,
2542 xevent->xexpose.width, xevent->xexpose.height));
2543 gdk_compress_exposures (xevent, window);
2545 event->expose.type = GDK_EXPOSE;
2546 event->expose.window = window;
2547 event->expose.area.x = xevent->xexpose.x;
2548 event->expose.area.y = xevent->xexpose.y;
2549 event->expose.area.width = xevent->xexpose.width;
2550 event->expose.area.height = xevent->xexpose.height;
2551 event->expose.count = xevent->xexpose.count;
2555 case GraphicsExpose:
2556 /* Print debugging info.
2559 g_message ("graphics expose:\tdrawable: %ld",
2560 xevent->xgraphicsexpose.drawable - base_id));
2562 event->expose.type = GDK_EXPOSE;
2563 event->expose.window = window;
2564 event->expose.area.x = xevent->xgraphicsexpose.x;
2565 event->expose.area.y = xevent->xgraphicsexpose.y;
2566 event->expose.area.width = xevent->xgraphicsexpose.width;
2567 event->expose.area.height = xevent->xgraphicsexpose.height;
2568 event->expose.count = xevent->xexpose.count;
2573 /* Print debugging info.
2576 g_message ("no expose:\t\tdrawable: %ld",
2577 xevent->xnoexpose.drawable - base_id));
2579 event->no_expose.type = GDK_NO_EXPOSE;
2580 event->no_expose.window = window;
2584 case VisibilityNotify:
2585 /* Print debugging info.
2587 #ifdef G_ENABLE_DEBUG
2588 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2589 switch (xevent->xvisibility.state)
2591 case VisibilityFullyObscured:
2592 g_message ("visibility notify:\twindow: %ld none",
2593 xevent->xvisibility.window - base_id);
2595 case VisibilityPartiallyObscured:
2596 g_message ("visibility notify:\twindow: %ld partial",
2597 xevent->xvisibility.window - base_id);
2599 case VisibilityUnobscured:
2600 g_message ("visibility notify:\twindow: %ld full",
2601 xevent->xvisibility.window - base_id);
2604 #endif /* G_ENABLE_DEBUG */
2606 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2607 event->visibility.window = window;
2609 switch (xevent->xvisibility.state)
2611 case VisibilityFullyObscured:
2612 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2615 case VisibilityPartiallyObscured:
2616 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2619 case VisibilityUnobscured:
2620 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2627 /* Not currently handled */
2631 /* Print debugging info.
2634 g_message ("destroy notify:\twindow: %ld",
2635 xevent->xdestroywindow.window - base_id));
2637 event->any.type = GDK_DESTROY;
2638 event->any.window = window;
2640 return_val = window_private && !window_private->destroyed;
2642 if(window && window_private->xwindow != GDK_ROOT_WINDOW())
2643 gdk_window_destroy_notify (window);
2647 /* Print debugging info.
2650 g_message ("unmap notify:\t\twindow: %ld",
2651 xevent->xmap.window - base_id));
2653 event->any.type = GDK_UNMAP;
2654 event->any.window = window;
2656 if (xgrab_window == window_private)
2657 xgrab_window = NULL;
2662 /* Print debugging info.
2665 g_message ("map notify:\t\twindow: %ld",
2666 xevent->xmap.window - base_id));
2668 event->any.type = GDK_MAP;
2669 event->any.window = window;
2673 case ReparentNotify:
2674 /* Print debugging info.
2677 g_message ("reparent notify:\twindow: %ld",
2678 xevent->xreparent.window - base_id));
2680 /* Not currently handled */
2684 case ConfigureNotify:
2685 /* Print debugging info.
2687 while ((XPending (gdk_display) > 0) &&
2688 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2689 ConfigureNotify, xevent))
2691 GdkFilterReturn result;
2694 g_message ("configure notify discarded:\twindow: %ld",
2695 xevent->xconfigure.window - base_id));
2697 result = gdk_event_apply_filters (xevent, event,
2699 ?window_private->filters
2700 :gdk_default_filters);
2702 /* If the result is GDK_FILTER_REMOVE, there will be
2703 * trouble, but anybody who filtering the Configure events
2704 * better know what they are doing
2706 if (result != GDK_FILTER_CONTINUE)
2708 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2711 /*XSync (gdk_display, 0);*/
2716 g_message ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d",
2717 xevent->xconfigure.window - base_id,
2718 xevent->xconfigure.x,
2719 xevent->xconfigure.y,
2720 xevent->xconfigure.width,
2721 xevent->xconfigure.height,
2722 xevent->xconfigure.border_width,
2723 xevent->xconfigure.above - base_id,
2724 xevent->xconfigure.override_redirect));
2726 if (!window_private->destroyed &&
2727 (window_private->extension_events != 0) &&
2728 gdk_input_vtable.configure_event)
2729 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2731 if (window_private->window_type == GDK_WINDOW_CHILD)
2735 event->configure.type = GDK_CONFIGURE;
2736 event->configure.window = window;
2737 event->configure.width = xevent->xconfigure.width;
2738 event->configure.height = xevent->xconfigure.height;
2740 if (!xevent->xconfigure.x &&
2741 !xevent->xconfigure.y &&
2742 !window_private->destroyed)
2746 Window child_window = 0;
2748 if (!XTranslateCoordinates (window_private->xdisplay,
2749 window_private->xwindow,
2754 g_warning ("GdkWindow %ld doesn't share root windows display?",
2755 window_private->xwindow - base_id);
2756 event->configure.x = tx;
2757 event->configure.y = ty;
2761 event->configure.x = xevent->xconfigure.x;
2762 event->configure.y = xevent->xconfigure.y;
2764 window_private->x = event->configure.x;
2765 window_private->y = event->configure.y;
2766 window_private->width = xevent->xconfigure.width;
2767 window_private->height = xevent->xconfigure.height;
2768 if (window_private->resize_count > 1)
2769 window_private->resize_count -= 1;
2773 case PropertyNotify:
2774 /* Print debugging info.
2777 g_message ("property notify:\twindow: %ld",
2778 xevent->xproperty.window - base_id));
2780 event->property.type = GDK_PROPERTY_NOTIFY;
2781 event->property.window = window;
2782 event->property.atom = xevent->xproperty.atom;
2783 event->property.time = xevent->xproperty.time;
2784 event->property.state = xevent->xproperty.state;
2788 case SelectionClear:
2790 g_message ("selection clear:\twindow: %ld",
2791 xevent->xproperty.window - base_id));
2793 event->selection.type = GDK_SELECTION_CLEAR;
2794 event->selection.window = window;
2795 event->selection.selection = xevent->xselectionclear.selection;
2796 event->selection.time = xevent->xselectionclear.time;
2800 case SelectionRequest:
2802 g_message ("selection request:\twindow: %ld",
2803 xevent->xproperty.window - base_id));
2805 event->selection.type = GDK_SELECTION_REQUEST;
2806 event->selection.window = window;
2807 event->selection.selection = xevent->xselectionrequest.selection;
2808 event->selection.target = xevent->xselectionrequest.target;
2809 event->selection.property = xevent->xselectionrequest.property;
2810 event->selection.requestor = xevent->xselectionrequest.requestor;
2811 event->selection.time = xevent->xselectionrequest.time;
2815 case SelectionNotify:
2817 g_message ("selection notify:\twindow: %ld",
2818 xevent->xproperty.window - base_id));
2821 event->selection.type = GDK_SELECTION_NOTIFY;
2822 event->selection.window = window;
2823 event->selection.selection = xevent->xselection.selection;
2824 event->selection.target = xevent->xselection.target;
2825 event->selection.property = xevent->xselection.property;
2826 event->selection.time = xevent->xselection.time;
2830 case ColormapNotify:
2831 /* Print debugging info.
2834 g_message ("colormap notify:\twindow: %ld",
2835 xevent->xcolormap.window - base_id));
2837 /* Not currently handled */
2844 GdkFilterReturn result = GDK_FILTER_CONTINUE;
2846 /* Print debugging info.
2849 g_message ("client message:\twindow: %ld",
2850 xevent->xclient.window - base_id));
2852 tmp_list = client_filters;
2855 GdkClientFilter *filter = tmp_list->data;
2856 if (filter->type == xevent->xclient.message_type)
2858 result = (*filter->function) (xevent, event, filter->data);
2862 tmp_list = tmp_list->next;
2867 case GDK_FILTER_REMOVE:
2870 case GDK_FILTER_TRANSLATE:
2873 case GDK_FILTER_CONTINUE:
2874 /* Send unknown ClientMessage's on to Gtk for it to use */
2875 event->client.type = GDK_CLIENT_EVENT;
2876 event->client.window = window;
2877 event->client.message_type = xevent->xclient.message_type;
2878 event->client.data_format = xevent->xclient.format;
2879 memcpy(&event->client.data, &xevent->xclient.data,
2880 sizeof(event->client.data));
2887 /* Print debugging info.
2890 g_message ("mapping notify"));
2892 /* Let XLib know that there is a new keyboard mapping.
2894 XRefreshKeyboardMapping (&xevent->xmapping);
2899 /* something else - (e.g., a Xinput event) */
2901 if (window_private &&
2902 !window_private->destroyed &&
2903 (window_private->extension_events != 0) &&
2904 gdk_input_vtable.other_event)
2905 return_val = gdk_input_vtable.other_event(event, xevent, window);
2914 if (event->any.window)
2915 gdk_window_ref (event->any.window);
2916 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2917 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2918 (event->crossing.subwindow != NULL))
2919 gdk_window_ref (event->crossing.subwindow);
2923 /* Mark this event as having no resources to be freed */
2924 event->any.window = NULL;
2925 event->any.type = GDK_NOTHING;
2929 gdk_window_unref (window);
2935 gdk_wm_protocols_filter (GdkXEvent *xev,
2939 XEvent *xevent = (XEvent *)xev;
2941 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2943 /* The delete window request specifies a window
2944 * to delete. We don't actually destroy the
2945 * window because "it is only a request". (The
2946 * window might contain vital data that the
2947 * program does not want destroyed). Instead
2948 * the event is passed along to the program,
2949 * which should then destroy the window.
2952 g_message ("delete window:\t\twindow: %ld",
2953 xevent->xclient.window - base_id));
2955 event->any.type = GDK_DELETE;
2957 return GDK_FILTER_TRANSLATE;
2959 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2963 return GDK_FILTER_REMOVE;
2968 gdk_event_get_type (Display *display,
2975 if (gdk_event_translate (&event, xevent))
2977 pred = (GdkPredicate*) arg;
2978 return (* pred->func) (&event, pred->data);
2986 gdk_synthesize_click (GdkEvent *event,
2989 GdkEvent temp_event;
2991 g_return_if_fail (event != NULL);
2993 temp_event = *event;
2994 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2996 gdk_event_put (&temp_event);
3000 *--------------------------------------------------------------
3003 * This is the "atexit" function that makes sure the
3004 * library gets a chance to cleanup.
3011 * The library is un-initialized and the program exits.
3013 *--------------------------------------------------------------
3017 gdk_exit_func (void)
3019 static gboolean in_gdk_exit_func = FALSE;
3021 /* This is to avoid an infinite loop if a program segfaults in
3022 an atexit() handler (and yes, it does happen, especially if a program
3023 has trounced over memory too badly for even g_message to work) */
3024 if (in_gdk_exit_func == TRUE)
3026 in_gdk_exit_func = TRUE;
3028 if (gdk_initialized)
3038 gdk_key_repeat_restore ();
3040 XCloseDisplay (gdk_display);
3041 gdk_initialized = 0;
3046 *--------------------------------------------------------------
3049 * The X error handling routine.
3052 * "display" is the X display the error orignated from.
3053 * "error" is the XErrorEvent that we are handling.
3056 * Either we were expecting some sort of error to occur,
3057 * in which case we set the "gdk_error_code" flag, or this
3058 * error was unexpected, in which case we will print an
3059 * error message and exit. (Since trying to continue will
3060 * most likely simply lead to more errors).
3064 *--------------------------------------------------------------
3068 gdk_x_error (Display *display,
3073 if (gdk_error_warnings)
3075 XGetErrorText (display, error->error_code, buf, 63);
3076 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
3080 error->request_code,
3084 gdk_error_code = -1;
3089 *--------------------------------------------------------------
3092 * The X I/O error handling routine.
3095 * "display" is the X display the error orignated from.
3098 * An X I/O error basically means we lost our connection
3099 * to the X server. There is not much we can do to
3100 * continue, so simply print an error message and exit.
3104 *--------------------------------------------------------------
3108 gdk_x_io_error (Display *display)
3110 g_error ("an x io error occurred");
3115 *--------------------------------------------------------------
3118 * The signal handler.
3121 * "sig_num" is the number of the signal we received.
3124 * The signals we catch are all fatal. So we simply build
3125 * up a nice little error message and print it and exit.
3126 * If in the process of doing so another signal is received
3127 * we notice that we are already exiting and simply kill
3132 *--------------------------------------------------------------
3136 gdk_signal (int sig_num)
3138 static int caught_fatal_sig = 0;
3141 if (caught_fatal_sig)
3142 kill (getpid (), sig_num);
3143 caught_fatal_sig = 1;
3169 sig = "unknown signal";
3173 g_message ("\n** ERROR **: %s caught", sig);
3174 #ifdef G_ENABLE_DEBUG
3176 #else /* !G_ENABLE_DEBUG */
3178 #endif /* !G_ENABLE_DEBUG */
3181 /* Sends a ClientMessage to all toplevel client windows */
3183 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
3187 g_return_val_if_fail(event != NULL, FALSE);
3189 /* Set up our event to send, with the exception of its target window */
3190 sev.xclient.type = ClientMessage;
3191 sev.xclient.display = gdk_display;
3192 sev.xclient.format = event->client.data_format;
3193 sev.xclient.window = xid;
3194 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3195 sev.xclient.message_type = event->client.message_type;
3197 return gdk_send_xevent (xid, False, NoEventMask, &sev);
3200 /* Sends a ClientMessage to all toplevel client windows */
3202 gdk_event_send_client_message_to_all_recurse (XEvent *xev,
3206 static GdkAtom wm_state_atom = GDK_NONE;
3210 unsigned long nitems, after;
3211 unsigned char *data;
3213 Window *ret_children, ret_root, ret_parent;
3214 unsigned int ret_nchildren;
3217 gboolean send = FALSE;
3218 gboolean found = FALSE;
3221 wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
3224 XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
3225 &type, &format, &nitems, &after, &data);
3240 /* OK, we're all set, now let's find some windows to send this to */
3241 if (XQueryTree(gdk_display, xid, &ret_root, &ret_parent,
3242 &ret_children, &ret_nchildren) != True)
3248 for(i = 0; i < ret_nchildren; i++)
3249 if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], level + 1))
3252 XFree(ret_children);
3255 if (send || (!found && (level == 1)))
3257 xev->xclient.window = xid;
3258 gdk_send_xevent (xid, False, NoEventMask, xev);
3261 return (send || found);
3265 gdk_event_send_clientmessage_toall (GdkEvent *event)
3268 gint old_warnings = gdk_error_warnings;
3270 g_return_if_fail(event != NULL);
3272 /* Set up our event to send, with the exception of its target window */
3273 sev.xclient.type = ClientMessage;
3274 sev.xclient.display = gdk_display;
3275 sev.xclient.format = event->client.data_format;
3276 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3277 sev.xclient.message_type = event->client.message_type;
3279 gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
3281 gdk_error_warnings = old_warnings;
3285 gdk_get_display(void)
3287 return (gchar *)XDisplayName (gdk_display_name);
3291 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
3295 gint old_warnings = gdk_error_warnings;
3299 gdk_error_warnings = 0;
3300 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
3301 XSync (gdk_display, False);
3302 gdk_error_warnings = old_warnings;
3304 return result && (gdk_error_code != -1);
3307 #ifndef HAVE_XCONVERTCASE
3308 /* compatibility function from X11R6.3, since XConvertCase is not
3309 * supplied by X11R5.
3312 gdkx_XConvertCase (KeySym symbol,
3316 register KeySym sym = symbol;
3318 g_return_if_fail (lower != NULL);
3319 g_return_if_fail (upper != NULL);
3326 #if defined (GDK_A) && defined (GDK_Ooblique)
3327 case 0: /* Latin 1 */
3328 if ((sym >= GDK_A) && (sym <= GDK_Z))
3329 *lower += (GDK_a - GDK_A);
3330 else if ((sym >= GDK_a) && (sym <= GDK_z))
3331 *upper -= (GDK_a - GDK_A);
3332 else if ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis))
3333 *lower += (GDK_agrave - GDK_Agrave);
3334 else if ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis))
3335 *upper -= (GDK_agrave - GDK_Agrave);
3336 else if ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn))
3337 *lower += (GDK_oslash - GDK_Ooblique);
3338 else if ((sym >= GDK_oslash) && (sym <= GDK_thorn))
3339 *upper -= (GDK_oslash - GDK_Ooblique);
3343 #if defined (GDK_Aogonek) && defined (GDK_tcedilla)
3344 case 1: /* Latin 2 */
3345 /* Assume the KeySym is a legal value (ignore discontinuities) */
3346 if (sym == GDK_Aogonek)
3347 *lower = GDK_aogonek;
3348 else if (sym >= GDK_Lstroke && sym <= GDK_Sacute)
3349 *lower += (GDK_lstroke - GDK_Lstroke);
3350 else if (sym >= GDK_Scaron && sym <= GDK_Zacute)
3351 *lower += (GDK_scaron - GDK_Scaron);
3352 else if (sym >= GDK_Zcaron && sym <= GDK_Zabovedot)
3353 *lower += (GDK_zcaron - GDK_Zcaron);
3354 else if (sym == GDK_aogonek)
3355 *upper = GDK_Aogonek;
3356 else if (sym >= GDK_lstroke && sym <= GDK_sacute)
3357 *upper -= (GDK_lstroke - GDK_Lstroke);
3358 else if (sym >= GDK_scaron && sym <= GDK_zacute)
3359 *upper -= (GDK_scaron - GDK_Scaron);
3360 else if (sym >= GDK_zcaron && sym <= GDK_zabovedot)
3361 *upper -= (GDK_zcaron - GDK_Zcaron);
3362 else if (sym >= GDK_Racute && sym <= GDK_Tcedilla)
3363 *lower += (GDK_racute - GDK_Racute);
3364 else if (sym >= GDK_racute && sym <= GDK_tcedilla)
3365 *upper -= (GDK_racute - GDK_Racute);
3369 #if defined (GDK_Hstroke) && defined (GDK_Cabovedot)
3370 case 2: /* Latin 3 */
3371 /* Assume the KeySym is a legal value (ignore discontinuities) */
3372 if (sym >= GDK_Hstroke && sym <= GDK_Hcircumflex)
3373 *lower += (GDK_hstroke - GDK_Hstroke);
3374 else if (sym >= GDK_Gbreve && sym <= GDK_Jcircumflex)
3375 *lower += (GDK_gbreve - GDK_Gbreve);
3376 else if (sym >= GDK_hstroke && sym <= GDK_hcircumflex)
3377 *upper -= (GDK_hstroke - GDK_Hstroke);
3378 else if (sym >= GDK_gbreve && sym <= GDK_jcircumflex)
3379 *upper -= (GDK_gbreve - GDK_Gbreve);
3380 else if (sym >= GDK_Cabovedot && sym <= GDK_Scircumflex)
3381 *lower += (GDK_cabovedot - GDK_Cabovedot);
3382 else if (sym >= GDK_cabovedot && sym <= GDK_scircumflex)
3383 *upper -= (GDK_cabovedot - GDK_Cabovedot);
3387 #if defined (GDK_Rcedilla) && defined (GDK_Amacron)
3388 case 3: /* Latin 4 */
3389 /* Assume the KeySym is a legal value (ignore discontinuities) */
3390 if (sym >= GDK_Rcedilla && sym <= GDK_Tslash)
3391 *lower += (GDK_rcedilla - GDK_Rcedilla);
3392 else if (sym >= GDK_rcedilla && sym <= GDK_tslash)
3393 *upper -= (GDK_rcedilla - GDK_Rcedilla);
3394 else if (sym == GDK_ENG)
3396 else if (sym == GDK_eng)
3398 else if (sym >= GDK_Amacron && sym <= GDK_Umacron)
3399 *lower += (GDK_amacron - GDK_Amacron);
3400 else if (sym >= GDK_amacron && sym <= GDK_umacron)
3401 *upper -= (GDK_amacron - GDK_Amacron);
3405 #if defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
3406 case 6: /* Cyrillic */
3407 /* Assume the KeySym is a legal value (ignore discontinuities) */
3408 if (sym >= GDK_Serbian_DJE && sym <= GDK_Serbian_DZE)
3409 *lower -= (GDK_Serbian_DJE - GDK_Serbian_dje);
3410 else if (sym >= GDK_Serbian_dje && sym <= GDK_Serbian_dze)
3411 *upper += (GDK_Serbian_DJE - GDK_Serbian_dje);
3412 else if (sym >= GDK_Cyrillic_YU && sym <= GDK_Cyrillic_HARDSIGN)
3413 *lower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
3414 else if (sym >= GDK_Cyrillic_yu && sym <= GDK_Cyrillic_hardsign)
3415 *upper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
3417 #endif /* CYRILLIC */
3419 #if defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
3421 /* Assume the KeySym is a legal value (ignore discontinuities) */
3422 if (sym >= GDK_Greek_ALPHAaccent && sym <= GDK_Greek_OMEGAaccent)
3423 *lower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
3424 else if (sym >= GDK_Greek_alphaaccent && sym <= GDK_Greek_omegaaccent &&
3425 sym != GDK_Greek_iotaaccentdieresis &&
3426 sym != GDK_Greek_upsilonaccentdieresis)
3427 *upper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
3428 else if (sym >= GDK_Greek_ALPHA && sym <= GDK_Greek_OMEGA)
3429 *lower += (GDK_Greek_alpha - GDK_Greek_ALPHA);
3430 else if (sym >= GDK_Greek_alpha && sym <= GDK_Greek_omega &&
3431 sym != GDK_Greek_finalsmallsigma)
3432 *upper -= (GDK_Greek_alpha - GDK_Greek_ALPHA);
3440 gdk_keyval_name (guint keyval)
3442 return XKeysymToString (keyval);
3446 gdk_keyval_from_name (const gchar *keyval_name)
3448 g_return_val_if_fail (keyval_name != NULL, 0);
3450 return XStringToKeysym (keyval_name);
3454 gdk_keyval_to_upper (guint keyval)
3458 KeySym lower_val = 0;
3459 KeySym upper_val = 0;
3461 XConvertCase (keyval, &lower_val, &upper_val);
3468 gdk_keyval_to_lower (guint keyval)
3472 KeySym lower_val = 0;
3473 KeySym upper_val = 0;
3475 XConvertCase (keyval, &lower_val, &upper_val);
3482 gdk_keyval_is_upper (guint keyval)
3486 KeySym lower_val = 0;
3487 KeySym upper_val = 0;
3489 XConvertCase (keyval, &lower_val, &upper_val);
3490 return upper_val == keyval;
3496 gdk_keyval_is_lower (guint keyval)
3500 KeySym lower_val = 0;
3501 KeySym upper_val = 0;
3503 XConvertCase (keyval, &lower_val, &upper_val);
3504 return lower_val == keyval;