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)
1289 if (!window_private->destroyed)
1290 return_val = XGrabPointer (window_private->xdisplay,
1294 GrabModeAsync, GrabModeAsync,
1299 return_val = AlreadyGrabbed;
1302 if (return_val == GrabSuccess)
1303 xgrab_window = window_private;
1309 *--------------------------------------------------------------
1310 * gdk_pointer_ungrab
1312 * Releases any pointer grab
1320 *--------------------------------------------------------------
1324 gdk_pointer_ungrab (guint32 time)
1326 if (gdk_input_vtable.ungrab_pointer)
1327 gdk_input_vtable.ungrab_pointer (time);
1329 XUngrabPointer (gdk_display, time);
1330 xgrab_window = NULL;
1334 *--------------------------------------------------------------
1335 * gdk_pointer_is_grabbed
1337 * Tell wether there is an active x pointer grab in effect
1345 *--------------------------------------------------------------
1349 gdk_pointer_is_grabbed (void)
1351 return xgrab_window != NULL;
1355 *--------------------------------------------------------------
1358 * Grabs the keyboard to a specific window
1361 * "window" is the window which will receive the grab
1362 * "owner_events" specifies whether events will be reported as is,
1363 * or relative to "window"
1364 * "time" specifies the time
1369 * requires a corresponding call to gdk_keyboard_ungrab
1371 *--------------------------------------------------------------
1375 gdk_keyboard_grab (GdkWindow * window,
1379 GdkWindowPrivate *window_private;
1382 g_return_val_if_fail (window != NULL, 0);
1384 window_private = (GdkWindowPrivate*) window;
1385 xwindow = window_private->xwindow;
1387 if (!window_private->destroyed)
1388 return XGrabKeyboard (window_private->xdisplay,
1391 GrabModeAsync, GrabModeAsync,
1394 return AlreadyGrabbed;
1398 *--------------------------------------------------------------
1399 * gdk_keyboard_ungrab
1401 * Releases any keyboard grab
1409 *--------------------------------------------------------------
1413 gdk_keyboard_ungrab (guint32 time)
1415 XUngrabKeyboard (gdk_display, time);
1419 *--------------------------------------------------------------
1422 * Return the width of the screen.
1430 *--------------------------------------------------------------
1438 return_val = DisplayWidth (gdk_display, gdk_screen);
1444 *--------------------------------------------------------------
1447 * Return the height of the screen.
1455 *--------------------------------------------------------------
1459 gdk_screen_height ()
1463 return_val = DisplayHeight (gdk_display, gdk_screen);
1469 gdk_key_repeat_disable ()
1471 XAutoRepeatOff (gdk_display);
1475 gdk_key_repeat_restore ()
1478 XAutoRepeatOn (gdk_display);
1480 XAutoRepeatOff (gdk_display);
1485 *--------------------------------------------------------------
1488 * Flushes the Xlib output buffer and then waits
1489 * until all requests have been received and processed
1490 * by the X server. The only real use for this function
1491 * is in dealing with XShm.
1499 *--------------------------------------------------------------
1504 XSync (gdk_display, False);
1511 XBell(gdk_display, 100);
1516 *--------------------------------------------------------------
1519 * Waits until an event occurs or the timer runs out.
1524 * Returns TRUE if an event is ready to be read and FALSE
1525 * if the timer ran out.
1529 *--------------------------------------------------------------
1537 GdkInputCondition condition;
1538 SELECT_MASK readfds;
1539 SELECT_MASK writefds;
1540 SELECT_MASK exceptfds;
1544 /* If there are no events pending we will wait for an event.
1545 * The time we wait is dependant on the "timer". If no timer
1546 * has been specified then we'll block until an event arrives.
1547 * If a timer has been specified we'll block until an event
1548 * arrives or the timer expires. (This is all done using the
1549 * "select" system call).
1552 if (XPending (gdk_display) == 0)
1555 FD_ZERO (&writefds);
1556 FD_ZERO (&exceptfds);
1558 FD_SET (connection_number, &readfds);
1559 max_input = connection_number;
1567 if (input->condition & GDK_INPUT_READ)
1568 FD_SET (input->source, &readfds);
1569 if (input->condition & GDK_INPUT_WRITE)
1570 FD_SET (input->source, &writefds);
1571 if (input->condition & GDK_INPUT_EXCEPTION)
1572 FD_SET (input->source, &exceptfds);
1574 max_input = MAX (max_input, input->source);
1577 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1584 if (FD_ISSET (connection_number, &readfds))
1586 if (XPending (gdk_display) == 0)
1590 XNoOp (gdk_display);
1591 XFlush (gdk_display);
1606 if (FD_ISSET (input->source, &readfds))
1607 condition |= GDK_INPUT_READ;
1608 if (FD_ISSET (input->source, &writefds))
1609 condition |= GDK_INPUT_WRITE;
1610 if (FD_ISSET (input->source, &exceptfds))
1611 condition |= GDK_INPUT_EXCEPTION;
1613 if (condition && input->function)
1614 (* input->function) (input->data, input->source, condition);
1625 gdk_event_apply_filters (XEvent *xevent,
1629 GdkEventFilter *filter;
1631 GdkFilterReturn result;
1637 filter = (GdkEventFilter *)tmp_list->data;
1639 result = (*filter->function)(xevent, event, filter->data);
1640 if (result != GDK_FILTER_CONTINUE)
1643 tmp_list = tmp_list->next;
1646 return GDK_FILTER_CONTINUE;
1650 gdk_event_translate (GdkEvent *event,
1655 GdkWindowPrivate *window_private;
1656 XComposeStatus compose;
1659 static gchar* buf = NULL;
1660 static gint buf_len= 0;
1666 /* Are static variables used for this purpose thread-safe? */
1667 static GdkPoint dnd_drag_start = {0,0},
1668 dnd_drag_oldpos = {0,0};
1669 static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
1670 static gint dnd_drag_perhaps = 0;
1671 static gboolean dnd_grabbed = FALSE;
1672 static GdkWindowPrivate *real_sw = NULL;
1673 static Window dnd_drag_curwin = None, dnd_drag_target = None;
1677 /* Find the GdkWindow that this event occurred in.
1678 * All events occur in some GdkWindow (otherwise, why
1679 * would we be receiving them). It really is an error
1680 * to receive an event for which we cannot find the
1681 * corresponding GdkWindow. We handle events with window=None
1682 * specially - they are generated by XFree86's XInput under
1683 * some circumstances.
1686 if ((xevent->xany.window == None) &&
1687 gdk_input_vtable.window_none_event)
1689 return_val = gdk_input_vtable.window_none_event (event,xevent);
1691 if (return_val >= 0) /* was handled */
1697 window = gdk_window_lookup (xevent->xany.window);
1698 window_private = (GdkWindowPrivate *) window;
1701 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1703 gdk_window_ref (window);
1706 /* Check for filters for this window */
1710 GdkFilterReturn result;
1711 result = gdk_event_apply_filters (xevent, event, window_private->filters);
1713 if (result != GDK_FILTER_CONTINUE)
1715 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1719 /* We do a "manual" conversion of the XEvent to a
1720 * GdkEvent. The structures are mostly the same so
1721 * the conversion is fairly straightforward. We also
1722 * optionally print debugging info regarding events
1726 * During drag & drop you get events where the pointer is
1727 * in other windows. Need to just do finer-grained checking
1729 switch (xevent->type)
1732 /* Lookup the string corresponding to the given keysym.
1738 buf = g_new (gchar, buf_len);
1740 if (xim_using == TRUE && xim_ic)
1744 /* Clear keyval. Depending on status, may not be set */
1745 event->key.keyval = GDK_VoidSymbol;
1746 charcount = XmbLookupString(xim_ic->xic,
1747 &xevent->xkey, buf, buf_len-1,
1748 (KeySym*) &event->key.keyval,
1750 if (status == XBufferOverflow)
1752 /* alloc adequate size of buffer */
1753 if (gdk_debug_level >= 1)
1754 g_print("XIM: overflow (required %i)\n", charcount);
1756 while (buf_len <= charcount)
1758 buf = (gchar *) g_realloc (buf, buf_len);
1760 charcount = XmbLookupString (xim_ic->xic,
1761 &xevent->xkey, buf, buf_len-1,
1762 (KeySym*) &event->key.keyval,
1765 if (status == XLookupNone)
1772 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1773 (KeySym*) &event->key.keyval,
1776 charcount = XLookupString (&xevent->xkey, buf, 16,
1777 (KeySym*) &event->key.keyval,
1780 if (charcount > 0 && buf[charcount-1] == '\0')
1783 buf[charcount] = '\0';
1785 /* Print debugging info.
1787 if (gdk_show_events)
1789 g_print ("key press:\twindow: %ld key: %12s %d\n",
1790 xevent->xkey.window - base_id,
1791 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1794 g_print ("\t\tlength: %4d string: \"%s\"\n",
1798 event->key.type = GDK_KEY_PRESS;
1799 event->key.window = window;
1800 event->key.time = xevent->xkey.time;
1801 event->key.state = (GdkModifierType) xevent->xkey.state;
1802 event->key.string = g_strdup (buf);
1803 event->key.length = charcount;
1805 return_val = window_private && !window_private->destroyed;
1808 g_free (event->key.string);
1813 /* Lookup the string corresponding to the given keysym.
1815 charcount = XLookupString (&xevent->xkey, buf, 16,
1816 (KeySym*) &event->key.keyval,
1819 /* Print debugging info.
1821 if (gdk_show_events)
1822 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1823 xevent->xkey.window - base_id,
1824 XKeysymToString (event->key.keyval),
1827 event->key.type = GDK_KEY_RELEASE;
1828 event->key.window = window;
1829 event->key.time = xevent->xkey.time;
1830 event->key.state = (GdkModifierType) xevent->xkey.state;
1831 event->key.length = 0;
1832 event->key.string = NULL;
1834 return_val = window_private && !window_private->destroyed;
1838 /* Print debugging info.
1840 if (gdk_show_events)
1841 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1842 window_private?window_private->dnd_drag_enabled:0,
1843 xevent->xbutton.window - base_id,
1844 xevent->xbutton.x, xevent->xbutton.y,
1845 xevent->xbutton.button);
1847 if (window_private &&
1848 (window_private->extension_events != 0) &&
1849 gdk_input_ignore_core)
1852 event->button.type = GDK_BUTTON_PRESS;
1853 event->button.window = window;
1854 event->button.time = xevent->xbutton.time;
1855 event->button.x = xevent->xbutton.x;
1856 event->button.y = xevent->xbutton.y;
1857 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1858 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1859 event->button.pressure = 0.5;
1860 event->button.xtilt = 0;
1861 event->button.ytilt = 0;
1862 event->button.state = (GdkModifierType) xevent->xbutton.state;
1863 event->button.button = xevent->xbutton.button;
1864 event->button.source = GDK_SOURCE_MOUSE;
1865 event->button.deviceid = GDK_CORE_POINTER;
1867 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1868 (event->button.window == button_window[1]) &&
1869 (event->button.button == button_number[1]))
1871 gdk_synthesize_click (event, 3);
1873 button_click_time[1] = 0;
1874 button_click_time[0] = 0;
1875 button_window[1] = NULL;
1876 button_window[0] = 0;
1877 button_number[1] = -1;
1878 button_number[0] = -1;
1880 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1881 (event->button.window == button_window[0]) &&
1882 (event->button.button == button_number[0]))
1884 gdk_synthesize_click (event, 2);
1886 button_click_time[1] = button_click_time[0];
1887 button_click_time[0] = event->button.time;
1888 button_window[1] = button_window[0];
1889 button_window[0] = event->button.window;
1890 button_number[1] = button_number[0];
1891 button_number[0] = event->button.button;
1895 button_click_time[1] = 0;
1896 button_click_time[0] = event->button.time;
1897 button_window[1] = NULL;
1898 button_window[0] = event->button.window;
1899 button_number[1] = -1;
1900 button_number[0] = event->button.button;
1903 && window_private->dnd_drag_enabled
1904 && !dnd_drag_perhaps
1905 && !gdk_dnd.drag_really)
1907 dnd_drag_perhaps = 1;
1908 dnd_drag_start.x = xevent->xbutton.x_root;
1909 dnd_drag_start.y = xevent->xbutton.y_root;
1910 real_sw = window_private;
1912 if(gdk_dnd.drag_startwindows)
1914 g_free(gdk_dnd.drag_startwindows);
1915 gdk_dnd.drag_startwindows = NULL;
1917 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1918 dnd_grabbed = FALSE;
1921 /* Set motion mask for first DnD'd window, since it
1922 will be the one that is actually dragged */
1923 XWindowAttributes dnd_winattr;
1924 XSetWindowAttributes dnd_setwinattr;
1926 /* We need to get motion events while the button is down, so
1927 we can know whether to really start dragging or not... */
1928 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1931 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1932 dnd_setwinattr.event_mask =
1933 window_private->dnd_drag_eventmask = ButtonMotionMask | EnterWindowMask | LeaveWindowMask;
1934 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1935 CWEventMask, &dnd_setwinattr);
1938 return_val = window_private && !window_private->destroyed;
1942 /* Print debugging info.
1944 if (gdk_show_events)
1945 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
1946 window_private?window_private->dnd_drag_enabled:0,
1947 xevent->xbutton.window - base_id,
1948 xevent->xbutton.x, xevent->xbutton.y,
1949 xevent->xbutton.button);
1951 if (window_private &&
1952 (window_private->extension_events != 0) &&
1953 gdk_input_ignore_core)
1956 event->button.type = GDK_BUTTON_RELEASE;
1957 event->button.window = window;
1958 event->button.time = xevent->xbutton.time;
1959 event->button.x = xevent->xbutton.x;
1960 event->button.y = xevent->xbutton.y;
1961 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1962 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1963 event->button.pressure = 0.5;
1964 event->button.xtilt = 0;
1965 event->button.ytilt = 0;
1966 event->button.state = (GdkModifierType) xevent->xbutton.state;
1967 event->button.button = xevent->xbutton.button;
1968 event->button.source = GDK_SOURCE_MOUSE;
1969 event->button.deviceid = GDK_CORE_POINTER;
1971 if(dnd_drag_perhaps)
1974 XSetWindowAttributes attrs;
1975 /* Reset event mask to pre-drag value, assuming event_mask
1976 doesn't change during drag */
1977 attrs.event_mask = real_sw->dnd_drag_savedeventmask;
1978 XChangeWindowAttributes(gdk_display, real_sw->xwindow,
1979 CWEventMask, &attrs);
1984 XUngrabPointer(gdk_display, CurrentTime);
1985 dnd_grabbed = FALSE;
1988 if(gdk_dnd.drag_really)
1991 foo.x = xevent->xbutton.x_root;
1992 foo.y = xevent->xbutton.y_root;
1994 if(dnd_drag_target != None)
1995 gdk_dnd_drag_end(dnd_drag_target, foo);
1996 gdk_dnd.drag_really = 0;
1998 gdk_dnd.drag_numwindows = 0;
1999 if(gdk_dnd.drag_startwindows)
2001 g_free(gdk_dnd.drag_startwindows);
2002 gdk_dnd.drag_startwindows = NULL;
2008 dnd_drag_perhaps = 0;
2009 dnd_drag_start.x = dnd_drag_start.y = 0;
2010 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2011 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2012 dnd_drag_curwin = None;
2013 return_val = window_private?TRUE:FALSE;
2015 return_val = window_private && !window_private->destroyed;
2019 /* Print debugging info.
2021 if (gdk_show_events)
2022 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2023 xevent->xmotion.window - base_id,
2024 xevent->xmotion.x, xevent->xmotion.y,
2025 (xevent->xmotion.is_hint) ? "true" : "false",
2026 dnd_drag_perhaps, gdk_dnd.drag_really);
2028 if (window_private &&
2029 (window_private->extension_events != 0) &&
2030 gdk_input_ignore_core)
2033 event->motion.type = GDK_MOTION_NOTIFY;
2034 event->motion.window = window;
2035 event->motion.time = xevent->xmotion.time;
2036 event->motion.x = xevent->xmotion.x;
2037 event->motion.y = xevent->xmotion.y;
2038 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2039 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2040 event->motion.pressure = 0.5;
2041 event->motion.xtilt = 0;
2042 event->motion.ytilt = 0;
2043 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2044 event->motion.is_hint = xevent->xmotion.is_hint;
2045 event->motion.source = GDK_SOURCE_MOUSE;
2046 event->motion.deviceid = GDK_CORE_POINTER;
2048 #define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
2049 && cy >= dnd_drag_dropzone.y \
2050 && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
2051 && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
2053 if(dnd_drag_perhaps && gdk_dnd.drag_really)
2055 /* First, we have to find what window the motion was in... */
2056 /* XXX there has to be a better way to do this, perhaps with
2057 XTranslateCoordinates or XQueryTree - I don't know how,
2058 and this sort of works */
2059 static Window lastwin = None, curwin = None, twin;
2060 Window childwin = gdk_root_window;
2063 curwin = gdk_root_window;
2064 ox = x = xevent->xmotion.x_root;
2065 oy = y = xevent->xmotion.y_root;
2066 while(childwin != None)
2070 XTranslateCoordinates(gdk_display, curwin, curwin,
2071 x, y, &x, &y, &childwin);
2072 if(childwin != None)
2074 XTranslateCoordinates(gdk_display, curwin, childwin,
2075 x, y, &x, &y, &twin);
2078 #if defined(DEBUG_DND) /* && defined(DEBUG_DND_MORE_DETAILS) */
2079 g_print("Drag is now in window %#x, lastwin was %#x, ddc = %#x\n",
2080 curwin, lastwin, dnd_drag_curwin);
2082 if(curwin != dnd_drag_curwin && curwin != lastwin)
2084 /* We have left one window and entered another
2085 (do leave & enter bits) */
2086 if(dnd_drag_curwin != None)
2087 gdk_dnd_drag_leave(dnd_drag_curwin);
2088 dnd_drag_curwin = curwin;
2089 gdk_dnd_drag_enter(dnd_drag_curwin);
2090 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2091 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2092 dnd_drag_target = None;
2094 g_print("curwin = %#x, lastwin = %#x, dnd_drag_curwin = %#x\n",
2095 curwin, lastwin, dnd_drag_curwin);
2097 XChangeActivePointerGrab(gdk_display,
2099 ButtonPressMask | ButtonReleaseMask,
2100 gdk_dnd.gdk_cursor_dragdefault,
2103 else if(dnd_drag_dropzone.width > 0
2104 && dnd_drag_dropzone.height > 0
2105 && curwin == dnd_drag_curwin)
2107 /* Handle all that dropzone stuff - thanks John ;-) */
2108 if (dnd_drag_target != None)
2110 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2111 xevent->xmotion.y_root);
2112 gboolean old_in_zone = IS_IN_ZONE(dnd_drag_oldpos.x,
2115 if (!in_zone && old_in_zone)
2117 /* We were in the drop zone and moved out */
2118 dnd_drag_target = None;
2119 gdk_dnd_drag_leave(curwin);
2121 else if (!in_zone && !old_in_zone)
2123 /* We were outside drop zone but in the window
2124 - have to send enter events */
2125 gdk_dnd_drag_enter(curwin);
2126 dnd_drag_curwin = curwin;
2127 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2128 dnd_drag_target = None;
2132 dnd_drag_curwin = None; */
2136 return_val = window_private && !window_private->destroyed;
2140 /* Print debugging info.
2142 #if !(defined(DEBUG_DND) && defined(DEBUG_DND_MORE_DETAILS))
2143 if (gdk_show_events)
2145 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2146 xevent->xcrossing.window - base_id,
2147 xevent->xcrossing.detail,
2148 xevent->xcrossing.subwindow - base_id);
2150 /* Tell XInput stuff about it if appropriate */
2151 if (window_private &&
2152 (window_private->extension_events != 0) &&
2153 gdk_input_vtable.enter_event)
2154 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2156 event->crossing.type = GDK_ENTER_NOTIFY;
2157 event->crossing.window = window;
2159 /* If the subwindow field of the XEvent is non-NULL, then
2160 * lookup the corresponding GdkWindow.
2162 if (xevent->xcrossing.subwindow != None)
2163 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2165 event->crossing.subwindow = NULL;
2167 /* Translate the crossing detail into Gdk terms.
2169 switch (xevent->xcrossing.detail)
2171 case NotifyInferior:
2172 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2174 case NotifyAncestor:
2175 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2178 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2180 case NotifyNonlinear:
2181 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2183 case NotifyNonlinearVirtual:
2184 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2187 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2192 if(dnd_drag_perhaps)
2194 g_print("We may[%d] have a drag into %#x = %#x\n",
2195 gdk_dnd.drag_really,
2196 xevent->xcrossing.window, real_sw->xwindow);
2199 if (dnd_drag_perhaps && gdk_dnd.drag_really &&
2200 (xevent->xcrossing.window == real_sw->xwindow))
2202 gdk_dnd.drag_really = 0;
2204 g_print("Ungrabbed\n");
2206 gdk_dnd.drag_numwindows = 0;
2207 g_free(gdk_dnd.drag_startwindows);
2208 gdk_dnd.drag_startwindows = NULL;
2209 /* We don't want to ungrab the pointer here, or we'll
2210 * start getting spurious enter/leave events */
2211 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2214 return_val = window_private && !window_private->destroyed;
2218 /* Print debugging info.
2220 #if !(defined(DEBUG_DND) && defined(DEBUG_DND_MORE_DETAILS))
2221 if (gdk_show_events)
2223 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2224 xevent->xcrossing.window - base_id,
2225 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
2227 event->crossing.type = GDK_LEAVE_NOTIFY;
2228 event->crossing.window = window;
2230 /* If the subwindow field of the XEvent is non-NULL, then
2231 * lookup the corresponding GdkWindow.
2233 if (xevent->xcrossing.subwindow != None)
2234 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2236 event->crossing.subwindow = NULL;
2238 /* Translate the crossing detail into Gdk terms.
2240 switch (xevent->xcrossing.detail)
2242 case NotifyInferior:
2243 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2245 case NotifyAncestor:
2246 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2249 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2251 case NotifyNonlinear:
2252 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2254 case NotifyNonlinearVirtual:
2255 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2258 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2262 if(dnd_drag_perhaps)
2264 g_print("We may[%d] have a drag out of %#x = %#x\n",
2265 gdk_dnd.drag_really,
2266 xevent->xcrossing.window, real_sw->xwindow);
2269 if (dnd_drag_perhaps && !gdk_dnd.drag_really &&
2270 (xevent->xcrossing.window == real_sw->xwindow))
2272 gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
2273 gdk_dnd_drag_begin((GdkWindow *) real_sw);
2274 XGrabPointer(gdk_display, real_sw->xwindow, False,
2276 ButtonPressMask | ButtonReleaseMask,
2277 GrabModeAsync, GrabModeAsync, gdk_root_window,
2278 gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
2280 gdk_dnd.drag_really = 1;
2283 return_val = window_private && !window_private->destroyed;
2288 /* We only care about focus events that indicate that _this_
2289 * window (not a ancestor or child) got or lost the focus
2291 switch (xevent->xfocus.detail)
2293 case NotifyAncestor:
2294 case NotifyInferior:
2295 case NotifyNonlinear:
2296 /* Print debugging info.
2298 if (gdk_show_events)
2299 g_print ("focus %s:\t\twindow: %ld\n",
2300 (xevent->xany.type == FocusIn) ? "in" : "out",
2301 xevent->xfocus.window - base_id);
2303 event->focus_change.type = GDK_FOCUS_CHANGE;
2304 event->focus_change.window = window;
2305 event->focus_change.in = (xevent->xany.type == FocusIn);
2307 return_val = window_private && !window_private->destroyed;
2315 /* Print debugging info.
2317 if (gdk_show_events)
2318 g_print ("keymap notify\n");
2320 /* Not currently handled */
2324 /* Print debugging info.
2326 if (gdk_show_events)
2327 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2328 xevent->xexpose.window - base_id, xevent->xexpose.count,
2329 xevent->xexpose.x, xevent->xexpose.y,
2330 xevent->xexpose.width, xevent->xexpose.height);
2332 event->expose.type = GDK_EXPOSE;
2333 event->expose.window = window;
2334 event->expose.area.x = xevent->xexpose.x;
2335 event->expose.area.y = xevent->xexpose.y;
2336 event->expose.area.width = xevent->xexpose.width;
2337 event->expose.area.height = xevent->xexpose.height;
2338 event->expose.count = xevent->xexpose.count;
2340 return_val = window_private && !window_private->destroyed;
2343 case GraphicsExpose:
2344 /* Print debugging info.
2346 if (gdk_show_events)
2347 g_print ("graphics expose:\tdrawable: %ld\n",
2348 xevent->xgraphicsexpose.drawable - base_id);
2350 event->expose.type = GDK_EXPOSE;
2351 event->expose.window = window;
2352 event->expose.area.x = xevent->xgraphicsexpose.x;
2353 event->expose.area.y = xevent->xgraphicsexpose.y;
2354 event->expose.area.width = xevent->xgraphicsexpose.width;
2355 event->expose.area.height = xevent->xgraphicsexpose.height;
2356 event->expose.count = xevent->xexpose.count;
2358 return_val = window_private && !window_private->destroyed;
2362 /* Print debugging info.
2364 if (gdk_show_events)
2365 g_print ("no expose:\t\tdrawable: %ld\n",
2366 xevent->xnoexpose.drawable - base_id);
2368 event->no_expose.type = GDK_NO_EXPOSE;
2369 event->no_expose.window = window;
2371 return_val = window_private && !window_private->destroyed;
2374 case VisibilityNotify:
2375 /* Print debugging info.
2377 if (gdk_show_events)
2378 switch (xevent->xvisibility.state)
2380 case VisibilityFullyObscured:
2381 g_print ("visibility notify:\twindow: %ld none\n",
2382 xevent->xvisibility.window - base_id);
2384 case VisibilityPartiallyObscured:
2385 g_print ("visibility notify:\twindow: %ld partial\n",
2386 xevent->xvisibility.window - base_id);
2388 case VisibilityUnobscured:
2389 g_print ("visibility notify:\twindow: %ld full\n",
2390 xevent->xvisibility.window - base_id);
2394 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2395 event->visibility.window = window;
2397 switch (xevent->xvisibility.state)
2399 case VisibilityFullyObscured:
2400 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2403 case VisibilityPartiallyObscured:
2404 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2407 case VisibilityUnobscured:
2408 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2412 return_val = window_private && !window_private->destroyed;
2416 /* Not currently handled */
2420 /* Print debugging info.
2422 if (gdk_show_events)
2423 g_print ("destroy notify:\twindow: %ld\n",
2424 xevent->xdestroywindow.window - base_id);
2426 event->any.type = GDK_DESTROY;
2427 event->any.window = window;
2429 return_val = window_private && !window_private->destroyed;
2431 gdk_window_destroy_notify (window);
2435 /* Print debugging info.
2437 if (gdk_show_events)
2438 g_print ("unmap notify:\t\twindow: %ld\n",
2439 xevent->xmap.window - base_id);
2441 event->any.type = GDK_UNMAP;
2442 event->any.window = window;
2444 if (xgrab_window == window_private)
2445 xgrab_window = NULL;
2447 return_val = window_private && !window_private->destroyed;
2451 /* Print debugging info.
2453 if (gdk_show_events)
2454 g_print ("map notify:\t\twindow: %ld\n",
2455 xevent->xmap.window - base_id);
2457 event->any.type = GDK_MAP;
2458 event->any.window = window;
2460 return_val = window_private && !window_private->destroyed;
2463 case ReparentNotify:
2464 /* Print debugging info.
2466 if (gdk_show_events)
2467 g_print ("reparent notify:\twindow: %ld\n",
2468 xevent->xreparent.window - base_id);
2470 /* Not currently handled */
2473 case ConfigureNotify:
2474 /* Print debugging info.
2476 while ((XPending (gdk_display) > 0) &&
2477 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2478 ConfigureNotify, xevent))
2479 /*XSync (gdk_display, 0)*/;
2481 if (gdk_show_events)
2482 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2483 xevent->xconfigure.window - base_id,
2484 xevent->xconfigure.x,
2485 xevent->xconfigure.y,
2486 xevent->xconfigure.width,
2487 xevent->xconfigure.height,
2488 xevent->xconfigure.border_width,
2489 xevent->xconfigure.above - base_id,
2490 xevent->xconfigure.override_redirect);
2494 if ((window_private->extension_events != 0) &&
2495 gdk_input_vtable.configure_event)
2496 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2498 if (window_private->window_type != GDK_WINDOW_CHILD)
2500 event->configure.type = GDK_CONFIGURE;
2501 event->configure.window = window;
2502 event->configure.width = xevent->xconfigure.width;
2503 event->configure.height = xevent->xconfigure.height;
2505 if (!xevent->xconfigure.x &&
2506 !xevent->xconfigure.y)
2510 Window child_window = 0;
2512 if (!XTranslateCoordinates (window_private->xdisplay,
2513 window_private->xwindow,
2518 g_warning ("GdkWindow %ld doesn't share root windows display?",
2519 window_private->xwindow - base_id);
2520 event->configure.x = tx;
2521 event->configure.y = ty;
2525 event->configure.x = xevent->xconfigure.x;
2526 event->configure.y = xevent->xconfigure.y;
2528 window_private->x = event->configure.x;
2529 window_private->y = event->configure.y;
2530 window_private->width = xevent->xconfigure.width;
2531 window_private->height = xevent->xconfigure.height;
2532 if (window_private->resize_count > 1)
2533 window_private->resize_count -= 1;
2535 return_val = !window_private->destroyed;
2540 case PropertyNotify:
2541 /* Print debugging info.
2543 if (gdk_show_events)
2544 g_print ("property notify:\twindow: %ld\n",
2545 xevent->xproperty.window - base_id);
2547 event->property.type = GDK_PROPERTY_NOTIFY;
2548 event->property.window = window;
2549 event->property.atom = xevent->xproperty.atom;
2550 event->property.time = xevent->xproperty.time;
2551 event->property.state = xevent->xproperty.state;
2553 return_val = window_private && !window_private->destroyed;
2556 case SelectionClear:
2557 if (gdk_show_events)
2558 g_print ("selection clear:\twindow: %ld\n",
2559 xevent->xproperty.window - base_id);
2561 event->selection.type = GDK_SELECTION_CLEAR;
2562 event->selection.window = window;
2563 event->selection.selection = xevent->xselectionclear.selection;
2564 event->selection.time = xevent->xselectionclear.time;
2566 return_val = window_private && !window_private->destroyed;
2569 case SelectionRequest:
2570 if (gdk_show_events)
2571 g_print ("selection request:\twindow: %ld\n",
2572 xevent->xproperty.window - base_id);
2574 event->selection.type = GDK_SELECTION_REQUEST;
2575 event->selection.window = window;
2576 event->selection.selection = xevent->xselectionrequest.selection;
2577 event->selection.target = xevent->xselectionrequest.target;
2578 event->selection.property = xevent->xselectionrequest.property;
2579 event->selection.requestor = xevent->xselectionrequest.requestor;
2580 event->selection.time = xevent->xselectionrequest.time;
2582 return_val = window_private && !window_private->destroyed;
2585 case SelectionNotify:
2586 if (gdk_show_events)
2587 g_print ("selection notify:\twindow: %ld\n",
2588 xevent->xproperty.window - base_id);
2591 event->selection.type = GDK_SELECTION_NOTIFY;
2592 event->selection.window = window;
2593 event->selection.selection = xevent->xselection.selection;
2594 event->selection.target = xevent->xselection.target;
2595 event->selection.property = xevent->xselection.property;
2596 event->selection.time = xevent->xselection.time;
2598 return_val = window_private && !window_private->destroyed;
2601 case ColormapNotify:
2602 /* Print debugging info.
2604 if (gdk_show_events)
2605 g_print ("colormap notify:\twindow: %ld\n",
2606 xevent->xcolormap.window - base_id);
2608 /* Not currently handled */
2612 /* Print debugging info.
2614 if (gdk_show_events)
2615 g_print ("client message:\twindow: %ld\n",
2616 xevent->xclient.window - base_id);
2618 /* Client messages are the means of the window manager
2619 * communicating with a program. We'll first check to
2620 * see if this is really the window manager talking
2623 if (xevent->xclient.message_type == gdk_wm_protocols)
2625 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2627 /* The delete window request specifies a window
2628 * to delete. We don't actually destroy the
2629 * window because "it is only a request". (The
2630 * window might contain vital data that the
2631 * program does not want destroyed). Instead
2632 * the event is passed along to the program,
2633 * which should then destroy the window.
2636 /* Print debugging info.
2638 if (gdk_show_events)
2639 g_print ("delete window:\t\twindow: %ld\n",
2640 xevent->xclient.window - base_id);
2642 event->any.type = GDK_DELETE;
2643 event->any.window = window;
2645 return_val = window_private && !window_private->destroyed;
2647 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2651 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2655 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2657 if (gdk_show_events)
2659 g_print ("GDK_DROP_ENTER [%d][%d]\n",
2660 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply);
2663 /* Now figure out if we really want this drop...
2664 * If someone is trying funky clipboard stuff, ignore
2667 && window_private->dnd_drop_enabled
2668 && event->dropenter.u.flags.sendreply
2669 && (reptype = gdk_dnd_check_types (window, xevent)))
2673 replyev.xclient.type = ClientMessage;
2674 replyev.xclient.window = xevent->xclient.data.l[0];
2675 replyev.xclient.format = 32;
2676 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2677 replyev.xclient.data.l[0] = window_private->xwindow;
2679 event->dragrequest.u.allflags = 0;
2680 event->dragrequest.u.flags.protocol_version =
2681 DND_PROTOCOL_VERSION;
2682 event->dragrequest.u.flags.willaccept = 1;
2683 event->dragrequest.u.flags.delete_data =
2684 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2686 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2687 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2688 replyev.xclient.data.l[4] = reptype;
2690 XSendEvent (gdk_display, replyev.xclient.window,
2691 False, NoEventMask, &replyev);
2693 event->any.type = GDK_DROP_ENTER;
2694 event->any.window = window;
2695 event->dropenter.requestor = replyev.xclient.window;
2696 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2698 g_print("We sent a GDK_DROP_ENTER on to Gtk\n");
2703 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2706 if (gdk_show_events)
2708 g_print ("GDK_DROP_LEAVE\n");
2709 if (window_private && window_private->dnd_drop_enabled)
2711 event->dropleave.type = GDK_DROP_LEAVE;
2712 event->dropleave.window = window;
2713 event->dropleave.requestor = xevent->xclient.data.l[0];
2714 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2720 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2723 * make sure to only handle requests from the window the cursor is
2727 if (gdk_show_events)
2729 g_print ("GDK_DRAG_REQUEST\n");
2730 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2733 if (window && gdk_dnd.drag_really &&
2734 xevent->xclient.data.l[0] == dnd_drag_curwin &&
2735 event->dragrequest.u.flags.sendreply == 0)
2737 /* Got request - do we need to ask user? */
2738 if (!event->dragrequest.u.flags.willaccept
2739 && event->dragrequest.u.flags.senddata)
2742 event->dragrequest.type = GDK_DRAG_REQUEST;
2743 event->dragrequest.window = window;
2744 event->dragrequest.requestor = xevent->xclient.data.l[0];
2745 event->dragrequest.isdrop = 0;
2746 event->dragrequest.drop_coords.x =
2747 event->dragrequest.drop_coords.y = 0;
2750 else if (event->dragrequest.u.flags.willaccept)
2752 window_private->dnd_drag_destructive_op =
2753 event->dragrequest.u.flags.delete_data;
2754 window_private->dnd_drag_accepted = 1;
2755 window_private->dnd_drag_data_type =
2756 xevent->xclient.data.l[4];
2758 dnd_drag_target = dnd_drag_curwin;
2759 XChangeActivePointerGrab (gdk_display,
2763 EnterWindowMask | LeaveWindowMask,
2764 gdk_dnd.gdk_cursor_dragok,
2767 dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2768 dnd_drag_dropzone.y =
2769 (xevent->xclient.data.l[2] >> 16) & 65535;
2770 dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2771 dnd_drag_dropzone.height =
2772 (xevent->xclient.data.l[3] >> 16) & 65535;
2775 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2777 gint tmp_int; Atom tmp_atom;
2779 guchar *tmp_charptr;
2784 g_print("GDK_DROP_DATA_AVAIL\n");
2785 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2787 /* No preview of data ATM */
2788 && event->dropdataavailable.u.flags.isdrop)
2790 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2791 event->dropdataavailable.window = window;
2792 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2793 event->dropdataavailable.data_type =
2794 gdk_atom_name(xevent->xclient.data.l[2]);
2795 if(XGetWindowProperty (gdk_display,
2796 event->dropdataavailable.requestor,
2797 xevent->xclient.data.l[2],
2799 False, XA_PRIMARY, &tmp_atom,
2801 &event->dropdataavailable.data_numbytes,
2806 g_warning("XGetWindowProperty on %#x may have failed\n",
2807 event->dropdataavailable.requestor);
2808 event->dropdataavailable.data = NULL;
2813 g_print("XGetWindowProperty got us %d bytes\n",
2814 event->dropdataavailable.data_numbytes);
2816 event->dropdataavailable.data =
2817 g_malloc (event->dropdataavailable.data_numbytes);
2818 memcpy (event->dropdataavailable.data,
2819 tmp_charptr, event->dropdataavailable.data_numbytes);
2828 /* Send unknown ClientMessage's on to Gtk for it to use */
2829 event->client.type = GDK_CLIENT_EVENT;
2830 event->client.window = window;
2831 event->client.message_type = xevent->xclient.message_type;
2832 event->client.data_format = xevent->xclient.format;
2833 memcpy(&event->client.data, &xevent->xclient.data,
2834 sizeof(event->client.data));
2841 return_val = return_val && !window_private->destroyed;
2845 /* Print debugging info.
2847 if (gdk_show_events)
2848 g_print ("mapping notify\n");
2850 /* Let XLib know that there is a new keyboard mapping.
2852 XRefreshKeyboardMapping (&xevent->xmapping);
2856 /* something else - (e.g., a Xinput event) */
2858 if (window_private &&
2859 (window_private->extension_events != 0) &&
2860 gdk_input_vtable.other_event)
2861 return_val = gdk_input_vtable.other_event(event, xevent, window);
2865 if (return_val < 0) /* not an XInput event, convert */
2867 event->other.type = GDK_OTHER_EVENT;
2868 event->other.window = window;
2869 event->other.xevent = (GdkXEvent *)&other_xevent[other_xevent_i];
2870 memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
2871 other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
2875 return_val = return_val && !window_private->destroyed;
2882 if (event->any.window)
2883 gdk_window_ref (event->any.window);
2884 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2885 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2886 (event->crossing.subwindow != NULL))
2887 gdk_window_ref (event->crossing.subwindow);
2891 /* Mark this event as having no resources to be freed */
2892 event->any.window = NULL;
2893 event->any.type = GDK_NOTHING;
2897 gdk_window_unref (window);
2904 gdk_event_get_type (Display *display,
2911 if (gdk_event_translate (&event, xevent))
2913 pred = (GdkPredicate*) arg;
2914 return (* pred->func) (&event, pred->data);
2922 gdk_synthesize_click (GdkEvent *event,
2925 GdkEvent temp_event;
2927 g_return_if_fail (event != NULL);
2929 temp_event = *event;
2930 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2932 gdk_event_put (&temp_event);
2936 *--------------------------------------------------------------
2939 * This is the "atexit" function that makes sure the
2940 * library gets a chance to cleanup.
2947 * The library is un-initialized and the program exits.
2949 *--------------------------------------------------------------
2955 static gboolean in_gdk_exit_func = FALSE;
2957 /* This is to avoid an infinite loop if a program segfaults in
2958 an atexit() handler (and yes, it does happen, especially if a program
2959 has trounced over memory too badly for even g_print to work) */
2960 if(in_gdk_exit_func == TRUE) return;
2961 in_gdk_exit_func = TRUE;
2973 gdk_key_repeat_restore ();
2975 XCloseDisplay (gdk_display);
2981 *--------------------------------------------------------------
2984 * The X error handling routine.
2987 * "display" is the X display the error orignated from.
2988 * "error" is the XErrorEvent that we are handling.
2991 * Either we were expecting some sort of error to occur,
2992 * in which case we set the "gdk_error_code" flag, or this
2993 * error was unexpected, in which case we will print an
2994 * error message and exit. (Since trying to continue will
2995 * most likely simply lead to more errors).
2999 *--------------------------------------------------------------
3003 gdk_x_error (Display *display,
3008 if (gdk_error_warnings)
3010 XGetErrorText (display, error->error_code, buf, 63);
3011 g_error ("%s", buf);
3014 gdk_error_code = -1;
3019 *--------------------------------------------------------------
3022 * The X I/O error handling routine.
3025 * "display" is the X display the error orignated from.
3028 * An X I/O error basically means we lost our connection
3029 * to the X server. There is not much we can do to
3030 * continue, so simply print an error message and exit.
3034 *--------------------------------------------------------------
3038 gdk_x_io_error (Display *display)
3040 g_error ("an x io error occurred");
3045 *--------------------------------------------------------------
3048 * The signal handler.
3051 * "sig_num" is the number of the signal we received.
3054 * The signals we catch are all fatal. So we simply build
3055 * up a nice little error message and print it and exit.
3056 * If in the process of doing so another signal is received
3057 * we notice that we are already exiting and simply kill
3062 *--------------------------------------------------------------
3066 gdk_signal (int sig_num)
3068 static int caught_fatal_sig = 0;
3071 if (caught_fatal_sig)
3072 kill (getpid (), sig_num);
3073 caught_fatal_sig = 1;
3099 sig = "unknown signal";
3103 g_print ("\n** ERROR **: %s caught\n", sig);
3108 gdk_dnd_drag_begin (GdkWindow *initial_window)
3110 GdkEventDragBegin tev;
3111 tev.type = GDK_DRAG_BEGIN;
3112 tev.window = initial_window;
3114 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3116 gdk_event_put ((GdkEvent *) &tev);
3120 gdk_dnd_drag_enter (Window dest)
3123 GdkEventDropEnter tev;
3125 GdkWindowPrivate *wp;
3127 sev.xclient.type = ClientMessage;
3128 sev.xclient.format = 32;
3129 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3130 sev.xclient.window = dest;
3133 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3134 tev.u.flags.sendreply = 1;
3135 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3137 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3138 if (wp->dnd_drag_data_numtypesavail)
3140 sev.xclient.data.l[0] = wp->xwindow;
3141 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3142 sev.xclient.data.l[1] = tev.u.allflags;
3143 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3144 if (wp->dnd_drag_data_numtypesavail > 1)
3146 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3147 if (wp->dnd_drag_data_numtypesavail > 2)
3149 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3152 sev.xclient.data.l[4] = None;
3155 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3156 XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
3166 *--------------------------------------------------------------
3169 * Begin using input method with XIM Protocol(X11R6 standard)
3172 * "ic" is the "Input Context" which is created by gtk_ic_new.
3173 * The input area is specified with "window".
3176 * The gdk's event handling routine is switched to XIM based routine.
3177 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3178 * and uses XmbLookupString instead of XLookupString.
3182 *--------------------------------------------------------------
3186 gdk_im_begin (GdkIC ic, GdkWindow* window)
3188 GdkICPrivate *private;
3191 g_return_if_fail (ic != NULL);
3192 g_return_if_fail (window);
3194 private = (GdkICPrivate *) ic;
3198 xim_window = window;
3201 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3202 if (xwin != GDK_WINDOW_XWINDOW(window))
3203 XSetICValues (private->xic, XNFocusWindow,
3204 GDK_WINDOW_XWINDOW(window), NULL);
3205 if (private != xim_ic)
3206 XSetICFocus (private->xic);
3211 *--------------------------------------------------------------
3214 * End using input method with XIM Protocol(X11R6 standard)
3219 * The gdk's event handling routine is switched to normal routine.
3220 * User should call this function before ic and window will be destroyed.
3224 *--------------------------------------------------------------
3242 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3244 GdkIMStyle s1, s2, u;
3246 if (style1 == 0) return style2;
3247 if (style2 == 0) return style1;
3248 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3249 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3252 s1 = style1 & GdkIMPreeditMask;
3253 s2 = style2 & GdkIMPreeditMask;
3256 if (u & GdkIMPreeditCallbacks)
3257 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3258 else if (u & GdkIMPreeditPosition)
3259 return (s1 == GdkIMPreeditPosition)? style1:style2;
3260 else if (u & GdkIMPreeditArea)
3261 return (s1 == GdkIMPreeditArea)? style1:style2;
3262 else if (u & GdkIMPreeditNothing)
3263 return (s1 == GdkIMPreeditNothing)? style1:style2;
3265 s1 = style1 & GdkIMStatusMask;
3266 s2 = style2 & GdkIMStatusMask;
3268 if ( u & GdkIMStatusCallbacks)
3269 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3270 else if ( u & GdkIMStatusArea)
3271 return (s1 == GdkIMStatusArea)? style1:style2;
3272 else if ( u & GdkIMStatusNothing)
3273 return (s1 == GdkIMStatusNothing)? style1:style2;
3274 else if ( u & GdkIMStatusNone)
3275 return (s1 == GdkIMStatusNone)? style1:style2;
3277 return 0; /* Get rid of stupid warning */
3281 gdk_im_decide_style (GdkIMStyle supported_style)
3284 GdkIMStyle style, tmp;
3286 g_return_val_if_fail (xim_styles != NULL, 0);
3289 for (i=0; i<xim_styles->count_styles; i++)
3291 tmp = xim_styles->supported_styles[i];
3292 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3293 style = gdk_im_choose_better_style (style, tmp);
3299 gdk_im_set_best_style (GdkIMStyle style)
3301 if (style & GdkIMPreeditMask)
3303 xim_best_allowed_style &= ~GdkIMPreeditMask;
3305 xim_best_allowed_style |= GdkIMPreeditNone;
3306 if (!(style & GdkIMPreeditNone))
3308 xim_best_allowed_style |= GdkIMPreeditNothing;
3309 if (!(style & GdkIMPreeditNothing))
3311 xim_best_allowed_style |= GdkIMPreeditArea;
3312 if (!(style & GdkIMPreeditArea))
3314 xim_best_allowed_style |= GdkIMPreeditPosition;
3315 if (!(style & GdkIMPreeditPosition))
3316 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3321 if (style & GdkIMStatusMask)
3323 xim_best_allowed_style &= ~GdkIMStatusMask;
3325 xim_best_allowed_style |= GdkIMStatusNone;
3326 if (!(style & GdkIMStatusNone))
3328 xim_best_allowed_style |= GdkIMStatusNothing;
3329 if (!(style & GdkIMStatusNothing))
3331 xim_best_allowed_style |= GdkIMStatusArea;
3332 if (!(style & GdkIMStatusArea))
3333 xim_best_allowed_style |= GdkIMStatusCallbacks;
3338 return xim_best_allowed_style;
3342 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3344 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3347 g_warning ("Don\'t open IM.");
3350 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3373 return (xim_im != NULL);
3377 gdk_ic_new (GdkWindow* client_window,
3378 GdkWindow* focus_window,
3379 GdkIMStyle style, ...)
3382 GdkICPrivate *private;
3383 XVaNestedList preedit_attr;
3385 g_return_val_if_fail (client_window != NULL, NULL);
3386 g_return_val_if_fail (focus_window != NULL, NULL);
3387 g_return_val_if_fail (gdk_im_ready(), NULL);
3389 private = g_new (GdkICPrivate, 1);
3391 va_start (list, style);
3392 preedit_attr = (XVaNestedList) & (va_arg (list, void *));
3395 private->style = gdk_im_decide_style (style);
3396 if (private->style != style)
3398 g_warning ("can not create input context with specified input style.");
3403 private->xic = XCreateIC(gdk_im_get (),
3404 XNInputStyle, style,
3405 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3406 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3407 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3415 xim_ic_list = g_list_append (xim_ic_list, private);
3420 gdk_ic_destroy (GdkIC ic)
3422 GdkICPrivate *private;
3424 g_return_if_fail (ic != NULL);
3426 private = (GdkICPrivate *) ic;
3428 if (xim_ic == private)
3431 XDestroyIC (private->xic);
3432 xim_ic_list = g_list_remove (xim_ic_list, private);
3436 gdk_ic_get_style (GdkIC ic)
3438 GdkICPrivate *private;
3440 g_return_val_if_fail (ic != NULL, 0);
3442 private = (GdkICPrivate *) ic;
3444 return private->style;
3448 gdk_ic_set_values (GdkIC ic, ...)
3452 GdkICPrivate *private;
3454 g_return_if_fail (ic != NULL);
3456 private = (GdkICPrivate *) ic;
3458 va_start (list, ic);
3459 args = (XVaNestedList) & (va_arg (list, void *));
3462 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3466 gdk_ic_get_values (GdkIC ic, ...)
3470 GdkICPrivate *private;
3472 g_return_if_fail (ic != NULL);
3474 private = (GdkICPrivate *) ic;
3476 va_start (list, ic);
3477 args = (XVaNestedList) & (va_arg (list, void *));
3480 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3484 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3488 GdkICPrivate *private;
3490 g_return_if_fail (ic != NULL);
3491 g_return_if_fail (target != NULL);
3493 private = (GdkICPrivate *) ic;
3495 va_start (list, target);
3496 attr = (XVaNestedList) & (va_arg (list, void *));
3499 XSetICValues (private->xic, target, attr, NULL);
3503 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3507 GdkICPrivate *private;
3509 g_return_if_fail (ic != NULL);
3510 g_return_if_fail (target != NULL);
3512 private = (GdkICPrivate *) ic;
3514 va_start (list, target);
3515 attr = (XVaNestedList) & (va_arg (list, void *));
3518 XGetICValues (private->xic, target, attr, NULL);
3522 gdk_ic_get_events (GdkIC ic)
3527 GdkICPrivate *private;
3530 /* From gdkwindow.c */
3531 extern int nevent_masks;
3532 extern int event_mask_table[];
3534 g_return_val_if_fail (ic != NULL, 0);
3536 private = (GdkICPrivate *) ic;
3538 XGetICValues (private->xic, XNFilterEvents, &xmask, NULL);
3541 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3542 if (xmask & event_mask_table [i])
3545 xmask &= ~ event_mask_table [i];
3549 g_warning ("ic requires the events not supported by the application (%04lx)", xmask);
3555 gdk_ic_cleanup (void)
3559 GdkICPrivate *private;
3562 for (node = xim_ic_list; node != NULL; node = node->next)
3566 private = (GdkICPrivate *) (node->data);
3567 XDestroyIC (private->xic);
3572 if (gdk_debug_level >= 1 && destroyed > 0)
3574 g_warning ("Cleanuped %i IC\n", destroyed);
3576 g_list_free(xim_ic_list);
3580 #else /* !USE_XIM */
3583 gdk_im_begin (GdkIC ic, GdkWindow* window)
3593 gdk_im_decide_style (GdkIMStyle supported_style)
3595 return GdkIMPreeditNone | GdkIMStatusNone;
3599 gdk_im_set_best_style (GdkIMStyle style)
3601 return GdkIMPreeditNone | GdkIMStatusNone;
3611 gdk_ic_new (GdkWindow* client_window,
3612 GdkWindow* focus_window,
3613 GdkIMStyle style, ...)
3619 gdk_ic_destroy (GdkIC ic)
3624 gdk_ic_get_style (GdkIC ic)
3626 return GdkIMPreeditNone | GdkIMStatusNone;
3630 gdk_ic_set_values (GdkIC ic, ...)
3635 gdk_ic_get_values (GdkIC ic, ...)
3640 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3645 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3650 gdk_ic_get_events (GdkIC ic)
3655 #endif /* USE_XIM */
3660 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3662 static wchar_t wcs[MB_CUR_MAX + 1];
3663 static gchar mbs[MB_CUR_MAX + 1];
3665 wcs[0] = (wchar_t) NULL;
3668 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3671 else if (wcs[0] == (wchar_t) NULL)
3674 len = _Xwctomb (mbs, wcs[0]);
3683 #endif /* X_LOCALE */
3686 gdk_dnd_drag_leave (Window dest)
3689 GdkEventDropLeave tev;
3691 GdkWindowPrivate *wp;
3695 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3696 sev.xclient.type = ClientMessage;
3697 sev.xclient.window = dest;
3698 sev.xclient.format = 32;
3699 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3700 sev.xclient.data.l[1] = tev.u.allflags;
3701 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3703 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3704 sev.xclient.data.l[0] = wp->xwindow;
3705 XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
3706 wp->dnd_drag_accepted = 0;
3711 * when a drop occurs, we go through the list of windows being dragged and
3712 * tell them that it has occurred, so that they can set things up and reply
3716 gdk_dnd_drag_end (Window dest,
3719 GdkWindowPrivate *wp;
3720 GdkEventDragRequest tev;
3723 tev.type = GDK_DRAG_REQUEST;
3724 tev.drop_coords = coords;
3725 tev.requestor = dest;
3727 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3730 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3732 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3733 if (wp->dnd_drag_accepted)
3735 tev.window = (GdkWindow *) wp;
3736 tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
3738 gdk_atom_name(wp->dnd_drag_data_type);
3740 gdk_event_put((GdkEvent *) &tev);
3746 gdk_dnd_check_types (GdkWindow *window,
3749 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3751 GdkEventDropEnter event;
3753 g_return_val_if_fail(window != NULL, 0);
3754 g_return_val_if_fail(xevent != NULL, 0);
3755 g_return_val_if_fail(xevent->type == ClientMessage, 0);
3756 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3758 if(wp->dnd_drop_data_numtypesavail <= 0 ||
3759 !wp->dnd_drop_data_typesavail)
3762 for (i = 2; i <= 4; i++)
3764 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3766 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3767 return xevent->xclient.data.l[i];
3771 /* Now we get the extended type list if it's available */
3772 event.u.allflags = xevent->xclient.data.l[1];
3773 if (event.u.flags.extended_typelist)
3775 Atom *exttypes, realtype;
3776 gulong nitems, nbar;
3779 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3780 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
3781 False, AnyPropertyType, &realtype, &realfmt,
3782 &nitems, &nbar, (unsigned char **) &exttypes)
3786 if (realfmt != (sizeof(Atom) * 8))
3788 g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
3789 realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
3793 for (i = 0; i <= nitems; i++)
3795 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3797 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
3810 * used for debugging only
3814 gdk_print_atom (GdkAtom anatom)
3816 gchar *tmpstr = NULL;
3817 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
3818 g_print("Atom %lu has name %s\n", anatom, tmpstr);
3825 * used only by below routine and itself
3828 getchildren (Display *dpy,
3832 Window root, parent, *children, inf = 0;
3834 unsigned int nchildren, i;
3836 unsigned long nitems, after;
3837 unsigned char *data;
3839 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
3842 for (i = 0; !inf && (i < nchildren); i++)
3844 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
3845 AnyPropertyType, &type, &format, &nitems,
3852 for (i = 0; !inf && (i < nchildren); i++)
3853 inf = getchildren (dpy, children[i], WM_STATE);
3855 if (children != None)
3856 XFree ((char *) children);
3862 * find a window with WM_STATE, else return win itself, as per ICCCM
3864 * modification of the XmuClientWindow() routine from X11R6.3
3867 gdk_get_client_window (Display *dpy,
3873 unsigned long nitems, after;
3874 unsigned char *data;
3878 return DefaultRootWindow(dpy);
3880 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
3883 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
3884 &type, &format, &nitems, &after, &data);
3888 inf = getchildren (dpy, win, WM_STATE);
3896 #ifdef WE_HAVE_MOTIF_DROPS_DONE
3898 gdk_drop_get_real_window (GdkWindow *w,
3902 GdkWindow *retval = w;
3903 GdkWindowPrivate *awin;
3905 gint16 myx = *x, myy = *y;
3907 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
3913 for (children = gdk_window_get_children(retval);
3914 children && children->next;
3915 children = children->next)
3917 awin = (GdkWindowPrivate *) children->data;
3918 if ((myx >= awin->x) && (myy >= awin->y)
3919 && (myx < (awin->x + awin->width))
3920 && (myy < (awin->y + awin->height)))
3922 retval = (GdkWindow *) awin;
3936 /* Sends a ClientMessage to all toplevel client windows */
3938 gdk_event_send_clientmessage_toall(GdkEvent *event)
3941 Window *ret_children, ret_root, ret_parent, curwin;
3942 unsigned int ret_nchildren;
3945 g_return_if_fail(event != NULL);
3947 /* Set up our event to send, with the exception of its target window */
3948 sev.xclient.type = ClientMessage;
3949 sev.xclient.display = gdk_display;
3950 sev.xclient.format = event->client.data_format;
3951 sev.xclient.serial = CurrentTime;
3952 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3953 sev.xclient.message_type = event->client.message_type;
3955 /* OK, we're all set, now let's find some windows to send this to */
3956 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
3957 &ret_children, &ret_nchildren) != True)
3960 /* foreach true child window of the root window, send an event to it */
3961 for(i = 0; i < ret_nchildren; i++) {
3962 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
3963 sev.xclient.window = curwin;
3964 XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
3967 XFree(ret_children);
3971 gdk_get_display(void)
3973 return (gchar *)XDisplayName (gdk_display_name);