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>
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
37 #endif /* HAVE_SYS_SELECT_H_ */
39 #define XLIB_ILLEGAL_ACCESS
40 #include <X11/Xatom.h>
43 #include <X11/Xutil.h>
44 #include <X11/Xmu/WinUtil.h>
46 #include <X11/Xresource.h>
48 #include <X11/cursorfont.h>
50 #include "gdkprivate.h"
53 #include "gdkkeysyms.h"
56 #ifndef X_GETTIMEOFDAY
57 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
58 #endif /* X_GETTIMEOFDAY */
61 #define DOUBLE_CLICK_TIME 250
62 #define TRIPLE_CLICK_TIME 500
63 #define DOUBLE_CLICK_DIST 5
64 #define TRIPLE_CLICK_DIST 5
68 # define SELECT_MASK fd_set
74 # define SELECT_MASK void
76 # define SELECT_MASK int
81 typedef struct _GdkInput GdkInput;
82 typedef struct _GdkPredicate GdkPredicate;
88 GdkInputCondition condition;
89 GdkInputFunction function;
91 GdkDestroyNotify destroy;
101 * Private function declarations
104 static GdkEvent *gdk_event_new (void);
105 static gint gdk_event_wait (void);
106 static gint gdk_event_apply_filters (XEvent *xevent,
109 static gint gdk_event_translate (GdkEvent *event,
112 static Bool gdk_event_get_type (Display *display,
116 static void gdk_synthesize_click (GdkEvent *event,
119 #ifndef HAVE_XCONVERTCASE
120 static void gdkx_XConvertCase (KeySym symbol,
123 #define XConvertCase gdkx_XConvertCase
127 * old junk from offix, we might use it though so leave it
129 Window gdk_get_client_window (Display *dpy,
131 #ifdef WE_HAVE_MOTIF_DROPS_DONE
132 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
136 static void gdk_exit_func (void);
137 static int gdk_x_error (Display *display,
139 static int gdk_x_io_error (Display *display);
140 static RETSIGTYPE gdk_signal (int signum);
144 static guint gdk_im_va_count (va_list list);
145 static XVaNestedList gdk_im_va_to_nested (va_list list,
148 static GdkIM gdk_im_get (void);
149 static gint gdk_im_open (XrmDatabase db,
152 static void gdk_im_close (void);
153 static void gdk_ic_cleanup (void);
157 GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
161 /* Private variable declarations
163 static int gdk_initialized = 0; /* 1 if the library is initialized,
166 static int connection_number = 0; /* The file descriptor number of our
167 * connection to the X server. This
168 * is used so that we may determine
169 * when events are pending by using
170 * the "select" system call.
174 static struct timeval start; /* The time at which the library was
177 static struct timeval timer; /* Timeout interval to use in the call
178 * to "select". This is used in
179 * conjunction with "timerp" to create
180 * a maximum time to wait for an event
183 static struct timeval *timerp; /* The actual timer passed to "select"
184 * This may be NULL, in which case
185 * "select" will block until an event
188 static guint32 timer_val; /* The timeout length as specified by
189 * the user in milliseconds.
191 static GList *inputs; /* A list of the input file descriptors
192 * that we care about. Each list node
193 * contains a GdkInput struct that describes
194 * when we are interested in the specified
195 * file descriptor. That is, when it is
196 * available for read, write or has an
199 static guint32 button_click_time[2]; /* The last 2 button click times. Used
200 * to determine if the latest button click
201 * is part of a double or triple click.
203 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
204 * Also used to determine if the latest button
205 * click is part of a double or triple click.
207 static guint button_number[2]; /* The last 2 buttons to be pressed.
209 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
213 static GList *client_filters; /* Filters for client messages */
216 static gint xim_using; /* using XIM Protocol if TRUE */
217 static GdkIM xim_im; /* global IM */
218 static XIMStyles* xim_styles; /* im supports these styles */
219 static XIMStyle xim_best_allowed_style;
220 static GdkICPrivate *xim_ic; /* currently using IC */
221 static GdkWindow* xim_window; /* currently using Widow */
222 static GList* xim_ic_list;
226 static GList *putback_events = NULL;
228 static gulong base_id;
229 static gint autorepeat;
231 #ifdef G_ENABLE_DEBUG
232 static const GDebugKey gdk_debug_keys[] = {
233 {"events", GDK_DEBUG_EVENTS},
234 {"misc", GDK_DEBUG_MISC},
235 {"dnd", GDK_DEBUG_DND},
236 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
237 {"xim", GDK_DEBUG_XIM}
240 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
242 #endif /* G_ENABLE_DEBUG */
245 *--------------------------------------------------------------
248 * Initialize the library for use.
251 * "argc" is the number of arguments.
252 * "argv" is an array of strings.
255 * "argc" and "argv" are modified to reflect any arguments
256 * which were not handled. (Such arguments should either
257 * be handled by the application or dismissed).
260 * The library is initialized.
262 *--------------------------------------------------------------
269 XKeyboardState keyboard_state;
272 XClassHint *class_hint;
273 gchar **argv_orig = NULL;
283 argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
284 for (i = 0; i < argc_orig; i++)
285 argv_orig[i] = g_strdup ((*argv)[i]);
286 argv_orig[argc_orig] = NULL;
289 X_GETTIMEOFDAY (&start);
291 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
292 signal (SIGHUP, gdk_signal);
293 signal (SIGINT, gdk_signal);
294 signal (SIGQUIT, gdk_signal);
295 signal (SIGBUS, gdk_signal);
296 signal (SIGSEGV, gdk_signal);
297 signal (SIGPIPE, gdk_signal);
298 signal (SIGTERM, gdk_signal);
301 gdk_display_name = NULL;
303 XSetErrorHandler (gdk_x_error);
304 XSetIOErrorHandler (gdk_x_io_error);
308 #ifdef G_ENABLE_DEBUG
310 gchar *debug_string = getenv("GDK_DEBUG");
311 if (debug_string != NULL)
312 gdk_debug_flags = g_parse_debug_string (debug_string,
316 #endif /* G_ENABLE_DEBUG */
324 d = strrchr((*argv)[0],'/');
326 g_set_prgname (d + 1);
328 g_set_prgname ((*argv)[0]);
331 for (i = 1; i < *argc;)
333 #ifdef G_ENABLE_DEBUG
334 if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
335 (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
337 gchar *equal_pos = strchr ((*argv)[i], '=');
339 if (equal_pos != NULL)
341 gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
345 else if ((i + 1) < *argc && (*argv)[i + 1])
347 gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
355 else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
356 (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
358 gchar *equal_pos = strchr ((*argv)[i], '=');
360 if (equal_pos != NULL)
362 gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
366 else if ((i + 1) < *argc && (*argv)[i + 1])
368 gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
377 #endif /* G_ENABLE_DEBUG */
378 if (strcmp ("--display", (*argv)[i]) == 0)
382 if ((i + 1) < *argc && (*argv)[i + 1])
384 gdk_display_name = g_strdup ((*argv)[i + 1]);
385 (*argv)[i + 1] = NULL;
389 else if (strcmp ("--sync", (*argv)[i]) == 0)
394 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
397 gdk_use_xshm = FALSE;
399 else if (strcmp ("--name", (*argv)[i]) == 0)
401 if ((i + 1) < *argc && (*argv)[i + 1])
404 g_set_prgname ((*argv)[i]);
408 else if (strcmp ("--class", (*argv)[i]) == 0)
410 if ((i + 1) < *argc && (*argv)[i + 1])
413 gdk_progclass = (*argv)[i];
418 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
420 if ((i + 1) < *argc && (*argv)[i + 1])
423 gdk_input_gxid_host = ((*argv)[i]);
427 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
429 if ((i + 1) < *argc && (*argv)[i + 1])
432 gdk_input_gxid_port = atoi ((*argv)[i]);
438 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
440 if ((i + 1) < *argc && (*argv)[i + 1])
443 if (strcmp ("none", (*argv)[i]) == 0)
444 gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
445 else if (strcmp ("nothing", (*argv)[i]) == 0)
446 gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
447 else if (strcmp ("area", (*argv)[i]) == 0)
448 gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
449 else if (strcmp ("position", (*argv)[i]) == 0)
450 gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
451 else if (strcmp ("callbacks", (*argv)[i]) == 0)
452 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
455 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
457 if ((i + 1) < *argc && (*argv)[i + 1])
460 if (strcmp ("none", (*argv)[i]) == 0)
461 gdk_im_set_best_style (GDK_IM_STATUS_NONE);
462 else if (strcmp ("nothing", (*argv)[i]) == 0)
463 gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
464 else if (strcmp ("area", (*argv)[i]) == 0)
465 gdk_im_set_best_style (GDK_IM_STATUS_AREA);
466 else if (strcmp ("callbacks", (*argv)[i]) == 0)
467 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
475 for (i = 1; i < *argc; i++)
477 for (k = i; k < *argc; k++)
478 if ((*argv)[k] != NULL)
484 for (j = i + k; j < *argc; j++)
485 (*argv)[j-k] = (*argv)[j];
492 g_set_prgname ("<unknown>");
495 GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));
497 gdk_display = XOpenDisplay (gdk_display_name);
500 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
504 /* This is really crappy. We have to look into the display structure
505 * to find the base resource id. This is only needed for recording
506 * and playback of events.
508 /* base_id = RESOURCE_BASE; */
510 GDK_NOTE (EVENTS, g_message ("base id: %lu", base_id));
512 connection_number = ConnectionNumber (gdk_display);
514 g_message ("connection number: %d", connection_number));
517 XSynchronize (gdk_display, True);
519 gdk_screen = DefaultScreen (gdk_display);
520 gdk_root_window = RootWindow (gdk_display, gdk_screen);
522 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
523 10, 10, 10, 10, 0, 0 , 0);
524 class_hint = XAllocClassHint();
525 class_hint->res_name = g_get_prgname ();
526 if (gdk_progclass == NULL)
528 gdk_progclass = g_strdup (g_get_prgname ());
529 gdk_progclass[0] = toupper (gdk_progclass[0]);
531 class_hint->res_class = gdk_progclass;
532 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
533 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
536 for (i = 0; i < argc_orig; i++)
537 g_free(argv_orig[i]);
540 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
541 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
542 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
543 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
544 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
545 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
547 XGetKeyboardControl (gdk_display, &keyboard_state);
548 autorepeat = keyboard_state.global_auto_repeat;
554 button_click_time[0] = 0;
555 button_click_time[1] = 0;
556 button_window[0] = NULL;
557 button_window[1] = NULL;
558 button_number[0] = -1;
559 button_number[1] = -1;
561 g_atexit (gdk_exit_func);
569 gdk_add_client_message_filter (gdk_wm_protocols,
570 gdk_wm_protocols_filter, NULL);
573 /* initialize XIM Protocol variables */
577 if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
578 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
579 if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
580 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
582 xim_window = (GdkWindow*)NULL;
584 gdk_im_open (NULL, NULL, NULL);
591 *--------------------------------------------------------------
594 * Restores the library to an un-itialized state and exits
595 * the program using the "exit" system call.
598 * "errorcode" is the error value to pass to "exit".
601 * Allocated structures are freed and the program exits
606 *--------------------------------------------------------------
610 gdk_exit (int errorcode)
612 /* de-initialisation is done by the gdk_exit_funct(),
613 no need to do this here (Alex J.) */
618 *--------------------------------------------------------------
627 *--------------------------------------------------------------
631 gdk_set_locale (void)
633 if (!setlocale (LC_ALL,""))
634 g_message ("locale not supported by C library");
636 if (!XSupportsLocale ())
638 g_message ("locale not supported by Xlib, locale set to C");
639 setlocale (LC_ALL, "C");
642 if (!XSetLocaleModifiers (""))
644 g_message ("can not set locale modifiers");
647 return setlocale (LC_ALL,NULL);
651 *--------------------------------------------------------------
654 * Returns the number of events pending on the queue.
655 * These events have already been read from the server
661 * Returns the number of events on XLib's event queue.
665 *--------------------------------------------------------------
669 gdk_events_pending (void)
674 result = XPending (gdk_display);
676 tmp_list = putback_events;
680 tmp_list = tmp_list->next;
687 *--------------------------------------------------------------
688 * gdk_event_get_graphics_expose
690 * Waits for a GraphicsExpose or NoExpose event
695 * For GraphicsExpose events, returns a pointer to the event
696 * converted into a GdkEvent Otherwise, returns NULL.
700 *-------------------------------------------------------------- */
703 graphics_expose_predicate (Display *display,
707 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
709 g_return_val_if_fail (private != NULL, False);
711 if ((xevent->xany.window == private->xwindow) &&
712 ((xevent->xany.type == GraphicsExpose) ||
713 (xevent->xany.type == NoExpose)))
720 gdk_event_get_graphics_expose (GdkWindow *window)
725 g_return_val_if_fail (window != NULL, NULL);
727 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
729 if (xevent.xany.type == GraphicsExpose)
731 event = gdk_event_new ();
733 if (gdk_event_translate (event, &xevent))
736 gdk_event_free (event);
742 /************************
743 * Exposure compression *
744 ************************/
747 * The following implements simple exposure compression. It is
748 * modelled after the way Xt does exposure compression - in
749 * particular compress_expose = XtExposeCompressMultiple.
750 * It compress consecutive sequences of exposure events,
751 * but not sequences that cross other events. (This is because
752 * if it crosses a ConfigureNotify, we could screw up and
753 * mistakenly compress the exposures generated for the new
754 * size - could we just check for ConfigureNotify?)
756 * Xt compresses to a region / bounding rectangle, we compress
757 * to two rectangles, and try find the two rectangles of minimal
758 * area for this - this is supposed to handle the typical
759 * L-shaped regions generated by OpaqueMove.
762 /* Given three rectangles, find the two rectangles that cover
763 * them with the smallest area.
766 gdk_add_rect_to_rects (GdkRectangle *rect1,
768 GdkRectangle *new_rect)
770 GdkRectangle t1, t2, t3;
771 gint size1, size2, size3;
773 gdk_rectangle_union (rect1, rect2, &t1);
774 gdk_rectangle_union (rect1, new_rect, &t2);
775 gdk_rectangle_union (rect2, new_rect, &t3);
777 size1 = t1.width * t1.height + new_rect->width * new_rect->height;
778 size2 = t2.width * t2.height + rect2->width * rect2->height;
779 size3 = t1.width * t1.height + rect1->width * rect1->height;
800 typedef struct _GdkExposeInfo GdkExposeInfo;
802 struct _GdkExposeInfo {
804 gboolean seen_nonmatching;
808 expose_predicate (Display *display, XEvent *xevent, XPointer arg)
810 GdkExposeInfo *info = (GdkExposeInfo *)arg;
812 if (xevent->xany.type != Expose)
814 info->seen_nonmatching = TRUE;
817 if (info->seen_nonmatching || (xevent->xany.window != info->window))
824 gdk_compress_exposures (XEvent *xevent, GdkWindow *window)
830 GdkRectangle tmp_rect;
832 GdkFilterReturn result;
836 info.window = xevent->xany.window;
837 info.seen_nonmatching = FALSE;
839 rect1.x = xevent->xexpose.x;
840 rect1.y = xevent->xexpose.y;
841 rect1.width = xevent->xexpose.width;
842 rect1.height = xevent->xexpose.height;
848 if (!XCheckIfEvent (gdk_display,
855 XIfEvent (gdk_display,
860 /* We apply filters here, and if it was filtered, completely
863 result = gdk_event_apply_filters (xevent, &event,
865 ((GdkWindowPrivate *)window)->filters
866 : gdk_default_filters);
868 if (result != GDK_FILTER_CONTINUE)
870 if (result == GDK_FILTER_TRANSLATE)
871 gdk_event_put (&event);
877 rect2.x = tmp_event.xexpose.x;
878 rect2.y = tmp_event.xexpose.y;
879 rect2.width = tmp_event.xexpose.width;
880 rect2.height = tmp_event.xexpose.height;
886 tmp_rect.x = tmp_event.xexpose.x;
887 tmp_rect.y = tmp_event.xexpose.y;
888 tmp_rect.width = tmp_event.xexpose.width;
889 tmp_rect.height = tmp_event.xexpose.height;
891 gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
894 count = tmp_event.xexpose.count;
899 gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
901 if ((tmp_rect.width * tmp_rect.height) <
902 2 * (rect1.height * rect1.width +
903 rect2.height * rect2.width))
912 event.expose.type = GDK_EXPOSE;
913 event.expose.window = window;
914 event.expose.area.x = rect2.x;
915 event.expose.area.y = rect2.y;
916 event.expose.area.width = rect2.width;
917 event.expose.area.height = rect2.height;
918 event.expose.count = 0;
920 gdk_event_put (&event);
923 xevent->xexpose.count = nrects - 1;
924 xevent->xexpose.x = rect1.x;
925 xevent->xexpose.y = rect1.y;
926 xevent->xexpose.width = rect1.width;
927 xevent->xexpose.height = rect1.height;
931 *--------------------------------------------------------------
934 * Gets the next event.
939 * If an event was received that we care about, returns
940 * a pointer to that event, to be freed with gdk_event_free.
941 * Otherwise, returns NULL. This function will also return
942 * before an event is received if the timeout interval
947 *--------------------------------------------------------------
960 temp_list = putback_events;
963 temp_event = temp_list->data;
965 if ((* pred) (temp_event, data))
968 *event = *temp_event;
969 putback_events = g_list_remove_link (putback_events, temp_list);
970 g_list_free (temp_list);
974 temp_list = temp_list->next;
977 event_pred.func = pred;
978 event_pred.data = data;
980 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
982 return gdk_event_translate (event, &xevent);
988 event = putback_events->data;
990 temp_list = putback_events;
991 putback_events = g_list_remove_link (putback_events, temp_list);
992 g_list_free_1 (temp_list);
997 /* Wait for an event to occur or the timeout to elapse.
998 * If an event occurs "gdk_event_wait" will return TRUE.
999 * If the timeout elapses "gdk_event_wait" will return
1002 if (gdk_event_wait ())
1004 /* If we get here we can rest assurred that an event
1005 * has occurred. Read it.
1009 if (xim_using && xim_window)
1011 { /* don't dispatch events used by IM */
1012 XNextEvent (gdk_display, &xevent);
1013 filter_status = XFilterEvent (&xevent,
1014 GDK_WINDOW_XWINDOW (xim_window));
1015 } while (filter_status == True);
1017 XNextEvent (gdk_display, &xevent);
1019 XNextEvent (gdk_display, &xevent);
1022 event = gdk_event_new ();
1024 event->any.type = GDK_NOTHING;
1025 event->any.window = NULL;
1026 event->any.send_event = FALSE;
1027 event->any.send_event = xevent.xany.send_event;
1029 if (gdk_event_translate (event, &xevent))
1032 gdk_event_free (event);
1039 gdk_event_put (GdkEvent *event)
1041 GdkEvent *new_event;
1043 g_return_if_fail (event != NULL);
1045 new_event = gdk_event_copy (event);
1047 putback_events = g_list_prepend (putback_events, new_event);
1051 *--------------------------------------------------------------
1054 * Copy a event structure into new storage.
1057 * "event" is the event struct to copy.
1060 * A new event structure. Free it with gdk_event_free.
1063 * The reference count of the window in the event is increased.
1065 *--------------------------------------------------------------
1068 static GMemChunk *event_chunk;
1071 gdk_event_new (void)
1073 GdkEvent *new_event;
1075 if (event_chunk == NULL)
1076 event_chunk = g_mem_chunk_new ("events",
1081 new_event = g_chunk_new (GdkEvent, event_chunk);
1087 gdk_event_copy (GdkEvent *event)
1089 GdkEvent *new_event;
1091 g_return_val_if_fail (event != NULL, NULL);
1093 new_event = gdk_event_new ();
1095 *new_event = *event;
1096 gdk_window_ref (new_event->any.window);
1098 switch (event->any.type)
1101 case GDK_KEY_RELEASE:
1102 new_event->key.string = g_strdup (event->key.string);
1105 case GDK_ENTER_NOTIFY:
1106 case GDK_LEAVE_NOTIFY:
1107 if (event->crossing.subwindow != NULL)
1108 gdk_window_ref (event->crossing.subwindow);
1111 case GDK_DRAG_ENTER:
1112 case GDK_DRAG_LEAVE:
1113 case GDK_DRAG_MOTION:
1114 case GDK_DRAG_STATUS:
1115 case GDK_DROP_START:
1116 case GDK_DROP_FINISHED:
1117 gdk_drag_context_ref (event->dnd.context);
1129 *--------------------------------------------------------------
1132 * Free a event structure obtained from gdk_event_copy. Do not use
1133 * with other event structures.
1136 * "event" is the event struct to free.
1141 * The reference count of the window in the event is decreased and
1142 * might be freed, too.
1144 *-------------------------------------------------------------- */
1147 gdk_event_free (GdkEvent *event)
1149 g_assert (event_chunk != NULL);
1150 g_return_if_fail (event != NULL);
1152 if (event->any.window)
1153 gdk_window_unref (event->any.window);
1155 switch (event->any.type)
1158 case GDK_KEY_RELEASE:
1159 g_free (event->key.string);
1162 case GDK_ENTER_NOTIFY:
1163 case GDK_LEAVE_NOTIFY:
1164 if (event->crossing.subwindow != NULL)
1165 gdk_window_unref (event->crossing.subwindow);
1168 case GDK_DRAG_ENTER:
1169 case GDK_DRAG_LEAVE:
1170 case GDK_DRAG_MOTION:
1171 case GDK_DRAG_STATUS:
1172 case GDK_DROP_START:
1173 case GDK_DROP_FINISHED:
1174 gdk_drag_context_unref (event->dnd.context);
1182 g_mem_chunk_free (event_chunk, event);
1186 *--------------------------------------------------------------
1187 * gdk_set_show_events
1189 * Turns on/off the showing of events.
1192 * "show_events" is a boolean describing whether or
1193 * not to show the events gdk receives.
1198 * When "show_events" is TRUE, calls to "gdk_event_get"
1199 * will output debugging informatin regarding the event
1200 * received to stdout.
1202 *--------------------------------------------------------------
1206 *--------------------------------------------------------------
1207 * gdk_event_get_time:
1208 * Get the timestamp from an event.
1212 * The event's time stamp, if it has one, otherwise
1214 *--------------------------------------------------------------
1218 gdk_event_get_time (GdkEvent *event)
1221 switch (event->type)
1223 case GDK_MOTION_NOTIFY:
1224 return event->motion.time;
1225 case GDK_BUTTON_PRESS:
1226 case GDK_2BUTTON_PRESS:
1227 case GDK_3BUTTON_PRESS:
1228 case GDK_BUTTON_RELEASE:
1229 return event->button.time;
1231 case GDK_KEY_RELEASE:
1232 return event->key.time;
1233 case GDK_ENTER_NOTIFY:
1234 case GDK_LEAVE_NOTIFY:
1235 return event->crossing.time;
1236 case GDK_PROPERTY_NOTIFY:
1237 return event->property.time;
1238 case GDK_SELECTION_CLEAR:
1239 case GDK_SELECTION_REQUEST:
1240 case GDK_SELECTION_NOTIFY:
1241 return event->selection.time;
1242 case GDK_PROXIMITY_IN:
1243 case GDK_PROXIMITY_OUT:
1244 return event->proximity.time;
1245 case GDK_DRAG_ENTER:
1246 case GDK_DRAG_LEAVE:
1247 case GDK_DRAG_MOTION:
1248 case GDK_DRAG_STATUS:
1249 case GDK_DROP_START:
1250 case GDK_DROP_FINISHED:
1251 return event->dnd.time;
1252 default: /* use current time */
1256 return GDK_CURRENT_TIME;
1260 gdk_set_show_events (int show_events)
1263 gdk_debug_flags |= GDK_DEBUG_EVENTS;
1265 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1269 gdk_set_use_xshm (gint use_xshm)
1271 gdk_use_xshm = use_xshm;
1275 gdk_get_show_events (void)
1277 return gdk_debug_flags & GDK_DEBUG_EVENTS;
1281 gdk_get_use_xshm (void)
1283 return gdk_use_xshm;
1287 *--------------------------------------------------------------
1290 * Get the number of milliseconds since the library was
1296 * The time since the library was initialized is returned.
1297 * This time value is accurate to milliseconds even though
1298 * a more accurate time down to the microsecond could be
1303 *--------------------------------------------------------------
1310 struct timeval elapsed;
1311 guint32 milliseconds;
1313 X_GETTIMEOFDAY (&end);
1315 if (start.tv_usec > end.tv_usec)
1317 end.tv_usec += 1000000;
1320 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1321 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1323 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1325 return milliseconds;
1329 *--------------------------------------------------------------
1332 * Returns the current timer.
1337 * Returns the current timer interval. This interval is
1338 * in units of milliseconds.
1342 *--------------------------------------------------------------
1346 gdk_timer_get (void)
1352 *--------------------------------------------------------------
1355 * Sets the timer interval.
1358 * "milliseconds" is the new value for the timer.
1363 * Calls to "gdk_event_get" will last for a maximum
1364 * of time of "milliseconds". However, a value of 0
1365 * milliseconds will cause "gdk_event_get" to block
1366 * indefinately until an event is received.
1368 *--------------------------------------------------------------
1372 gdk_timer_set (guint32 milliseconds)
1374 timer_val = milliseconds;
1375 timer.tv_sec = milliseconds / 1000;
1376 timer.tv_usec = (milliseconds % 1000) * 1000;
1381 gdk_timer_enable (void)
1387 gdk_timer_disable (void)
1393 gdk_input_add_full (gint source,
1394 GdkInputCondition condition,
1395 GdkInputFunction function,
1397 GdkDestroyNotify destroy)
1399 static gint next_tag = 1;
1412 if ((input->source == source) && (input->condition == condition))
1415 (input->destroy) (input->data);
1416 input->function = function;
1418 input->destroy = destroy;
1425 input = g_new (GdkInput, 1);
1426 input->tag = next_tag++;
1427 input->source = source;
1428 input->condition = condition;
1429 input->function = function;
1431 input->destroy = destroy;
1434 inputs = g_list_prepend (inputs, input);
1441 gdk_input_add (gint source,
1442 GdkInputCondition condition,
1443 GdkInputFunction function,
1446 return gdk_input_add_interp (source, condition, function, data, NULL);
1450 gdk_input_remove (gint tag)
1460 if (input->tag == tag)
1463 (input->destroy) (input->data);
1465 input->tag = 0; /* do not free it here */
1466 input->condition = 0; /* it's done in gdk_event_wait */
1476 *--------------------------------------------------------------
1479 * Grabs the pointer to a specific window
1482 * "window" is the window which will receive the grab
1483 * "owner_events" specifies whether events will be reported as is,
1484 * or relative to "window"
1485 * "event_mask" masks only interesting events
1486 * "confine_to" limits the cursor movement to the specified window
1487 * "cursor" changes the cursor for the duration of the grab
1488 * "time" specifies the time
1493 * requires a corresponding call to gdk_pointer_ungrab
1495 *--------------------------------------------------------------
1499 gdk_pointer_grab (GdkWindow * window,
1501 GdkEventMask event_mask,
1502 GdkWindow * confine_to,
1506 /* From gdkwindow.c */
1507 extern const int nevent_masks;
1508 extern const int event_mask_table[];
1511 GdkWindowPrivate *window_private;
1512 GdkWindowPrivate *confine_to_private;
1513 GdkCursorPrivate *cursor_private;
1520 g_return_val_if_fail (window != NULL, 0);
1522 window_private = (GdkWindowPrivate*) window;
1523 confine_to_private = (GdkWindowPrivate*) confine_to;
1524 cursor_private = (GdkCursorPrivate*) cursor;
1526 xwindow = window_private->xwindow;
1528 if (!confine_to || confine_to_private->destroyed)
1531 xconfine_to = confine_to_private->xwindow;
1536 xcursor = cursor_private->xcursor;
1540 for (i = 0; i < nevent_masks; i++)
1542 if (event_mask & (1 << (i + 1)))
1543 xevent_mask |= event_mask_table[i];
1546 if (gdk_input_vtable.grab_pointer)
1547 return_val = gdk_input_vtable.grab_pointer (window,
1553 return_val = Success;
1555 if (return_val == Success)
1557 if (!window_private->destroyed)
1558 return_val = XGrabPointer (window_private->xdisplay,
1562 GrabModeAsync, GrabModeAsync,
1567 return_val = AlreadyGrabbed;
1570 if (return_val == GrabSuccess)
1571 xgrab_window = window_private;
1577 *--------------------------------------------------------------
1578 * gdk_pointer_ungrab
1580 * Releases any pointer grab
1588 *--------------------------------------------------------------
1592 gdk_pointer_ungrab (guint32 time)
1594 if (gdk_input_vtable.ungrab_pointer)
1595 gdk_input_vtable.ungrab_pointer (time);
1597 XUngrabPointer (gdk_display, time);
1598 xgrab_window = NULL;
1602 *--------------------------------------------------------------
1603 * gdk_pointer_is_grabbed
1605 * Tell wether there is an active x pointer grab in effect
1613 *--------------------------------------------------------------
1617 gdk_pointer_is_grabbed (void)
1619 return xgrab_window != NULL;
1623 *--------------------------------------------------------------
1626 * Grabs the keyboard to a specific window
1629 * "window" is the window which will receive the grab
1630 * "owner_events" specifies whether events will be reported as is,
1631 * or relative to "window"
1632 * "time" specifies the time
1637 * requires a corresponding call to gdk_keyboard_ungrab
1639 *--------------------------------------------------------------
1643 gdk_keyboard_grab (GdkWindow * window,
1647 GdkWindowPrivate *window_private;
1650 g_return_val_if_fail (window != NULL, 0);
1652 window_private = (GdkWindowPrivate*) window;
1653 xwindow = window_private->xwindow;
1655 if (!window_private->destroyed)
1656 return XGrabKeyboard (window_private->xdisplay,
1659 GrabModeAsync, GrabModeAsync,
1662 return AlreadyGrabbed;
1666 *--------------------------------------------------------------
1667 * gdk_keyboard_ungrab
1669 * Releases any keyboard grab
1677 *--------------------------------------------------------------
1681 gdk_keyboard_ungrab (guint32 time)
1683 XUngrabKeyboard (gdk_display, time);
1687 *--------------------------------------------------------------
1690 * Return the width of the screen.
1698 *--------------------------------------------------------------
1702 gdk_screen_width (void)
1706 return_val = DisplayWidth (gdk_display, gdk_screen);
1712 *--------------------------------------------------------------
1715 * Return the height of the screen.
1723 *--------------------------------------------------------------
1727 gdk_screen_height (void)
1731 return_val = DisplayHeight (gdk_display, gdk_screen);
1737 *--------------------------------------------------------------
1738 * gdk_screen_width_mm
1740 * Return the width of the screen in millimeters.
1748 *--------------------------------------------------------------
1752 gdk_screen_width_mm (void)
1756 return_val = DisplayWidthMM (gdk_display, gdk_screen);
1762 *--------------------------------------------------------------
1765 * Return the height of the screen in millimeters.
1773 *--------------------------------------------------------------
1777 gdk_screen_height_mm (void)
1781 return_val = DisplayHeightMM (gdk_display, gdk_screen);
1787 gdk_key_repeat_disable (void)
1789 XAutoRepeatOff (gdk_display);
1793 gdk_key_repeat_restore (void)
1796 XAutoRepeatOn (gdk_display);
1798 XAutoRepeatOff (gdk_display);
1803 *--------------------------------------------------------------
1806 * Flushes the Xlib output buffer and then waits
1807 * until all requests have been received and processed
1808 * by the X server. The only real use for this function
1809 * is in dealing with XShm.
1817 *--------------------------------------------------------------
1820 void gdk_flush (void)
1822 XSync (gdk_display, False);
1829 XBell(gdk_display, 100);
1834 *--------------------------------------------------------------
1837 * Waits until an event occurs or the timer runs out.
1842 * Returns TRUE if an event is ready to be read and FALSE
1843 * if the timer ran out.
1847 *--------------------------------------------------------------
1851 gdk_event_wait (void)
1856 GdkInputCondition condition;
1857 SELECT_MASK readfds;
1858 SELECT_MASK writefds;
1859 SELECT_MASK exceptfds;
1863 /* If there are no events pending we will wait for an event.
1864 * The time we wait is dependant on the "timer". If no timer
1865 * has been specified then we'll block until an event arrives.
1866 * If a timer has been specified we'll block until an event
1867 * arrives or the timer expires. (This is all done using the
1868 * "select" system call).
1871 if (XPending (gdk_display) == 0)
1874 FD_ZERO (&writefds);
1875 FD_ZERO (&exceptfds);
1877 FD_SET (connection_number, &readfds);
1878 max_input = connection_number;
1887 if (input->condition & GDK_INPUT_READ)
1888 FD_SET (input->source, &readfds);
1889 if (input->condition & GDK_INPUT_WRITE)
1890 FD_SET (input->source, &writefds);
1891 if (input->condition & GDK_INPUT_EXCEPTION)
1892 FD_SET (input->source, &exceptfds);
1894 max_input = MAX (max_input, input->source);
1897 else /* free removed inputs */
1902 list->next->prev = list->prev;
1904 list->prev->next = list->next;
1906 inputs = list->next;
1910 temp_list->next = NULL;
1911 temp_list->prev = NULL;
1913 g_free (temp_list->data);
1914 g_list_free (temp_list);
1919 if (gdk_using_threads)
1921 gdk_select_waiting = TRUE;
1923 FD_SET (gdk_threads_pipe[0], &readfds);
1924 max_input = MAX (max_input, gdk_threads_pipe[0]);
1925 gdk_threads_leave ();
1929 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1932 if (gdk_using_threads)
1935 gdk_threads_enter ();
1936 gdk_select_waiting = FALSE;
1938 if (FD_ISSET (gdk_threads_pipe[0], &readfds))
1939 read (gdk_threads_pipe[0], &c, 1);
1948 if (FD_ISSET (connection_number, &readfds))
1950 if (XPending (gdk_display) == 0)
1954 XNoOp (gdk_display);
1955 XFlush (gdk_display);
1970 if (FD_ISSET (input->source, &readfds))
1971 condition |= GDK_INPUT_READ;
1972 if (FD_ISSET (input->source, &writefds))
1973 condition |= GDK_INPUT_WRITE;
1974 if (FD_ISSET (input->source, &exceptfds))
1975 condition |= GDK_INPUT_EXCEPTION;
1977 if (condition && input->function)
1978 (* input->function) (input->data, input->source, condition);
1989 gdk_event_apply_filters (XEvent *xevent,
1993 GdkEventFilter *filter;
1995 GdkFilterReturn result;
2001 filter = (GdkEventFilter *)tmp_list->data;
2003 result = (*filter->function)(xevent, event, filter->data);
2004 if (result != GDK_FILTER_CONTINUE)
2007 tmp_list = tmp_list->next;
2010 return GDK_FILTER_CONTINUE;
2014 gdk_add_client_message_filter (GdkAtom message_type,
2018 GdkClientFilter *filter = g_new (GdkClientFilter, 1);
2020 filter->type = message_type;
2021 filter->function = func;
2022 filter->data = data;
2024 client_filters = g_list_prepend (client_filters, filter);
2028 gdk_event_translate (GdkEvent *event,
2033 GdkWindowPrivate *window_private;
2034 static XComposeStatus compose;
2038 static gchar* buf = NULL;
2039 static gint buf_len= 0;
2047 /* Find the GdkWindow that this event occurred in.
2049 * We handle events with window=None
2050 * specially - they are generated by XFree86's XInput under
2051 * some circumstances.
2054 if ((xevent->xany.window == None) &&
2055 gdk_input_vtable.window_none_event)
2057 return_val = gdk_input_vtable.window_none_event (event,xevent);
2059 if (return_val >= 0) /* was handled */
2065 window = gdk_window_lookup (xevent->xany.window);
2066 window_private = (GdkWindowPrivate *) window;
2069 gdk_window_ref (window);
2071 else if (XFilterEvent(xevent, None)) /* for xlib XIM handling */
2076 g_message ("Got event for unknown window: %#lx\n", xevent->xany.window));
2078 event->any.window = window;
2079 event->any.send_event = xevent->xany.send_event;
2081 if (window_private && window_private->destroyed)
2083 if (xevent->type != DestroyNotify)
2088 /* Check for filters for this window */
2090 GdkFilterReturn result;
2091 result = gdk_event_apply_filters (xevent, event,
2093 ?window_private->filters
2094 :gdk_default_filters);
2096 if (result != GDK_FILTER_CONTINUE)
2098 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2102 /* We do a "manual" conversion of the XEvent to a
2103 * GdkEvent. The structures are mostly the same so
2104 * the conversion is fairly straightforward. We also
2105 * optionally print debugging info regarding events
2111 switch (xevent->type)
2114 /* Lookup the string corresponding to the given keysym.
2120 buf = g_new (gchar, buf_len);
2122 keysym = GDK_VoidSymbol;
2124 if (xim_using == TRUE && xim_ic)
2128 /* Clear keyval. Depending on status, may not be set */
2129 charcount = XmbLookupString(xim_ic->xic,
2130 &xevent->xkey, buf, buf_len-1,
2132 if (status == XBufferOverflow)
2134 /* alloc adequate size of buffer */
2136 g_message("XIM: overflow (required %i)", charcount));
2138 while (buf_len <= charcount)
2140 buf = (gchar *) g_realloc (buf, buf_len);
2142 charcount = XmbLookupString (xim_ic->xic,
2143 &xevent->xkey, buf, buf_len-1,
2146 if (status == XLookupNone)
2153 charcount = XLookupString (&xevent->xkey, buf, buf_len,
2156 charcount = XLookupString (&xevent->xkey, buf, 16,
2159 event->key.keyval = keysym;
2161 if (charcount > 0 && buf[charcount-1] == '\0')
2164 buf[charcount] = '\0';
2166 /* Print debugging info.
2168 #ifdef G_ENABLE_DEBUG
2169 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2171 g_message ("key press:\twindow: %ld key: %12s %d",
2172 xevent->xkey.window - base_id,
2173 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
2176 g_message ("\t\tlength: %4d string: \"%s\"",
2179 #endif /* G_ENABLE_DEBUG */
2181 event->key.type = GDK_KEY_PRESS;
2182 event->key.window = window;
2183 event->key.time = xevent->xkey.time;
2184 event->key.state = (GdkModifierType) xevent->xkey.state;
2185 event->key.string = g_strdup (buf);
2186 event->key.length = charcount;
2191 /* Lookup the string corresponding to the given keysym.
2197 buf = g_new (gchar, buf_len);
2200 keysym = GDK_VoidSymbol;
2201 charcount = XLookupString (&xevent->xkey, buf, 16,
2203 event->key.keyval = keysym;
2205 /* Print debugging info.
2208 g_message ("key release:\t\twindow: %ld key: %12s %d",
2209 xevent->xkey.window - base_id,
2210 XKeysymToString (event->key.keyval),
2211 event->key.keyval));
2213 event->key.type = GDK_KEY_RELEASE;
2214 event->key.window = window;
2215 event->key.time = xevent->xkey.time;
2216 event->key.state = (GdkModifierType) xevent->xkey.state;
2217 event->key.length = 0;
2218 event->key.string = NULL;
2223 /* Print debugging info.
2226 g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
2227 xevent->xbutton.window - base_id,
2228 xevent->xbutton.x, xevent->xbutton.y,
2229 xevent->xbutton.button));
2231 if (window_private &&
2232 (window_private->extension_events != 0) &&
2233 gdk_input_ignore_core)
2239 event->button.type = GDK_BUTTON_PRESS;
2240 event->button.window = window;
2241 event->button.time = xevent->xbutton.time;
2242 event->button.x = xevent->xbutton.x;
2243 event->button.y = xevent->xbutton.y;
2244 event->button.x_root = (gfloat)xevent->xbutton.x_root;
2245 event->button.y_root = (gfloat)xevent->xbutton.y_root;
2246 event->button.pressure = 0.5;
2247 event->button.xtilt = 0;
2248 event->button.ytilt = 0;
2249 event->button.state = (GdkModifierType) xevent->xbutton.state;
2250 event->button.button = xevent->xbutton.button;
2251 event->button.source = GDK_SOURCE_MOUSE;
2252 event->button.deviceid = GDK_CORE_POINTER;
2254 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
2255 (event->button.window == button_window[1]) &&
2256 (event->button.button == button_number[1]))
2258 gdk_synthesize_click (event, 3);
2260 button_click_time[1] = 0;
2261 button_click_time[0] = 0;
2262 button_window[1] = NULL;
2263 button_window[0] = 0;
2264 button_number[1] = -1;
2265 button_number[0] = -1;
2267 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
2268 (event->button.window == button_window[0]) &&
2269 (event->button.button == button_number[0]))
2271 gdk_synthesize_click (event, 2);
2273 button_click_time[1] = button_click_time[0];
2274 button_click_time[0] = event->button.time;
2275 button_window[1] = button_window[0];
2276 button_window[0] = event->button.window;
2277 button_number[1] = button_number[0];
2278 button_number[0] = event->button.button;
2282 button_click_time[1] = 0;
2283 button_click_time[0] = event->button.time;
2284 button_window[1] = NULL;
2285 button_window[0] = event->button.window;
2286 button_number[1] = -1;
2287 button_number[0] = event->button.button;
2293 /* Print debugging info.
2296 g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
2297 xevent->xbutton.window - base_id,
2298 xevent->xbutton.x, xevent->xbutton.y,
2299 xevent->xbutton.button));
2301 if (window_private &&
2302 (window_private->extension_events != 0) &&
2303 gdk_input_ignore_core)
2309 event->button.type = GDK_BUTTON_RELEASE;
2310 event->button.window = window;
2311 event->button.time = xevent->xbutton.time;
2312 event->button.x = xevent->xbutton.x;
2313 event->button.y = xevent->xbutton.y;
2314 event->button.x_root = (gfloat)xevent->xbutton.x_root;
2315 event->button.y_root = (gfloat)xevent->xbutton.y_root;
2316 event->button.pressure = 0.5;
2317 event->button.xtilt = 0;
2318 event->button.ytilt = 0;
2319 event->button.state = (GdkModifierType) xevent->xbutton.state;
2320 event->button.button = xevent->xbutton.button;
2321 event->button.source = GDK_SOURCE_MOUSE;
2322 event->button.deviceid = GDK_CORE_POINTER;
2327 /* Print debugging info.
2330 g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
2331 xevent->xmotion.window - base_id,
2332 xevent->xmotion.x, xevent->xmotion.y,
2333 (xevent->xmotion.is_hint) ? "true" : "false"));
2335 if (window_private &&
2336 (window_private->extension_events != 0) &&
2337 gdk_input_ignore_core)
2343 event->motion.type = GDK_MOTION_NOTIFY;
2344 event->motion.window = window;
2345 event->motion.time = xevent->xmotion.time;
2346 event->motion.x = xevent->xmotion.x;
2347 event->motion.y = xevent->xmotion.y;
2348 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2349 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2350 event->motion.pressure = 0.5;
2351 event->motion.xtilt = 0;
2352 event->motion.ytilt = 0;
2353 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2354 event->motion.is_hint = xevent->xmotion.is_hint;
2355 event->motion.source = GDK_SOURCE_MOUSE;
2356 event->motion.deviceid = GDK_CORE_POINTER;
2361 /* Print debugging info.
2364 g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
2365 xevent->xcrossing.window - base_id,
2366 xevent->xcrossing.detail,
2367 xevent->xcrossing.subwindow - base_id));
2369 /* Tell XInput stuff about it if appropriate */
2370 if (window_private &&
2371 !window_private->destroyed &&
2372 (window_private->extension_events != 0) &&
2373 gdk_input_vtable.enter_event)
2374 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2376 event->crossing.type = GDK_ENTER_NOTIFY;
2377 event->crossing.window = window;
2379 /* If the subwindow field of the XEvent is non-NULL, then
2380 * lookup the corresponding GdkWindow.
2382 if (xevent->xcrossing.subwindow != None)
2383 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2385 event->crossing.subwindow = NULL;
2387 event->crossing.time = xevent->xcrossing.time;
2388 event->crossing.x = xevent->xcrossing.x;
2389 event->crossing.y = xevent->xcrossing.y;
2390 event->crossing.x_root = xevent->xcrossing.x_root;
2391 event->crossing.y_root = xevent->xcrossing.y_root;
2393 /* Translate the crossing mode into Gdk terms.
2395 switch (xevent->xcrossing.mode)
2398 event->crossing.mode = GDK_CROSSING_NORMAL;
2401 event->crossing.mode = GDK_CROSSING_GRAB;
2404 event->crossing.mode = GDK_CROSSING_UNGRAB;
2408 /* Translate the crossing detail into Gdk terms.
2410 switch (xevent->xcrossing.detail)
2412 case NotifyInferior:
2413 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2415 case NotifyAncestor:
2416 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2419 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2421 case NotifyNonlinear:
2422 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2424 case NotifyNonlinearVirtual:
2425 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2428 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2432 event->crossing.focus = xevent->xcrossing.focus;
2433 event->crossing.state = xevent->xcrossing.state;
2438 /* Print debugging info.
2441 g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
2442 xevent->xcrossing.window - base_id,
2443 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2445 event->crossing.type = GDK_LEAVE_NOTIFY;
2446 event->crossing.window = window;
2448 /* If the subwindow field of the XEvent is non-NULL, then
2449 * lookup the corresponding GdkWindow.
2451 if (xevent->xcrossing.subwindow != None)
2452 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2454 event->crossing.subwindow = NULL;
2456 event->crossing.time = xevent->xcrossing.time;
2457 event->crossing.x = xevent->xcrossing.x;
2458 event->crossing.y = xevent->xcrossing.y;
2459 event->crossing.x_root = xevent->xcrossing.x_root;
2460 event->crossing.y_root = xevent->xcrossing.y_root;
2462 /* Translate the crossing mode into Gdk terms.
2464 switch (xevent->xcrossing.mode)
2467 event->crossing.mode = GDK_CROSSING_NORMAL;
2470 event->crossing.mode = GDK_CROSSING_GRAB;
2473 event->crossing.mode = GDK_CROSSING_UNGRAB;
2477 /* Translate the crossing detail into Gdk terms.
2479 switch (xevent->xcrossing.detail)
2481 case NotifyInferior:
2482 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2484 case NotifyAncestor:
2485 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2488 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2490 case NotifyNonlinear:
2491 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2493 case NotifyNonlinearVirtual:
2494 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2497 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2501 event->crossing.focus = xevent->xcrossing.focus;
2502 event->crossing.state = xevent->xcrossing.state;
2508 /* We only care about focus events that indicate that _this_
2509 * window (not a ancestor or child) got or lost the focus
2511 switch (xevent->xfocus.detail)
2513 case NotifyAncestor:
2514 case NotifyInferior:
2515 case NotifyNonlinear:
2516 /* Print debugging info.
2519 g_message ("focus %s:\t\twindow: %ld",
2520 (xevent->xany.type == FocusIn) ? "in" : "out",
2521 xevent->xfocus.window - base_id));
2523 event->focus_change.type = GDK_FOCUS_CHANGE;
2524 event->focus_change.window = window;
2525 event->focus_change.in = (xevent->xany.type == FocusIn);
2534 /* Print debugging info.
2537 g_message ("keymap notify"));
2539 /* Not currently handled */
2544 /* Print debugging info.
2547 g_message ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d",
2548 xevent->xexpose.window - base_id, xevent->xexpose.count,
2549 xevent->xexpose.x, xevent->xexpose.y,
2550 xevent->xexpose.width, xevent->xexpose.height));
2551 gdk_compress_exposures (xevent, window);
2553 event->expose.type = GDK_EXPOSE;
2554 event->expose.window = window;
2555 event->expose.area.x = xevent->xexpose.x;
2556 event->expose.area.y = xevent->xexpose.y;
2557 event->expose.area.width = xevent->xexpose.width;
2558 event->expose.area.height = xevent->xexpose.height;
2559 event->expose.count = xevent->xexpose.count;
2563 case GraphicsExpose:
2564 /* Print debugging info.
2567 g_message ("graphics expose:\tdrawable: %ld",
2568 xevent->xgraphicsexpose.drawable - base_id));
2570 event->expose.type = GDK_EXPOSE;
2571 event->expose.window = window;
2572 event->expose.area.x = xevent->xgraphicsexpose.x;
2573 event->expose.area.y = xevent->xgraphicsexpose.y;
2574 event->expose.area.width = xevent->xgraphicsexpose.width;
2575 event->expose.area.height = xevent->xgraphicsexpose.height;
2576 event->expose.count = xevent->xexpose.count;
2581 /* Print debugging info.
2584 g_message ("no expose:\t\tdrawable: %ld",
2585 xevent->xnoexpose.drawable - base_id));
2587 event->no_expose.type = GDK_NO_EXPOSE;
2588 event->no_expose.window = window;
2592 case VisibilityNotify:
2593 /* Print debugging info.
2595 #ifdef G_ENABLE_DEBUG
2596 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2597 switch (xevent->xvisibility.state)
2599 case VisibilityFullyObscured:
2600 g_message ("visibility notify:\twindow: %ld none",
2601 xevent->xvisibility.window - base_id);
2603 case VisibilityPartiallyObscured:
2604 g_message ("visibility notify:\twindow: %ld partial",
2605 xevent->xvisibility.window - base_id);
2607 case VisibilityUnobscured:
2608 g_message ("visibility notify:\twindow: %ld full",
2609 xevent->xvisibility.window - base_id);
2612 #endif /* G_ENABLE_DEBUG */
2614 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2615 event->visibility.window = window;
2617 switch (xevent->xvisibility.state)
2619 case VisibilityFullyObscured:
2620 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2623 case VisibilityPartiallyObscured:
2624 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2627 case VisibilityUnobscured:
2628 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2635 /* Not currently handled */
2639 /* Print debugging info.
2642 g_message ("destroy notify:\twindow: %ld",
2643 xevent->xdestroywindow.window - base_id));
2645 event->any.type = GDK_DESTROY;
2646 event->any.window = window;
2648 return_val = window_private && !window_private->destroyed;
2650 if(window && window_private->xwindow != GDK_ROOT_WINDOW())
2651 gdk_window_destroy_notify (window);
2655 /* Print debugging info.
2658 g_message ("unmap notify:\t\twindow: %ld",
2659 xevent->xmap.window - base_id));
2661 event->any.type = GDK_UNMAP;
2662 event->any.window = window;
2664 if (xgrab_window == window_private)
2665 xgrab_window = NULL;
2670 /* Print debugging info.
2673 g_message ("map notify:\t\twindow: %ld",
2674 xevent->xmap.window - base_id));
2676 event->any.type = GDK_MAP;
2677 event->any.window = window;
2681 case ReparentNotify:
2682 /* Print debugging info.
2685 g_message ("reparent notify:\twindow: %ld",
2686 xevent->xreparent.window - base_id));
2688 /* Not currently handled */
2692 case ConfigureNotify:
2693 /* Print debugging info.
2695 while ((XPending (gdk_display) > 0) &&
2696 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2697 ConfigureNotify, xevent))
2699 GdkFilterReturn result;
2702 g_message ("configure notify discarded:\twindow: %ld",
2703 xevent->xconfigure.window - base_id));
2705 result = gdk_event_apply_filters (xevent, event,
2707 ?window_private->filters
2708 :gdk_default_filters);
2710 /* If the result is GDK_FILTER_REMOVE, there will be
2711 * trouble, but anybody who filtering the Configure events
2712 * better know what they are doing
2714 if (result != GDK_FILTER_CONTINUE)
2716 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2719 /*XSync (gdk_display, 0);*/
2724 g_message ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d",
2725 xevent->xconfigure.window - base_id,
2726 xevent->xconfigure.x,
2727 xevent->xconfigure.y,
2728 xevent->xconfigure.width,
2729 xevent->xconfigure.height,
2730 xevent->xconfigure.border_width,
2731 xevent->xconfigure.above - base_id,
2732 xevent->xconfigure.override_redirect));
2734 if (!window_private->destroyed &&
2735 (window_private->extension_events != 0) &&
2736 gdk_input_vtable.configure_event)
2737 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2739 if (window_private->window_type == GDK_WINDOW_CHILD)
2743 event->configure.type = GDK_CONFIGURE;
2744 event->configure.window = window;
2745 event->configure.width = xevent->xconfigure.width;
2746 event->configure.height = xevent->xconfigure.height;
2748 if (!xevent->xconfigure.x &&
2749 !xevent->xconfigure.y &&
2750 !window_private->destroyed)
2754 Window child_window = 0;
2756 if (!XTranslateCoordinates (window_private->xdisplay,
2757 window_private->xwindow,
2762 g_warning ("GdkWindow %ld doesn't share root windows display?",
2763 window_private->xwindow - base_id);
2764 event->configure.x = tx;
2765 event->configure.y = ty;
2769 event->configure.x = xevent->xconfigure.x;
2770 event->configure.y = xevent->xconfigure.y;
2772 window_private->x = event->configure.x;
2773 window_private->y = event->configure.y;
2774 window_private->width = xevent->xconfigure.width;
2775 window_private->height = xevent->xconfigure.height;
2776 if (window_private->resize_count > 1)
2777 window_private->resize_count -= 1;
2781 case PropertyNotify:
2782 /* Print debugging info.
2785 g_message ("property notify:\twindow: %ld",
2786 xevent->xproperty.window - base_id));
2788 event->property.type = GDK_PROPERTY_NOTIFY;
2789 event->property.window = window;
2790 event->property.atom = xevent->xproperty.atom;
2791 event->property.time = xevent->xproperty.time;
2792 event->property.state = xevent->xproperty.state;
2796 case SelectionClear:
2798 g_message ("selection clear:\twindow: %ld",
2799 xevent->xproperty.window - base_id));
2801 event->selection.type = GDK_SELECTION_CLEAR;
2802 event->selection.window = window;
2803 event->selection.selection = xevent->xselectionclear.selection;
2804 event->selection.time = xevent->xselectionclear.time;
2808 case SelectionRequest:
2810 g_message ("selection request:\twindow: %ld",
2811 xevent->xproperty.window - base_id));
2813 event->selection.type = GDK_SELECTION_REQUEST;
2814 event->selection.window = window;
2815 event->selection.selection = xevent->xselectionrequest.selection;
2816 event->selection.target = xevent->xselectionrequest.target;
2817 event->selection.property = xevent->xselectionrequest.property;
2818 event->selection.requestor = xevent->xselectionrequest.requestor;
2819 event->selection.time = xevent->xselectionrequest.time;
2823 case SelectionNotify:
2825 g_message ("selection notify:\twindow: %ld",
2826 xevent->xproperty.window - base_id));
2829 event->selection.type = GDK_SELECTION_NOTIFY;
2830 event->selection.window = window;
2831 event->selection.selection = xevent->xselection.selection;
2832 event->selection.target = xevent->xselection.target;
2833 event->selection.property = xevent->xselection.property;
2834 event->selection.time = xevent->xselection.time;
2838 case ColormapNotify:
2839 /* Print debugging info.
2842 g_message ("colormap notify:\twindow: %ld",
2843 xevent->xcolormap.window - base_id));
2845 /* Not currently handled */
2852 GdkFilterReturn result = GDK_FILTER_CONTINUE;
2854 /* Print debugging info.
2857 g_message ("client message:\twindow: %ld",
2858 xevent->xclient.window - base_id));
2860 tmp_list = client_filters;
2863 GdkClientFilter *filter = tmp_list->data;
2864 if (filter->type == xevent->xclient.message_type)
2866 result = (*filter->function) (xevent, event, filter->data);
2870 tmp_list = tmp_list->next;
2875 case GDK_FILTER_REMOVE:
2878 case GDK_FILTER_TRANSLATE:
2881 case GDK_FILTER_CONTINUE:
2882 /* Send unknown ClientMessage's on to Gtk for it to use */
2883 event->client.type = GDK_CLIENT_EVENT;
2884 event->client.window = window;
2885 event->client.message_type = xevent->xclient.message_type;
2886 event->client.data_format = xevent->xclient.format;
2887 memcpy(&event->client.data, &xevent->xclient.data,
2888 sizeof(event->client.data));
2895 /* Print debugging info.
2898 g_message ("mapping notify"));
2900 /* Let XLib know that there is a new keyboard mapping.
2902 XRefreshKeyboardMapping (&xevent->xmapping);
2907 /* something else - (e.g., a Xinput event) */
2909 if (window_private &&
2910 !window_private->destroyed &&
2911 (window_private->extension_events != 0) &&
2912 gdk_input_vtable.other_event)
2913 return_val = gdk_input_vtable.other_event(event, xevent, window);
2922 if (event->any.window)
2923 gdk_window_ref (event->any.window);
2924 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2925 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2926 (event->crossing.subwindow != NULL))
2927 gdk_window_ref (event->crossing.subwindow);
2931 /* Mark this event as having no resources to be freed */
2932 event->any.window = NULL;
2933 event->any.type = GDK_NOTHING;
2937 gdk_window_unref (window);
2943 gdk_wm_protocols_filter (GdkXEvent *xev,
2947 XEvent *xevent = (XEvent *)xev;
2949 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2951 /* The delete window request specifies a window
2952 * to delete. We don't actually destroy the
2953 * window because "it is only a request". (The
2954 * window might contain vital data that the
2955 * program does not want destroyed). Instead
2956 * the event is passed along to the program,
2957 * which should then destroy the window.
2960 g_message ("delete window:\t\twindow: %ld",
2961 xevent->xclient.window - base_id));
2963 event->any.type = GDK_DELETE;
2965 return GDK_FILTER_TRANSLATE;
2967 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2971 return GDK_FILTER_REMOVE;
2976 gdk_event_get_type (Display *display,
2983 if (gdk_event_translate (&event, xevent))
2985 pred = (GdkPredicate*) arg;
2986 return (* pred->func) (&event, pred->data);
2994 gdk_synthesize_click (GdkEvent *event,
2997 GdkEvent temp_event;
2999 g_return_if_fail (event != NULL);
3001 temp_event = *event;
3002 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
3004 gdk_event_put (&temp_event);
3008 *--------------------------------------------------------------
3011 * This is the "atexit" function that makes sure the
3012 * library gets a chance to cleanup.
3019 * The library is un-initialized and the program exits.
3021 *--------------------------------------------------------------
3025 gdk_exit_func (void)
3027 static gboolean in_gdk_exit_func = FALSE;
3029 /* This is to avoid an infinite loop if a program segfaults in
3030 an atexit() handler (and yes, it does happen, especially if a program
3031 has trounced over memory too badly for even g_message to work) */
3032 if (in_gdk_exit_func == TRUE)
3034 in_gdk_exit_func = TRUE;
3036 if (gdk_initialized)
3046 gdk_key_repeat_restore ();
3048 XCloseDisplay (gdk_display);
3049 gdk_initialized = 0;
3054 *--------------------------------------------------------------
3057 * The X error handling routine.
3060 * "display" is the X display the error orignated from.
3061 * "error" is the XErrorEvent that we are handling.
3064 * Either we were expecting some sort of error to occur,
3065 * in which case we set the "gdk_error_code" flag, or this
3066 * error was unexpected, in which case we will print an
3067 * error message and exit. (Since trying to continue will
3068 * most likely simply lead to more errors).
3072 *--------------------------------------------------------------
3076 gdk_x_error (Display *display,
3081 if (gdk_error_warnings)
3083 XGetErrorText (display, error->error_code, buf, 63);
3084 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
3088 error->request_code,
3092 gdk_error_code = -1;
3097 *--------------------------------------------------------------
3100 * The X I/O error handling routine.
3103 * "display" is the X display the error orignated from.
3106 * An X I/O error basically means we lost our connection
3107 * to the X server. There is not much we can do to
3108 * continue, so simply print an error message and exit.
3112 *--------------------------------------------------------------
3116 gdk_x_io_error (Display *display)
3118 g_error ("an x io error occurred");
3123 *--------------------------------------------------------------
3126 * The signal handler.
3129 * "sig_num" is the number of the signal we received.
3132 * The signals we catch are all fatal. So we simply build
3133 * up a nice little error message and print it and exit.
3134 * If in the process of doing so another signal is received
3135 * we notice that we are already exiting and simply kill
3140 *--------------------------------------------------------------
3144 gdk_signal (int sig_num)
3146 static int caught_fatal_sig = 0;
3149 if (caught_fatal_sig)
3150 kill (getpid (), sig_num);
3151 caught_fatal_sig = 1;
3177 sig = "unknown signal";
3181 g_message ("\n** ERROR **: %s caught", sig);
3182 #ifdef G_ENABLE_DEBUG
3184 #else /* !G_ENABLE_DEBUG */
3186 #endif /* !G_ENABLE_DEBUG */
3191 /* The following routines duplicate functionality in Xlib to
3192 * translate from varargs to X's internal opaque XVaNestedList.
3194 * If all vendors have stuck close to the reference implementation,
3195 * then we should hopefully be OK.
3198 /* This needs to match XIMArg as defined in Xlcint.h exactly */
3205 /*************************************************************
3207 * Counts the number of name/value pairs in the vararg list
3212 *************************************************************/
3215 gdk_im_va_count (va_list list)
3220 name = va_arg (list, gchar *);
3224 (void)va_arg (list, gpointer);
3225 name = va_arg (list, gchar *);
3231 /*************************************************************
3232 * gdk_im_va_to_nested:
3233 * Given a varargs list and the result of gdk_im_va_count,
3234 * create a XVaNestedList.
3239 *************************************************************/
3241 static XVaNestedList
3242 gdk_im_va_to_nested (va_list list, guint count)
3252 result = g_new (GdkImArg, count+1);
3255 name = va_arg (list, gchar *);
3259 arg->value = va_arg (list, gpointer);
3261 name = va_arg (list, gchar *);
3266 return (XVaNestedList)result;
3270 *--------------------------------------------------------------
3273 * Begin using input method with XIM Protocol(X11R6 standard)
3276 * "ic" is the "Input Context" which is created by gtk_ic_new.
3277 * The input area is specified with "window".
3280 * The gdk's event handling routine is switched to XIM based routine.
3281 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3282 * and uses XmbLookupString instead of XLookupString.
3286 *--------------------------------------------------------------
3290 gdk_im_begin (GdkIC ic, GdkWindow* window)
3292 GdkICPrivate *private;
3295 g_return_if_fail (ic != NULL);
3296 g_return_if_fail (window);
3298 private = (GdkICPrivate *) ic;
3302 xim_window = window;
3305 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3306 if (xwin != GDK_WINDOW_XWINDOW(window))
3307 XSetICValues (private->xic, XNFocusWindow,
3308 GDK_WINDOW_XWINDOW(window), NULL);
3309 if (private != xim_ic)
3310 XSetICFocus (private->xic);
3315 *--------------------------------------------------------------
3318 * End using input method with XIM Protocol(X11R6 standard)
3323 * The gdk's event handling routine is switched to normal routine.
3324 * User should call this function before ic and window will be destroyed.
3328 *--------------------------------------------------------------
3346 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3348 GdkIMStyle s1, s2, u;
3350 if (style1 == 0) return style2;
3351 if (style2 == 0) return style1;
3352 if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
3353 == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
3356 s1 = style1 & GDK_IM_PREEDIT_MASK;
3357 s2 = style2 & GDK_IM_PREEDIT_MASK;
3360 if (u & GDK_IM_PREEDIT_CALLBACKS)
3361 return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
3362 else if (u & GDK_IM_PREEDIT_POSITION)
3363 return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
3364 else if (u & GDK_IM_PREEDIT_AREA)
3365 return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
3366 else if (u & GDK_IM_PREEDIT_NOTHING)
3367 return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
3369 s1 = style1 & GDK_IM_STATUS_MASK;
3370 s2 = style2 & GDK_IM_STATUS_MASK;
3372 if ( u & GDK_IM_STATUS_CALLBACKS)
3373 return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
3374 else if ( u & GDK_IM_STATUS_AREA)
3375 return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
3376 else if ( u & GDK_IM_STATUS_NOTHING)
3377 return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
3378 else if ( u & GDK_IM_STATUS_NONE)
3379 return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
3381 return 0; /* Get rid of stupid warning */
3385 gdk_im_decide_style (GdkIMStyle supported_style)
3388 GdkIMStyle style, tmp;
3390 g_return_val_if_fail (xim_styles != NULL, 0);
3393 for (i=0; i<xim_styles->count_styles; i++)
3395 tmp = xim_styles->supported_styles[i];
3396 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3397 style = gdk_im_choose_better_style (style, tmp);
3403 gdk_im_set_best_style (GdkIMStyle style)
3405 if (style & GDK_IM_PREEDIT_MASK)
3407 xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
3409 xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
3410 if (!(style & GDK_IM_PREEDIT_NONE))
3412 xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
3413 if (!(style & GDK_IM_PREEDIT_NOTHING))
3415 xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
3416 if (!(style & GDK_IM_PREEDIT_AREA))
3418 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
3419 if (!(style & GDK_IM_PREEDIT_POSITION))
3420 xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
3425 if (style & GDK_IM_STATUS_MASK)
3427 xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
3429 xim_best_allowed_style |= GDK_IM_STATUS_NONE;
3430 if (!(style & GDK_IM_STATUS_NONE))
3432 xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
3433 if (!(style & GDK_IM_STATUS_NOTHING))
3435 xim_best_allowed_style |= GDK_IM_STATUS_AREA;
3436 if (!(style & GDK_IM_STATUS_AREA))
3437 xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
3442 return xim_best_allowed_style;
3446 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3448 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3451 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
3454 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3477 return (xim_im != NULL);
3481 gdk_ic_new (GdkWindow* client_window,
3482 GdkWindow* focus_window,
3483 GdkIMStyle style, ...)
3486 GdkICPrivate *private;
3487 XVaNestedList preedit_attr = NULL;
3490 g_return_val_if_fail (client_window != NULL, NULL);
3491 g_return_val_if_fail (focus_window != NULL, NULL);
3492 g_return_val_if_fail (gdk_im_ready(), NULL);
3494 private = g_new (GdkICPrivate, 1);
3496 va_start (list, style);
3497 count = gdk_im_va_count (list);
3500 va_start (list, style);
3501 preedit_attr = gdk_im_va_to_nested (list, count);
3504 private->style = gdk_im_decide_style (style);
3505 if (private->style != style)
3507 g_warning ("can not create input context with specified input style.");
3512 private->xic = XCreateIC(gdk_im_get (),
3513 XNInputStyle, style,
3514 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3515 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3516 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3519 g_free (preedit_attr);
3527 xim_ic_list = g_list_append (xim_ic_list, private);
3532 gdk_ic_destroy (GdkIC ic)
3534 GdkICPrivate *private;
3536 g_return_if_fail (ic != NULL);
3538 private = (GdkICPrivate *) ic;
3540 if (xim_ic == private)
3543 XDestroyIC (private->xic);
3544 xim_ic_list = g_list_remove (xim_ic_list, private);
3549 gdk_ic_get_style (GdkIC ic)
3551 GdkICPrivate *private;
3553 g_return_val_if_fail (ic != NULL, 0);
3555 private = (GdkICPrivate *) ic;
3557 return private->style;
3561 gdk_ic_set_values (GdkIC ic, ...)
3565 GdkICPrivate *private;
3568 g_return_if_fail (ic != NULL);
3570 private = (GdkICPrivate *) ic;
3572 va_start (list, ic);
3573 count = gdk_im_va_count (list);
3576 va_start (list, ic);
3577 args = gdk_im_va_to_nested (list, count);
3580 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3586 gdk_ic_get_values (GdkIC ic, ...)
3590 GdkICPrivate *private;
3593 g_return_if_fail (ic != NULL);
3595 private = (GdkICPrivate *) ic;
3597 va_start (list, ic);
3598 count = gdk_im_va_count (list);
3601 va_start (list, ic);
3602 args = gdk_im_va_to_nested (list, count);
3605 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3611 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3615 GdkICPrivate *private;
3618 g_return_if_fail (ic != NULL);
3619 g_return_if_fail (target != NULL);
3621 private = (GdkICPrivate *) ic;
3623 va_start (list, target);
3624 count = gdk_im_va_count (list);
3627 va_start (list, target);
3628 attr = gdk_im_va_to_nested (list, count);
3631 XSetICValues (private->xic, target, attr, NULL);
3637 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3641 GdkICPrivate *private;
3644 g_return_if_fail (ic != NULL);
3645 g_return_if_fail (target != NULL);
3647 private = (GdkICPrivate *) ic;
3649 va_start (list, target);
3650 count = gdk_im_va_count (list);
3653 va_start (list, target);
3654 attr = gdk_im_va_to_nested (list, count);
3657 XGetICValues (private->xic, target, attr, NULL);
3663 gdk_ic_get_events (GdkIC ic)
3668 GdkICPrivate *private;
3671 /* From gdkwindow.c */
3672 extern int nevent_masks;
3673 extern int event_mask_table[];
3675 g_return_val_if_fail (ic != NULL, 0);
3677 private = (GdkICPrivate *) ic;
3679 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
3681 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
3686 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3687 if (xmask & event_mask_table [i])
3690 xmask &= ~ event_mask_table [i];
3694 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
3700 gdk_ic_cleanup (void)
3704 GdkICPrivate *private;
3707 for (node = xim_ic_list; node != NULL; node = node->next)
3711 private = (GdkICPrivate *) (node->data);
3712 XDestroyIC (private->xic);
3717 #ifdef G_ENABLE_DEBUG
3718 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3720 g_warning ("Cleaned up %i IC(s)\n", destroyed);
3722 #endif /* G_ENABLE_DEBUG */
3723 g_list_free(xim_ic_list);
3727 #else /* !USE_XIM */
3730 gdk_im_begin (GdkIC ic, GdkWindow* window)
3740 gdk_im_decide_style (GdkIMStyle supported_style)
3742 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
3746 gdk_im_set_best_style (GdkIMStyle style)
3748 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
3758 gdk_ic_new (GdkWindow* client_window,
3759 GdkWindow* focus_window,
3760 GdkIMStyle style, ...)
3766 gdk_ic_destroy (GdkIC ic)
3771 gdk_ic_get_style (GdkIC ic)
3773 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
3777 gdk_ic_set_values (GdkIC ic, ...)
3782 gdk_ic_get_values (GdkIC ic, ...)
3787 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3792 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3797 gdk_ic_get_events (GdkIC ic)
3802 #endif /* USE_XIM */
3807 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3809 static wchar_t wcs[MB_CUR_MAX + 1];
3810 static gchar mbs[MB_CUR_MAX + 1];
3812 wcs[0] = (wchar_t) NULL;
3815 /* The last argument isn't a mistake. The X locale code trims
3816 * the input string to the length of the output string!
3818 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3821 else if (wcs[0] == (wchar_t) NULL)
3824 len = _Xwctomb (mbs, wcs[0]);
3833 #endif /* X_LOCALE */
3835 /* Sends a ClientMessage to all toplevel client windows */
3837 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
3841 g_return_val_if_fail(event != NULL, FALSE);
3843 /* Set up our event to send, with the exception of its target window */
3844 sev.xclient.type = ClientMessage;
3845 sev.xclient.display = gdk_display;
3846 sev.xclient.format = event->client.data_format;
3847 sev.xclient.window = xid;
3848 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3849 sev.xclient.message_type = event->client.message_type;
3851 return gdk_send_xevent (xid, False, NoEventMask, &sev);
3854 /* Sends a ClientMessage to all toplevel client windows */
3856 gdk_event_send_client_message_to_all_recurse (XEvent *xev,
3860 static GdkAtom wm_state_atom = GDK_NONE;
3864 unsigned long nitems, after;
3865 unsigned char *data;
3867 Window *ret_children, ret_root, ret_parent;
3868 unsigned int ret_nchildren;
3871 gboolean send = FALSE;
3872 gboolean found = FALSE;
3875 wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
3878 XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
3879 &type, &format, &nitems, &after, &data);
3894 /* OK, we're all set, now let's find some windows to send this to */
3895 if (XQueryTree(gdk_display, xid, &ret_root, &ret_parent,
3896 &ret_children, &ret_nchildren) != True)
3902 for(i = 0; i < ret_nchildren; i++)
3903 if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], level + 1))
3906 XFree(ret_children);
3909 if (send || (!found && (level == 1)))
3911 xev->xclient.window = xid;
3912 gdk_send_xevent (xid, False, NoEventMask, xev);
3915 return (send || found);
3919 gdk_event_send_clientmessage_toall (GdkEvent *event)
3922 gint old_warnings = gdk_error_warnings;
3924 g_return_if_fail(event != NULL);
3926 /* Set up our event to send, with the exception of its target window */
3927 sev.xclient.type = ClientMessage;
3928 sev.xclient.display = gdk_display;
3929 sev.xclient.format = event->client.data_format;
3930 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3931 sev.xclient.message_type = event->client.message_type;
3933 gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
3935 gdk_error_warnings = old_warnings;
3939 gdk_get_display(void)
3941 return (gchar *)XDisplayName (gdk_display_name);
3945 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
3949 gint old_warnings = gdk_error_warnings;
3953 gdk_error_warnings = 0;
3954 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
3955 XSync (gdk_display, False);
3956 gdk_error_warnings = old_warnings;
3958 return result && (gdk_error_code != -1);
3961 #ifndef HAVE_XCONVERTCASE
3962 /* compatibility function from X11R6.3, since XConvertCase is not
3963 * supplied by X11R5.
3966 gdkx_XConvertCase (KeySym symbol,
3970 register KeySym sym = symbol;
3972 g_return_if_fail (lower != NULL);
3973 g_return_if_fail (upper != NULL);
3980 #if defined (GDK_A) && defined (GDK_Ooblique)
3981 case 0: /* Latin 1 */
3982 if ((sym >= GDK_A) && (sym <= GDK_Z))
3983 *lower += (GDK_a - GDK_A);
3984 else if ((sym >= GDK_a) && (sym <= GDK_z))
3985 *upper -= (GDK_a - GDK_A);
3986 else if ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis))
3987 *lower += (GDK_agrave - GDK_Agrave);
3988 else if ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis))
3989 *upper -= (GDK_agrave - GDK_Agrave);
3990 else if ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn))
3991 *lower += (GDK_oslash - GDK_Ooblique);
3992 else if ((sym >= GDK_oslash) && (sym <= GDK_thorn))
3993 *upper -= (GDK_oslash - GDK_Ooblique);
3997 #if defined (GDK_Aogonek) && defined (GDK_tcedilla)
3998 case 1: /* Latin 2 */
3999 /* Assume the KeySym is a legal value (ignore discontinuities) */
4000 if (sym == GDK_Aogonek)
4001 *lower = GDK_aogonek;
4002 else if (sym >= GDK_Lstroke && sym <= GDK_Sacute)
4003 *lower += (GDK_lstroke - GDK_Lstroke);
4004 else if (sym >= GDK_Scaron && sym <= GDK_Zacute)
4005 *lower += (GDK_scaron - GDK_Scaron);
4006 else if (sym >= GDK_Zcaron && sym <= GDK_Zabovedot)
4007 *lower += (GDK_zcaron - GDK_Zcaron);
4008 else if (sym == GDK_aogonek)
4009 *upper = GDK_Aogonek;
4010 else if (sym >= GDK_lstroke && sym <= GDK_sacute)
4011 *upper -= (GDK_lstroke - GDK_Lstroke);
4012 else if (sym >= GDK_scaron && sym <= GDK_zacute)
4013 *upper -= (GDK_scaron - GDK_Scaron);
4014 else if (sym >= GDK_zcaron && sym <= GDK_zabovedot)
4015 *upper -= (GDK_zcaron - GDK_Zcaron);
4016 else if (sym >= GDK_Racute && sym <= GDK_Tcedilla)
4017 *lower += (GDK_racute - GDK_Racute);
4018 else if (sym >= GDK_racute && sym <= GDK_tcedilla)
4019 *upper -= (GDK_racute - GDK_Racute);
4023 #if defined (GDK_Hstroke) && defined (GDK_Cabovedot)
4024 case 2: /* Latin 3 */
4025 /* Assume the KeySym is a legal value (ignore discontinuities) */
4026 if (sym >= GDK_Hstroke && sym <= GDK_Hcircumflex)
4027 *lower += (GDK_hstroke - GDK_Hstroke);
4028 else if (sym >= GDK_Gbreve && sym <= GDK_Jcircumflex)
4029 *lower += (GDK_gbreve - GDK_Gbreve);
4030 else if (sym >= GDK_hstroke && sym <= GDK_hcircumflex)
4031 *upper -= (GDK_hstroke - GDK_Hstroke);
4032 else if (sym >= GDK_gbreve && sym <= GDK_jcircumflex)
4033 *upper -= (GDK_gbreve - GDK_Gbreve);
4034 else if (sym >= GDK_Cabovedot && sym <= GDK_Scircumflex)
4035 *lower += (GDK_cabovedot - GDK_Cabovedot);
4036 else if (sym >= GDK_cabovedot && sym <= GDK_scircumflex)
4037 *upper -= (GDK_cabovedot - GDK_Cabovedot);
4041 #if defined (GDK_Rcedilla) && defined (GDK_Amacron)
4042 case 3: /* Latin 4 */
4043 /* Assume the KeySym is a legal value (ignore discontinuities) */
4044 if (sym >= GDK_Rcedilla && sym <= GDK_Tslash)
4045 *lower += (GDK_rcedilla - GDK_Rcedilla);
4046 else if (sym >= GDK_rcedilla && sym <= GDK_tslash)
4047 *upper -= (GDK_rcedilla - GDK_Rcedilla);
4048 else if (sym == GDK_ENG)
4050 else if (sym == GDK_eng)
4052 else if (sym >= GDK_Amacron && sym <= GDK_Umacron)
4053 *lower += (GDK_amacron - GDK_Amacron);
4054 else if (sym >= GDK_amacron && sym <= GDK_umacron)
4055 *upper -= (GDK_amacron - GDK_Amacron);
4059 #if defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
4060 case 6: /* Cyrillic */
4061 /* Assume the KeySym is a legal value (ignore discontinuities) */
4062 if (sym >= GDK_Serbian_DJE && sym <= GDK_Serbian_DZE)
4063 *lower -= (GDK_Serbian_DJE - GDK_Serbian_dje);
4064 else if (sym >= GDK_Serbian_dje && sym <= GDK_Serbian_dze)
4065 *upper += (GDK_Serbian_DJE - GDK_Serbian_dje);
4066 else if (sym >= GDK_Cyrillic_YU && sym <= GDK_Cyrillic_HARDSIGN)
4067 *lower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
4068 else if (sym >= GDK_Cyrillic_yu && sym <= GDK_Cyrillic_hardsign)
4069 *upper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
4071 #endif /* CYRILLIC */
4073 #if defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
4075 /* Assume the KeySym is a legal value (ignore discontinuities) */
4076 if (sym >= GDK_Greek_ALPHAaccent && sym <= GDK_Greek_OMEGAaccent)
4077 *lower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
4078 else if (sym >= GDK_Greek_alphaaccent && sym <= GDK_Greek_omegaaccent &&
4079 sym != GDK_Greek_iotaaccentdieresis &&
4080 sym != GDK_Greek_upsilonaccentdieresis)
4081 *upper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
4082 else if (sym >= GDK_Greek_ALPHA && sym <= GDK_Greek_OMEGA)
4083 *lower += (GDK_Greek_alpha - GDK_Greek_ALPHA);
4084 else if (sym >= GDK_Greek_alpha && sym <= GDK_Greek_omega &&
4085 sym != GDK_Greek_finalsmallsigma)
4086 *upper -= (GDK_Greek_alpha - GDK_Greek_ALPHA);
4094 gdk_keyval_name (guint keyval)
4096 return XKeysymToString (keyval);
4100 gdk_keyval_from_name (const gchar *keyval_name)
4102 g_return_val_if_fail (keyval_name != NULL, 0);
4104 return XStringToKeysym (keyval_name);
4108 gdk_keyval_to_upper (guint keyval)
4112 KeySym lower_val = 0;
4113 KeySym upper_val = 0;
4115 XConvertCase (keyval, &lower_val, &upper_val);
4122 gdk_keyval_to_lower (guint keyval)
4126 KeySym lower_val = 0;
4127 KeySym upper_val = 0;
4129 XConvertCase (keyval, &lower_val, &upper_val);
4136 gdk_keyval_is_upper (guint keyval)
4140 KeySym lower_val = 0;
4141 KeySym upper_val = 0;
4143 XConvertCase (keyval, &lower_val, &upper_val);
4144 return upper_val == keyval;
4150 gdk_keyval_is_lower (guint keyval)
4154 KeySym lower_val = 0;
4155 KeySym upper_val = 0;
4157 XConvertCase (keyval, &lower_val, &upper_val);
4158 return lower_val == keyval;