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 g_return_val_if_fail (private != NULL, False);
648 if ((xevent->xany.window == private->xwindow) &&
649 ((xevent->xany.type == GraphicsExpose) ||
650 (xevent->xany.type == NoExpose)))
657 gdk_event_get_graphics_expose (GdkWindow *window)
662 g_return_val_if_fail (window != NULL, NULL);
664 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
666 if (xevent.xany.type == GraphicsExpose)
668 event = gdk_event_new ();
670 if (gdk_event_translate (event, &xevent))
673 gdk_event_free (event);
680 *--------------------------------------------------------------
683 * Gets the next event.
688 * If an event was received that we care about, returns
689 * a pointer to that event, to be freed with gdk_event_free.
690 * Otherwise, returns NULL. This function will also return
691 * before an event is received if the timeout interval
696 *--------------------------------------------------------------
709 temp_list = putback_events;
712 temp_event = temp_list->data;
714 if ((* pred) (temp_event, data))
717 *event = *temp_event;
718 putback_events = g_list_remove_link (putback_events, temp_list);
719 g_list_free (temp_list);
723 temp_list = temp_list->next;
726 event_pred.func = pred;
727 event_pred.data = data;
729 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
731 return gdk_event_translate (event, &xevent);
737 event = putback_events->data;
739 temp_list = putback_events;
740 putback_events = g_list_remove_link (putback_events, temp_list);
741 g_list_free_1 (temp_list);
746 /* Wait for an event to occur or the timeout to elapse.
747 * If an event occurs "gdk_event_wait" will return TRUE.
748 * If the timeout elapses "gdk_event_wait" will return
751 if (gdk_event_wait ())
753 /* If we get here we can rest assurred that an event
754 * has occurred. Read it.
758 if (xim_using && xim_window)
760 { /* don't dispatch events used by IM */
761 XNextEvent (gdk_display, &xevent);
762 filter_status = XFilterEvent (&xevent,
763 GDK_WINDOW_XWINDOW (xim_window));
764 } while (filter_status == True);
766 XNextEvent (gdk_display, &xevent);
768 XNextEvent (gdk_display, &xevent);
770 event = gdk_event_new ();
772 event->any.type = GDK_NOTHING;
773 event->any.window = NULL;
774 event->any.send_event = FALSE;
775 event->any.send_event = xevent.xany.send_event;
777 if (gdk_event_translate (event, &xevent))
780 gdk_event_free (event);
787 gdk_event_put (GdkEvent *event)
791 g_return_if_fail (event != NULL);
793 new_event = gdk_event_copy (event);
795 putback_events = g_list_prepend (putback_events, new_event);
799 *--------------------------------------------------------------
802 * Copy a event structure into new storage.
805 * "event" is the event struct to copy.
808 * A new event structure. Free it with gdk_event_free.
811 * The reference count of the window in the event is increased.
813 *--------------------------------------------------------------
816 static GMemChunk *event_chunk;
823 if (event_chunk == NULL)
824 event_chunk = g_mem_chunk_new ("events",
829 new_event = g_chunk_new (GdkEvent, event_chunk);
835 gdk_event_copy (GdkEvent *event)
839 g_return_val_if_fail (event != NULL, NULL);
841 new_event = gdk_event_new ();
844 gdk_window_ref (new_event->any.window);
846 switch (event->any.type)
849 case GDK_KEY_RELEASE:
850 new_event->key.string = g_strdup (event->key.string);
853 case GDK_ENTER_NOTIFY:
854 case GDK_LEAVE_NOTIFY:
855 if (event->crossing.subwindow != NULL)
856 gdk_window_ref (event->crossing.subwindow);
859 case GDK_DROP_DATA_AVAIL:
860 new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
861 new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
862 memcpy (new_event->dropdataavailable.data,
863 event->dropdataavailable.data,
864 event->dropdataavailable.data_numbytes);
875 *--------------------------------------------------------------
878 * Free a event structure obtained from gdk_event_copy. Do not use
879 * with other event structures.
882 * "event" is the event struct to free.
887 * The reference count of the window in the event is decreased and
888 * might be freed, too.
890 *-------------------------------------------------------------- */
893 gdk_event_free (GdkEvent *event)
895 g_assert (event_chunk != NULL);
896 g_return_if_fail (event != NULL);
898 if (event->any.window)
899 gdk_window_unref (event->any.window);
901 switch (event->any.type)
904 case GDK_KEY_RELEASE:
905 g_free (event->key.string);
908 case GDK_ENTER_NOTIFY:
909 case GDK_LEAVE_NOTIFY:
910 if (event->crossing.subwindow != NULL)
911 gdk_window_unref (event->crossing.subwindow);
914 case GDK_DROP_DATA_AVAIL:
915 g_free (event->dropdataavailable.data_type);
916 g_free (event->dropdataavailable.data);
919 case GDK_DRAG_REQUEST:
920 g_free (event->dragrequest.data_type);
927 g_mem_chunk_free (event_chunk, event);
931 *--------------------------------------------------------------
932 * gdk_set_debug_level
934 * Sets the debugging level.
937 * "level" is the new debugging level.
942 * Other function calls to "gdk" use the debugging
943 * level to determine what kind of debugging information
946 *--------------------------------------------------------------
950 gdk_set_debug_level (int level)
952 gdk_debug_level = level;
956 *--------------------------------------------------------------
957 * gdk_set_show_events
959 * Turns on/off the showing of events.
962 * "show_events" is a boolean describing whether or
963 * not to show the events gdk receives.
968 * When "show_events" is TRUE, calls to "gdk_event_get"
969 * will output debugging informatin regarding the event
970 * received to stdout.
972 *--------------------------------------------------------------
976 gdk_set_show_events (int show_events)
978 gdk_show_events = show_events;
982 gdk_set_use_xshm (gint use_xshm)
984 gdk_use_xshm = use_xshm;
988 gdk_get_debug_level ()
990 return gdk_debug_level;
994 gdk_get_show_events ()
996 return gdk_show_events;
1002 return gdk_use_xshm;
1006 *--------------------------------------------------------------
1009 * Get the number of milliseconds since the library was
1015 * The time since the library was initialized is returned.
1016 * This time value is accurate to milliseconds even though
1017 * a more accurate time down to the microsecond could be
1022 *--------------------------------------------------------------
1029 struct timeval elapsed;
1030 guint32 milliseconds;
1032 X_GETTIMEOFDAY (&end);
1034 if (start.tv_usec > end.tv_usec)
1036 end.tv_usec += 1000000;
1039 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1040 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1042 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1044 return milliseconds;
1048 *--------------------------------------------------------------
1051 * Returns the current timer.
1056 * Returns the current timer interval. This interval is
1057 * in units of milliseconds.
1061 *--------------------------------------------------------------
1071 *--------------------------------------------------------------
1074 * Sets the timer interval.
1077 * "milliseconds" is the new value for the timer.
1082 * Calls to "gdk_event_get" will last for a maximum
1083 * of time of "milliseconds". However, a value of 0
1084 * milliseconds will cause "gdk_event_get" to block
1085 * indefinately until an event is received.
1087 *--------------------------------------------------------------
1091 gdk_timer_set (guint32 milliseconds)
1093 timer_val = milliseconds;
1094 timer.tv_sec = milliseconds / 1000;
1095 timer.tv_usec = (milliseconds % 1000) * 1000;
1106 gdk_timer_disable ()
1112 gdk_input_add_full (gint source,
1113 GdkInputCondition condition,
1114 GdkInputFunction function,
1116 GdkDestroyNotify destroy)
1118 static gint next_tag = 1;
1131 if ((input->source == source) && (input->condition == condition))
1134 (input->destroy) (input->data);
1135 input->function = function;
1137 input->destroy = destroy;
1144 input = g_new (GdkInput, 1);
1145 input->tag = next_tag++;
1146 input->source = source;
1147 input->condition = condition;
1148 input->function = function;
1150 input->destroy = destroy;
1153 inputs = g_list_prepend (inputs, input);
1160 gdk_input_add (gint source,
1161 GdkInputCondition condition,
1162 GdkInputFunction function,
1165 return gdk_input_add_interp (source, condition, function, data, NULL);
1169 gdk_input_remove (gint tag)
1180 if (input->tag == tag)
1183 (input->destroy) (input->data);
1188 list->next->prev = list->prev;
1190 list->prev->next = list->next;
1192 inputs = list->next;
1194 temp_list->next = NULL;
1195 temp_list->prev = NULL;
1197 g_free (temp_list->data);
1198 g_list_free (temp_list);
1207 *--------------------------------------------------------------
1210 * Grabs the pointer to a specific window
1213 * "window" is the window which will receive the grab
1214 * "owner_events" specifies whether events will be reported as is,
1215 * or relative to "window"
1216 * "event_mask" masks only interesting events
1217 * "confine_to" limits the cursor movement to the specified window
1218 * "cursor" changes the cursor for the duration of the grab
1219 * "time" specifies the time
1224 * requires a corresponding call to gdk_pointer_ungrab
1226 *--------------------------------------------------------------
1230 gdk_pointer_grab (GdkWindow * window,
1232 GdkEventMask event_mask,
1233 GdkWindow * confine_to,
1237 /* From gdkwindow.c */
1238 extern int nevent_masks;
1239 extern int event_mask_table[];
1242 GdkWindowPrivate *window_private;
1243 GdkWindowPrivate *confine_to_private;
1244 GdkCursorPrivate *cursor_private;
1251 g_return_val_if_fail (window != NULL, 0);
1253 window_private = (GdkWindowPrivate*) window;
1254 confine_to_private = (GdkWindowPrivate*) confine_to;
1255 cursor_private = (GdkCursorPrivate*) cursor;
1257 xwindow = window_private->xwindow;
1259 if (!confine_to || confine_to_private->destroyed)
1262 xconfine_to = confine_to_private->xwindow;
1267 xcursor = cursor_private->xcursor;
1271 for (i = 0; i < nevent_masks; i++)
1273 if (event_mask & (1 << (i + 1)))
1274 xevent_mask |= event_mask_table[i];
1277 if (((GdkWindowPrivate *)window)->extension_events &&
1278 gdk_input_vtable.grab_pointer)
1279 return_val = gdk_input_vtable.grab_pointer (window,
1285 return_val = Success;;
1287 if (return_val == Success)
1288 if (!window_private->destroyed)
1289 return_val = XGrabPointer (window_private->xdisplay,
1293 GrabModeAsync, GrabModeAsync,
1298 return_val = AlreadyGrabbed;
1300 if (return_val == GrabSuccess)
1301 xgrab_window = window_private;
1307 *--------------------------------------------------------------
1308 * gdk_pointer_ungrab
1310 * Releases any pointer grab
1318 *--------------------------------------------------------------
1322 gdk_pointer_ungrab (guint32 time)
1324 if (gdk_input_vtable.ungrab_pointer)
1325 gdk_input_vtable.ungrab_pointer (time);
1327 XUngrabPointer (gdk_display, time);
1328 xgrab_window = NULL;
1332 *--------------------------------------------------------------
1333 * gdk_pointer_is_grabbed
1335 * Tell wether there is an active x pointer grab in effect
1343 *--------------------------------------------------------------
1347 gdk_pointer_is_grabbed (void)
1349 return xgrab_window != NULL;
1353 *--------------------------------------------------------------
1356 * Grabs the keyboard to a specific window
1359 * "window" is the window which will receive the grab
1360 * "owner_events" specifies whether events will be reported as is,
1361 * or relative to "window"
1362 * "time" specifies the time
1367 * requires a corresponding call to gdk_keyboard_ungrab
1369 *--------------------------------------------------------------
1373 gdk_keyboard_grab (GdkWindow * window,
1377 GdkWindowPrivate *window_private;
1380 g_return_val_if_fail (window != NULL, 0);
1382 window_private = (GdkWindowPrivate*) window;
1383 xwindow = window_private->xwindow;
1385 if (!window_private->destroyed)
1386 return XGrabKeyboard (window_private->xdisplay,
1389 GrabModeAsync, GrabModeAsync,
1392 return AlreadyGrabbed;
1396 *--------------------------------------------------------------
1397 * gdk_keyboard_ungrab
1399 * Releases any keyboard grab
1407 *--------------------------------------------------------------
1411 gdk_keyboard_ungrab (guint32 time)
1413 XUngrabKeyboard (gdk_display, time);
1417 *--------------------------------------------------------------
1420 * Return the width of the screen.
1428 *--------------------------------------------------------------
1436 return_val = DisplayWidth (gdk_display, gdk_screen);
1442 *--------------------------------------------------------------
1445 * Return the height of the screen.
1453 *--------------------------------------------------------------
1457 gdk_screen_height ()
1461 return_val = DisplayHeight (gdk_display, gdk_screen);
1467 gdk_key_repeat_disable ()
1469 XAutoRepeatOff (gdk_display);
1473 gdk_key_repeat_restore ()
1476 XAutoRepeatOn (gdk_display);
1478 XAutoRepeatOff (gdk_display);
1483 *--------------------------------------------------------------
1486 * Flushes the Xlib output buffer and then waits
1487 * until all requests have been received and processed
1488 * by the X server. The only real use for this function
1489 * is in dealing with XShm.
1497 *--------------------------------------------------------------
1502 XSync (gdk_display, False);
1509 XBell(gdk_display, 100);
1514 *--------------------------------------------------------------
1517 * Waits until an event occurs or the timer runs out.
1522 * Returns TRUE if an event is ready to be read and FALSE
1523 * if the timer ran out.
1527 *--------------------------------------------------------------
1535 GdkInputCondition condition;
1536 SELECT_MASK readfds;
1537 SELECT_MASK writefds;
1538 SELECT_MASK exceptfds;
1542 /* If there are no events pending we will wait for an event.
1543 * The time we wait is dependant on the "timer". If no timer
1544 * has been specified then we'll block until an event arrives.
1545 * If a timer has been specified we'll block until an event
1546 * arrives or the timer expires. (This is all done using the
1547 * "select" system call).
1550 if (XPending (gdk_display) == 0)
1553 FD_ZERO (&writefds);
1554 FD_ZERO (&exceptfds);
1556 FD_SET (connection_number, &readfds);
1557 max_input = connection_number;
1565 if (input->condition & GDK_INPUT_READ)
1566 FD_SET (input->source, &readfds);
1567 if (input->condition & GDK_INPUT_WRITE)
1568 FD_SET (input->source, &writefds);
1569 if (input->condition & GDK_INPUT_EXCEPTION)
1570 FD_SET (input->source, &exceptfds);
1572 max_input = MAX (max_input, input->source);
1575 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1582 if (FD_ISSET (connection_number, &readfds))
1584 if (XPending (gdk_display) == 0)
1588 XNoOp (gdk_display);
1589 XFlush (gdk_display);
1604 if (FD_ISSET (input->source, &readfds))
1605 condition |= GDK_INPUT_READ;
1606 if (FD_ISSET (input->source, &writefds))
1607 condition |= GDK_INPUT_WRITE;
1608 if (FD_ISSET (input->source, &exceptfds))
1609 condition |= GDK_INPUT_EXCEPTION;
1611 if (condition && input->function)
1612 (* input->function) (input->data, input->source, condition);
1623 gdk_event_apply_filters (XEvent *xevent,
1627 GdkEventFilter *filter;
1629 GdkFilterReturn result;
1635 filter = (GdkEventFilter *)tmp_list->data;
1637 result = (*filter->function)(xevent, event, filter->data);
1638 if (result != GDK_FILTER_CONTINUE)
1641 tmp_list = tmp_list->next;
1644 return GDK_FILTER_CONTINUE;
1648 gdk_event_translate (GdkEvent *event,
1653 GdkWindowPrivate *window_private;
1654 XComposeStatus compose;
1657 static gchar* buf = NULL;
1658 static gint buf_len= 0;
1664 /* Are static variables used for this purpose thread-safe? */
1665 static GdkPoint dnd_drag_start = {0,0},
1666 dnd_drag_oldpos = {0,0};
1667 static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
1668 static gint dnd_drag_perhaps = 0;
1669 static gboolean dnd_grabbed = FALSE;
1670 static GdkWindowPrivate *real_sw = NULL;
1671 static Window dnd_drag_curwin = None, dnd_drag_target = None;
1675 /* Find the GdkWindow that this event occurred in.
1676 * All events occur in some GdkWindow (otherwise, why
1677 * would we be receiving them). It really is an error
1678 * to receive an event for which we cannot find the
1679 * corresponding GdkWindow. We handle events with window=None
1680 * specially - they are generated by XFree86's XInput under
1681 * some circumstances.
1684 if ((xevent->xany.window == None) &&
1685 gdk_input_vtable.window_none_event)
1687 return_val = gdk_input_vtable.window_none_event (event,xevent);
1689 if (return_val >= 0) /* was handled */
1695 window = gdk_window_lookup (xevent->xany.window);
1696 window_private = (GdkWindowPrivate *) window;
1699 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1701 gdk_window_ref (window);
1704 /* Check for filters for this window */
1708 GdkFilterReturn result;
1709 result = gdk_event_apply_filters (xevent, event, window_private->filters);
1711 if (result != GDK_FILTER_CONTINUE)
1713 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1717 /* We do a "manual" conversion of the XEvent to a
1718 * GdkEvent. The structures are mostly the same so
1719 * the conversion is fairly straightforward. We also
1720 * optionally print debugging info regarding events
1724 * During drag & drop you get events where the pointer is
1725 * in other windows. Need to just do finer-grained checking
1727 switch (xevent->type)
1730 /* Lookup the string corresponding to the given keysym.
1736 buf = g_new (gchar, buf_len);
1738 if (xim_using == TRUE && xim_ic)
1742 /* Clear keyval. Depending on status, may not be set */
1743 event->key.keyval = GDK_VoidSymbol;
1744 charcount = XmbLookupString(xim_ic->xic,
1745 &xevent->xkey, buf, buf_len-1,
1746 (KeySym*) &event->key.keyval,
1748 if (status == XBufferOverflow)
1750 /* alloc adequate size of buffer */
1751 if (gdk_debug_level >= 1)
1752 g_print("XIM: overflow (required %i)\n", charcount);
1754 while (buf_len <= charcount)
1756 buf = (gchar *) g_realloc (buf, buf_len);
1758 charcount = XmbLookupString (xim_ic->xic,
1759 &xevent->xkey, buf, buf_len-1,
1760 (KeySym*) &event->key.keyval,
1763 if (status == XLookupNone)
1770 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1771 (KeySym*) &event->key.keyval,
1774 charcount = XLookupString (&xevent->xkey, buf, 16,
1775 (KeySym*) &event->key.keyval,
1778 if (charcount > 0 && buf[charcount-1] == '\0')
1781 buf[charcount] = '\0';
1783 /* Print debugging info.
1785 if (gdk_show_events)
1787 g_print ("key press:\twindow: %ld key: %12s %d\n",
1788 xevent->xkey.window - base_id,
1789 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1792 g_print ("\t\tlength: %4d string: \"%s\"\n",
1796 event->key.type = GDK_KEY_PRESS;
1797 event->key.window = window;
1798 event->key.time = xevent->xkey.time;
1799 event->key.state = (GdkModifierType) xevent->xkey.state;
1800 event->key.string = g_strdup (buf);
1801 event->key.length = charcount;
1803 return_val = window_private && !window_private->destroyed;
1806 g_free (event->key.string);
1811 /* Lookup the string corresponding to the given keysym.
1813 charcount = XLookupString (&xevent->xkey, buf, 16,
1814 (KeySym*) &event->key.keyval,
1817 /* Print debugging info.
1819 if (gdk_show_events)
1820 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1821 xevent->xkey.window - base_id,
1822 XKeysymToString (event->key.keyval),
1825 event->key.type = GDK_KEY_RELEASE;
1826 event->key.window = window;
1827 event->key.time = xevent->xkey.time;
1828 event->key.state = (GdkModifierType) xevent->xkey.state;
1829 event->key.length = 0;
1830 event->key.string = NULL;
1832 return_val = window_private && !window_private->destroyed;
1836 /* Print debugging info.
1838 if (gdk_show_events)
1839 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1840 window_private?window_private->dnd_drag_enabled:0,
1841 xevent->xbutton.window - base_id,
1842 xevent->xbutton.x, xevent->xbutton.y,
1843 xevent->xbutton.button);
1845 if (window_private &&
1846 (window_private->extension_events != 0) &&
1847 gdk_input_ignore_core)
1850 event->button.type = GDK_BUTTON_PRESS;
1851 event->button.window = window;
1852 event->button.time = xevent->xbutton.time;
1853 event->button.x = xevent->xbutton.x;
1854 event->button.y = xevent->xbutton.y;
1855 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1856 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1857 event->button.pressure = 0.5;
1858 event->button.xtilt = 0;
1859 event->button.ytilt = 0;
1860 event->button.state = (GdkModifierType) xevent->xbutton.state;
1861 event->button.button = xevent->xbutton.button;
1862 event->button.source = GDK_SOURCE_MOUSE;
1863 event->button.deviceid = GDK_CORE_POINTER;
1865 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1866 (event->button.window == button_window[1]) &&
1867 (event->button.button == button_number[1]))
1869 gdk_synthesize_click (event, 3);
1871 button_click_time[1] = 0;
1872 button_click_time[0] = 0;
1873 button_window[1] = NULL;
1874 button_window[0] = 0;
1875 button_number[1] = -1;
1876 button_number[0] = -1;
1878 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1879 (event->button.window == button_window[0]) &&
1880 (event->button.button == button_number[0]))
1882 gdk_synthesize_click (event, 2);
1884 button_click_time[1] = button_click_time[0];
1885 button_click_time[0] = event->button.time;
1886 button_window[1] = button_window[0];
1887 button_window[0] = event->button.window;
1888 button_number[1] = button_number[0];
1889 button_number[0] = event->button.button;
1893 button_click_time[1] = 0;
1894 button_click_time[0] = event->button.time;
1895 button_window[1] = NULL;
1896 button_window[0] = event->button.window;
1897 button_number[1] = -1;
1898 button_number[0] = event->button.button;
1901 && window_private->dnd_drag_enabled
1902 && !dnd_drag_perhaps
1903 && !gdk_dnd.drag_really)
1905 dnd_drag_perhaps = 1;
1906 dnd_drag_start.x = xevent->xbutton.x_root;
1907 dnd_drag_start.y = xevent->xbutton.y_root;
1908 real_sw = window_private;
1910 if(gdk_dnd.drag_startwindows)
1912 g_free(gdk_dnd.drag_startwindows);
1913 gdk_dnd.drag_startwindows = NULL;
1915 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1916 dnd_grabbed = FALSE;
1919 /* Set motion mask for first DnD'd window, since it
1920 will be the one that is actually dragged */
1921 XWindowAttributes dnd_winattr;
1922 XSetWindowAttributes dnd_setwinattr;
1924 /* We need to get motion events while the button is down, so
1925 we can know whether to really start dragging or not... */
1926 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1929 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1930 dnd_setwinattr.event_mask =
1931 window_private->dnd_drag_eventmask = ButtonMotionMask | EnterWindowMask | LeaveWindowMask;
1932 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1933 CWEventMask, &dnd_setwinattr);
1936 return_val = window_private && !window_private->destroyed;
1940 /* Print debugging info.
1942 if (gdk_show_events)
1943 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
1944 window_private?window_private->dnd_drag_enabled:0,
1945 xevent->xbutton.window - base_id,
1946 xevent->xbutton.x, xevent->xbutton.y,
1947 xevent->xbutton.button);
1949 if (window_private &&
1950 (window_private->extension_events != 0) &&
1951 gdk_input_ignore_core)
1954 event->button.type = GDK_BUTTON_RELEASE;
1955 event->button.window = window;
1956 event->button.time = xevent->xbutton.time;
1957 event->button.x = xevent->xbutton.x;
1958 event->button.y = xevent->xbutton.y;
1959 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1960 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1961 event->button.pressure = 0.5;
1962 event->button.xtilt = 0;
1963 event->button.ytilt = 0;
1964 event->button.state = (GdkModifierType) xevent->xbutton.state;
1965 event->button.button = xevent->xbutton.button;
1966 event->button.source = GDK_SOURCE_MOUSE;
1967 event->button.deviceid = GDK_CORE_POINTER;
1969 if(dnd_drag_perhaps)
1972 XSetWindowAttributes attrs;
1973 /* Reset event mask to pre-drag value, assuming event_mask
1974 doesn't change during drag */
1975 attrs.event_mask = real_sw->dnd_drag_savedeventmask;
1976 XChangeWindowAttributes(gdk_display, real_sw->xwindow,
1977 CWEventMask, &attrs);
1982 XUngrabPointer(gdk_display, CurrentTime);
1983 dnd_grabbed = FALSE;
1986 if(gdk_dnd.drag_really)
1989 foo.x = xevent->xbutton.x_root;
1990 foo.y = xevent->xbutton.y_root;
1992 if(dnd_drag_target != None)
1993 gdk_dnd_drag_end(dnd_drag_target, foo);
1994 gdk_dnd.drag_really = 0;
1996 gdk_dnd.drag_numwindows = 0;
1997 if(gdk_dnd.drag_startwindows)
1999 g_free(gdk_dnd.drag_startwindows);
2000 gdk_dnd.drag_startwindows = NULL;
2006 dnd_drag_perhaps = 0;
2007 dnd_drag_start.x = dnd_drag_start.y = 0;
2008 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2009 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2010 dnd_drag_curwin = None;
2011 return_val = window_private?TRUE:FALSE;
2013 return_val = window_private && !window_private->destroyed;
2017 /* Print debugging info.
2019 if (gdk_show_events)
2020 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2021 xevent->xmotion.window - base_id,
2022 xevent->xmotion.x, xevent->xmotion.y,
2023 (xevent->xmotion.is_hint) ? "true" : "false",
2024 dnd_drag_perhaps, gdk_dnd.drag_really);
2026 if (window_private &&
2027 (window_private->extension_events != 0) &&
2028 gdk_input_ignore_core)
2031 event->motion.type = GDK_MOTION_NOTIFY;
2032 event->motion.window = window;
2033 event->motion.time = xevent->xmotion.time;
2034 event->motion.x = xevent->xmotion.x;
2035 event->motion.y = xevent->xmotion.y;
2036 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2037 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2038 event->motion.pressure = 0.5;
2039 event->motion.xtilt = 0;
2040 event->motion.ytilt = 0;
2041 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2042 event->motion.is_hint = xevent->xmotion.is_hint;
2043 event->motion.source = GDK_SOURCE_MOUSE;
2044 event->motion.deviceid = GDK_CORE_POINTER;
2046 #define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
2047 && cy >= dnd_drag_dropzone.y \
2048 && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
2049 && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
2051 if(dnd_drag_perhaps && gdk_dnd.drag_really)
2053 /* First, we have to find what window the motion was in... */
2054 /* XXX there has to be a better way to do this, perhaps with
2055 XTranslateCoordinates or XQueryTree - I don't know how,
2056 and this sort of works */
2057 static Window lastwin = None, curwin = None, twin;
2058 Window childwin = gdk_root_window;
2061 curwin = gdk_root_window;
2062 ox = x = xevent->xmotion.x_root;
2063 oy = y = xevent->xmotion.y_root;
2064 while(childwin != None)
2068 XTranslateCoordinates(gdk_display, curwin, curwin,
2069 x, y, &x, &y, &childwin);
2070 if(childwin != None)
2072 XTranslateCoordinates(gdk_display, curwin, childwin,
2073 x, y, &x, &y, &twin);
2076 #if defined(DEBUG_DND) /* && defined(DEBUG_DND_MORE_DETAILS) */
2077 g_print("Drag is now in window %#x, lastwin was %#x, ddc = %#x\n",
2078 curwin, lastwin, dnd_drag_curwin);
2080 if(curwin != dnd_drag_curwin && curwin != lastwin)
2082 /* We have left one window and entered another
2083 (do leave & enter bits) */
2084 if(dnd_drag_curwin != None)
2085 gdk_dnd_drag_leave(dnd_drag_curwin);
2086 dnd_drag_curwin = curwin;
2087 gdk_dnd_drag_enter(dnd_drag_curwin);
2088 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2089 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2090 dnd_drag_target = None;
2092 g_print("curwin = %#x, lastwin = %#x, dnd_drag_curwin = %#x\n",
2093 curwin, lastwin, dnd_drag_curwin);
2095 XChangeActivePointerGrab(gdk_display,
2097 ButtonPressMask | ButtonReleaseMask,
2098 gdk_dnd.gdk_cursor_dragdefault,
2101 else if(dnd_drag_dropzone.width > 0
2102 && dnd_drag_dropzone.height > 0
2103 && curwin == dnd_drag_curwin)
2105 /* Handle all that dropzone stuff - thanks John ;-) */
2106 if (dnd_drag_target != None)
2108 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2109 xevent->xmotion.y_root);
2110 gboolean old_in_zone = IS_IN_ZONE(dnd_drag_oldpos.x,
2113 if (!in_zone && old_in_zone)
2115 /* We were in the drop zone and moved out */
2116 dnd_drag_target = None;
2117 gdk_dnd_drag_leave(curwin);
2119 else if (!in_zone && !old_in_zone)
2121 /* We were outside drop zone but in the window
2122 - have to send enter events */
2123 gdk_dnd_drag_enter(curwin);
2124 dnd_drag_curwin = curwin;
2125 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2126 dnd_drag_target = None;
2130 dnd_drag_curwin = None; */
2134 return_val = window_private && !window_private->destroyed;
2138 /* Print debugging info.
2140 #if !(defined(DEBUG_DND) && defined(DEBUG_DND_MORE_DETAILS))
2141 if (gdk_show_events)
2143 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2144 xevent->xcrossing.window - base_id,
2145 xevent->xcrossing.detail,
2146 xevent->xcrossing.subwindow - base_id);
2148 /* Tell XInput stuff about it if appropriate */
2149 if (window_private &&
2150 (window_private->extension_events != 0) &&
2151 gdk_input_vtable.enter_event)
2152 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2154 event->crossing.type = GDK_ENTER_NOTIFY;
2155 event->crossing.window = window;
2157 /* If the subwindow field of the XEvent is non-NULL, then
2158 * lookup the corresponding GdkWindow.
2160 if (xevent->xcrossing.subwindow != None)
2161 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2163 event->crossing.subwindow = NULL;
2165 /* Translate the crossing detail into Gdk terms.
2167 switch (xevent->xcrossing.detail)
2169 case NotifyInferior:
2170 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2172 case NotifyAncestor:
2173 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2176 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2178 case NotifyNonlinear:
2179 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2181 case NotifyNonlinearVirtual:
2182 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2185 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2190 if(dnd_drag_perhaps)
2192 g_print("We may[%d] have a drag into %#x = %#x\n",
2193 gdk_dnd.drag_really,
2194 xevent->xcrossing.window, real_sw->xwindow);
2197 if (dnd_drag_perhaps && gdk_dnd.drag_really &&
2198 (xevent->xcrossing.window == real_sw->xwindow))
2200 gdk_dnd.drag_really = 0;
2202 g_print("Ungrabbed\n");
2204 gdk_dnd.drag_numwindows = 0;
2205 g_free(gdk_dnd.drag_startwindows);
2206 gdk_dnd.drag_startwindows = NULL;
2207 /* We don't want to ungrab the pointer here, or we'll
2208 * start getting spurious enter/leave events */
2209 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2212 return_val = window_private && !window_private->destroyed;
2216 /* Print debugging info.
2218 #if !(defined(DEBUG_DND) && defined(DEBUG_DND_MORE_DETAILS))
2219 if (gdk_show_events)
2221 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2222 xevent->xcrossing.window - base_id,
2223 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
2225 event->crossing.type = GDK_LEAVE_NOTIFY;
2226 event->crossing.window = window;
2228 /* If the subwindow field of the XEvent is non-NULL, then
2229 * lookup the corresponding GdkWindow.
2231 if (xevent->xcrossing.subwindow != None)
2232 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2234 event->crossing.subwindow = NULL;
2236 /* Translate the crossing detail into Gdk terms.
2238 switch (xevent->xcrossing.detail)
2240 case NotifyInferior:
2241 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2243 case NotifyAncestor:
2244 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2247 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2249 case NotifyNonlinear:
2250 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2252 case NotifyNonlinearVirtual:
2253 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2256 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2260 if(dnd_drag_perhaps)
2262 g_print("We may[%d] have a drag out of %#x = %#x\n",
2263 gdk_dnd.drag_really,
2264 xevent->xcrossing.window, real_sw->xwindow);
2267 if (dnd_drag_perhaps && !gdk_dnd.drag_really &&
2268 (xevent->xcrossing.window == real_sw->xwindow))
2270 gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
2271 gdk_dnd_drag_begin((GdkWindow *) real_sw);
2272 XGrabPointer(gdk_display, real_sw->xwindow, False,
2274 ButtonPressMask | ButtonReleaseMask,
2275 GrabModeAsync, GrabModeAsync, gdk_root_window,
2276 gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
2278 gdk_dnd.drag_really = 1;
2281 return_val = window_private && !window_private->destroyed;
2286 /* We only care about focus events that indicate that _this_
2287 * window (not a ancestor or child) got or lost the focus
2289 switch (xevent->xfocus.detail)
2291 case NotifyAncestor:
2292 case NotifyInferior:
2293 case NotifyNonlinear:
2294 /* Print debugging info.
2296 if (gdk_show_events)
2297 g_print ("focus %s:\t\twindow: %ld\n",
2298 (xevent->xany.type == FocusIn) ? "in" : "out",
2299 xevent->xfocus.window - base_id);
2301 event->focus_change.type = GDK_FOCUS_CHANGE;
2302 event->focus_change.window = window;
2303 event->focus_change.in = (xevent->xany.type == FocusIn);
2305 return_val = window_private && !window_private->destroyed;
2313 /* Print debugging info.
2315 if (gdk_show_events)
2316 g_print ("keymap notify\n");
2318 /* Not currently handled */
2322 /* Print debugging info.
2324 if (gdk_show_events)
2325 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2326 xevent->xexpose.window - base_id, xevent->xexpose.count,
2327 xevent->xexpose.x, xevent->xexpose.y,
2328 xevent->xexpose.width, xevent->xexpose.height);
2330 event->expose.type = GDK_EXPOSE;
2331 event->expose.window = window;
2332 event->expose.area.x = xevent->xexpose.x;
2333 event->expose.area.y = xevent->xexpose.y;
2334 event->expose.area.width = xevent->xexpose.width;
2335 event->expose.area.height = xevent->xexpose.height;
2336 event->expose.count = xevent->xexpose.count;
2338 return_val = window_private && !window_private->destroyed;
2341 case GraphicsExpose:
2342 /* Print debugging info.
2344 if (gdk_show_events)
2345 g_print ("graphics expose:\tdrawable: %ld\n",
2346 xevent->xgraphicsexpose.drawable - base_id);
2348 event->expose.type = GDK_EXPOSE;
2349 event->expose.window = window;
2350 event->expose.area.x = xevent->xgraphicsexpose.x;
2351 event->expose.area.y = xevent->xgraphicsexpose.y;
2352 event->expose.area.width = xevent->xgraphicsexpose.width;
2353 event->expose.area.height = xevent->xgraphicsexpose.height;
2354 event->expose.count = xevent->xexpose.count;
2356 return_val = window_private && !window_private->destroyed;
2360 /* Print debugging info.
2362 if (gdk_show_events)
2363 g_print ("no expose:\t\tdrawable: %ld\n",
2364 xevent->xnoexpose.drawable - base_id);
2366 event->no_expose.type = GDK_NO_EXPOSE;
2367 event->no_expose.window = window;
2369 return_val = window_private && !window_private->destroyed;
2372 case VisibilityNotify:
2373 /* Print debugging info.
2375 if (gdk_show_events)
2376 switch (xevent->xvisibility.state)
2378 case VisibilityFullyObscured:
2379 g_print ("visibility notify:\twindow: %ld none\n",
2380 xevent->xvisibility.window - base_id);
2382 case VisibilityPartiallyObscured:
2383 g_print ("visibility notify:\twindow: %ld partial\n",
2384 xevent->xvisibility.window - base_id);
2386 case VisibilityUnobscured:
2387 g_print ("visibility notify:\twindow: %ld full\n",
2388 xevent->xvisibility.window - base_id);
2392 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2393 event->visibility.window = window;
2395 switch (xevent->xvisibility.state)
2397 case VisibilityFullyObscured:
2398 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2401 case VisibilityPartiallyObscured:
2402 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2405 case VisibilityUnobscured:
2406 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2410 return_val = window_private && !window_private->destroyed;
2414 /* Not currently handled */
2418 /* Print debugging info.
2420 if (gdk_show_events)
2421 g_print ("destroy notify:\twindow: %ld\n",
2422 xevent->xdestroywindow.window - base_id);
2424 event->any.type = GDK_DESTROY;
2425 event->any.window = window;
2427 return_val = window_private && !window_private->destroyed;
2429 gdk_window_destroy_notify (window);
2433 /* Print debugging info.
2435 if (gdk_show_events)
2436 g_print ("unmap notify:\t\twindow: %ld\n",
2437 xevent->xmap.window - base_id);
2439 event->any.type = GDK_UNMAP;
2440 event->any.window = window;
2442 if (xgrab_window == window_private)
2443 xgrab_window = NULL;
2445 return_val = window_private && !window_private->destroyed;
2449 /* Print debugging info.
2451 if (gdk_show_events)
2452 g_print ("map notify:\t\twindow: %ld\n",
2453 xevent->xmap.window - base_id);
2455 event->any.type = GDK_MAP;
2456 event->any.window = window;
2458 return_val = window_private && !window_private->destroyed;
2461 case ReparentNotify:
2462 /* Print debugging info.
2464 if (gdk_show_events)
2465 g_print ("reparent notify:\twindow: %ld\n",
2466 xevent->xreparent.window - base_id);
2468 /* Not currently handled */
2471 case ConfigureNotify:
2472 /* Print debugging info.
2474 while ((XPending (gdk_display) > 0) &&
2475 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2476 ConfigureNotify, xevent))
2477 /*XSync (gdk_display, 0)*/;
2479 if (gdk_show_events)
2480 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2481 xevent->xconfigure.window - base_id,
2482 xevent->xconfigure.x,
2483 xevent->xconfigure.y,
2484 xevent->xconfigure.width,
2485 xevent->xconfigure.height,
2486 xevent->xconfigure.border_width,
2487 xevent->xconfigure.above - base_id,
2488 xevent->xconfigure.override_redirect);
2492 if ((window_private->extension_events != 0) &&
2493 gdk_input_vtable.configure_event)
2494 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2496 if (window_private->window_type != GDK_WINDOW_CHILD)
2498 event->configure.type = GDK_CONFIGURE;
2499 event->configure.window = window;
2500 event->configure.width = xevent->xconfigure.width;
2501 event->configure.height = xevent->xconfigure.height;
2503 if (!xevent->xconfigure.x &&
2504 !xevent->xconfigure.y)
2508 Window child_window = 0;
2510 if (!XTranslateCoordinates (window_private->xdisplay,
2511 window_private->xwindow,
2516 g_warning ("GdkWindow %ld doesn't share root windows display?",
2517 window_private->xwindow - base_id);
2518 event->configure.x = tx;
2519 event->configure.y = ty;
2523 event->configure.x = xevent->xconfigure.x;
2524 event->configure.y = xevent->xconfigure.y;
2526 window_private->x = event->configure.x;
2527 window_private->y = event->configure.y;
2528 window_private->width = xevent->xconfigure.width;
2529 window_private->height = xevent->xconfigure.height;
2530 if (window_private->resize_count > 1)
2531 window_private->resize_count -= 1;
2533 return_val = !window_private->destroyed;
2538 case PropertyNotify:
2539 /* Print debugging info.
2541 if (gdk_show_events)
2542 g_print ("property notify:\twindow: %ld\n",
2543 xevent->xproperty.window - base_id);
2545 event->property.type = GDK_PROPERTY_NOTIFY;
2546 event->property.window = window;
2547 event->property.atom = xevent->xproperty.atom;
2548 event->property.time = xevent->xproperty.time;
2549 event->property.state = xevent->xproperty.state;
2551 return_val = window_private && !window_private->destroyed;
2554 case SelectionClear:
2555 if (gdk_show_events)
2556 g_print ("selection clear:\twindow: %ld\n",
2557 xevent->xproperty.window - base_id);
2559 event->selection.type = GDK_SELECTION_CLEAR;
2560 event->selection.window = window;
2561 event->selection.selection = xevent->xselectionclear.selection;
2562 event->selection.time = xevent->xselectionclear.time;
2564 return_val = window_private && !window_private->destroyed;
2567 case SelectionRequest:
2568 if (gdk_show_events)
2569 g_print ("selection request:\twindow: %ld\n",
2570 xevent->xproperty.window - base_id);
2572 event->selection.type = GDK_SELECTION_REQUEST;
2573 event->selection.window = window;
2574 event->selection.selection = xevent->xselectionrequest.selection;
2575 event->selection.target = xevent->xselectionrequest.target;
2576 event->selection.property = xevent->xselectionrequest.property;
2577 event->selection.requestor = xevent->xselectionrequest.requestor;
2578 event->selection.time = xevent->xselectionrequest.time;
2580 return_val = window_private && !window_private->destroyed;
2583 case SelectionNotify:
2584 if (gdk_show_events)
2585 g_print ("selection notify:\twindow: %ld\n",
2586 xevent->xproperty.window - base_id);
2589 event->selection.type = GDK_SELECTION_NOTIFY;
2590 event->selection.window = window;
2591 event->selection.selection = xevent->xselection.selection;
2592 event->selection.target = xevent->xselection.target;
2593 event->selection.property = xevent->xselection.property;
2594 event->selection.time = xevent->xselection.time;
2596 return_val = window_private && !window_private->destroyed;
2599 case ColormapNotify:
2600 /* Print debugging info.
2602 if (gdk_show_events)
2603 g_print ("colormap notify:\twindow: %ld\n",
2604 xevent->xcolormap.window - base_id);
2606 /* Not currently handled */
2610 /* Print debugging info.
2612 if (gdk_show_events)
2613 g_print ("client message:\twindow: %ld\n",
2614 xevent->xclient.window - base_id);
2616 /* Client messages are the means of the window manager
2617 * communicating with a program. We'll first check to
2618 * see if this is really the window manager talking
2621 if (xevent->xclient.message_type == gdk_wm_protocols)
2623 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2625 /* The delete window request specifies a window
2626 * to delete. We don't actually destroy the
2627 * window because "it is only a request". (The
2628 * window might contain vital data that the
2629 * program does not want destroyed). Instead
2630 * the event is passed along to the program,
2631 * which should then destroy the window.
2634 /* Print debugging info.
2636 if (gdk_show_events)
2637 g_print ("delete window:\t\twindow: %ld\n",
2638 xevent->xclient.window - base_id);
2640 event->any.type = GDK_DELETE;
2641 event->any.window = window;
2643 return_val = window_private && !window_private->destroyed;
2645 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2649 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2653 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2655 if (gdk_show_events)
2657 g_print ("GDK_DROP_ENTER [%d][%d]\n",
2658 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply);
2661 /* Now figure out if we really want this drop...
2662 * If someone is trying funky clipboard stuff, ignore
2665 && window_private->dnd_drop_enabled
2666 && event->dropenter.u.flags.sendreply
2667 && (reptype = gdk_dnd_check_types (window, xevent)))
2671 replyev.xclient.type = ClientMessage;
2672 replyev.xclient.window = xevent->xclient.data.l[0];
2673 replyev.xclient.format = 32;
2674 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2675 replyev.xclient.data.l[0] = window_private->xwindow;
2677 event->dragrequest.u.allflags = 0;
2678 event->dragrequest.u.flags.protocol_version =
2679 DND_PROTOCOL_VERSION;
2680 event->dragrequest.u.flags.willaccept = 1;
2681 event->dragrequest.u.flags.delete_data =
2682 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2684 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2685 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2686 replyev.xclient.data.l[4] = reptype;
2688 XSendEvent (gdk_display, replyev.xclient.window,
2689 False, NoEventMask, &replyev);
2691 event->any.type = GDK_DROP_ENTER;
2692 event->any.window = window;
2693 event->dropenter.requestor = replyev.xclient.window;
2694 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2696 g_print("We sent a GDK_DROP_ENTER on to Gtk\n");
2701 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2704 if (gdk_show_events)
2706 g_print ("GDK_DROP_LEAVE\n");
2707 if (window_private && window_private->dnd_drop_enabled)
2709 event->dropleave.type = GDK_DROP_LEAVE;
2710 event->dropleave.window = window;
2711 event->dropleave.requestor = xevent->xclient.data.l[0];
2712 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2718 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2721 * make sure to only handle requests from the window the cursor is
2725 if (gdk_show_events)
2727 g_print ("GDK_DRAG_REQUEST\n");
2728 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2731 if (window && gdk_dnd.drag_really &&
2732 xevent->xclient.data.l[0] == dnd_drag_curwin &&
2733 event->dragrequest.u.flags.sendreply == 0)
2735 /* Got request - do we need to ask user? */
2736 if (!event->dragrequest.u.flags.willaccept
2737 && event->dragrequest.u.flags.senddata)
2740 event->dragrequest.type = GDK_DRAG_REQUEST;
2741 event->dragrequest.window = window;
2742 event->dragrequest.requestor = xevent->xclient.data.l[0];
2743 event->dragrequest.isdrop = 0;
2744 event->dragrequest.drop_coords.x =
2745 event->dragrequest.drop_coords.y = 0;
2748 else if (event->dragrequest.u.flags.willaccept)
2750 window_private->dnd_drag_destructive_op =
2751 event->dragrequest.u.flags.delete_data;
2752 window_private->dnd_drag_accepted = 1;
2753 window_private->dnd_drag_data_type =
2754 xevent->xclient.data.l[4];
2756 dnd_drag_target = dnd_drag_curwin;
2757 XChangeActivePointerGrab (gdk_display,
2761 EnterWindowMask | LeaveWindowMask,
2762 gdk_dnd.gdk_cursor_dragok,
2765 dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2766 dnd_drag_dropzone.y =
2767 (xevent->xclient.data.l[2] >> 16) & 65535;
2768 dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2769 dnd_drag_dropzone.height =
2770 (xevent->xclient.data.l[3] >> 16) & 65535;
2773 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2775 gint tmp_int; Atom tmp_atom;
2777 guchar *tmp_charptr;
2782 g_print("GDK_DROP_DATA_AVAIL\n");
2783 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2785 /* No preview of data ATM */
2786 && event->dropdataavailable.u.flags.isdrop)
2788 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2789 event->dropdataavailable.window = window;
2790 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2791 event->dropdataavailable.data_type =
2792 gdk_atom_name(xevent->xclient.data.l[2]);
2793 if(XGetWindowProperty (gdk_display,
2794 event->dropdataavailable.requestor,
2795 xevent->xclient.data.l[2],
2797 False, XA_PRIMARY, &tmp_atom,
2799 &event->dropdataavailable.data_numbytes,
2804 g_warning("XGetWindowProperty on %#x may have failed\n",
2805 event->dropdataavailable.requestor);
2806 event->dropdataavailable.data = NULL;
2811 g_print("XGetWindowProperty got us %d bytes\n",
2812 event->dropdataavailable.data_numbytes);
2814 event->dropdataavailable.data =
2815 g_malloc (event->dropdataavailable.data_numbytes);
2816 memcpy (event->dropdataavailable.data,
2817 tmp_charptr, event->dropdataavailable.data_numbytes);
2826 /* Send unknown ClientMessage's on to Gtk for it to use */
2827 event->client.type = GDK_CLIENT_EVENT;
2828 event->client.window = window;
2829 event->client.message_type = xevent->xclient.message_type;
2830 event->client.data_format = xevent->xclient.format;
2831 memcpy(&event->client.data, &xevent->xclient.data,
2832 sizeof(event->client.data));
2839 return_val = return_val && !window_private->destroyed;
2843 /* Print debugging info.
2845 if (gdk_show_events)
2846 g_print ("mapping notify\n");
2848 /* Let XLib know that there is a new keyboard mapping.
2850 XRefreshKeyboardMapping (&xevent->xmapping);
2854 /* something else - (e.g., a Xinput event) */
2856 if (window_private &&
2857 (window_private->extension_events != 0) &&
2858 gdk_input_vtable.other_event)
2859 return_val = gdk_input_vtable.other_event(event, xevent, window);
2863 if (return_val < 0) /* not an XInput event, convert */
2865 event->other.type = GDK_OTHER_EVENT;
2866 event->other.window = window;
2867 event->other.xevent = (GdkXEvent *)&other_xevent[other_xevent_i];
2868 memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
2869 other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
2873 return_val = return_val && !window_private->destroyed;
2880 if (event->any.window)
2881 gdk_window_ref (event->any.window);
2882 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2883 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2884 (event->crossing.subwindow != NULL))
2885 gdk_window_ref (event->crossing.subwindow);
2889 /* Mark this event as having no resources to be freed */
2890 event->any.window = NULL;
2891 event->any.type = GDK_NOTHING;
2895 gdk_window_unref (window);
2902 gdk_event_get_type (Display *display,
2909 if (gdk_event_translate (&event, xevent))
2911 pred = (GdkPredicate*) arg;
2912 return (* pred->func) (&event, pred->data);
2920 gdk_synthesize_click (GdkEvent *event,
2923 GdkEvent temp_event;
2925 g_return_if_fail (event != NULL);
2927 temp_event = *event;
2928 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2930 gdk_event_put (&temp_event);
2934 *--------------------------------------------------------------
2937 * This is the "atexit" function that makes sure the
2938 * library gets a chance to cleanup.
2945 * The library is un-initialized and the program exits.
2947 *--------------------------------------------------------------
2953 static gboolean in_gdk_exit_func = FALSE;
2955 /* This is to avoid an infinite loop if a program segfaults in
2956 an atexit() handler (and yes, it does happen, especially if a program
2957 has trounced over memory too badly for even g_print to work) */
2958 if(in_gdk_exit_func == TRUE) return;
2959 in_gdk_exit_func = TRUE;
2971 gdk_key_repeat_restore ();
2973 XCloseDisplay (gdk_display);
2979 *--------------------------------------------------------------
2982 * The X error handling routine.
2985 * "display" is the X display the error orignated from.
2986 * "error" is the XErrorEvent that we are handling.
2989 * Either we were expecting some sort of error to occur,
2990 * in which case we set the "gdk_error_code" flag, or this
2991 * error was unexpected, in which case we will print an
2992 * error message and exit. (Since trying to continue will
2993 * most likely simply lead to more errors).
2997 *--------------------------------------------------------------
3001 gdk_x_error (Display *display,
3006 if (gdk_error_warnings)
3008 XGetErrorText (display, error->error_code, buf, 63);
3009 g_error ("%s", buf);
3012 gdk_error_code = -1;
3017 *--------------------------------------------------------------
3020 * The X I/O error handling routine.
3023 * "display" is the X display the error orignated from.
3026 * An X I/O error basically means we lost our connection
3027 * to the X server. There is not much we can do to
3028 * continue, so simply print an error message and exit.
3032 *--------------------------------------------------------------
3036 gdk_x_io_error (Display *display)
3038 g_error ("an x io error occurred");
3043 *--------------------------------------------------------------
3046 * The signal handler.
3049 * "sig_num" is the number of the signal we received.
3052 * The signals we catch are all fatal. So we simply build
3053 * up a nice little error message and print it and exit.
3054 * If in the process of doing so another signal is received
3055 * we notice that we are already exiting and simply kill
3060 *--------------------------------------------------------------
3064 gdk_signal (int sig_num)
3066 static int caught_fatal_sig = 0;
3069 if (caught_fatal_sig)
3070 kill (getpid (), sig_num);
3071 caught_fatal_sig = 1;
3097 sig = "unknown signal";
3101 g_print ("\n** ERROR **: %s caught\n", sig);
3106 gdk_dnd_drag_begin (GdkWindow *initial_window)
3108 GdkEventDragBegin tev;
3109 tev.type = GDK_DRAG_BEGIN;
3110 tev.window = initial_window;
3112 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3114 gdk_event_put ((GdkEvent *) &tev);
3118 gdk_dnd_drag_enter (Window dest)
3121 GdkEventDropEnter tev;
3123 GdkWindowPrivate *wp;
3125 sev.xclient.type = ClientMessage;
3126 sev.xclient.format = 32;
3127 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3128 sev.xclient.window = dest;
3131 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3132 tev.u.flags.sendreply = 1;
3133 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3135 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3136 if (wp->dnd_drag_data_numtypesavail)
3138 sev.xclient.data.l[0] = wp->xwindow;
3139 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3140 sev.xclient.data.l[1] = tev.u.allflags;
3141 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3142 if (wp->dnd_drag_data_numtypesavail > 1)
3144 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3145 if (wp->dnd_drag_data_numtypesavail > 2)
3147 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3150 sev.xclient.data.l[4] = None;
3153 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3154 XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
3164 *--------------------------------------------------------------
3167 * Begin using input method with XIM Protocol(X11R6 standard)
3170 * "ic" is the "Input Context" which is created by gtk_ic_new.
3171 * The input area is specified with "window".
3174 * The gdk's event handling routine is switched to XIM based routine.
3175 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3176 * and uses XmbLookupString instead of XLookupString.
3180 *--------------------------------------------------------------
3184 gdk_im_begin (GdkIC ic, GdkWindow* window)
3186 GdkICPrivate *private;
3189 g_return_if_fail (ic != NULL);
3190 g_return_if_fail (window);
3192 private = (GdkICPrivate *) ic;
3196 xim_window = window;
3199 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3200 if (xwin != GDK_WINDOW_XWINDOW(window))
3201 XSetICValues (private->xic, XNFocusWindow,
3202 GDK_WINDOW_XWINDOW(window), NULL);
3203 if (private != xim_ic)
3204 XSetICFocus (private->xic);
3209 *--------------------------------------------------------------
3212 * End using input method with XIM Protocol(X11R6 standard)
3217 * The gdk's event handling routine is switched to normal routine.
3218 * User should call this function before ic and window will be destroyed.
3222 *--------------------------------------------------------------
3240 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3242 GdkIMStyle s1, s2, u;
3244 if (style1 == 0) return style2;
3245 if (style2 == 0) return style1;
3246 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3247 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3250 s1 = style1 & GdkIMPreeditMask;
3251 s2 = style2 & GdkIMPreeditMask;
3254 if (u & GdkIMPreeditCallbacks)
3255 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3256 else if (u & GdkIMPreeditPosition)
3257 return (s1 == GdkIMPreeditPosition)? style1:style2;
3258 else if (u & GdkIMPreeditArea)
3259 return (s1 == GdkIMPreeditArea)? style1:style2;
3260 else if (u & GdkIMPreeditNothing)
3261 return (s1 == GdkIMPreeditNothing)? style1:style2;
3263 s1 = style1 & GdkIMStatusMask;
3264 s2 = style2 & GdkIMStatusMask;
3266 if ( u & GdkIMStatusCallbacks)
3267 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3268 else if ( u & GdkIMStatusArea)
3269 return (s1 == GdkIMStatusArea)? style1:style2;
3270 else if ( u & GdkIMStatusNothing)
3271 return (s1 == GdkIMStatusNothing)? style1:style2;
3272 else if ( u & GdkIMStatusNone)
3273 return (s1 == GdkIMStatusNone)? style1:style2;
3275 return 0; /* Get rid of stupid warning */
3279 gdk_im_decide_style (GdkIMStyle supported_style)
3282 GdkIMStyle style, tmp;
3284 g_return_val_if_fail (xim_styles != NULL, 0);
3287 for (i=0; i<xim_styles->count_styles; i++)
3289 tmp = xim_styles->supported_styles[i];
3290 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3291 style = gdk_im_choose_better_style (style, tmp);
3297 gdk_im_set_best_style (GdkIMStyle style)
3299 if (style & GdkIMPreeditMask)
3301 xim_best_allowed_style &= ~GdkIMPreeditMask;
3303 xim_best_allowed_style |= GdkIMPreeditNone;
3304 if (!(style & GdkIMPreeditNone))
3306 xim_best_allowed_style |= GdkIMPreeditNothing;
3307 if (!(style & GdkIMPreeditNothing))
3309 xim_best_allowed_style |= GdkIMPreeditArea;
3310 if (!(style & GdkIMPreeditArea))
3312 xim_best_allowed_style |= GdkIMPreeditPosition;
3313 if (!(style & GdkIMPreeditPosition))
3314 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3319 if (style & GdkIMStatusMask)
3321 xim_best_allowed_style &= ~GdkIMStatusMask;
3323 xim_best_allowed_style |= GdkIMStatusNone;
3324 if (!(style & GdkIMStatusNone))
3326 xim_best_allowed_style |= GdkIMStatusNothing;
3327 if (!(style & GdkIMStatusNothing))
3329 xim_best_allowed_style |= GdkIMStatusArea;
3330 if (!(style & GdkIMStatusArea))
3331 xim_best_allowed_style |= GdkIMStatusCallbacks;
3336 return xim_best_allowed_style;
3340 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3342 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3345 g_warning ("Don\'t open IM.");
3348 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3371 return (xim_im != NULL);
3375 gdk_ic_new (GdkWindow* client_window,
3376 GdkWindow* focus_window,
3377 GdkIMStyle style, ...)
3380 GdkICPrivate *private;
3381 XVaNestedList preedit_attr;
3383 g_return_val_if_fail (client_window != NULL, NULL);
3384 g_return_val_if_fail (focus_window != NULL, NULL);
3385 g_return_val_if_fail (gdk_im_ready(), NULL);
3387 private = g_new (GdkICPrivate, 1);
3389 va_start (list, style);
3390 preedit_attr = (XVaNestedList) & (va_arg (list, void *));
3393 private->style = gdk_im_decide_style (style);
3394 if (private->style != style)
3396 g_warning ("can not create input context with specified input style.");
3401 private->xic = XCreateIC(gdk_im_get (),
3402 XNInputStyle, style,
3403 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3404 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3405 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3413 xim_ic_list = g_list_append (xim_ic_list, private);
3418 gdk_ic_destroy (GdkIC ic)
3420 GdkICPrivate *private;
3422 g_return_if_fail (ic != NULL);
3424 private = (GdkICPrivate *) ic;
3426 if (xim_ic == private)
3429 XDestroyIC (private->xic);
3430 xim_ic_list = g_list_remove (xim_ic_list, private);
3434 gdk_ic_get_style (GdkIC ic)
3436 GdkICPrivate *private;
3438 g_return_val_if_fail (ic != NULL, 0);
3440 private = (GdkICPrivate *) ic;
3442 return private->style;
3446 gdk_ic_set_values (GdkIC ic, ...)
3450 GdkICPrivate *private;
3452 g_return_if_fail (ic != NULL);
3454 private = (GdkICPrivate *) ic;
3456 va_start (list, ic);
3457 args = (XVaNestedList) & (va_arg (list, void *));
3460 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3464 gdk_ic_get_values (GdkIC ic, ...)
3468 GdkICPrivate *private;
3470 g_return_if_fail (ic != NULL);
3472 private = (GdkICPrivate *) ic;
3474 va_start (list, ic);
3475 args = (XVaNestedList) & (va_arg (list, void *));
3478 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3482 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3486 GdkICPrivate *private;
3488 g_return_if_fail (ic != NULL);
3489 g_return_if_fail (target != NULL);
3491 private = (GdkICPrivate *) ic;
3493 va_start (list, target);
3494 attr = (XVaNestedList) & (va_arg (list, void *));
3497 XSetICValues (private->xic, target, attr, NULL);
3501 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3505 GdkICPrivate *private;
3507 g_return_if_fail (ic != NULL);
3508 g_return_if_fail (target != NULL);
3510 private = (GdkICPrivate *) ic;
3512 va_start (list, target);
3513 attr = (XVaNestedList) & (va_arg (list, void *));
3516 XGetICValues (private->xic, target, attr, NULL);
3520 gdk_ic_get_events (GdkIC ic)
3525 GdkICPrivate *private;
3528 /* From gdkwindow.c */
3529 extern int nevent_masks;
3530 extern int event_mask_table[];
3532 g_return_val_if_fail (ic != NULL, 0);
3534 private = (GdkICPrivate *) ic;
3536 XGetICValues (private->xic, XNFilterEvents, &xmask, NULL);
3539 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3540 if (xmask & event_mask_table [i])
3543 xmask &= ~ event_mask_table [i];
3547 g_warning ("ic requires the events not supported by the application (%04lx)", xmask);
3553 gdk_ic_cleanup (void)
3557 GdkICPrivate *private;
3560 for (node = xim_ic_list; node != NULL; node = node->next)
3564 private = (GdkICPrivate *) (node->data);
3565 XDestroyIC (private->xic);
3570 if (gdk_debug_level >= 1 && destroyed > 0)
3572 g_warning ("Cleanuped %i IC\n", destroyed);
3574 g_list_free(xim_ic_list);
3578 #else /* !USE_XIM */
3581 gdk_im_begin (GdkIC ic, GdkWindow* window)
3591 gdk_im_decide_style (GdkIMStyle supported_style)
3593 return GdkIMPreeditNone | GdkIMStatusNone;
3597 gdk_im_set_best_style (GdkIMStyle style)
3599 return GdkIMPreeditNone | GdkIMStatusNone;
3609 gdk_ic_new (GdkWindow* client_window,
3610 GdkWindow* focus_window,
3611 GdkIMStyle style, ...)
3617 gdk_ic_destroy (GdkIC ic)
3622 gdk_ic_get_style (GdkIC ic)
3624 return GdkIMPreeditNone | GdkIMStatusNone;
3628 gdk_ic_set_values (GdkIC ic, ...)
3633 gdk_ic_get_values (GdkIC ic, ...)
3638 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3643 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3648 gdk_ic_get_events (GdkIC ic)
3653 #endif /* USE_XIM */
3658 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3660 static wchar_t wcs[MB_CUR_MAX + 1];
3661 static gchar mbs[MB_CUR_MAX + 1];
3663 wcs[0] = (wchar_t) NULL;
3666 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3669 else if (wcs[0] == (wchar_t) NULL)
3672 len = _Xwctomb (mbs, wcs[0]);
3681 #endif /* X_LOCALE */
3684 gdk_dnd_drag_leave (Window dest)
3687 GdkEventDropLeave tev;
3689 GdkWindowPrivate *wp;
3693 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3694 sev.xclient.type = ClientMessage;
3695 sev.xclient.window = dest;
3696 sev.xclient.format = 32;
3697 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3698 sev.xclient.data.l[1] = tev.u.allflags;
3699 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3701 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3702 sev.xclient.data.l[0] = wp->xwindow;
3703 XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
3704 wp->dnd_drag_accepted = 0;
3709 * when a drop occurs, we go through the list of windows being dragged and
3710 * tell them that it has occurred, so that they can set things up and reply
3714 gdk_dnd_drag_end (Window dest,
3717 GdkWindowPrivate *wp;
3718 GdkEventDragRequest tev;
3721 tev.type = GDK_DRAG_REQUEST;
3722 tev.drop_coords = coords;
3723 tev.requestor = dest;
3725 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3728 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3730 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3731 if (wp->dnd_drag_accepted)
3733 tev.window = (GdkWindow *) wp;
3734 tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
3736 gdk_atom_name(wp->dnd_drag_data_type);
3738 gdk_event_put((GdkEvent *) &tev);
3744 gdk_dnd_check_types (GdkWindow *window,
3747 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3749 GdkEventDropEnter event;
3751 g_return_val_if_fail(window != NULL, 0);
3752 g_return_val_if_fail(xevent != NULL, 0);
3753 g_return_val_if_fail(xevent->type == ClientMessage, 0);
3754 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3756 if(wp->dnd_drop_data_numtypesavail <= 0 ||
3757 !wp->dnd_drop_data_typesavail)
3760 for (i = 2; i <= 4; i++)
3762 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3764 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3765 return xevent->xclient.data.l[i];
3769 /* Now we get the extended type list if it's available */
3770 event.u.allflags = xevent->xclient.data.l[1];
3771 if (event.u.flags.extended_typelist)
3773 Atom *exttypes, realtype;
3774 gulong nitems, nbar;
3777 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3778 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
3779 False, AnyPropertyType, &realtype, &realfmt,
3780 &nitems, &nbar, (unsigned char **) &exttypes)
3784 if (realfmt != (sizeof(Atom) * 8))
3786 g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
3787 realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
3791 for (i = 0; i <= nitems; i++)
3793 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3795 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
3808 * used for debugging only
3812 gdk_print_atom (GdkAtom anatom)
3814 gchar *tmpstr = NULL;
3815 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
3816 g_print("Atom %lu has name %s\n", anatom, tmpstr);
3823 * used only by below routine and itself
3826 getchildren (Display *dpy,
3830 Window root, parent, *children, inf = 0;
3832 unsigned int nchildren, i;
3834 unsigned long nitems, after;
3835 unsigned char *data;
3837 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
3840 for (i = 0; !inf && (i < nchildren); i++)
3842 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
3843 AnyPropertyType, &type, &format, &nitems,
3850 for (i = 0; !inf && (i < nchildren); i++)
3851 inf = getchildren (dpy, children[i], WM_STATE);
3853 if (children != None)
3854 XFree ((char *) children);
3860 * find a window with WM_STATE, else return win itself, as per ICCCM
3862 * modification of the XmuClientWindow() routine from X11R6.3
3865 gdk_get_client_window (Display *dpy,
3871 unsigned long nitems, after;
3872 unsigned char *data;
3876 return DefaultRootWindow(dpy);
3878 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
3881 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
3882 &type, &format, &nitems, &after, &data);
3886 inf = getchildren (dpy, win, WM_STATE);
3894 #ifdef WE_HAVE_MOTIF_DROPS_DONE
3896 gdk_drop_get_real_window (GdkWindow *w,
3900 GdkWindow *retval = w;
3901 GdkWindowPrivate *awin;
3903 gint16 myx = *x, myy = *y;
3905 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
3911 for (children = gdk_window_get_children(retval);
3912 children && children->next;
3913 children = children->next)
3915 awin = (GdkWindowPrivate *) children->data;
3916 if ((myx >= awin->x) && (myy >= awin->y)
3917 && (myx < (awin->x + awin->width))
3918 && (myy < (awin->y + awin->height)))
3920 retval = (GdkWindow *) awin;
3934 /* Sends a ClientMessage to all toplevel client windows */
3936 gdk_event_send_clientmessage_toall(GdkEvent *event)
3939 Window *ret_children, ret_root, ret_parent, curwin;
3940 unsigned int ret_nchildren;
3943 g_return_if_fail(event != NULL);
3945 /* Set up our event to send, with the exception of its target window */
3946 sev.xclient.type = ClientMessage;
3947 sev.xclient.display = gdk_display;
3948 sev.xclient.format = event->client.data_format;
3949 sev.xclient.serial = CurrentTime;
3950 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3951 sev.xclient.message_type = event->client.message_type;
3953 /* OK, we're all set, now let's find some windows to send this to */
3954 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
3955 &ret_children, &ret_nchildren) != True)
3958 /* foreach true child window of the root window, send an event to it */
3959 for(i = 0; i < ret_nchildren; i++) {
3960 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
3961 sev.xclient.window = curwin;
3962 XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
3965 XFree(ret_children);
3969 gdk_get_display(void)
3971 return (gchar *)XDisplayName (gdk_display_name);