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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "../config.h"
20 /* #define DEBUG_DND 1 */ /* Shouldn't be needed much these days */
22 /* If you don't want to use gdk's signal handlers define this */
23 /* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */
25 #include <X11/Xlocale.h>
36 #ifdef HAVE_SYS_SELECT_H
37 #include <sys/select.h>
38 #endif /* HAVE_SYS_SELECT_H_ */
40 #define XLIB_ILLEGAL_ACCESS
41 #include <X11/Xatom.h>
44 #include <X11/Xutil.h>
45 #include <X11/Xmu/WinUtil.h>
47 #include <X11/Xresource.h>
49 #include <X11/cursorfont.h>
51 #include "gdkprivate.h"
55 #include "gdkkeysyms.h"
59 #ifndef X_GETTIMEOFDAY
60 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
61 #endif /* X_GETTIMEOFDAY */
64 #define DOUBLE_CLICK_TIME 250
65 #define TRIPLE_CLICK_TIME 500
66 #define DOUBLE_CLICK_DIST 5
67 #define TRIPLE_CLICK_DIST 5
71 # define SELECT_MASK fd_set
77 # define SELECT_MASK void
79 # define SELECT_MASK int
84 typedef struct _GdkInput GdkInput;
85 typedef struct _GdkPredicate GdkPredicate;
91 GdkInputCondition condition;
92 GdkInputFunction function;
94 GdkDestroyNotify destroy;
104 * Private function declarations
107 static GdkEvent *gdk_event_new (void);
108 static gint gdk_event_wait (void);
109 static gint gdk_event_apply_filters (XEvent *xevent,
112 static gint gdk_event_translate (GdkEvent *event,
115 static Bool gdk_event_get_type (Display *display,
119 static void gdk_synthesize_click (GdkEvent *event,
122 static void gdk_dnd_drag_begin (GdkWindow *initial_window);
123 static void gdk_dnd_drag_enter (Window dest);
124 static void gdk_dnd_drag_leave (Window dest);
125 static void gdk_dnd_drag_end (Window dest,
127 static GdkAtom gdk_dnd_check_types (GdkWindow *window,
130 static void gdk_print_atom (GdkAtom anatom);
134 * old junk from offix, we might use it though so leave it
136 Window gdk_get_client_window (Display *dpy,
138 #ifdef WE_HAVE_MOTIF_DROPS_DONE
139 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
143 static void gdk_exit_func (void);
144 static int gdk_x_error (Display *display,
146 static int gdk_x_io_error (Display *display);
147 static RETSIGTYPE gdk_signal (int signum);
151 static GdkIM gdk_im_get (void);
152 static gint gdk_im_open (XrmDatabase db,
155 static void gdk_im_close (void);
156 static void gdk_ic_cleanup (void);
159 /* Private variable declarations
161 static int initialized = 0; /* 1 if the library is initialized,
164 static int connection_number = 0; /* The file descriptor number of our
165 * connection to the X server. This
166 * is used so that we may determine
167 * when events are pending by using
168 * the "select" system call.
172 static struct timeval start; /* The time at which the library was
175 static struct timeval timer; /* Timeout interval to use in the call
176 * to "select". This is used in
177 * conjunction with "timerp" to create
178 * a maximum time to wait for an event
181 static struct timeval *timerp; /* The actual timer passed to "select"
182 * This may be NULL, in which case
183 * "select" will block until an event
186 static guint32 timer_val; /* The timeout length as specified by
187 * the user in milliseconds.
189 static GList *inputs; /* A list of the input file descriptors
190 * that we care about. Each list node
191 * contains a GdkInput struct that describes
192 * when we are interested in the specified
193 * file descriptor. That is, when it is
194 * available for read, write or has an
197 static guint32 button_click_time[2]; /* The last 2 button click times. Used
198 * to determine if the latest button click
199 * is part of a double or triple click.
201 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
202 * Also used to determine if the latest button
203 * click is part of a double or triple click.
205 static guint button_number[2]; /* The last 2 buttons to be pressed.
207 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
212 static gint xim_using; /* using XIM Protocol if TRUE */
213 static GdkIM xim_im; /* global IM */
214 static XIMStyles* xim_styles; /* im supports these styles */
215 static XIMStyle xim_best_allowed_style;
216 static GdkICPrivate *xim_ic; /* currently using IC */
217 static GdkWindow* xim_window; /* currently using Widow */
218 static GList* xim_ic_list;
222 #define OTHER_XEVENT_BUFSIZE 4
223 static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
224 static int other_xevent_i = 0;
225 static GList *putback_events = NULL;
227 static gulong base_id;
228 static gint autorepeat;
232 *--------------------------------------------------------------
235 * Initialize the library for use.
238 * "argc" is the number of arguments.
239 * "argv" is an array of strings.
242 * "argc" and "argv" are modified to reflect any arguments
243 * which were not handled. (Such arguments should either
244 * be handled by the application or dismissed).
247 * The library is initialized.
249 *--------------------------------------------------------------
256 XKeyboardState keyboard_state;
259 XClassHint *class_hint;
260 int argc_orig = *argc;
263 argv_orig = malloc ((argc_orig + 1) * sizeof (char*));
264 for (i = 0; i < argc_orig; i++)
265 argv_orig[i] = g_strdup ((*argv)[i]);
266 argv_orig[argc_orig] = NULL;
268 X_GETTIMEOFDAY (&start);
270 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
271 signal (SIGHUP, gdk_signal);
272 signal (SIGINT, gdk_signal);
273 signal (SIGQUIT, gdk_signal);
274 signal (SIGBUS, gdk_signal);
275 signal (SIGSEGV, gdk_signal);
276 signal (SIGPIPE, gdk_signal);
277 signal (SIGTERM, gdk_signal);
280 gdk_display_name = NULL;
282 XSetErrorHandler (gdk_x_error);
283 XSetIOErrorHandler (gdk_x_io_error);
290 gdk_progname = (*argv)[0];
292 for (i = 1; i < *argc;)
294 if (strcmp ("--display", (*argv)[i]) == 0)
300 gdk_display_name = g_strdup ((*argv)[i + 1]);
301 (*argv)[i + 1] = NULL;
305 else if (strcmp ("--sync", (*argv)[i]) == 0)
310 else if (strcmp ("--show-events", (*argv)[i]) == 0)
313 gdk_show_events = TRUE;
315 else if (strcmp ("--no-show-events", (*argv)[i]) == 0)
318 gdk_show_events = FALSE;
320 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
323 gdk_use_xshm = FALSE;
325 else if (strcmp ("--debug-level", (*argv)[i]) == 0)
330 gdk_debug_level = atoi ((*argv)[i]);
334 else if (strcmp ("--name", (*argv)[i]) == 0)
339 gdk_progname = (*argv)[i];
343 else if (strcmp ("--class", (*argv)[i]) == 0)
348 gdk_progclass = (*argv)[i];
353 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
358 gdk_input_gxid_host = ((*argv)[i]);
362 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
367 gdk_input_gxid_port = atoi ((*argv)[i]);
373 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
378 if (strcmp ("none", (*argv)[i]) == 0)
379 gdk_im_set_best_style (GdkIMPreeditNone);
380 else if (strcmp ("nothing", (*argv)[i]) == 0)
381 gdk_im_set_best_style (GdkIMPreeditNothing);
382 else if (strcmp ("area", (*argv)[i]) == 0)
383 gdk_im_set_best_style (GdkIMPreeditArea);
384 else if (strcmp ("position", (*argv)[i]) == 0)
385 gdk_im_set_best_style (GdkIMPreeditPosition);
386 else if (strcmp ("callbacks", (*argv)[i]) == 0)
387 gdk_im_set_best_style (GdkIMPreeditCallbacks);
390 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
395 if (strcmp ("none", (*argv)[i]) == 0)
396 gdk_im_set_best_style (GdkIMStatusNone);
397 else if (strcmp ("nothing", (*argv)[i]) == 0)
398 gdk_im_set_best_style (GdkIMStatusNothing);
399 else if (strcmp ("area", (*argv)[i]) == 0)
400 gdk_im_set_best_style (GdkIMStatusArea);
401 else if (strcmp ("callbacks", (*argv)[i]) == 0)
402 gdk_im_set_best_style (GdkIMStatusCallbacks);
410 for (i = 1; i < *argc; i++)
412 for (k = i; k < *argc; k++)
413 if ((*argv)[k] != NULL)
419 for (j = i + k; j < *argc; j++)
420 (*argv)[j-k] = (*argv)[j];
427 gdk_progname = "<unknown>";
430 gdk_display = XOpenDisplay (gdk_display_name);
433 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
437 /* This is really crappy. We have to look into the display structure
438 * to find the base resource id. This is only needed for recording
439 * and playback of events.
441 /* base_id = RESOURCE_BASE; */
444 g_print ("base id: %lu\n", base_id);
446 connection_number = ConnectionNumber (gdk_display);
447 if (gdk_debug_level >= 1)
448 g_print ("connection number: %d\n", connection_number);
451 XSynchronize (gdk_display, True);
453 gdk_screen = DefaultScreen (gdk_display);
454 gdk_root_window = RootWindow (gdk_display, gdk_screen);
456 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
457 10, 10, 10, 10, 0, 0 , 0);
458 class_hint = XAllocClassHint();
459 class_hint->res_name = gdk_progname;
460 if (gdk_progclass == NULL)
462 gdk_progclass = g_strdup (gdk_progname);
463 gdk_progclass[0] = toupper (gdk_progclass[0]);
465 class_hint->res_class = gdk_progclass;
466 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
467 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
470 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
471 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
472 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
473 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
474 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
475 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
477 gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
478 gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
479 gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
480 gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
481 gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
482 gdk_dnd.gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
483 gdk_dnd.gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
485 XGetKeyboardControl (gdk_display, &keyboard_state);
486 autorepeat = keyboard_state.global_auto_repeat;
492 button_click_time[0] = 0;
493 button_click_time[1] = 0;
494 button_window[0] = NULL;
495 button_window[1] = NULL;
496 button_number[0] = -1;
497 button_number[1] = -1;
499 if (ATEXIT (gdk_exit_func))
500 g_warning ("unable to register exit function");
508 /* initialize XIM Protocol variables */
512 if (!(xim_best_allowed_style & GdkIMPreeditMask))
513 gdk_im_set_best_style (GdkIMPreeditCallbacks);
514 if (!(xim_best_allowed_style & GdkIMStatusMask))
515 gdk_im_set_best_style (GdkIMStatusCallbacks);
517 xim_window = (GdkWindow*)NULL;
519 gdk_im_open (NULL, NULL, NULL);
520 if (gdk_im_get () == NULL)
521 g_warning ("unable to open input method.");
528 *--------------------------------------------------------------
531 * Restores the library to an un-itialized state and exits
532 * the program using the "exit" system call.
535 * "errorcode" is the error value to pass to "exit".
538 * Allocated structures are freed and the program exits
543 *--------------------------------------------------------------
547 gdk_exit (int errorcode)
549 /* de-initialisation is done by the gdk_exit_funct(),
550 no need to do this here (Alex J.) */
555 *--------------------------------------------------------------
564 *--------------------------------------------------------------
570 if (!setlocale (LC_ALL,""))
571 g_print ("locale not supported by C library\n");
573 if (!XSupportsLocale ())
575 g_print ("locale not supported by Xlib, locale set to C\n");
576 setlocale (LC_ALL, "C");
579 if (!XSetLocaleModifiers (""))
581 g_print ("can not set locale modifiers\n");
584 return setlocale (LC_ALL,NULL);
588 *--------------------------------------------------------------
591 * Returns the number of events pending on the queue.
592 * These events have already been read from the server
598 * Returns the number of events on XLib's event queue.
602 *--------------------------------------------------------------
606 gdk_events_pending ()
611 result = XPending (gdk_display);
613 tmp_list = putback_events;
617 tmp_list = tmp_list->next;
624 *--------------------------------------------------------------
625 * gdk_event_get_graphics_expose
627 * Waits for a GraphicsExpose or NoExpose event
632 * For GraphicsExpose events, returns a pointer to the event
633 * converted into a GdkEvent Otherwise, returns NULL.
637 *-------------------------------------------------------------- */
640 graphics_expose_predicate (Display *display,
644 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
646 if ((xevent->xany.window == private->xwindow) &&
647 ((xevent->xany.type == GraphicsExpose) ||
648 (xevent->xany.type == NoExpose)))
655 gdk_event_get_graphics_expose (GdkWindow *window)
660 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
662 if (xevent.xany.type == GraphicsExpose)
664 event = gdk_event_new ();
666 if (gdk_event_translate (event, &xevent))
669 gdk_event_free (event);
676 *--------------------------------------------------------------
679 * Gets the next event.
684 * If an event was received that we care about, returns
685 * a pointer to that event, to be freed with gdk_event_free.
686 * Otherwise, returns NULL. This function will also return
687 * before an event is received if the timeout interval
692 *--------------------------------------------------------------
705 temp_list = putback_events;
708 temp_event = temp_list->data;
710 if ((* pred) (temp_event, data))
713 *event = *temp_event;
714 putback_events = g_list_remove_link (putback_events, temp_list);
715 g_list_free (temp_list);
719 temp_list = temp_list->next;
722 event_pred.func = pred;
723 event_pred.data = data;
725 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
727 return gdk_event_translate (event, &xevent);
733 event = putback_events->data;
735 temp_list = putback_events;
736 putback_events = g_list_remove_link (putback_events, temp_list);
737 g_list_free_1 (temp_list);
742 /* Wait for an event to occur or the timeout to elapse.
743 * If an event occurs "gdk_event_wait" will return TRUE.
744 * If the timeout elapses "gdk_event_wait" will return
747 if (gdk_event_wait ())
749 /* If we get here we can rest assurred that an event
750 * has occurred. Read it.
754 if (xim_using && xim_window)
756 { /* don't dispatch events used by IM */
757 XNextEvent (gdk_display, &xevent);
758 filter_status = XFilterEvent (&xevent,
759 GDK_WINDOW_XWINDOW (xim_window));
760 } while (filter_status == True);
762 XNextEvent (gdk_display, &xevent);
764 XNextEvent (gdk_display, &xevent);
766 event = gdk_event_new ();
768 event->any.type = GDK_NOTHING;
769 event->any.window = NULL;
770 event->any.send_event = FALSE;
771 event->any.send_event = xevent.xany.send_event;
773 if (gdk_event_translate (event, &xevent))
776 gdk_event_free (event);
783 gdk_event_put (GdkEvent *event)
787 g_return_if_fail (event != NULL);
789 new_event = gdk_event_copy (event);
791 putback_events = g_list_prepend (putback_events, new_event);
795 *--------------------------------------------------------------
798 * Copy a event structure into new storage.
801 * "event" is the event struct to copy.
804 * A new event structure. Free it with gdk_event_free.
807 * The reference count of the window in the event is increased.
809 *--------------------------------------------------------------
812 static GMemChunk *event_chunk;
819 if (event_chunk == NULL)
820 event_chunk = g_mem_chunk_new ("events",
825 new_event = g_chunk_new (GdkEvent, event_chunk);
831 gdk_event_copy (GdkEvent *event)
835 g_return_val_if_fail (event != NULL, NULL);
837 new_event = gdk_event_new ();
840 gdk_window_ref (new_event->any.window);
842 switch (event->any.type)
845 case GDK_KEY_RELEASE:
846 new_event->key.string = g_strdup (event->key.string);
849 case GDK_ENTER_NOTIFY:
850 case GDK_LEAVE_NOTIFY:
851 if (event->crossing.subwindow != NULL)
852 gdk_window_ref (event->crossing.subwindow);
855 case GDK_DROP_DATA_AVAIL:
856 new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
857 new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
858 memcpy (new_event->dropdataavailable.data,
859 event->dropdataavailable.data,
860 event->dropdataavailable.data_numbytes);
871 *--------------------------------------------------------------
874 * Free a event structure obtained from gdk_event_copy. Do not use
875 * with other event structures.
878 * "event" is the event struct to free.
883 * The reference count of the window in the event is decreased and
884 * might be freed, too.
886 *-------------------------------------------------------------- */
889 gdk_event_free (GdkEvent *event)
891 g_assert (event_chunk != NULL);
892 g_return_if_fail (event != NULL);
894 if (event->any.window)
895 gdk_window_unref (event->any.window);
897 switch (event->any.type)
900 case GDK_KEY_RELEASE:
901 g_free (event->key.string);
904 case GDK_ENTER_NOTIFY:
905 case GDK_LEAVE_NOTIFY:
906 if (event->crossing.subwindow != NULL)
907 gdk_window_unref (event->crossing.subwindow);
910 case GDK_DROP_DATA_AVAIL:
911 g_free (event->dropdataavailable.data_type);
912 g_free (event->dropdataavailable.data);
919 g_mem_chunk_free (event_chunk, event);
923 *--------------------------------------------------------------
924 * gdk_set_debug_level
926 * Sets the debugging level.
929 * "level" is the new debugging level.
934 * Other function calls to "gdk" use the debugging
935 * level to determine what kind of debugging information
938 *--------------------------------------------------------------
942 gdk_set_debug_level (int level)
944 gdk_debug_level = level;
948 *--------------------------------------------------------------
949 * gdk_set_show_events
951 * Turns on/off the showing of events.
954 * "show_events" is a boolean describing whether or
955 * not to show the events gdk receives.
960 * When "show_events" is TRUE, calls to "gdk_event_get"
961 * will output debugging informatin regarding the event
962 * received to stdout.
964 *--------------------------------------------------------------
968 gdk_set_show_events (int show_events)
970 gdk_show_events = show_events;
974 gdk_set_use_xshm (gint use_xshm)
976 gdk_use_xshm = use_xshm;
980 gdk_get_debug_level ()
982 return gdk_debug_level;
986 gdk_get_show_events ()
988 return gdk_show_events;
998 *--------------------------------------------------------------
1001 * Get the number of milliseconds since the library was
1007 * The time since the library was initialized is returned.
1008 * This time value is accurate to milliseconds even though
1009 * a more accurate time down to the microsecond could be
1014 *--------------------------------------------------------------
1021 struct timeval elapsed;
1022 guint32 milliseconds;
1024 X_GETTIMEOFDAY (&end);
1026 if (start.tv_usec > end.tv_usec)
1028 end.tv_usec += 1000000;
1031 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1032 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1034 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1036 return milliseconds;
1040 *--------------------------------------------------------------
1043 * Returns the current timer.
1048 * Returns the current timer interval. This interval is
1049 * in units of milliseconds.
1053 *--------------------------------------------------------------
1063 *--------------------------------------------------------------
1066 * Sets the timer interval.
1069 * "milliseconds" is the new value for the timer.
1074 * Calls to "gdk_event_get" will last for a maximum
1075 * of time of "milliseconds". However, a value of 0
1076 * milliseconds will cause "gdk_event_get" to block
1077 * indefinately until an event is received.
1079 *--------------------------------------------------------------
1083 gdk_timer_set (guint32 milliseconds)
1085 timer_val = milliseconds;
1086 timer.tv_sec = milliseconds / 1000;
1087 timer.tv_usec = (milliseconds % 1000) * 1000;
1098 gdk_timer_disable ()
1104 gdk_input_add_interp (gint source,
1105 GdkInputCondition condition,
1106 GdkInputFunction function,
1108 GdkDestroyNotify destroy)
1110 static gint next_tag = 1;
1123 if ((input->source == source) && (input->condition == condition))
1126 (input->destroy) (input->data);
1127 input->function = function;
1129 input->destroy = destroy;
1136 input = g_new (GdkInput, 1);
1137 input->tag = next_tag++;
1138 input->source = source;
1139 input->condition = condition;
1140 input->function = function;
1142 input->destroy = destroy;
1145 inputs = g_list_prepend (inputs, input);
1152 gdk_input_add (gint source,
1153 GdkInputCondition condition,
1154 GdkInputFunction function,
1157 return gdk_input_add_interp (source, condition, function, data, NULL);
1161 gdk_input_remove (gint tag)
1172 if (input->tag == tag)
1175 (input->destroy) (input->data);
1180 list->next->prev = list->prev;
1182 list->prev->next = list->next;
1184 inputs = list->next;
1186 temp_list->next = NULL;
1187 temp_list->prev = NULL;
1189 g_free (temp_list->data);
1190 g_list_free (temp_list);
1199 *--------------------------------------------------------------
1202 * Grabs the pointer to a specific window
1205 * "window" is the window which will receive the grab
1206 * "owner_events" specifies whether events will be reported as is,
1207 * or relative to "window"
1208 * "event_mask" masks only interesting events
1209 * "confine_to" limits the cursor movement to the specified window
1210 * "cursor" changes the cursor for the duration of the grab
1211 * "time" specifies the time
1216 * requires a corresponding call to gdk_pointer_ungrab
1218 *--------------------------------------------------------------
1222 gdk_pointer_grab (GdkWindow * window,
1224 GdkEventMask event_mask,
1225 GdkWindow * confine_to,
1229 /* From gdkwindow.c */
1230 extern int nevent_masks;
1231 extern int event_mask_table[];
1234 GdkWindowPrivate *window_private;
1235 GdkWindowPrivate *confine_to_private;
1236 GdkCursorPrivate *cursor_private;
1243 g_return_val_if_fail (window != NULL, 0);
1245 window_private = (GdkWindowPrivate*) window;
1246 confine_to_private = (GdkWindowPrivate*) confine_to;
1247 cursor_private = (GdkCursorPrivate*) cursor;
1249 xwindow = window_private->xwindow;
1251 if (!confine_to || confine_to_private->destroyed)
1254 xconfine_to = confine_to_private->xwindow;
1259 xcursor = cursor_private->xcursor;
1263 for (i = 0; i < nevent_masks; i++)
1265 if (event_mask & (1 << (i + 1)))
1266 xevent_mask |= event_mask_table[i];
1269 if (((GdkWindowPrivate *)window)->extension_events &&
1270 gdk_input_vtable.grab_pointer)
1271 return_val = gdk_input_vtable.grab_pointer (window,
1277 return_val = Success;;
1279 if (return_val == Success)
1280 if (!window_private->destroyed)
1281 return_val = XGrabPointer (window_private->xdisplay,
1285 GrabModeAsync, GrabModeAsync,
1290 return_val = AlreadyGrabbed;
1292 if (return_val == GrabSuccess)
1293 xgrab_window = window_private;
1299 *--------------------------------------------------------------
1300 * gdk_pointer_ungrab
1302 * Releases any pointer grab
1310 *--------------------------------------------------------------
1314 gdk_pointer_ungrab (guint32 time)
1316 if (gdk_input_vtable.ungrab_pointer)
1317 gdk_input_vtable.ungrab_pointer (time);
1319 XUngrabPointer (gdk_display, time);
1320 xgrab_window = NULL;
1324 *--------------------------------------------------------------
1325 * gdk_pointer_is_grabbed
1327 * Tell wether there is an active x pointer grab in effect
1335 *--------------------------------------------------------------
1339 gdk_pointer_is_grabbed (void)
1341 return xgrab_window != NULL;
1345 *--------------------------------------------------------------
1348 * Grabs the keyboard to a specific window
1351 * "window" is the window which will receive the grab
1352 * "owner_events" specifies whether events will be reported as is,
1353 * or relative to "window"
1354 * "time" specifies the time
1359 * requires a corresponding call to gdk_keyboard_ungrab
1361 *--------------------------------------------------------------
1365 gdk_keyboard_grab (GdkWindow * window,
1369 GdkWindowPrivate *window_private;
1372 g_return_val_if_fail (window != NULL, 0);
1374 window_private = (GdkWindowPrivate*) window;
1375 xwindow = window_private->xwindow;
1377 if (!window_private->destroyed)
1378 return XGrabKeyboard (window_private->xdisplay,
1381 GrabModeAsync, GrabModeAsync,
1384 return AlreadyGrabbed;
1388 *--------------------------------------------------------------
1389 * gdk_keyboard_ungrab
1391 * Releases any keyboard grab
1399 *--------------------------------------------------------------
1403 gdk_keyboard_ungrab (guint32 time)
1405 XUngrabKeyboard (gdk_display, time);
1409 *--------------------------------------------------------------
1412 * Return the width of the screen.
1420 *--------------------------------------------------------------
1428 return_val = DisplayWidth (gdk_display, gdk_screen);
1434 *--------------------------------------------------------------
1437 * Return the height of the screen.
1445 *--------------------------------------------------------------
1449 gdk_screen_height ()
1453 return_val = DisplayHeight (gdk_display, gdk_screen);
1459 gdk_key_repeat_disable ()
1461 XAutoRepeatOff (gdk_display);
1465 gdk_key_repeat_restore ()
1468 XAutoRepeatOn (gdk_display);
1470 XAutoRepeatOff (gdk_display);
1475 *--------------------------------------------------------------
1478 * Flushes the Xlib output buffer and then waits
1479 * until all requests have been received and processed
1480 * by the X server. The only real use for this function
1481 * is in dealing with XShm.
1489 *--------------------------------------------------------------
1494 XSync (gdk_display, False);
1501 XBell(gdk_display, 100);
1506 *--------------------------------------------------------------
1509 * Waits until an event occurs or the timer runs out.
1514 * Returns TRUE if an event is ready to be read and FALSE
1515 * if the timer ran out.
1519 *--------------------------------------------------------------
1527 GdkInputCondition condition;
1528 SELECT_MASK readfds;
1529 SELECT_MASK writefds;
1530 SELECT_MASK exceptfds;
1534 /* If there are no events pending we will wait for an event.
1535 * The time we wait is dependant on the "timer". If no timer
1536 * has been specified then we'll block until an event arrives.
1537 * If a timer has been specified we'll block until an event
1538 * arrives or the timer expires. (This is all done using the
1539 * "select" system call).
1542 if (XPending (gdk_display) == 0)
1545 FD_ZERO (&writefds);
1546 FD_ZERO (&exceptfds);
1548 FD_SET (connection_number, &readfds);
1549 max_input = connection_number;
1557 if (input->condition & GDK_INPUT_READ)
1558 FD_SET (input->source, &readfds);
1559 if (input->condition & GDK_INPUT_WRITE)
1560 FD_SET (input->source, &writefds);
1561 if (input->condition & GDK_INPUT_EXCEPTION)
1562 FD_SET (input->source, &exceptfds);
1564 max_input = MAX (max_input, input->source);
1567 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1574 if (FD_ISSET (connection_number, &readfds))
1576 if (XPending (gdk_display) == 0)
1580 XNoOp (gdk_display);
1581 XFlush (gdk_display);
1596 if (FD_ISSET (input->source, &readfds))
1597 condition |= GDK_INPUT_READ;
1598 if (FD_ISSET (input->source, &writefds))
1599 condition |= GDK_INPUT_WRITE;
1600 if (FD_ISSET (input->source, &exceptfds))
1601 condition |= GDK_INPUT_EXCEPTION;
1603 if (condition && input->function)
1604 (* input->function) (input->data, input->source, condition);
1615 gdk_event_apply_filters (XEvent *xevent,
1619 GdkEventFilter *filter;
1621 GdkFilterReturn result;
1627 filter = (GdkEventFilter *)tmp_list->data;
1629 result = (*filter->function)(xevent, event, filter->data);
1630 if (result != GDK_FILTER_CONTINUE)
1633 tmp_list = tmp_list->next;
1636 return GDK_FILTER_CONTINUE;
1640 gdk_event_translate (GdkEvent *event,
1645 GdkWindowPrivate *window_private;
1646 XComposeStatus compose;
1649 static gchar* buf = NULL;
1650 static gint buf_len= 0;
1656 /* Are static variables used for this purpose thread-safe? */
1657 static GdkPoint dnd_drag_start = {0,0},
1658 dnd_drag_oldpos = {0,0};
1659 static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
1660 static gint dnd_drag_perhaps = 0;
1661 static gboolean dnd_grabbed = FALSE;
1662 static GdkWindowPrivate *real_sw = NULL;
1663 static Window dnd_drag_curwin = None, dnd_drag_target = None;
1667 /* Find the GdkWindow that this event occurred in.
1668 * All events occur in some GdkWindow (otherwise, why
1669 * would we be receiving them). It really is an error
1670 * to receive an event for which we cannot find the
1671 * corresponding GdkWindow. We handle events with window=None
1672 * specially - they are generated by XFree86's XInput under
1673 * some circumstances.
1676 if ((xevent->xany.window == None) &&
1677 gdk_input_vtable.window_none_event)
1679 return_val = gdk_input_vtable.window_none_event (event,xevent);
1681 if (return_val >= 0) /* was handled */
1687 window = gdk_window_lookup (xevent->xany.window);
1688 window_private = (GdkWindowPrivate *) window;
1691 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1693 gdk_window_ref (window);
1696 /* Check for filters for this window */
1700 GdkFilterReturn result;
1701 result = gdk_event_apply_filters (xevent, event, window_private->filters);
1703 if (result != GDK_FILTER_CONTINUE)
1705 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1709 /* We do a "manual" conversion of the XEvent to a
1710 * GdkEvent. The structures are mostly the same so
1711 * the conversion is fairly straightforward. We also
1712 * optionally print debugging info regarding events
1716 * During drag & drop you get events where the pointer is
1717 * in other windows. Need to just do finer-grained checking
1719 switch (xevent->type)
1722 /* Lookup the string corresponding to the given keysym.
1728 buf = g_new (gchar, buf_len);
1730 if (xim_using == TRUE && xim_ic)
1734 /* Clear keyval. Depending on status, may not be set */
1735 event->key.keyval = GDK_VoidSymbol;
1736 charcount = XmbLookupString(xim_ic->xic,
1737 &xevent->xkey, buf, buf_len-1,
1738 (KeySym*) &event->key.keyval,
1740 if (status == XBufferOverflow)
1742 /* alloc adequate size of buffer */
1743 if (gdk_debug_level >= 1)
1744 g_print("XIM: overflow (required %i)\n", charcount);
1746 while (buf_len <= charcount)
1748 buf = (gchar *) g_realloc (buf, buf_len);
1750 charcount = XmbLookupString (xim_ic->xic,
1751 &xevent->xkey, buf, buf_len-1,
1752 (KeySym*) &event->key.keyval,
1755 if (status == XLookupNone)
1762 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1763 (KeySym*) &event->key.keyval,
1766 charcount = XLookupString (&xevent->xkey, buf, 16,
1767 (KeySym*) &event->key.keyval,
1770 if (charcount > 0 && buf[charcount-1] == '\0')
1773 buf[charcount] = '\0';
1775 /* Print debugging info.
1777 if (gdk_show_events)
1779 g_print ("key press:\twindow: %ld key: %12s %d\n",
1780 xevent->xkey.window - base_id,
1781 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1784 g_print ("\t\tlength: %4d string: \"%s\"\n",
1788 event->key.type = GDK_KEY_PRESS;
1789 event->key.window = window;
1790 event->key.time = xevent->xkey.time;
1791 event->key.state = (GdkModifierType) xevent->xkey.state;
1792 event->key.string = g_strdup (buf);
1793 event->key.length = charcount;
1795 return_val = window_private && !window_private->destroyed;
1798 g_free (event->key.string);
1803 /* Lookup the string corresponding to the given keysym.
1805 charcount = XLookupString (&xevent->xkey, buf, 16,
1806 (KeySym*) &event->key.keyval,
1809 /* Print debugging info.
1811 if (gdk_show_events)
1812 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1813 xevent->xkey.window - base_id,
1814 XKeysymToString (event->key.keyval),
1817 event->key.type = GDK_KEY_RELEASE;
1818 event->key.window = window;
1819 event->key.time = xevent->xkey.time;
1820 event->key.state = (GdkModifierType) xevent->xkey.state;
1821 event->key.length = 0;
1822 event->key.string = NULL;
1824 return_val = window_private && !window_private->destroyed;
1828 /* Print debugging info.
1830 if (gdk_show_events)
1831 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1832 window_private?window_private->dnd_drag_enabled:0,
1833 xevent->xbutton.window - base_id,
1834 xevent->xbutton.x, xevent->xbutton.y,
1835 xevent->xbutton.button);
1837 if (window_private &&
1838 (window_private->extension_events != 0) &&
1839 gdk_input_ignore_core)
1842 event->button.type = GDK_BUTTON_PRESS;
1843 event->button.window = window;
1844 event->button.time = xevent->xbutton.time;
1845 event->button.x = xevent->xbutton.x;
1846 event->button.y = xevent->xbutton.y;
1847 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1848 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1849 event->button.pressure = 0.5;
1850 event->button.xtilt = 0;
1851 event->button.ytilt = 0;
1852 event->button.state = (GdkModifierType) xevent->xbutton.state;
1853 event->button.button = xevent->xbutton.button;
1854 event->button.source = GDK_SOURCE_MOUSE;
1855 event->button.deviceid = GDK_CORE_POINTER;
1857 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1858 (event->button.window == button_window[1]) &&
1859 (event->button.button == button_number[1]))
1861 gdk_synthesize_click (event, 3);
1863 button_click_time[1] = 0;
1864 button_click_time[0] = 0;
1865 button_window[1] = NULL;
1866 button_window[0] = 0;
1867 button_number[1] = -1;
1868 button_number[0] = -1;
1870 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1871 (event->button.window == button_window[0]) &&
1872 (event->button.button == button_number[0]))
1874 gdk_synthesize_click (event, 2);
1876 button_click_time[1] = button_click_time[0];
1877 button_click_time[0] = event->button.time;
1878 button_window[1] = button_window[0];
1879 button_window[0] = event->button.window;
1880 button_number[1] = button_number[0];
1881 button_number[0] = event->button.button;
1885 button_click_time[1] = 0;
1886 button_click_time[0] = event->button.time;
1887 button_window[1] = NULL;
1888 button_window[0] = event->button.window;
1889 button_number[1] = -1;
1890 button_number[0] = event->button.button;
1893 && window_private->dnd_drag_enabled
1894 && !dnd_drag_perhaps
1895 && !gdk_dnd.drag_really)
1897 dnd_drag_perhaps = 1;
1898 dnd_drag_start.x = xevent->xbutton.x_root;
1899 dnd_drag_start.y = xevent->xbutton.y_root;
1900 real_sw = window_private;
1902 if(gdk_dnd.drag_startwindows)
1904 g_free(gdk_dnd.drag_startwindows);
1905 gdk_dnd.drag_startwindows = NULL;
1907 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1908 dnd_grabbed = FALSE;
1911 /* Set motion mask for first DnD'd window, since it
1912 will be the one that is actually dragged */
1913 XWindowAttributes dnd_winattr;
1914 XSetWindowAttributes dnd_setwinattr;
1916 /* We need to get motion events while the button is down, so
1917 we can know whether to really start dragging or not... */
1918 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1921 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1922 dnd_setwinattr.event_mask =
1923 window_private->dnd_drag_eventmask = ButtonMotionMask | EnterWindowMask | LeaveWindowMask;
1924 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1925 CWEventMask, &dnd_setwinattr);
1928 return_val = window_private && !window_private->destroyed;
1932 /* Print debugging info.
1934 if (gdk_show_events)
1935 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
1936 window_private?window_private->dnd_drag_enabled:0,
1937 xevent->xbutton.window - base_id,
1938 xevent->xbutton.x, xevent->xbutton.y,
1939 xevent->xbutton.button);
1941 if (window_private &&
1942 (window_private->extension_events != 0) &&
1943 gdk_input_ignore_core)
1946 event->button.type = GDK_BUTTON_RELEASE;
1947 event->button.window = window;
1948 event->button.time = xevent->xbutton.time;
1949 event->button.x = xevent->xbutton.x;
1950 event->button.y = xevent->xbutton.y;
1951 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1952 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1953 event->button.pressure = 0.5;
1954 event->button.xtilt = 0;
1955 event->button.ytilt = 0;
1956 event->button.state = (GdkModifierType) xevent->xbutton.state;
1957 event->button.button = xevent->xbutton.button;
1958 event->button.source = GDK_SOURCE_MOUSE;
1959 event->button.deviceid = GDK_CORE_POINTER;
1961 if(dnd_drag_perhaps)
1964 XSetWindowAttributes attrs;
1965 /* Reset event mask to pre-drag value, assuming event_mask
1966 doesn't change during drag */
1967 attrs.event_mask = real_sw->dnd_drag_savedeventmask;
1968 XChangeWindowAttributes(gdk_display, real_sw->xwindow,
1969 CWEventMask, &attrs);
1974 XUngrabPointer(gdk_display, CurrentTime);
1975 dnd_grabbed = FALSE;
1978 if(gdk_dnd.drag_really)
1981 foo.x = xevent->xbutton.x_root;
1982 foo.y = xevent->xbutton.y_root;
1984 if(dnd_drag_target != None)
1985 gdk_dnd_drag_end(dnd_drag_target, foo);
1986 gdk_dnd.drag_really = 0;
1988 gdk_dnd.drag_numwindows = 0;
1989 if(gdk_dnd.drag_startwindows)
1991 g_free(gdk_dnd.drag_startwindows);
1992 gdk_dnd.drag_startwindows = NULL;
1998 dnd_drag_perhaps = 0;
1999 dnd_drag_start.x = dnd_drag_start.y = 0;
2000 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2001 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2002 dnd_drag_curwin = None;
2003 return_val = window_private?TRUE:FALSE;
2005 return_val = window_private && !window_private->destroyed;
2009 /* Print debugging info.
2011 if (gdk_show_events)
2012 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2013 xevent->xmotion.window - base_id,
2014 xevent->xmotion.x, xevent->xmotion.y,
2015 (xevent->xmotion.is_hint) ? "true" : "false",
2016 dnd_drag_perhaps, gdk_dnd.drag_really);
2018 if (window_private &&
2019 (window_private->extension_events != 0) &&
2020 gdk_input_ignore_core)
2023 event->motion.type = GDK_MOTION_NOTIFY;
2024 event->motion.window = window;
2025 event->motion.time = xevent->xmotion.time;
2026 event->motion.x = xevent->xmotion.x;
2027 event->motion.y = xevent->xmotion.y;
2028 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2029 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2030 event->motion.pressure = 0.5;
2031 event->motion.xtilt = 0;
2032 event->motion.ytilt = 0;
2033 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2034 event->motion.is_hint = xevent->xmotion.is_hint;
2035 event->motion.source = GDK_SOURCE_MOUSE;
2036 event->motion.deviceid = GDK_CORE_POINTER;
2038 #define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
2039 && cy >= dnd_drag_dropzone.y \
2040 && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
2041 && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
2043 if(dnd_drag_perhaps && gdk_dnd.drag_really)
2045 /* First, we have to find what window the motion was in... */
2046 /* XXX there has to be a better way to do this, perhaps with
2047 XTranslateCoordinates or XQueryTree - I don't know how,
2048 and this sort of works */
2049 static Window lastwin = None, curwin = None, twin;
2050 Window childwin = gdk_root_window;
2053 curwin = gdk_root_window;
2054 ox = x = xevent->xmotion.x_root;
2055 oy = y = xevent->xmotion.y_root;
2056 while(childwin != None)
2060 XTranslateCoordinates(gdk_display, curwin, curwin,
2061 x, y, &x, &y, &childwin);
2062 if(childwin != None)
2064 XTranslateCoordinates(gdk_display, curwin, childwin,
2065 x, y, &x, &y, &twin);
2069 g_print("Drag is now in window %#x, lastwin was %#x\n",
2072 if(curwin != dnd_drag_curwin && curwin != lastwin)
2074 /* We have left one window and entered another
2075 (do leave & enter bits) */
2076 if(dnd_drag_curwin != real_sw->xwindow && dnd_drag_curwin != None)
2077 gdk_dnd_drag_leave(dnd_drag_curwin);
2078 dnd_drag_curwin = curwin;
2079 gdk_dnd_drag_enter(dnd_drag_curwin);
2080 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2081 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2082 dnd_drag_target = None;
2084 g_print("curwin = %#x, lastwin = %#x, dnd_drag_curwin = %#x\n",
2085 curwin, lastwin, dnd_drag_curwin);
2087 XChangeActivePointerGrab(gdk_display,
2089 ButtonPressMask | ButtonReleaseMask,
2090 gdk_dnd.gdk_cursor_dragdefault,
2093 else if(dnd_drag_dropzone.width > 0
2094 && dnd_drag_dropzone.height > 0
2095 && curwin == dnd_drag_curwin)
2097 /* Handle all that dropzone stuff - thanks John ;-) */
2098 if (dnd_drag_target != None)
2100 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2101 xevent->xmotion.y_root);
2102 gboolean old_in_zone = IS_IN_ZONE(dnd_drag_oldpos.x,
2105 if (!in_zone && old_in_zone)
2107 /* We were in the drop zone and moved out */
2108 dnd_drag_target = None;
2109 gdk_dnd_drag_leave(curwin);
2111 else if (!in_zone && !old_in_zone)
2113 /* We were outside drop zone but in the window
2114 - have to send enter events */
2115 gdk_dnd_drag_enter(curwin);
2116 dnd_drag_curwin = curwin;
2117 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2118 dnd_drag_target = None;
2122 dnd_drag_curwin = None;
2126 return_val = window_private && !window_private->destroyed;
2130 /* Print debugging info.
2133 if (gdk_show_events)
2135 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2136 xevent->xcrossing.window - base_id,
2137 xevent->xcrossing.detail,
2138 xevent->xcrossing.subwindow - base_id);
2140 /* Tell XInput stuff about it if appropriate */
2141 if (window_private &&
2142 (window_private->extension_events != 0) &&
2143 gdk_input_vtable.enter_event)
2144 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2146 event->crossing.type = GDK_ENTER_NOTIFY;
2147 event->crossing.window = window;
2149 /* If the subwindow field of the XEvent is non-NULL, then
2150 * lookup the corresponding GdkWindow.
2152 if (xevent->xcrossing.subwindow != None)
2153 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2155 event->crossing.subwindow = NULL;
2157 /* Translate the crossing detail into Gdk terms.
2159 switch (xevent->xcrossing.detail)
2161 case NotifyInferior:
2162 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2164 case NotifyAncestor:
2165 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2168 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2170 case NotifyNonlinear:
2171 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2173 case NotifyNonlinearVirtual:
2174 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2177 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2182 if(dnd_drag_perhaps)
2184 g_print("We may[%d] have a drag into %#x = %#x\n",
2185 gdk_dnd.drag_really,
2186 xevent->xcrossing.window, real_sw->xwindow);
2189 if (dnd_drag_perhaps && gdk_dnd.drag_really &&
2190 (xevent->xcrossing.window == real_sw->xwindow))
2192 gdk_dnd.drag_really = 0;
2194 g_print("Ungrabbed\n");
2196 gdk_dnd.drag_numwindows = 0;
2197 g_free(gdk_dnd.drag_startwindows);
2198 gdk_dnd.drag_startwindows = NULL;
2199 /* We don't want to ungrab the pointer here, or we'll
2200 * start getting spurious enter/leave events */
2201 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2204 return_val = window_private && !window_private->destroyed;
2208 /* Print debugging info.
2211 if (gdk_show_events)
2213 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2214 xevent->xcrossing.window - base_id,
2215 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
2217 event->crossing.type = GDK_LEAVE_NOTIFY;
2218 event->crossing.window = window;
2220 /* If the subwindow field of the XEvent is non-NULL, then
2221 * lookup the corresponding GdkWindow.
2223 if (xevent->xcrossing.subwindow != None)
2224 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2226 event->crossing.subwindow = NULL;
2228 /* Translate the crossing detail into Gdk terms.
2230 switch (xevent->xcrossing.detail)
2232 case NotifyInferior:
2233 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2235 case NotifyAncestor:
2236 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2239 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2241 case NotifyNonlinear:
2242 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2244 case NotifyNonlinearVirtual:
2245 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2248 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2252 if(dnd_drag_perhaps)
2254 g_print("We may[%d] have a drag out of %#x = %#x\n",
2255 gdk_dnd.drag_really,
2256 xevent->xcrossing.window, real_sw->xwindow);
2259 if (dnd_drag_perhaps && !gdk_dnd.drag_really &&
2260 (xevent->xcrossing.window == real_sw->xwindow))
2262 gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
2263 gdk_dnd_drag_begin((GdkWindow *) real_sw);
2264 XGrabPointer(gdk_display, real_sw->xwindow, False,
2266 ButtonPressMask | ButtonReleaseMask,
2267 GrabModeAsync, GrabModeAsync, gdk_root_window,
2268 gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
2270 gdk_dnd.drag_really = 1;
2273 return_val = window_private && !window_private->destroyed;
2278 /* We only care about focus events that indicate that _this_
2279 * window (not a ancestor or child) got or lost the focus
2281 switch (xevent->xfocus.detail)
2283 case NotifyAncestor:
2284 case NotifyInferior:
2285 case NotifyNonlinear:
2286 /* Print debugging info.
2288 if (gdk_show_events)
2289 g_print ("focus %s:\t\twindow: %ld\n",
2290 (xevent->xany.type == FocusIn) ? "in" : "out",
2291 xevent->xfocus.window - base_id);
2293 event->focus_change.type = GDK_FOCUS_CHANGE;
2294 event->focus_change.window = window;
2295 event->focus_change.in = (xevent->xany.type == FocusIn);
2297 return_val = window_private && !window_private->destroyed;
2305 /* Print debugging info.
2307 if (gdk_show_events)
2308 g_print ("keymap notify\n");
2310 /* Not currently handled */
2314 /* Print debugging info.
2316 if (gdk_show_events)
2317 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2318 xevent->xexpose.window - base_id, xevent->xexpose.count,
2319 xevent->xexpose.x, xevent->xexpose.y,
2320 xevent->xexpose.width, xevent->xexpose.height);
2322 event->expose.type = GDK_EXPOSE;
2323 event->expose.window = window;
2324 event->expose.area.x = xevent->xexpose.x;
2325 event->expose.area.y = xevent->xexpose.y;
2326 event->expose.area.width = xevent->xexpose.width;
2327 event->expose.area.height = xevent->xexpose.height;
2328 event->expose.count = xevent->xexpose.count;
2330 return_val = window_private && !window_private->destroyed;
2333 case GraphicsExpose:
2334 /* Print debugging info.
2336 if (gdk_show_events)
2337 g_print ("graphics expose:\tdrawable: %ld\n",
2338 xevent->xgraphicsexpose.drawable - base_id);
2340 event->expose.type = GDK_EXPOSE;
2341 event->expose.window = window;
2342 event->expose.area.x = xevent->xgraphicsexpose.x;
2343 event->expose.area.y = xevent->xgraphicsexpose.y;
2344 event->expose.area.width = xevent->xgraphicsexpose.width;
2345 event->expose.area.height = xevent->xgraphicsexpose.height;
2346 event->expose.count = xevent->xexpose.count;
2348 return_val = window_private && !window_private->destroyed;
2352 /* Print debugging info.
2354 if (gdk_show_events)
2355 g_print ("no expose:\t\tdrawable: %ld\n",
2356 xevent->xnoexpose.drawable - base_id);
2358 event->no_expose.type = GDK_NO_EXPOSE;
2359 event->no_expose.window = window;
2361 return_val = window_private && !window_private->destroyed;
2364 case VisibilityNotify:
2365 /* Print debugging info.
2367 if (gdk_show_events)
2368 switch (xevent->xvisibility.state)
2370 case VisibilityFullyObscured:
2371 g_print ("visibility notify:\twindow: %ld none\n",
2372 xevent->xvisibility.window - base_id);
2374 case VisibilityPartiallyObscured:
2375 g_print ("visibility notify:\twindow: %ld partial\n",
2376 xevent->xvisibility.window - base_id);
2378 case VisibilityUnobscured:
2379 g_print ("visibility notify:\twindow: %ld full\n",
2380 xevent->xvisibility.window - base_id);
2384 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2385 event->visibility.window = window;
2387 switch (xevent->xvisibility.state)
2389 case VisibilityFullyObscured:
2390 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2393 case VisibilityPartiallyObscured:
2394 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2397 case VisibilityUnobscured:
2398 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2402 return_val = window_private && !window_private->destroyed;
2406 /* Not currently handled */
2410 /* Print debugging info.
2412 if (gdk_show_events)
2413 g_print ("destroy notify:\twindow: %ld\n",
2414 xevent->xdestroywindow.window - base_id);
2416 event->any.type = GDK_DESTROY;
2417 event->any.window = window;
2419 return_val = window_private && !window_private->destroyed;
2421 gdk_window_destroy_notify (window);
2425 /* Print debugging info.
2427 if (gdk_show_events)
2428 g_print ("unmap notify:\t\twindow: %ld\n",
2429 xevent->xmap.window - base_id);
2431 event->any.type = GDK_UNMAP;
2432 event->any.window = window;
2434 if (xgrab_window == window_private)
2435 xgrab_window = NULL;
2437 return_val = window_private && !window_private->destroyed;
2441 /* Print debugging info.
2443 if (gdk_show_events)
2444 g_print ("map notify:\t\twindow: %ld\n",
2445 xevent->xmap.window - base_id);
2447 event->any.type = GDK_MAP;
2448 event->any.window = window;
2450 return_val = window_private && !window_private->destroyed;
2453 case ReparentNotify:
2454 /* Print debugging info.
2456 if (gdk_show_events)
2457 g_print ("reparent notify:\twindow: %ld\n",
2458 xevent->xreparent.window - base_id);
2460 /* Not currently handled */
2463 case ConfigureNotify:
2464 /* Print debugging info.
2466 while ((XPending (gdk_display) > 0) &&
2467 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2468 ConfigureNotify, xevent))
2469 /*XSync (gdk_display, 0)*/;
2471 if (gdk_show_events)
2472 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2473 xevent->xconfigure.window - base_id,
2474 xevent->xconfigure.x,
2475 xevent->xconfigure.y,
2476 xevent->xconfigure.width,
2477 xevent->xconfigure.height,
2478 xevent->xconfigure.border_width,
2479 xevent->xconfigure.above - base_id,
2480 xevent->xconfigure.override_redirect);
2484 if ((window_private->extension_events != 0) &&
2485 gdk_input_vtable.configure_event)
2486 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2488 if (window_private->window_type != GDK_WINDOW_CHILD)
2490 event->configure.type = GDK_CONFIGURE;
2491 event->configure.window = window;
2492 event->configure.width = xevent->xconfigure.width;
2493 event->configure.height = xevent->xconfigure.height;
2495 if (!xevent->xconfigure.x &&
2496 !xevent->xconfigure.y)
2500 Window child_window = 0;
2502 if (!XTranslateCoordinates (window_private->xdisplay,
2503 window_private->xwindow,
2508 g_warning ("GdkWindow %ld doesn't share root windows display?",
2509 window_private->xwindow - base_id);
2510 event->configure.x = tx;
2511 event->configure.y = ty;
2515 event->configure.x = xevent->xconfigure.x;
2516 event->configure.y = xevent->xconfigure.y;
2518 window_private->x = event->configure.x;
2519 window_private->y = event->configure.y;
2520 window_private->width = xevent->xconfigure.width;
2521 window_private->height = xevent->xconfigure.height;
2522 if (window_private->resize_count > 1)
2523 window_private->resize_count -= 1;
2525 return_val = !window_private->destroyed;
2530 case PropertyNotify:
2531 /* Print debugging info.
2533 if (gdk_show_events)
2534 g_print ("property notify:\twindow: %ld\n",
2535 xevent->xproperty.window - base_id);
2537 event->property.type = GDK_PROPERTY_NOTIFY;
2538 event->property.window = window;
2539 event->property.atom = xevent->xproperty.atom;
2540 event->property.time = xevent->xproperty.time;
2541 event->property.state = xevent->xproperty.state;
2543 return_val = window_private && !window_private->destroyed;
2546 case SelectionClear:
2547 if (gdk_show_events)
2548 g_print ("selection clear:\twindow: %ld\n",
2549 xevent->xproperty.window - base_id);
2551 event->selection.type = GDK_SELECTION_CLEAR;
2552 event->selection.window = window;
2553 event->selection.selection = xevent->xselectionclear.selection;
2554 event->selection.time = xevent->xselectionclear.time;
2556 return_val = window_private && !window_private->destroyed;
2559 case SelectionRequest:
2560 if (gdk_show_events)
2561 g_print ("selection request:\twindow: %ld\n",
2562 xevent->xproperty.window - base_id);
2564 event->selection.type = GDK_SELECTION_REQUEST;
2565 event->selection.window = window;
2566 event->selection.selection = xevent->xselectionrequest.selection;
2567 event->selection.target = xevent->xselectionrequest.target;
2568 event->selection.property = xevent->xselectionrequest.property;
2569 event->selection.requestor = xevent->xselectionrequest.requestor;
2570 event->selection.time = xevent->xselectionrequest.time;
2572 return_val = window_private && !window_private->destroyed;
2575 case SelectionNotify:
2576 if (gdk_show_events)
2577 g_print ("selection notify:\twindow: %ld\n",
2578 xevent->xproperty.window - base_id);
2581 event->selection.type = GDK_SELECTION_NOTIFY;
2582 event->selection.window = window;
2583 event->selection.selection = xevent->xselection.selection;
2584 event->selection.target = xevent->xselection.target;
2585 event->selection.property = xevent->xselection.property;
2586 event->selection.time = xevent->xselection.time;
2588 return_val = window_private && !window_private->destroyed;
2591 case ColormapNotify:
2592 /* Print debugging info.
2594 if (gdk_show_events)
2595 g_print ("colormap notify:\twindow: %ld\n",
2596 xevent->xcolormap.window - base_id);
2598 /* Not currently handled */
2602 /* Print debugging info.
2604 if (gdk_show_events)
2605 g_print ("client message:\twindow: %ld\n",
2606 xevent->xclient.window - base_id);
2608 /* Client messages are the means of the window manager
2609 * communicating with a program. We'll first check to
2610 * see if this is really the window manager talking
2613 if (xevent->xclient.message_type == gdk_wm_protocols)
2615 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2617 /* The delete window request specifies a window
2618 * to delete. We don't actually destroy the
2619 * window because "it is only a request". (The
2620 * window might contain vital data that the
2621 * program does not want destroyed). Instead
2622 * the event is passed along to the program,
2623 * which should then destroy the window.
2626 /* Print debugging info.
2628 if (gdk_show_events)
2629 g_print ("delete window:\t\twindow: %ld\n",
2630 xevent->xclient.window - base_id);
2632 event->any.type = GDK_DELETE;
2633 event->any.window = window;
2635 return_val = window_private && !window_private->destroyed;
2637 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2641 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2645 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2647 if (gdk_show_events)
2649 g_print ("GDK_DROP_ENTER\n");
2652 /* Now figure out if we really want this drop...
2653 * If someone is trying funky clipboard stuff, ignore
2656 && window_private->dnd_drop_enabled
2657 && event->dropenter.u.flags.sendreply
2658 && (reptype = gdk_dnd_check_types (window, xevent)))
2662 replyev.xclient.type = ClientMessage;
2663 replyev.xclient.window = xevent->xclient.data.l[0];
2664 replyev.xclient.format = 32;
2665 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2666 replyev.xclient.data.l[0] = window_private->xwindow;
2668 event->dragrequest.u.allflags = 0;
2669 event->dragrequest.u.flags.protocol_version =
2670 DND_PROTOCOL_VERSION;
2671 event->dragrequest.u.flags.willaccept = 1;
2672 event->dragrequest.u.flags.delete_data =
2673 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2675 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2676 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2677 replyev.xclient.data.l[4] = reptype;
2679 XSendEvent (gdk_display, replyev.xclient.window,
2680 False, NoEventMask, &replyev);
2682 event->any.type = GDK_DROP_ENTER;
2683 event->dropenter.requestor = replyev.xclient.window;
2684 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2687 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2690 if (gdk_show_events)
2692 g_print ("GDK_DROP_LEAVE\n");
2693 if (window_private && window_private->dnd_drop_enabled)
2695 event->dropleave.type = GDK_DROP_LEAVE;
2696 event->dropleave.window = window;
2697 event->dropleave.requestor = xevent->xclient.data.l[0];
2698 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2704 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2707 * make sure to only handle requests from the window the cursor is
2711 if (gdk_show_events)
2713 g_print ("GDK_DRAG_REQUEST\n");
2714 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2717 if (window && gdk_dnd.drag_really &&
2718 xevent->xclient.data.l[0] == dnd_drag_curwin &&
2719 event->dragrequest.u.flags.sendreply == 0)
2721 /* Got request - do we need to ask user? */
2722 if (!event->dragrequest.u.flags.willaccept
2723 && event->dragrequest.u.flags.senddata)
2726 event->dragrequest.type = GDK_DRAG_REQUEST;
2727 event->dragrequest.window = window;
2728 event->dragrequest.requestor = xevent->xclient.data.l[0];
2729 event->dragrequest.isdrop = 0;
2730 event->dragrequest.drop_coords.x =
2731 event->dragrequest.drop_coords.y = 0;
2734 else if (event->dragrequest.u.flags.willaccept)
2736 window_private->dnd_drag_destructive_op =
2737 event->dragrequest.u.flags.delete_data;
2738 window_private->dnd_drag_accepted = 1;
2739 window_private->dnd_drag_data_type =
2740 xevent->xclient.data.l[4];
2742 dnd_drag_target = dnd_drag_curwin;
2743 XChangeActivePointerGrab (gdk_display,
2747 EnterWindowMask | LeaveWindowMask,
2748 gdk_dnd.gdk_cursor_dragok,
2751 dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2752 dnd_drag_dropzone.y =
2753 (xevent->xclient.data.l[2] >> 16) & 65535;
2754 dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2755 dnd_drag_dropzone.height =
2756 (xevent->xclient.data.l[3] >> 16) & 65535;
2759 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2761 gint tmp_int; Atom tmp_atom;
2763 guchar *tmp_charptr;
2768 g_print("GDK_DROP_DATA_AVAIL\n");
2769 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2771 /* No preview of data ATM */
2772 && event->dropdataavailable.u.flags.isdrop)
2774 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2775 event->dropdataavailable.window = window;
2776 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2777 event->dropdataavailable.data_type =
2778 gdk_atom_name(xevent->xclient.data.l[2]);
2779 if(XGetWindowProperty (gdk_display,
2780 event->dropdataavailable.requestor,
2781 xevent->xclient.data.l[2],
2783 False, XA_PRIMARY, &tmp_atom,
2785 &event->dropdataavailable.data_numbytes,
2790 g_warning("XGetWindowProperty on %#x may have failed\n",
2791 event->dropdataavailable.requestor);
2792 event->dropdataavailable.data = NULL;
2797 g_print("XGetWindowProperty got us %d bytes\n",
2798 event->dropdataavailable.data_numbytes);
2800 event->dropdataavailable.data =
2801 g_malloc (event->dropdataavailable.data_numbytes);
2802 memcpy (event->dropdataavailable.data,
2803 tmp_charptr, event->dropdataavailable.data_numbytes);
2812 /* Send unknown ClientMessage's on to Gtk for it to use */
2813 event->client.type = GDK_CLIENT_EVENT;
2814 event->client.window = window;
2815 event->client.message_type = xevent->xclient.message_type;
2816 event->client.data_format = xevent->xclient.format;
2817 memcpy(&event->client.data, &xevent->xclient.data,
2818 sizeof(event->client.data));
2825 return_val = return_val && !window_private->destroyed;
2829 /* Print debugging info.
2831 if (gdk_show_events)
2832 g_print ("mapping notify\n");
2834 /* Let XLib know that there is a new keyboard mapping.
2836 XRefreshKeyboardMapping (&xevent->xmapping);
2840 /* something else - (e.g., a Xinput event) */
2842 if (window_private &&
2843 (window_private->extension_events != 0) &&
2844 gdk_input_vtable.other_event)
2845 return_val = gdk_input_vtable.other_event(event, xevent, window);
2849 if (return_val < 0) /* not an XInput event, convert */
2851 event->other.type = GDK_OTHER_EVENT;
2852 event->other.window = window;
2853 event->other.xevent = (GdkXEvent *)&other_xevent[other_xevent_i];
2854 memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
2855 other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
2859 return_val = return_val && !window_private->destroyed;
2866 if (event->any.window)
2867 gdk_window_ref (event->any.window);
2868 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2869 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2870 (event->crossing.subwindow != NULL))
2871 gdk_window_ref (event->crossing.subwindow);
2875 /* Mark this event as having no resources to be freed */
2876 event->any.window = NULL;
2877 event->any.type = GDK_NOTHING;
2881 gdk_window_unref (window);
2888 gdk_event_get_type (Display *display,
2895 if (gdk_event_translate (&event, xevent))
2897 pred = (GdkPredicate*) arg;
2898 return (* pred->func) (&event, pred->data);
2906 gdk_synthesize_click (GdkEvent *event,
2909 GdkEvent temp_event;
2911 g_return_if_fail (event != NULL);
2913 temp_event = *event;
2914 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2916 gdk_event_put (&temp_event);
2920 *--------------------------------------------------------------
2923 * This is the "atexit" function that makes sure the
2924 * library gets a chance to cleanup.
2931 * The library is un-initialized and the program exits.
2933 *--------------------------------------------------------------
2939 static gboolean in_gdk_exit_func = FALSE;
2941 /* This is to avoid an infinite loop if a program segfaults in
2942 an atexit() handler (and yes, it does happen, especially if a program
2943 has trounced over memory too badly for even g_print to work) */
2944 if(in_gdk_exit_func == TRUE) return;
2945 in_gdk_exit_func = TRUE;
2957 gdk_key_repeat_restore ();
2959 XCloseDisplay (gdk_display);
2965 *--------------------------------------------------------------
2968 * The X error handling routine.
2971 * "display" is the X display the error orignated from.
2972 * "error" is the XErrorEvent that we are handling.
2975 * Either we were expecting some sort of error to occur,
2976 * in which case we set the "gdk_error_code" flag, or this
2977 * error was unexpected, in which case we will print an
2978 * error message and exit. (Since trying to continue will
2979 * most likely simply lead to more errors).
2983 *--------------------------------------------------------------
2987 gdk_x_error (Display *display,
2992 if (gdk_error_warnings)
2994 XGetErrorText (display, error->error_code, buf, 63);
2995 g_error ("%s", buf);
2998 gdk_error_code = -1;
3003 *--------------------------------------------------------------
3006 * The X I/O error handling routine.
3009 * "display" is the X display the error orignated from.
3012 * An X I/O error basically means we lost our connection
3013 * to the X server. There is not much we can do to
3014 * continue, so simply print an error message and exit.
3018 *--------------------------------------------------------------
3022 gdk_x_io_error (Display *display)
3024 g_error ("an x io error occurred");
3029 *--------------------------------------------------------------
3032 * The signal handler.
3035 * "sig_num" is the number of the signal we received.
3038 * The signals we catch are all fatal. So we simply build
3039 * up a nice little error message and print it and exit.
3040 * If in the process of doing so another signal is received
3041 * we notice that we are already exiting and simply kill
3046 *--------------------------------------------------------------
3050 gdk_signal (int sig_num)
3052 static int caught_fatal_sig = 0;
3055 if (caught_fatal_sig)
3056 kill (getpid (), sig_num);
3057 caught_fatal_sig = 1;
3083 sig = "unknown signal";
3087 g_print ("\n** ERROR **: %s caught\n", sig);
3092 gdk_dnd_drag_begin (GdkWindow *initial_window)
3094 GdkEventDragBegin tev;
3095 tev.type = GDK_DRAG_BEGIN;
3096 tev.window = initial_window;
3098 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3100 gdk_event_put ((GdkEvent *) &tev);
3104 gdk_dnd_drag_enter (Window dest)
3107 GdkEventDropEnter tev;
3109 GdkWindowPrivate *wp;
3111 sev.xclient.type = ClientMessage;
3112 sev.xclient.format = 32;
3113 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3114 sev.xclient.window = dest;
3117 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3118 tev.u.flags.sendreply = 1;
3119 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3121 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3122 if (wp->dnd_drag_data_numtypesavail)
3124 sev.xclient.data.l[0] = wp->xwindow;
3125 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3126 sev.xclient.data.l[1] = tev.u.allflags;
3127 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3128 if (wp->dnd_drag_data_numtypesavail > 1)
3130 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3131 if (wp->dnd_drag_data_numtypesavail > 2)
3133 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3136 sev.xclient.data.l[4] = None;
3139 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3140 XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
3150 *--------------------------------------------------------------
3153 * Begin using input method with XIM Protocol(X11R6 standard)
3156 * "ic" is the "Input Context" which is created by gtk_ic_new.
3157 * The input area is specified with "window".
3160 * The gdk's event handling routine is switched to XIM based routine.
3161 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3162 * and uses XmbLookupString instead of XLookupString.
3166 *--------------------------------------------------------------
3170 gdk_im_begin (GdkIC ic, GdkWindow* window)
3172 GdkICPrivate *private;
3175 g_return_if_fail (ic != NULL);
3176 g_return_if_fail (window);
3178 private = (GdkICPrivate *) ic;
3182 xim_window = window;
3185 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3186 if (xwin != GDK_WINDOW_XWINDOW(window))
3187 XSetICValues (private->xic, XNFocusWindow,
3188 GDK_WINDOW_XWINDOW(window), NULL);
3189 if (private != xim_ic)
3190 XSetICFocus (private->xic);
3195 *--------------------------------------------------------------
3198 * End using input method with XIM Protocol(X11R6 standard)
3203 * The gdk's event handling routine is switched to normal routine.
3204 * User should call this function before ic and window will be destroyed.
3208 *--------------------------------------------------------------
3226 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3228 GdkIMStyle s1, s2, u;
3230 if (style1 == 0) return style2;
3231 if (style2 == 0) return style1;
3232 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3233 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3236 s1 = style1 & GdkIMPreeditMask;
3237 s2 = style2 & GdkIMPreeditMask;
3240 if (u & GdkIMPreeditCallbacks)
3241 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3242 else if (u & GdkIMPreeditPosition)
3243 return (s1 == GdkIMPreeditPosition)? style1:style2;
3244 else if (u & GdkIMPreeditArea)
3245 return (s1 == GdkIMPreeditArea)? style1:style2;
3246 else if (u & GdkIMPreeditNothing)
3247 return (s1 == GdkIMPreeditNothing)? style1:style2;
3249 s1 = style1 & GdkIMStatusMask;
3250 s2 = style2 & GdkIMStatusMask;
3252 if ( u & GdkIMStatusCallbacks)
3253 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3254 else if ( u & GdkIMStatusArea)
3255 return (s1 == GdkIMStatusArea)? style1:style2;
3256 else if ( u & GdkIMStatusNothing)
3257 return (s1 == GdkIMStatusNothing)? style1:style2;
3258 else if ( u & GdkIMStatusNone)
3259 return (s1 == GdkIMStatusNone)? style1:style2;
3261 return 0; /* Get rid of stupid warning */
3265 gdk_im_decide_style (GdkIMStyle supported_style)
3268 GdkIMStyle style, tmp;
3270 g_return_val_if_fail (xim_styles != NULL, 0);
3273 for (i=0; i<xim_styles->count_styles; i++)
3275 tmp = xim_styles->supported_styles[i];
3276 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3277 style = gdk_im_choose_better_style (style, tmp);
3283 gdk_im_set_best_style (GdkIMStyle style)
3285 if (style & GdkIMPreeditMask)
3287 xim_best_allowed_style &= ~GdkIMPreeditMask;
3289 xim_best_allowed_style |= GdkIMPreeditNone;
3290 if (!(style & GdkIMPreeditNone))
3292 xim_best_allowed_style |= GdkIMPreeditNothing;
3293 if (!(style & GdkIMPreeditNothing))
3295 xim_best_allowed_style |= GdkIMPreeditArea;
3296 if (!(style & GdkIMPreeditArea))
3298 xim_best_allowed_style |= GdkIMPreeditPosition;
3299 if (!(style & GdkIMPreeditPosition))
3300 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3305 if (style & GdkIMStatusMask)
3307 xim_best_allowed_style &= ~GdkIMStatusMask;
3309 xim_best_allowed_style |= GdkIMStatusNone;
3310 if (!(style & GdkIMStatusNone))
3312 xim_best_allowed_style |= GdkIMStatusNothing;
3313 if (!(style & GdkIMStatusNothing))
3315 xim_best_allowed_style |= GdkIMStatusArea;
3316 if (!(style & GdkIMStatusArea))
3317 xim_best_allowed_style |= GdkIMStatusCallbacks;
3322 return xim_best_allowed_style;
3326 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3328 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3331 g_warning ("Don\'t open IM.");
3334 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3357 return (xim_im != NULL);
3361 gdk_ic_new (GdkWindow* client_window,
3362 GdkWindow* focus_window,
3363 GdkIMStyle style, ...)
3366 GdkICPrivate *private;
3367 XVaNestedList preedit_attr;
3369 g_return_val_if_fail (client_window != NULL, NULL);
3370 g_return_val_if_fail (focus_window != NULL, NULL);
3371 g_return_val_if_fail (gdk_im_ready(), NULL);
3373 private = g_new (GdkICPrivate, 1);
3375 va_start (list, style);
3376 preedit_attr = (XVaNestedList) & (va_arg (list, void *));
3379 private->style = gdk_im_decide_style (style);
3380 if (private->style != style)
3382 g_warning ("can not create input context with specified input style.");
3387 private->xic = XCreateIC(gdk_im_get (),
3388 XNInputStyle, style,
3389 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3390 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3391 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3399 xim_ic_list = g_list_append (xim_ic_list, private);
3404 gdk_ic_destroy (GdkIC ic)
3406 GdkICPrivate *private;
3408 g_return_if_fail (ic != NULL);
3410 private = (GdkICPrivate *) ic;
3412 if (xim_ic == private)
3415 XDestroyIC (private->xic);
3416 xim_ic_list = g_list_remove (xim_ic_list, private);
3420 gdk_ic_get_style (GdkIC ic)
3422 GdkICPrivate *private;
3424 g_return_val_if_fail (ic != NULL, 0);
3426 private = (GdkICPrivate *) ic;
3428 return private->style;
3432 gdk_ic_set_values (GdkIC ic, ...)
3436 GdkICPrivate *private;
3438 g_return_if_fail (ic != NULL);
3440 private = (GdkICPrivate *) ic;
3442 va_start (list, ic);
3443 args = (XVaNestedList) & (va_arg (list, void *));
3446 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3450 gdk_ic_get_values (GdkIC ic, ...)
3454 GdkICPrivate *private;
3456 g_return_if_fail (ic != NULL);
3458 private = (GdkICPrivate *) ic;
3460 va_start (list, ic);
3461 args = (XVaNestedList) & (va_arg (list, void *));
3464 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3468 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3472 GdkICPrivate *private;
3474 g_return_if_fail (ic != NULL);
3475 g_return_if_fail (target != NULL);
3477 private = (GdkICPrivate *) ic;
3479 va_start (list, target);
3480 attr = (XVaNestedList) & (va_arg (list, void *));
3483 XSetICValues (private->xic, target, attr, NULL);
3487 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3491 GdkICPrivate *private;
3493 g_return_if_fail (ic != NULL);
3494 g_return_if_fail (target != NULL);
3496 private = (GdkICPrivate *) ic;
3498 va_start (list, target);
3499 attr = (XVaNestedList) & (va_arg (list, void *));
3502 XGetICValues (private->xic, target, attr, NULL);
3506 gdk_ic_get_events (GdkIC ic)
3511 GdkICPrivate *private;
3514 /* From gdkwindow.c */
3515 extern int nevent_masks;
3516 extern int event_mask_table[];
3518 g_return_val_if_fail (ic != NULL, 0);
3520 private = (GdkICPrivate *) ic;
3522 XGetICValues (private->xic, XNFilterEvents, &xmask, NULL);
3525 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3526 if (xmask & event_mask_table [i])
3529 xmask &= ~ event_mask_table [i];
3533 g_warning ("ic requires the events not supported by the application (%04lx)", xmask);
3539 gdk_ic_cleanup (void)
3543 GdkICPrivate *private;
3546 for (node = xim_ic_list; node != NULL; node = node->next)
3550 private = (GdkICPrivate *) (node->data);
3551 XDestroyIC (private->xic);
3556 if (gdk_debug_level >= 1 && destroyed > 0)
3558 g_warning ("Cleanuped %i IC\n", destroyed);
3560 g_list_free(xim_ic_list);
3564 #else /* !USE_XIM */
3567 gdk_im_begin (GdkIC ic, GdkWindow* window)
3577 gdk_im_decide_style (GdkIMStyle supported_style)
3579 return GdkIMPreeditNone | GdkIMStatusNone;
3583 gdk_im_set_best_style (GdkIMStyle style)
3585 return GdkIMPreeditNone | GdkIMStatusNone;
3595 gdk_ic_new (GdkWindow* client_window,
3596 GdkWindow* focus_window,
3597 GdkIMStyle style, ...)
3603 gdk_ic_destroy (GdkIC ic)
3608 gdk_ic_get_style (GdkIC ic)
3610 return GdkIMPreeditNone | GdkIMStatusNone;
3614 gdk_ic_set_values (GdkIC ic, ...)
3619 gdk_ic_get_values (GdkIC ic, ...)
3624 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3629 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3634 gdk_ic_get_events (GdkIC ic)
3639 #endif /* USE_XIM */
3644 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3646 static wchar_t wcs[MB_CUR_MAX + 1];
3647 static gchar mbs[MB_CUR_MAX + 1];
3649 wcs[0] = (wchar_t) NULL;
3652 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3655 else if (wcs[0] == (wchar_t) NULL)
3658 len = _Xwctomb (mbs, wcs[0]);
3667 #endif /* X_LOCALE */
3670 gdk_dnd_drag_leave (Window dest)
3673 GdkEventDropLeave tev;
3675 GdkWindowPrivate *wp;
3679 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3680 sev.xclient.type = ClientMessage;
3681 sev.xclient.window = dest;
3682 sev.xclient.format = 32;
3683 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3684 sev.xclient.data.l[1] = tev.u.allflags;
3685 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3687 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3688 sev.xclient.data.l[0] = wp->xwindow;
3689 XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
3690 wp->dnd_drag_accepted = 0;
3695 * when a drop occurs, we go through the list of windows being dragged and
3696 * tell them that it has occurred, so that they can set things up and reply
3700 gdk_dnd_drag_end (Window dest,
3703 GdkWindowPrivate *wp;
3704 GdkEventDragRequest tev;
3707 tev.type = GDK_DRAG_REQUEST;
3708 tev.drop_coords = coords;
3709 tev.requestor = dest;
3711 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3714 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3716 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3717 if (wp->dnd_drag_accepted)
3719 tev.window = (GdkWindow *) wp;
3720 tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
3722 gdk_atom_name(wp->dnd_drag_data_type);
3724 gdk_event_put((GdkEvent *) &tev);
3730 gdk_dnd_check_types (GdkWindow *window,
3733 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3735 GdkEventDropEnter event;
3737 g_return_val_if_fail(window != NULL, 0);
3738 g_return_val_if_fail(xevent != NULL, 0);
3739 g_return_val_if_fail(xevent->type == ClientMessage, 0);
3740 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3742 if(wp->dnd_drop_data_numtypesavail <= 0 ||
3743 !wp->dnd_drop_data_typesavail)
3746 for (i = 2; i <= 4; i++)
3748 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3750 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3751 return xevent->xclient.data.l[i];
3755 /* Now we get the extended type list if it's available */
3756 event.u.allflags = xevent->xclient.data.l[1];
3757 if (event.u.flags.extended_typelist)
3759 Atom *exttypes, realtype;
3760 gulong nitems, nbar;
3763 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3764 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
3765 False, AnyPropertyType, &realtype, &realfmt,
3766 &nitems, &nbar, (unsigned char **) &exttypes)
3770 if (realfmt != (sizeof(Atom) * 8))
3772 g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
3773 realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
3777 for (i = 0; i <= nitems; i++)
3779 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3781 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
3794 * used for debugging only
3798 gdk_print_atom (GdkAtom anatom)
3800 gchar *tmpstr = NULL;
3801 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
3802 g_print("Atom %lu has name %s\n", anatom, tmpstr);
3809 * used only by below routine and itself
3812 getchildren (Display *dpy,
3816 Window root, parent, *children, inf = 0;
3818 unsigned int nchildren, i;
3820 unsigned long nitems, after;
3821 unsigned char *data;
3823 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
3826 for (i = 0; !inf && (i < nchildren); i++)
3828 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
3829 AnyPropertyType, &type, &format, &nitems,
3836 for (i = 0; !inf && (i < nchildren); i++)
3837 inf = getchildren (dpy, children[i], WM_STATE);
3839 if (children != None)
3840 XFree ((char *) children);
3846 * find a window with WM_STATE, else return win itself, as per ICCCM
3848 * modification of the XmuClientWindow() routine from X11R6.3
3851 gdk_get_client_window (Display *dpy,
3857 unsigned long nitems, after;
3858 unsigned char *data;
3862 return DefaultRootWindow(dpy);
3864 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
3867 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
3868 &type, &format, &nitems, &after, &data);
3872 inf = getchildren (dpy, win, WM_STATE);
3880 #ifdef WE_HAVE_MOTIF_DROPS_DONE
3882 gdk_drop_get_real_window (GdkWindow *w,
3886 GdkWindow *retval = w;
3887 GdkWindowPrivate *awin;
3889 gint16 myx = *x, myy = *y;
3891 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
3897 for (children = gdk_window_get_children(retval);
3898 children && children->next;
3899 children = children->next)
3901 awin = (GdkWindowPrivate *) children->data;
3902 if ((myx >= awin->x) && (myy >= awin->y)
3903 && (myx < (awin->x + awin->width))
3904 && (myy < (awin->y + awin->height)))
3906 retval = (GdkWindow *) awin;
3920 /* Sends a ClientMessage to all toplevel client windows */
3922 gdk_event_send_clientmessage_toall(GdkEvent *event)
3925 Window *ret_children, ret_root, ret_parent, curwin;
3926 unsigned int ret_nchildren;
3929 g_return_if_fail(event != NULL);
3931 /* Set up our event to send, with the exception of its target window */
3932 sev.xclient.type = ClientMessage;
3933 sev.xclient.display = gdk_display;
3934 sev.xclient.format = event->client.data_format;
3935 sev.xclient.serial = CurrentTime;
3936 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3937 sev.xclient.message_type = event->client.message_type;
3939 /* OK, we're all set, now let's find some windows to send this to */
3940 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
3941 &ret_children, &ret_nchildren) != True)
3944 /* foreach true child window of the root window, send an event to it */
3945 for(i = 0; i < ret_nchildren; i++) {
3946 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
3947 sev.xclient.window = curwin;
3948 XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
3951 XFree(ret_children);
3955 gdk_get_display(void)
3957 return (gchar *)XDisplayName (gdk_display_name);