1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 #include "../config.h"
21 /* If you don't want to use gdk's signal handlers define this */
22 /* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */
24 #include <X11/Xlocale.h>
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
37 #endif /* HAVE_SYS_SELECT_H_ */
39 #define XLIB_ILLEGAL_ACCESS
40 #include <X11/Xatom.h>
43 #include <X11/Xutil.h>
44 #include <X11/Xmu/WinUtil.h>
46 #include <X11/Xresource.h>
48 #include <X11/cursorfont.h>
50 #include "gdkprivate.h"
55 #include "gdkkeysyms.h"
58 #ifndef X_GETTIMEOFDAY
59 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
60 #endif /* X_GETTIMEOFDAY */
63 #define DOUBLE_CLICK_TIME 250
64 #define TRIPLE_CLICK_TIME 500
65 #define DOUBLE_CLICK_DIST 5
66 #define TRIPLE_CLICK_DIST 5
70 # define SELECT_MASK fd_set
76 # define SELECT_MASK void
78 # define SELECT_MASK int
83 typedef struct _GdkInput GdkInput;
84 typedef struct _GdkPredicate GdkPredicate;
90 GdkInputCondition condition;
91 GdkInputFunction function;
93 GdkDestroyNotify destroy;
103 * Private function declarations
106 static GdkEvent *gdk_event_new (void);
107 static gint gdk_event_wait (void);
108 static gint gdk_event_apply_filters (XEvent *xevent,
111 static gint gdk_event_translate (GdkEvent *event,
114 static Bool gdk_event_get_type (Display *display,
118 static void gdk_synthesize_click (GdkEvent *event,
121 static void gdk_dnd_drag_begin (GdkWindow *initial_window);
122 static void gdk_dnd_drag_enter (Window dest);
123 static void gdk_dnd_drag_leave (Window dest);
124 static void gdk_dnd_drag_end (Window dest,
126 static GdkAtom gdk_dnd_check_types (GdkWindow *window,
129 static void gdk_print_atom (GdkAtom anatom);
133 * old junk from offix, we might use it though so leave it
135 Window gdk_get_client_window (Display *dpy,
137 #ifdef WE_HAVE_MOTIF_DROPS_DONE
138 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
142 static void gdk_exit_func (void);
143 static int gdk_x_error (Display *display,
145 static int gdk_x_io_error (Display *display);
146 static RETSIGTYPE gdk_signal (int signum);
150 static guint gdk_im_va_count (va_list list);
151 static XVaNestedList gdk_im_va_to_nested (va_list list,
154 static GdkIM gdk_im_get (void);
155 static gint gdk_im_open (XrmDatabase db,
158 static void gdk_im_close (void);
159 static void gdk_ic_cleanup (void);
163 /* Private variable declarations
165 static int initialized = 0; /* 1 if the library is initialized,
168 static int connection_number = 0; /* The file descriptor number of our
169 * connection to the X server. This
170 * is used so that we may determine
171 * when events are pending by using
172 * the "select" system call.
176 static struct timeval start; /* The time at which the library was
179 static struct timeval timer; /* Timeout interval to use in the call
180 * to "select". This is used in
181 * conjunction with "timerp" to create
182 * a maximum time to wait for an event
185 static struct timeval *timerp; /* The actual timer passed to "select"
186 * This may be NULL, in which case
187 * "select" will block until an event
190 static guint32 timer_val; /* The timeout length as specified by
191 * the user in milliseconds.
193 static GList *inputs; /* A list of the input file descriptors
194 * that we care about. Each list node
195 * contains a GdkInput struct that describes
196 * when we are interested in the specified
197 * file descriptor. That is, when it is
198 * available for read, write or has an
201 static guint32 button_click_time[2]; /* The last 2 button click times. Used
202 * to determine if the latest button click
203 * is part of a double or triple click.
205 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
206 * Also used to determine if the latest button
207 * click is part of a double or triple click.
209 static guint button_number[2]; /* The last 2 buttons to be pressed.
211 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
216 static gint xim_using; /* using XIM Protocol if TRUE */
217 static GdkIM xim_im; /* global IM */
218 static XIMStyles* xim_styles; /* im supports these styles */
219 static XIMStyle xim_best_allowed_style;
220 static GdkICPrivate *xim_ic; /* currently using IC */
221 static GdkWindow* xim_window; /* currently using Widow */
222 static GList* xim_ic_list;
226 static GList *putback_events = NULL;
228 static gulong base_id;
229 static gint autorepeat;
231 #ifdef G_ENABLE_DEBUG
232 static GDebugKey gdk_debug_keys[] = {
233 {"events", GDK_DEBUG_EVENTS},
234 {"misc", GDK_DEBUG_MISC},
235 {"dnd", GDK_DEBUG_DND},
236 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
237 {"xim", GDK_DEBUG_XIM}
240 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
242 #endif /* G_ENABLE_DEBUG */
245 *--------------------------------------------------------------
248 * Initialize the library for use.
251 * "argc" is the number of arguments.
252 * "argv" is an array of strings.
255 * "argc" and "argv" are modified to reflect any arguments
256 * which were not handled. (Such arguments should either
257 * be handled by the application or dismissed).
260 * The library is initialized.
262 *--------------------------------------------------------------
269 XKeyboardState keyboard_state;
272 XClassHint *class_hint;
273 gint argc_orig = *argc;
276 argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
277 for (i = 0; i < argc_orig; i++)
278 argv_orig[i] = g_strdup ((*argv)[i]);
279 argv_orig[argc_orig] = NULL;
281 X_GETTIMEOFDAY (&start);
283 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
284 signal (SIGHUP, gdk_signal);
285 signal (SIGINT, gdk_signal);
286 signal (SIGQUIT, gdk_signal);
287 signal (SIGBUS, gdk_signal);
288 signal (SIGSEGV, gdk_signal);
289 signal (SIGPIPE, gdk_signal);
290 signal (SIGTERM, gdk_signal);
293 gdk_display_name = NULL;
295 XSetErrorHandler (gdk_x_error);
296 XSetIOErrorHandler (gdk_x_io_error);
300 #ifdef G_ENABLE_DEBUG
302 gchar *debug_string = getenv("GDK_DEBUG");
303 if (debug_string != NULL)
304 gdk_debug_flags = g_parse_debug_string (debug_string,
308 #endif /* G_ENABLE_DEBUG */
316 d = strrchr((*argv)[0],'/');
318 gdk_progname = g_strdup (d + 1);
320 gdk_progname = g_strdup ((*argv)[0]);
322 g_print ("Gdk: progname: \"%s\"\n", gdk_progname));
325 for (i = 1; i < *argc;)
327 #ifdef G_ENABLE_DEBUG
328 if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
329 (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
331 gchar *equal_pos = strchr ((*argv)[i], '=');
333 if (equal_pos != NULL)
335 gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
339 else if ((i + 1) < *argc && (*argv)[i + 1])
341 gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
349 else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
350 (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
352 gchar *equal_pos = strchr ((*argv)[i], '=');
354 if (equal_pos != NULL)
356 gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
360 else if ((i + 1) < *argc && (*argv)[i + 1])
362 gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
371 #endif /* G_ENABLE_DEBUG */
372 if (strcmp ("--display", (*argv)[i]) == 0)
376 if ((i + 1) < *argc && (*argv)[i + 1])
378 gdk_display_name = g_strdup ((*argv)[i + 1]);
379 (*argv)[i + 1] = NULL;
383 else if (strcmp ("--sync", (*argv)[i]) == 0)
388 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
391 gdk_use_xshm = FALSE;
393 else if (strcmp ("--name", (*argv)[i]) == 0)
395 if ((i + 1) < *argc && (*argv)[i + 1])
398 gdk_progname = (*argv)[i];
402 else if (strcmp ("--class", (*argv)[i]) == 0)
404 if ((i + 1) < *argc && (*argv)[i + 1])
407 gdk_progclass = (*argv)[i];
412 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
414 if ((i + 1) < *argc && (*argv)[i + 1])
417 gdk_input_gxid_host = ((*argv)[i]);
421 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
423 if ((i + 1) < *argc && (*argv)[i + 1])
426 gdk_input_gxid_port = atoi ((*argv)[i]);
432 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
434 if ((i + 1) < *argc && (*argv)[i + 1])
437 if (strcmp ("none", (*argv)[i]) == 0)
438 gdk_im_set_best_style (GdkIMPreeditNone);
439 else if (strcmp ("nothing", (*argv)[i]) == 0)
440 gdk_im_set_best_style (GdkIMPreeditNothing);
441 else if (strcmp ("area", (*argv)[i]) == 0)
442 gdk_im_set_best_style (GdkIMPreeditArea);
443 else if (strcmp ("position", (*argv)[i]) == 0)
444 gdk_im_set_best_style (GdkIMPreeditPosition);
445 else if (strcmp ("callbacks", (*argv)[i]) == 0)
446 gdk_im_set_best_style (GdkIMPreeditCallbacks);
449 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
451 if ((i + 1) < *argc && (*argv)[i + 1])
454 if (strcmp ("none", (*argv)[i]) == 0)
455 gdk_im_set_best_style (GdkIMStatusNone);
456 else if (strcmp ("nothing", (*argv)[i]) == 0)
457 gdk_im_set_best_style (GdkIMStatusNothing);
458 else if (strcmp ("area", (*argv)[i]) == 0)
459 gdk_im_set_best_style (GdkIMStatusArea);
460 else if (strcmp ("callbacks", (*argv)[i]) == 0)
461 gdk_im_set_best_style (GdkIMStatusCallbacks);
469 for (i = 1; i < *argc; i++)
471 for (k = i; k < *argc; k++)
472 if ((*argv)[k] != NULL)
478 for (j = i + k; j < *argc; j++)
479 (*argv)[j-k] = (*argv)[j];
486 gdk_progname = "<unknown>";
489 gdk_display = XOpenDisplay (gdk_display_name);
492 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
496 /* This is really crappy. We have to look into the display structure
497 * to find the base resource id. This is only needed for recording
498 * and playback of events.
500 /* base_id = RESOURCE_BASE; */
502 GDK_NOTE (EVENTS, g_print ("base id: %lu\n", base_id));
504 connection_number = ConnectionNumber (gdk_display);
506 g_print ("Gdk: connection number: %d\n", connection_number));
509 XSynchronize (gdk_display, True);
511 gdk_screen = DefaultScreen (gdk_display);
512 gdk_root_window = RootWindow (gdk_display, gdk_screen);
514 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
515 10, 10, 10, 10, 0, 0 , 0);
516 class_hint = XAllocClassHint();
517 class_hint->res_name = gdk_progname;
518 if (gdk_progclass == NULL)
520 gdk_progclass = g_strdup (gdk_progname);
521 gdk_progclass[0] = toupper (gdk_progclass[0]);
523 class_hint->res_class = gdk_progclass;
524 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
525 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
528 for (i = 0; i < argc_orig; i++)
529 g_free(argv_orig[i]);
532 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
533 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
534 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
535 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
536 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
537 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
539 gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
540 gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
541 gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
542 gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
543 gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
544 gdk_dnd.c->gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
545 gdk_dnd.c->gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
547 XGetKeyboardControl (gdk_display, &keyboard_state);
548 autorepeat = keyboard_state.global_auto_repeat;
554 button_click_time[0] = 0;
555 button_click_time[1] = 0;
556 button_window[0] = NULL;
557 button_window[1] = NULL;
558 button_number[0] = -1;
559 button_number[1] = -1;
561 if (ATEXIT (gdk_exit_func))
562 g_warning ("unable to register exit function");
570 /* initialize XIM Protocol variables */
574 if (!(xim_best_allowed_style & GdkIMPreeditMask))
575 gdk_im_set_best_style (GdkIMPreeditCallbacks);
576 if (!(xim_best_allowed_style & GdkIMStatusMask))
577 gdk_im_set_best_style (GdkIMStatusCallbacks);
579 xim_window = (GdkWindow*)NULL;
581 gdk_im_open (NULL, NULL, NULL);
588 *--------------------------------------------------------------
591 * Restores the library to an un-itialized state and exits
592 * the program using the "exit" system call.
595 * "errorcode" is the error value to pass to "exit".
598 * Allocated structures are freed and the program exits
603 *--------------------------------------------------------------
607 gdk_exit (int errorcode)
609 /* de-initialisation is done by the gdk_exit_funct(),
610 no need to do this here (Alex J.) */
615 *--------------------------------------------------------------
624 *--------------------------------------------------------------
628 gdk_set_locale (void)
630 if (!setlocale (LC_ALL,""))
631 g_print ("locale not supported by C library\n");
633 if (!XSupportsLocale ())
635 g_print ("locale not supported by Xlib, locale set to C\n");
636 setlocale (LC_ALL, "C");
639 if (!XSetLocaleModifiers (""))
641 g_print ("can not set locale modifiers\n");
644 return setlocale (LC_ALL,NULL);
648 *--------------------------------------------------------------
651 * Returns the number of events pending on the queue.
652 * These events have already been read from the server
658 * Returns the number of events on XLib's event queue.
662 *--------------------------------------------------------------
666 gdk_events_pending (void)
671 result = XPending (gdk_display);
673 tmp_list = putback_events;
677 tmp_list = tmp_list->next;
684 *--------------------------------------------------------------
685 * gdk_event_get_graphics_expose
687 * Waits for a GraphicsExpose or NoExpose event
692 * For GraphicsExpose events, returns a pointer to the event
693 * converted into a GdkEvent Otherwise, returns NULL.
697 *-------------------------------------------------------------- */
700 graphics_expose_predicate (Display *display,
704 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
706 g_return_val_if_fail (private != NULL, False);
708 if ((xevent->xany.window == private->xwindow) &&
709 ((xevent->xany.type == GraphicsExpose) ||
710 (xevent->xany.type == NoExpose)))
717 gdk_event_get_graphics_expose (GdkWindow *window)
722 g_return_val_if_fail (window != NULL, NULL);
724 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
726 if (xevent.xany.type == GraphicsExpose)
728 event = gdk_event_new ();
730 if (gdk_event_translate (event, &xevent))
733 gdk_event_free (event);
740 *--------------------------------------------------------------
743 * Gets the next event.
748 * If an event was received that we care about, returns
749 * a pointer to that event, to be freed with gdk_event_free.
750 * Otherwise, returns NULL. This function will also return
751 * before an event is received if the timeout interval
756 *--------------------------------------------------------------
769 temp_list = putback_events;
772 temp_event = temp_list->data;
774 if ((* pred) (temp_event, data))
777 *event = *temp_event;
778 putback_events = g_list_remove_link (putback_events, temp_list);
779 g_list_free (temp_list);
783 temp_list = temp_list->next;
786 event_pred.func = pred;
787 event_pred.data = data;
789 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
791 return gdk_event_translate (event, &xevent);
797 event = putback_events->data;
799 temp_list = putback_events;
800 putback_events = g_list_remove_link (putback_events, temp_list);
801 g_list_free_1 (temp_list);
806 /* Wait for an event to occur or the timeout to elapse.
807 * If an event occurs "gdk_event_wait" will return TRUE.
808 * If the timeout elapses "gdk_event_wait" will return
811 if (gdk_event_wait ())
813 /* If we get here we can rest assurred that an event
814 * has occurred. Read it.
818 if (xim_using && xim_window)
820 { /* don't dispatch events used by IM */
821 XNextEvent (gdk_display, &xevent);
822 filter_status = XFilterEvent (&xevent,
823 GDK_WINDOW_XWINDOW (xim_window));
824 } while (filter_status == True);
826 XNextEvent (gdk_display, &xevent);
828 XNextEvent (gdk_display, &xevent);
830 event = gdk_event_new ();
832 event->any.type = GDK_NOTHING;
833 event->any.window = NULL;
834 event->any.send_event = FALSE;
835 event->any.send_event = xevent.xany.send_event;
837 if (gdk_event_translate (event, &xevent))
840 gdk_event_free (event);
847 gdk_event_put (GdkEvent *event)
851 g_return_if_fail (event != NULL);
853 new_event = gdk_event_copy (event);
855 putback_events = g_list_prepend (putback_events, new_event);
859 *--------------------------------------------------------------
862 * Copy a event structure into new storage.
865 * "event" is the event struct to copy.
868 * A new event structure. Free it with gdk_event_free.
871 * The reference count of the window in the event is increased.
873 *--------------------------------------------------------------
876 static GMemChunk *event_chunk;
883 if (event_chunk == NULL)
884 event_chunk = g_mem_chunk_new ("events",
889 new_event = g_chunk_new (GdkEvent, event_chunk);
895 gdk_event_copy (GdkEvent *event)
899 g_return_val_if_fail (event != NULL, NULL);
901 new_event = gdk_event_new ();
904 gdk_window_ref (new_event->any.window);
906 switch (event->any.type)
909 case GDK_KEY_RELEASE:
910 new_event->key.string = g_strdup (event->key.string);
913 case GDK_ENTER_NOTIFY:
914 case GDK_LEAVE_NOTIFY:
915 if (event->crossing.subwindow != NULL)
916 gdk_window_ref (event->crossing.subwindow);
919 case GDK_DROP_DATA_AVAIL:
920 new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
921 new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
922 memcpy (new_event->dropdataavailable.data,
923 event->dropdataavailable.data,
924 event->dropdataavailable.data_numbytes);
935 *--------------------------------------------------------------
938 * Free a event structure obtained from gdk_event_copy. Do not use
939 * with other event structures.
942 * "event" is the event struct to free.
947 * The reference count of the window in the event is decreased and
948 * might be freed, too.
950 *-------------------------------------------------------------- */
953 gdk_event_free (GdkEvent *event)
955 g_assert (event_chunk != NULL);
956 g_return_if_fail (event != NULL);
958 if (event->any.window)
959 gdk_window_unref (event->any.window);
961 switch (event->any.type)
964 case GDK_KEY_RELEASE:
965 g_free (event->key.string);
968 case GDK_ENTER_NOTIFY:
969 case GDK_LEAVE_NOTIFY:
970 if (event->crossing.subwindow != NULL)
971 gdk_window_unref (event->crossing.subwindow);
974 case GDK_DROP_DATA_AVAIL:
975 g_free (event->dropdataavailable.data_type);
976 g_free (event->dropdataavailable.data);
979 case GDK_DRAG_REQUEST:
980 g_free (event->dragrequest.data_type);
987 g_mem_chunk_free (event_chunk, event);
991 *--------------------------------------------------------------
992 * gdk_set_show_events
994 * Turns on/off the showing of events.
997 * "show_events" is a boolean describing whether or
998 * not to show the events gdk receives.
1003 * When "show_events" is TRUE, calls to "gdk_event_get"
1004 * will output debugging informatin regarding the event
1005 * received to stdout.
1007 *--------------------------------------------------------------
1011 gdk_set_show_events (int show_events)
1014 gdk_debug_flags |= GDK_DEBUG_EVENTS;
1016 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1020 gdk_set_use_xshm (gint use_xshm)
1022 gdk_use_xshm = use_xshm;
1026 gdk_get_show_events (void)
1028 return gdk_debug_flags & GDK_DEBUG_EVENTS;
1032 gdk_get_use_xshm (void)
1034 return gdk_use_xshm;
1038 *--------------------------------------------------------------
1041 * Get the number of milliseconds since the library was
1047 * The time since the library was initialized is returned.
1048 * This time value is accurate to milliseconds even though
1049 * a more accurate time down to the microsecond could be
1054 *--------------------------------------------------------------
1061 struct timeval elapsed;
1062 guint32 milliseconds;
1064 X_GETTIMEOFDAY (&end);
1066 if (start.tv_usec > end.tv_usec)
1068 end.tv_usec += 1000000;
1071 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1072 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1074 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1076 return milliseconds;
1080 *--------------------------------------------------------------
1083 * Returns the current timer.
1088 * Returns the current timer interval. This interval is
1089 * in units of milliseconds.
1093 *--------------------------------------------------------------
1097 gdk_timer_get (void)
1103 *--------------------------------------------------------------
1106 * Sets the timer interval.
1109 * "milliseconds" is the new value for the timer.
1114 * Calls to "gdk_event_get" will last for a maximum
1115 * of time of "milliseconds". However, a value of 0
1116 * milliseconds will cause "gdk_event_get" to block
1117 * indefinately until an event is received.
1119 *--------------------------------------------------------------
1123 gdk_timer_set (guint32 milliseconds)
1125 timer_val = milliseconds;
1126 timer.tv_sec = milliseconds / 1000;
1127 timer.tv_usec = (milliseconds % 1000) * 1000;
1132 gdk_timer_enable (void)
1138 gdk_timer_disable (void)
1144 gdk_input_add_full (gint source,
1145 GdkInputCondition condition,
1146 GdkInputFunction function,
1148 GdkDestroyNotify destroy)
1150 static gint next_tag = 1;
1163 if ((input->source == source) && (input->condition == condition))
1166 (input->destroy) (input->data);
1167 input->function = function;
1169 input->destroy = destroy;
1176 input = g_new (GdkInput, 1);
1177 input->tag = next_tag++;
1178 input->source = source;
1179 input->condition = condition;
1180 input->function = function;
1182 input->destroy = destroy;
1185 inputs = g_list_prepend (inputs, input);
1192 gdk_input_add (gint source,
1193 GdkInputCondition condition,
1194 GdkInputFunction function,
1197 return gdk_input_add_interp (source, condition, function, data, NULL);
1201 gdk_input_remove (gint tag)
1212 if (input->tag == tag)
1215 (input->destroy) (input->data);
1220 list->next->prev = list->prev;
1222 list->prev->next = list->next;
1224 inputs = list->next;
1226 temp_list->next = NULL;
1227 temp_list->prev = NULL;
1229 g_free (temp_list->data);
1230 g_list_free (temp_list);
1239 *--------------------------------------------------------------
1242 * Grabs the pointer to a specific window
1245 * "window" is the window which will receive the grab
1246 * "owner_events" specifies whether events will be reported as is,
1247 * or relative to "window"
1248 * "event_mask" masks only interesting events
1249 * "confine_to" limits the cursor movement to the specified window
1250 * "cursor" changes the cursor for the duration of the grab
1251 * "time" specifies the time
1256 * requires a corresponding call to gdk_pointer_ungrab
1258 *--------------------------------------------------------------
1262 gdk_pointer_grab (GdkWindow * window,
1264 GdkEventMask event_mask,
1265 GdkWindow * confine_to,
1269 /* From gdkwindow.c */
1270 extern int nevent_masks;
1271 extern int event_mask_table[];
1274 GdkWindowPrivate *window_private;
1275 GdkWindowPrivate *confine_to_private;
1276 GdkCursorPrivate *cursor_private;
1283 g_return_val_if_fail (window != NULL, 0);
1285 window_private = (GdkWindowPrivate*) window;
1286 confine_to_private = (GdkWindowPrivate*) confine_to;
1287 cursor_private = (GdkCursorPrivate*) cursor;
1289 xwindow = window_private->xwindow;
1291 if (!confine_to || confine_to_private->destroyed)
1294 xconfine_to = confine_to_private->xwindow;
1299 xcursor = cursor_private->xcursor;
1303 for (i = 0; i < nevent_masks; i++)
1305 if (event_mask & (1 << (i + 1)))
1306 xevent_mask |= event_mask_table[i];
1309 if (((GdkWindowPrivate *)window)->extension_events &&
1310 gdk_input_vtable.grab_pointer)
1311 return_val = gdk_input_vtable.grab_pointer (window,
1317 return_val = Success;
1319 if (return_val == Success)
1321 if (!window_private->destroyed)
1322 return_val = XGrabPointer (window_private->xdisplay,
1326 GrabModeAsync, GrabModeAsync,
1331 return_val = AlreadyGrabbed;
1334 if (return_val == GrabSuccess)
1335 xgrab_window = window_private;
1341 *--------------------------------------------------------------
1342 * gdk_pointer_ungrab
1344 * Releases any pointer grab
1352 *--------------------------------------------------------------
1356 gdk_pointer_ungrab (guint32 time)
1358 if (gdk_input_vtable.ungrab_pointer)
1359 gdk_input_vtable.ungrab_pointer (time);
1361 XUngrabPointer (gdk_display, time);
1362 xgrab_window = NULL;
1366 *--------------------------------------------------------------
1367 * gdk_pointer_is_grabbed
1369 * Tell wether there is an active x pointer grab in effect
1377 *--------------------------------------------------------------
1381 gdk_pointer_is_grabbed (void)
1383 return xgrab_window != NULL;
1387 *--------------------------------------------------------------
1390 * Grabs the keyboard to a specific window
1393 * "window" is the window which will receive the grab
1394 * "owner_events" specifies whether events will be reported as is,
1395 * or relative to "window"
1396 * "time" specifies the time
1401 * requires a corresponding call to gdk_keyboard_ungrab
1403 *--------------------------------------------------------------
1407 gdk_keyboard_grab (GdkWindow * window,
1411 GdkWindowPrivate *window_private;
1414 g_return_val_if_fail (window != NULL, 0);
1416 window_private = (GdkWindowPrivate*) window;
1417 xwindow = window_private->xwindow;
1419 if (!window_private->destroyed)
1420 return XGrabKeyboard (window_private->xdisplay,
1423 GrabModeAsync, GrabModeAsync,
1426 return AlreadyGrabbed;
1430 *--------------------------------------------------------------
1431 * gdk_keyboard_ungrab
1433 * Releases any keyboard grab
1441 *--------------------------------------------------------------
1445 gdk_keyboard_ungrab (guint32 time)
1447 XUngrabKeyboard (gdk_display, time);
1451 *--------------------------------------------------------------
1454 * Return the width of the screen.
1462 *--------------------------------------------------------------
1466 gdk_screen_width (void)
1470 return_val = DisplayWidth (gdk_display, gdk_screen);
1476 *--------------------------------------------------------------
1479 * Return the height of the screen.
1487 *--------------------------------------------------------------
1491 gdk_screen_height (void)
1495 return_val = DisplayHeight (gdk_display, gdk_screen);
1501 gdk_key_repeat_disable (void)
1503 XAutoRepeatOff (gdk_display);
1507 gdk_key_repeat_restore (void)
1510 XAutoRepeatOn (gdk_display);
1512 XAutoRepeatOff (gdk_display);
1517 *--------------------------------------------------------------
1520 * Flushes the Xlib output buffer and then waits
1521 * until all requests have been received and processed
1522 * by the X server. The only real use for this function
1523 * is in dealing with XShm.
1531 *--------------------------------------------------------------
1534 void gdk_flush (void)
1536 XSync (gdk_display, False);
1543 XBell(gdk_display, 100);
1548 *--------------------------------------------------------------
1551 * Waits until an event occurs or the timer runs out.
1556 * Returns TRUE if an event is ready to be read and FALSE
1557 * if the timer ran out.
1561 *--------------------------------------------------------------
1565 gdk_event_wait (void)
1569 GdkInputCondition condition;
1570 SELECT_MASK readfds;
1571 SELECT_MASK writefds;
1572 SELECT_MASK exceptfds;
1576 /* If there are no events pending we will wait for an event.
1577 * The time we wait is dependant on the "timer". If no timer
1578 * has been specified then we'll block until an event arrives.
1579 * If a timer has been specified we'll block until an event
1580 * arrives or the timer expires. (This is all done using the
1581 * "select" system call).
1584 if (XPending (gdk_display) == 0)
1587 FD_ZERO (&writefds);
1588 FD_ZERO (&exceptfds);
1590 FD_SET (connection_number, &readfds);
1591 max_input = connection_number;
1599 if (input->condition & GDK_INPUT_READ)
1600 FD_SET (input->source, &readfds);
1601 if (input->condition & GDK_INPUT_WRITE)
1602 FD_SET (input->source, &writefds);
1603 if (input->condition & GDK_INPUT_EXCEPTION)
1604 FD_SET (input->source, &exceptfds);
1606 max_input = MAX (max_input, input->source);
1610 if (gdk_using_threads)
1612 gdk_select_waiting = TRUE;
1614 FD_SET (gdk_threads_pipe[0], &readfds);
1615 max_input = MAX (max_input, gdk_threads_pipe[0]);
1616 gdk_threads_leave ();
1620 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1623 if (gdk_using_threads)
1626 gdk_threads_enter ();
1627 gdk_select_waiting = FALSE;
1629 if (FD_ISSET (gdk_threads_pipe[0], &readfds))
1630 read (gdk_threads_pipe[0], &c, 1);
1639 if (FD_ISSET (connection_number, &readfds))
1641 if (XPending (gdk_display) == 0)
1645 XNoOp (gdk_display);
1646 XFlush (gdk_display);
1661 if (FD_ISSET (input->source, &readfds))
1662 condition |= GDK_INPUT_READ;
1663 if (FD_ISSET (input->source, &writefds))
1664 condition |= GDK_INPUT_WRITE;
1665 if (FD_ISSET (input->source, &exceptfds))
1666 condition |= GDK_INPUT_EXCEPTION;
1668 if (condition && input->function)
1669 (* input->function) (input->data, input->source, condition);
1680 gdk_event_apply_filters (XEvent *xevent,
1684 GdkEventFilter *filter;
1686 GdkFilterReturn result;
1692 filter = (GdkEventFilter *)tmp_list->data;
1694 result = (*filter->function)(xevent, event, filter->data);
1695 if (result != GDK_FILTER_CONTINUE)
1698 tmp_list = tmp_list->next;
1701 return GDK_FILTER_CONTINUE;
1705 gdk_event_translate (GdkEvent *event,
1710 GdkWindowPrivate *window_private;
1711 static XComposeStatus compose;
1715 static gchar* buf = NULL;
1716 static gint buf_len= 0;
1724 /* We need to play catch-up with the dnd motion events */
1725 if(gdk_dnd.drag_really && xevent->type == MotionNotify)
1726 while (XCheckTypedEvent(xevent->xany.display,MotionNotify,xevent));
1728 /* Find the GdkWindow that this event occurred in.
1729 * All events occur in some GdkWindow (otherwise, why
1730 * would we be receiving them). It really is an error
1731 * to receive an event for which we cannot find the
1732 * corresponding GdkWindow. We handle events with window=None
1733 * specially - they are generated by XFree86's XInput under
1734 * some circumstances.
1737 if ((xevent->xany.window == None) &&
1738 gdk_input_vtable.window_none_event)
1740 return_val = gdk_input_vtable.window_none_event (event,xevent);
1742 if (return_val >= 0) /* was handled */
1748 window = gdk_window_lookup (xevent->xany.window);
1749 window_private = (GdkWindowPrivate *) window;
1752 gdk_window_ref (window);
1753 else if(gdk_null_window_warnings) /* Special purpose programs that
1754 get events for other windows may
1755 want to disable this */
1756 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1758 /* Check for filters for this window */
1761 GdkFilterReturn result;
1762 result = gdk_event_apply_filters (xevent, event,
1764 ?window_private->filters
1765 :gdk_default_filters);
1767 if (result != GDK_FILTER_CONTINUE)
1769 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1773 /* We do a "manual" conversion of the XEvent to a
1774 * GdkEvent. The structures are mostly the same so
1775 * the conversion is fairly straightforward. We also
1776 * optionally print debugging info regarding events
1780 * During drag & drop you get events where the pointer is
1781 * in other windows. Need to just do finer-grained checking
1783 switch (xevent->type)
1786 /* Lookup the string corresponding to the given keysym.
1792 buf = g_new (gchar, buf_len);
1794 keysym = GDK_VoidSymbol;
1796 if (xim_using == TRUE && xim_ic)
1800 /* Clear keyval. Depending on status, may not be set */
1801 charcount = XmbLookupString(xim_ic->xic,
1802 &xevent->xkey, buf, buf_len-1,
1804 if (status == XBufferOverflow)
1806 /* alloc adequate size of buffer */
1808 g_print("XIM: overflow (required %i)\n", charcount));
1810 while (buf_len <= charcount)
1812 buf = (gchar *) g_realloc (buf, buf_len);
1814 charcount = XmbLookupString (xim_ic->xic,
1815 &xevent->xkey, buf, buf_len-1,
1818 if (status == XLookupNone)
1825 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1828 charcount = XLookupString (&xevent->xkey, buf, 16,
1831 event->key.keyval = keysym;
1833 if (charcount > 0 && buf[charcount-1] == '\0')
1836 buf[charcount] = '\0';
1838 /* Print debugging info.
1840 #ifdef G_ENABLE_DEBUG
1841 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1843 g_print ("key press:\twindow: %ld key: %12s %d\n",
1844 xevent->xkey.window - base_id,
1845 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1848 g_print ("\t\tlength: %4d string: \"%s\"\n",
1851 #endif /* G_ENABLE_DEBUG */
1853 event->key.type = GDK_KEY_PRESS;
1854 event->key.window = window;
1855 event->key.time = xevent->xkey.time;
1856 event->key.state = (GdkModifierType) xevent->xkey.state;
1857 event->key.string = g_strdup (buf);
1858 event->key.length = charcount;
1860 return_val = window_private && !window_private->destroyed;
1863 g_free (event->key.string);
1868 /* Lookup the string corresponding to the given keysym.
1870 keysym = GDK_VoidSymbol;
1871 charcount = XLookupString (&xevent->xkey, buf, 16,
1873 event->key.keyval = keysym;
1875 /* Print debugging info.
1878 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1879 xevent->xkey.window - base_id,
1880 XKeysymToString (event->key.keyval),
1881 event->key.keyval));
1883 event->key.type = GDK_KEY_RELEASE;
1884 event->key.window = window;
1885 event->key.time = xevent->xkey.time;
1886 event->key.state = (GdkModifierType) xevent->xkey.state;
1887 event->key.length = 0;
1888 event->key.string = NULL;
1890 return_val = window_private && !window_private->destroyed;
1894 /* Print debugging info.
1897 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1898 window_private?window_private->dnd_drag_enabled:0,
1899 xevent->xbutton.window - base_id,
1900 xevent->xbutton.x, xevent->xbutton.y,
1901 xevent->xbutton.button));
1903 if (window_private &&
1904 (window_private->extension_events != 0) &&
1905 gdk_input_ignore_core)
1908 event->button.type = GDK_BUTTON_PRESS;
1909 event->button.window = window;
1910 event->button.time = xevent->xbutton.time;
1911 event->button.x = xevent->xbutton.x;
1912 event->button.y = xevent->xbutton.y;
1913 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1914 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1915 event->button.pressure = 0.5;
1916 event->button.xtilt = 0;
1917 event->button.ytilt = 0;
1918 event->button.state = (GdkModifierType) xevent->xbutton.state;
1919 event->button.button = xevent->xbutton.button;
1920 event->button.source = GDK_SOURCE_MOUSE;
1921 event->button.deviceid = GDK_CORE_POINTER;
1923 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1924 (event->button.window == button_window[1]) &&
1925 (event->button.button == button_number[1]))
1927 gdk_synthesize_click (event, 3);
1929 button_click_time[1] = 0;
1930 button_click_time[0] = 0;
1931 button_window[1] = NULL;
1932 button_window[0] = 0;
1933 button_number[1] = -1;
1934 button_number[0] = -1;
1936 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1937 (event->button.window == button_window[0]) &&
1938 (event->button.button == button_number[0]))
1940 gdk_synthesize_click (event, 2);
1942 button_click_time[1] = button_click_time[0];
1943 button_click_time[0] = event->button.time;
1944 button_window[1] = button_window[0];
1945 button_window[0] = event->button.window;
1946 button_number[1] = button_number[0];
1947 button_number[0] = event->button.button;
1951 button_click_time[1] = 0;
1952 button_click_time[0] = event->button.time;
1953 button_window[1] = NULL;
1954 button_window[0] = event->button.window;
1955 button_number[1] = -1;
1956 button_number[0] = event->button.button;
1959 && window_private->dnd_drag_enabled
1960 && !gdk_dnd.drag_perhaps
1961 && event->button.button == 1
1962 && !gdk_dnd.drag_really)
1964 gdk_dnd.drag_perhaps = 1;
1965 gdk_dnd.dnd_drag_start.x = xevent->xbutton.x_root;
1966 gdk_dnd.dnd_drag_start.y = xevent->xbutton.y_root;
1967 gdk_dnd.real_sw = window_private;
1969 if(gdk_dnd.drag_startwindows)
1971 g_free(gdk_dnd.drag_startwindows);
1972 gdk_dnd.drag_startwindows = NULL;
1974 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1975 gdk_dnd.dnd_grabbed = FALSE;
1978 /* Set motion mask for first DnD'd window, since it
1979 will be the one that is actually dragged */
1980 XWindowAttributes dnd_winattr;
1981 XSetWindowAttributes dnd_setwinattr;
1983 /* We need to get motion events while the button is down, so
1984 we can know whether to really start dragging or not... */
1985 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1988 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1989 dnd_setwinattr.event_mask =
1990 window_private->dnd_drag_eventmask = ButtonMotionMask | ButtonPressMask | ButtonReleaseMask |
1991 EnterWindowMask | LeaveWindowMask | ExposureMask;
1992 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1993 CWEventMask, &dnd_setwinattr);
1996 return_val = window_private && !window_private->destroyed;
2000 /* Print debugging info.
2003 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
2004 window_private?window_private->dnd_drag_enabled:0,
2005 xevent->xbutton.window - base_id,
2006 xevent->xbutton.x, xevent->xbutton.y,
2007 xevent->xbutton.button));
2009 if (window_private &&
2010 (window_private->extension_events != 0) &&
2011 gdk_input_ignore_core)
2014 event->button.type = GDK_BUTTON_RELEASE;
2015 event->button.window = window;
2016 event->button.time = xevent->xbutton.time;
2017 event->button.x = xevent->xbutton.x;
2018 event->button.y = xevent->xbutton.y;
2019 event->button.x_root = (gfloat)xevent->xbutton.x_root;
2020 event->button.y_root = (gfloat)xevent->xbutton.y_root;
2021 event->button.pressure = 0.5;
2022 event->button.xtilt = 0;
2023 event->button.ytilt = 0;
2024 event->button.state = (GdkModifierType) xevent->xbutton.state;
2025 event->button.button = xevent->xbutton.button;
2026 event->button.source = GDK_SOURCE_MOUSE;
2027 event->button.deviceid = GDK_CORE_POINTER;
2029 gdk_dnd.last_drop_time = xevent->xbutton.time;
2030 if(gdk_dnd.drag_perhaps)
2033 XSetWindowAttributes attrs;
2034 /* Reset event mask to pre-drag value, assuming event_mask
2035 doesn't change during drag */
2036 attrs.event_mask = gdk_dnd.real_sw->dnd_drag_savedeventmask;
2037 XChangeWindowAttributes(gdk_display, gdk_dnd.real_sw->xwindow,
2038 CWEventMask, &attrs);
2041 if (gdk_dnd.dnd_grabbed)
2043 gdk_dnd_display_drag_cursor(-2,
2046 XUngrabPointer(gdk_display, CurrentTime);
2047 gdk_dnd.dnd_grabbed = FALSE;
2050 if(gdk_dnd.drag_really)
2053 foo.x = xevent->xbutton.x_root;
2054 foo.y = xevent->xbutton.y_root;
2056 if(gdk_dnd.dnd_drag_target != None)
2057 gdk_dnd_drag_end(gdk_dnd.dnd_drag_target, foo);
2058 gdk_dnd.drag_really = 0;
2060 gdk_dnd.drag_numwindows = 0;
2061 if(gdk_dnd.drag_startwindows)
2063 g_free(gdk_dnd.drag_startwindows);
2064 gdk_dnd.drag_startwindows = NULL;
2067 gdk_dnd.real_sw = NULL;
2070 gdk_dnd.drag_perhaps = 0;
2071 gdk_dnd.dnd_drag_start.x = gdk_dnd.dnd_drag_start.y = 0;
2072 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2073 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2074 gdk_dnd.dnd_drag_curwin = None;
2075 return_val = window_private?TRUE:FALSE;
2077 return_val = window_private && !window_private->destroyed;
2081 /* Print debugging info.
2084 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2085 xevent->xmotion.window - base_id,
2086 xevent->xmotion.x, xevent->xmotion.y,
2087 (xevent->xmotion.is_hint) ? "true" : "false",
2088 gdk_dnd.drag_perhaps, gdk_dnd.drag_really));
2090 if (window_private &&
2091 (window_private->extension_events != 0) &&
2092 gdk_input_ignore_core)
2095 event->motion.type = GDK_MOTION_NOTIFY;
2096 event->motion.window = window;
2097 event->motion.time = xevent->xmotion.time;
2098 event->motion.x = xevent->xmotion.x;
2099 event->motion.y = xevent->xmotion.y;
2100 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2101 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2102 event->motion.pressure = 0.5;
2103 event->motion.xtilt = 0;
2104 event->motion.ytilt = 0;
2105 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2106 event->motion.is_hint = xevent->xmotion.is_hint;
2107 event->motion.source = GDK_SOURCE_MOUSE;
2108 event->motion.deviceid = GDK_CORE_POINTER;
2110 #define IS_IN_ZONE(cx, cy) (cx >= gdk_dnd.dnd_drag_dropzone.x \
2111 && cy >= gdk_dnd.dnd_drag_dropzone.y \
2112 && cx < (gdk_dnd.dnd_drag_dropzone.x + gdk_dnd.dnd_drag_dropzone.width) \
2113 && cy < (gdk_dnd.dnd_drag_dropzone.y + gdk_dnd.dnd_drag_dropzone.height))
2115 if(gdk_dnd.drag_perhaps && gdk_dnd.drag_really
2116 /* && event->motion.is_hint */ /* HINTME */)
2118 /* First, we have to find what window the motion was in... */
2119 /* XXX there has to be a better way to do this, perhaps with
2120 XTranslateCoordinates or XQueryTree - I don't know how,
2121 and this sort of works */
2122 static Window lastwin = None, curwin = None;
2126 Window childwin = gdk_root_window;
2129 /* Interlude - display cursor for the drag ASAP */
2130 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2131 xevent->xmotion.y_root,
2132 gdk_dnd.dnd_drag_target?TRUE:FALSE,
2136 curwin = gdk_root_window;
2137 ox = x = xevent->xmotion.x_root;
2138 oy = y = xevent->xmotion.y_root;
2140 curwin = gdk_window_xid_at_coords(xevent->xmotion.x_root,
2141 xevent->xmotion.y_root,
2142 gdk_dnd.c->xids,TRUE);
2143 XTranslateCoordinates(gdk_display, gdk_root_window, curwin,
2144 x, y, &x, &y, &childwin);
2146 while(childwin != None)
2150 XTranslateCoordinates(gdk_display, curwin, curwin,
2151 x, y, &x, &y, &childwin);
2152 if(childwin != None)
2154 XTranslateCoordinates(gdk_display, curwin, childwin,
2155 x, y, &x, &y, &twin);
2160 g_print("Drag is now in window %#lx, lastwin was %#lx, ddc = %#lx\n",
2161 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2162 if(curwin != gdk_dnd.dnd_drag_curwin && curwin != lastwin)
2164 /* We have left one window and entered another
2165 (do leave & enter bits) */
2166 if(gdk_dnd.dnd_drag_curwin != None)
2167 gdk_dnd_drag_leave(gdk_dnd.dnd_drag_curwin);
2168 gdk_dnd.dnd_drag_curwin = curwin;
2169 gdk_dnd_drag_enter(gdk_dnd.dnd_drag_curwin);
2170 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2171 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2172 gdk_dnd.dnd_drag_target = None;
2174 g_print("curwin = %#lx, lastwin = %#lx, dnd_drag_curwin = %#lx\n",
2175 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2177 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2178 xevent->xmotion.y_root,
2181 else if(gdk_dnd.dnd_drag_dropzone.width > 0
2182 && gdk_dnd.dnd_drag_dropzone.height > 0
2183 && curwin == gdk_dnd.dnd_drag_curwin)
2185 /* Handle all that dropzone stuff - thanks John ;-) */
2186 if (gdk_dnd.dnd_drag_target != None)
2188 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2189 xevent->xmotion.y_root);
2190 gboolean old_in_zone = IS_IN_ZONE(gdk_dnd.dnd_drag_oldpos.x,
2191 gdk_dnd.dnd_drag_oldpos.y);
2193 if (!in_zone && old_in_zone)
2195 /* We were in the drop zone and moved out */
2196 gdk_dnd.dnd_drag_target = None;
2197 gdk_dnd_drag_leave(curwin);
2198 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2199 xevent->xmotion.y_root,
2202 else if (!in_zone && !old_in_zone)
2204 /* We were outside drop zone but in the window
2205 - have to send enter events */
2206 gdk_dnd_drag_enter(curwin);
2207 gdk_dnd.dnd_drag_curwin = curwin;
2208 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2209 gdk_dnd.dnd_drag_target = None;
2213 dnd_drag_curwin = None; */
2217 return_val = window_private && !window_private->destroyed;
2221 /* Print debugging info.
2224 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2225 xevent->xcrossing.window - base_id,
2226 xevent->xcrossing.detail,
2227 xevent->xcrossing.subwindow - base_id));
2229 /* Tell XInput stuff about it if appropriate */
2230 if (window_private &&
2231 (window_private->extension_events != 0) &&
2232 gdk_input_vtable.enter_event)
2233 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2235 event->crossing.type = GDK_ENTER_NOTIFY;
2236 event->crossing.window = window;
2238 /* If the subwindow field of the XEvent is non-NULL, then
2239 * lookup the corresponding GdkWindow.
2241 if (xevent->xcrossing.subwindow != None)
2242 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2244 event->crossing.subwindow = NULL;
2246 /* Translate the crossing detail into Gdk terms.
2248 switch (xevent->xcrossing.detail)
2250 case NotifyInferior:
2251 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2253 case NotifyAncestor:
2254 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2257 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2259 case NotifyNonlinear:
2260 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2262 case NotifyNonlinearVirtual:
2263 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2266 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2270 #ifdef G_ENABLE_DEBUG
2271 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2273 g_print("We may[%d] have a drag into %#lx = %#lx\n",
2274 gdk_dnd.drag_really,
2275 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2277 #endif /* G_ENABLE_DEBUG */
2279 if (gdk_dnd.drag_perhaps && gdk_dnd.drag_really &&
2280 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2283 gdk_dnd.drag_really = 0;
2285 GDK_NOTE (DND, g_print("Ungrabbed\n"));
2287 gdk_dnd.drag_numwindows = 0;
2288 g_free(gdk_dnd.drag_startwindows);
2289 gdk_dnd.drag_startwindows = NULL;
2290 /* We don't want to ungrab the pointer here, or we'll
2291 * start getting spurious enter/leave events */
2294 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2298 return_val = window_private && !window_private->destroyed;
2302 /* Print debugging info.
2305 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2306 xevent->xcrossing.window - base_id,
2307 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2309 event->crossing.type = GDK_LEAVE_NOTIFY;
2310 event->crossing.window = window;
2312 /* If the subwindow field of the XEvent is non-NULL, then
2313 * lookup the corresponding GdkWindow.
2315 if (xevent->xcrossing.subwindow != None)
2316 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2318 event->crossing.subwindow = NULL;
2320 /* Translate the crossing detail into Gdk terms.
2322 switch (xevent->xcrossing.detail)
2324 case NotifyInferior:
2325 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2327 case NotifyAncestor:
2328 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2331 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2333 case NotifyNonlinear:
2334 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2336 case NotifyNonlinearVirtual:
2337 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2340 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2343 #ifdef G_ENABLE_DEBUG
2344 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2346 g_print("We may[%d] have a drag out of %#lx = %#lx\n",
2347 gdk_dnd.drag_really,
2348 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2350 #endif /* G_ENABLE_DEBUG */
2351 if (gdk_dnd.drag_perhaps && !gdk_dnd.drag_really &&
2352 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2355 gdk_dnd_drag_addwindow((GdkWindow *) gdk_dnd.real_sw);
2356 gdk_dnd_drag_begin((GdkWindow *) gdk_dnd.real_sw);
2358 XGrabPointer(gdk_display, gdk_dnd.real_sw->xwindow, False,
2359 ButtonMotionMask | PointerMotionMask |
2360 /* PointerMotionHintMask | */ /* HINTME */
2361 ButtonPressMask | ButtonReleaseMask,
2362 GrabModeAsync, GrabModeAsync, None,
2364 #ifdef G_ENABLE_DEBUG
2365 GDK_NOTE(DND, g_print("xgpret = %d\n", xgpret));
2367 gdk_dnd.dnd_grabbed = TRUE;
2368 gdk_dnd.drag_really = 1;
2369 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2370 xevent->xmotion.y_root,
2374 return_val = window_private && !window_private->destroyed;
2379 /* We only care about focus events that indicate that _this_
2380 * window (not a ancestor or child) got or lost the focus
2382 switch (xevent->xfocus.detail)
2384 case NotifyAncestor:
2385 case NotifyInferior:
2386 case NotifyNonlinear:
2387 /* Print debugging info.
2390 g_print ("focus %s:\t\twindow: %ld\n",
2391 (xevent->xany.type == FocusIn) ? "in" : "out",
2392 xevent->xfocus.window - base_id));
2394 event->focus_change.type = GDK_FOCUS_CHANGE;
2395 event->focus_change.window = window;
2396 event->focus_change.in = (xevent->xany.type == FocusIn);
2398 return_val = window_private && !window_private->destroyed;
2406 /* Print debugging info.
2409 g_print ("keymap notify\n"));
2411 /* Not currently handled */
2415 /* Print debugging info.
2418 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2419 xevent->xexpose.window - base_id, xevent->xexpose.count,
2420 xevent->xexpose.x, xevent->xexpose.y,
2421 xevent->xexpose.width, xevent->xexpose.height));
2423 event->expose.type = GDK_EXPOSE;
2424 event->expose.window = window;
2425 event->expose.area.x = xevent->xexpose.x;
2426 event->expose.area.y = xevent->xexpose.y;
2427 event->expose.area.width = xevent->xexpose.width;
2428 event->expose.area.height = xevent->xexpose.height;
2429 event->expose.count = xevent->xexpose.count;
2431 return_val = window_private && !window_private->destroyed;
2434 case GraphicsExpose:
2435 /* Print debugging info.
2438 g_print ("graphics expose:\tdrawable: %ld\n",
2439 xevent->xgraphicsexpose.drawable - base_id));
2441 event->expose.type = GDK_EXPOSE;
2442 event->expose.window = window;
2443 event->expose.area.x = xevent->xgraphicsexpose.x;
2444 event->expose.area.y = xevent->xgraphicsexpose.y;
2445 event->expose.area.width = xevent->xgraphicsexpose.width;
2446 event->expose.area.height = xevent->xgraphicsexpose.height;
2447 event->expose.count = xevent->xexpose.count;
2449 return_val = window_private && !window_private->destroyed;
2453 /* Print debugging info.
2456 g_print ("no expose:\t\tdrawable: %ld\n",
2457 xevent->xnoexpose.drawable - base_id));
2459 event->no_expose.type = GDK_NO_EXPOSE;
2460 event->no_expose.window = window;
2462 return_val = window_private && !window_private->destroyed;
2465 case VisibilityNotify:
2466 /* Print debugging info.
2468 #ifdef G_ENABLE_DEBUG
2469 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2470 switch (xevent->xvisibility.state)
2472 case VisibilityFullyObscured:
2473 g_print ("visibility notify:\twindow: %ld none\n",
2474 xevent->xvisibility.window - base_id);
2476 case VisibilityPartiallyObscured:
2477 g_print ("visibility notify:\twindow: %ld partial\n",
2478 xevent->xvisibility.window - base_id);
2480 case VisibilityUnobscured:
2481 g_print ("visibility notify:\twindow: %ld full\n",
2482 xevent->xvisibility.window - base_id);
2485 #endif /* G_ENABLE_DEBUG */
2487 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2488 event->visibility.window = window;
2490 switch (xevent->xvisibility.state)
2492 case VisibilityFullyObscured:
2493 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2496 case VisibilityPartiallyObscured:
2497 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2500 case VisibilityUnobscured:
2501 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2505 return_val = window_private && !window_private->destroyed;
2509 /* Not currently handled */
2513 /* Print debugging info.
2516 g_print ("destroy notify:\twindow: %ld\n",
2517 xevent->xdestroywindow.window - base_id));
2519 event->any.type = GDK_DESTROY;
2520 event->any.window = window;
2522 return_val = window_private && !window_private->destroyed;
2524 if(window && window_private->xwindow != GDK_ROOT_WINDOW())
2525 gdk_window_destroy_notify (window);
2529 /* Print debugging info.
2532 g_print ("unmap notify:\t\twindow: %ld\n",
2533 xevent->xmap.window - base_id));
2535 event->any.type = GDK_UNMAP;
2536 event->any.window = window;
2538 if (xgrab_window == window_private)
2539 xgrab_window = NULL;
2541 return_val = window_private && !window_private->destroyed;
2545 /* Print debugging info.
2548 g_print ("map notify:\t\twindow: %ld\n",
2549 xevent->xmap.window - base_id));
2551 event->any.type = GDK_MAP;
2552 event->any.window = window;
2554 return_val = window_private && !window_private->destroyed;
2557 case ReparentNotify:
2558 /* Print debugging info.
2561 g_print ("reparent notify:\twindow: %ld\n",
2562 xevent->xreparent.window - base_id));
2564 /* Not currently handled */
2567 case ConfigureNotify:
2568 /* Print debugging info.
2570 while ((XPending (gdk_display) > 0) &&
2571 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2572 ConfigureNotify, xevent))
2574 GdkFilterReturn result;
2577 g_print ("configure notify discarded:\twindow: %ld\n",
2578 xevent->xconfigure.window - base_id));
2580 result = gdk_event_apply_filters (xevent, event,
2582 ?window_private->filters
2583 :gdk_default_filters);
2585 /* If the result is GDK_FILTER_REMOVE, there will be
2586 * trouble, but anybody who filtering the Configure events
2587 * better know what they are doing
2589 if (result != GDK_FILTER_CONTINUE)
2591 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2594 /*XSync (gdk_display, 0);*/
2599 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2600 xevent->xconfigure.window - base_id,
2601 xevent->xconfigure.x,
2602 xevent->xconfigure.y,
2603 xevent->xconfigure.width,
2604 xevent->xconfigure.height,
2605 xevent->xconfigure.border_width,
2606 xevent->xconfigure.above - base_id,
2607 xevent->xconfigure.override_redirect));
2611 if ((window_private->extension_events != 0) &&
2612 gdk_input_vtable.configure_event)
2613 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2615 if (window_private->window_type != GDK_WINDOW_CHILD)
2617 event->configure.type = GDK_CONFIGURE;
2618 event->configure.window = window;
2619 event->configure.width = xevent->xconfigure.width;
2620 event->configure.height = xevent->xconfigure.height;
2622 if (!xevent->xconfigure.x &&
2623 !xevent->xconfigure.y &&
2624 !window_private->destroyed)
2628 Window child_window = 0;
2630 if (!XTranslateCoordinates (window_private->xdisplay,
2631 window_private->xwindow,
2636 g_warning ("GdkWindow %ld doesn't share root windows display?",
2637 window_private->xwindow - base_id);
2638 event->configure.x = tx;
2639 event->configure.y = ty;
2643 event->configure.x = xevent->xconfigure.x;
2644 event->configure.y = xevent->xconfigure.y;
2646 window_private->x = event->configure.x;
2647 window_private->y = event->configure.y;
2648 window_private->width = xevent->xconfigure.width;
2649 window_private->height = xevent->xconfigure.height;
2650 if (window_private->resize_count > 1)
2651 window_private->resize_count -= 1;
2653 return_val = !window_private->destroyed;
2658 case PropertyNotify:
2659 /* Print debugging info.
2662 g_print ("property notify:\twindow: %ld\n",
2663 xevent->xproperty.window - base_id));
2665 event->property.type = GDK_PROPERTY_NOTIFY;
2666 event->property.window = window;
2667 event->property.atom = xevent->xproperty.atom;
2668 event->property.time = xevent->xproperty.time;
2669 event->property.state = xevent->xproperty.state;
2671 return_val = window_private && !window_private->destroyed;
2674 case SelectionClear:
2676 g_print ("selection clear:\twindow: %ld\n",
2677 xevent->xproperty.window - base_id));
2679 event->selection.type = GDK_SELECTION_CLEAR;
2680 event->selection.window = window;
2681 event->selection.selection = xevent->xselectionclear.selection;
2682 event->selection.time = xevent->xselectionclear.time;
2684 return_val = window_private && !window_private->destroyed;
2687 case SelectionRequest:
2689 g_print ("selection request:\twindow: %ld\n",
2690 xevent->xproperty.window - base_id));
2692 event->selection.type = GDK_SELECTION_REQUEST;
2693 event->selection.window = window;
2694 event->selection.selection = xevent->xselectionrequest.selection;
2695 event->selection.target = xevent->xselectionrequest.target;
2696 event->selection.property = xevent->xselectionrequest.property;
2697 event->selection.requestor = xevent->xselectionrequest.requestor;
2698 event->selection.time = xevent->xselectionrequest.time;
2700 return_val = window_private && !window_private->destroyed;
2703 case SelectionNotify:
2705 g_print ("selection notify:\twindow: %ld\n",
2706 xevent->xproperty.window - base_id));
2709 event->selection.type = GDK_SELECTION_NOTIFY;
2710 event->selection.window = window;
2711 event->selection.selection = xevent->xselection.selection;
2712 event->selection.target = xevent->xselection.target;
2713 event->selection.property = xevent->xselection.property;
2714 event->selection.time = xevent->xselection.time;
2716 return_val = window_private && !window_private->destroyed;
2719 case ColormapNotify:
2720 /* Print debugging info.
2723 g_print ("colormap notify:\twindow: %ld\n",
2724 xevent->xcolormap.window - base_id));
2726 /* Not currently handled */
2730 /* Print debugging info.
2733 g_print ("client message:\twindow: %ld\n",
2734 xevent->xclient.window - base_id));
2736 /* Client messages are the means of the window manager
2737 * communicating with a program. We'll first check to
2738 * see if this is really the window manager talking
2741 if (xevent->xclient.message_type == gdk_wm_protocols)
2743 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2745 /* The delete window request specifies a window
2746 * to delete. We don't actually destroy the
2747 * window because "it is only a request". (The
2748 * window might contain vital data that the
2749 * program does not want destroyed). Instead
2750 * the event is passed along to the program,
2751 * which should then destroy the window.
2754 /* Print debugging info.
2757 g_print ("delete window:\t\twindow: %ld\n",
2758 xevent->xclient.window - base_id));
2760 event->any.type = GDK_DELETE;
2761 event->any.window = window;
2763 return_val = window_private && !window_private->destroyed;
2765 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2769 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2773 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2775 GDK_NOTE (DND, g_print ("GDK_DROP_ENTER [%d][%d]\n",
2776 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply));
2779 /* Now figure out if we really want this drop...
2780 * If someone is trying funky clipboard stuff, ignore
2783 && window_private->dnd_drop_enabled
2784 && event->dropenter.u.flags.sendreply
2785 && (reptype = gdk_dnd_check_types (window, xevent)))
2789 replyev.xclient.type = ClientMessage;
2790 replyev.xclient.window = xevent->xclient.data.l[0];
2791 replyev.xclient.format = 32;
2792 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2793 replyev.xclient.data.l[0] = window_private->xwindow;
2795 event->dragrequest.u.allflags = 0;
2796 event->dragrequest.u.flags.protocol_version =
2797 DND_PROTOCOL_VERSION;
2798 event->dragrequest.u.flags.willaccept = 1;
2799 event->dragrequest.u.flags.delete_data =
2800 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2802 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2803 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2804 replyev.xclient.data.l[4] = reptype;
2806 if (!gdk_send_xevent (replyev.xclient.window, False,
2807 NoEventMask, &replyev))
2808 GDK_NOTE (DND, g_print("Sending XdeRequest to %#lx failed\n",
2809 replyev.xclient.window));
2811 event->any.type = GDK_DROP_ENTER;
2812 event->any.window = window;
2813 event->dropenter.requestor = replyev.xclient.window;
2814 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2816 GDK_NOTE (DND, g_print("We sent a GDK_DROP_ENTER on to Gtk\n"));
2820 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2822 #ifdef G_ENABLE_DEBUG
2823 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2824 g_print ("GDK_DROP_LEAVE\n");
2827 if (window_private && window_private->dnd_drop_enabled)
2829 event->dropleave.type = GDK_DROP_LEAVE;
2830 event->dropleave.window = window;
2831 event->dropleave.requestor = xevent->xclient.data.l[0];
2832 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2838 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2841 * make sure to only handle requests from the window the cursor is
2844 #ifdef G_ENABLE_DEBUG
2845 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2846 g_print ("GDK_DRAG_REQUEST\n");
2848 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2851 if (window && gdk_dnd.drag_really &&
2852 xevent->xclient.data.l[0] == gdk_dnd.dnd_drag_curwin &&
2853 event->dragrequest.u.flags.sendreply == 0)
2855 /* Got request - do we need to ask user? */
2856 if (!event->dragrequest.u.flags.willaccept
2857 && event->dragrequest.u.flags.senddata)
2860 event->dragrequest.type = GDK_DRAG_REQUEST;
2861 event->dragrequest.window = window;
2862 event->dragrequest.requestor = xevent->xclient.data.l[0];
2863 event->dragrequest.isdrop = 0;
2864 event->dragrequest.drop_coords.x =
2865 event->dragrequest.drop_coords.y = 0;
2868 else if (event->dragrequest.u.flags.willaccept)
2870 window_private->dnd_drag_destructive_op =
2871 event->dragrequest.u.flags.delete_data;
2872 window_private->dnd_drag_accepted = 1;
2873 window_private->dnd_drag_data_type =
2874 xevent->xclient.data.l[4];
2876 gdk_dnd.dnd_drag_target = gdk_dnd.dnd_drag_curwin;
2877 gdk_dnd_display_drag_cursor(-1, -1, TRUE, TRUE);
2879 gdk_dnd.dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2880 gdk_dnd.dnd_drag_dropzone.y =
2881 (xevent->xclient.data.l[2] >> 16) & 65535;
2882 gdk_dnd.dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2883 gdk_dnd.dnd_drag_dropzone.height =
2884 (xevent->xclient.data.l[3] >> 16) & 65535;
2887 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2889 gint tmp_int; Atom tmp_atom;
2891 guchar *tmp_charptr;
2893 #ifdef G_ENABLE_DEBUG
2894 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2895 g_print("GDK_DROP_DATA_AVAIL\n");
2897 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2898 event->dropdataavailable.timestamp = xevent->xclient.data.l[4];
2899 event->dropdataavailable.coords.x =
2900 xevent->xclient.data.l[3] & 0xffff;
2901 event->dropdataavailable.coords.y =
2902 (xevent->xclient.data.l[3] >> 16) & 0xffff;
2904 /* No preview of data ATM */
2905 && event->dropdataavailable.u.flags.isdrop)
2907 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2908 event->dropdataavailable.window = window;
2909 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2910 event->dropdataavailable.data_type =
2911 gdk_atom_name(xevent->xclient.data.l[2]);
2912 if(XGetWindowProperty (gdk_display,
2913 event->dropdataavailable.requestor,
2914 xevent->xclient.data.l[2],
2916 False, XA_PRIMARY, &tmp_atom,
2918 &event->dropdataavailable.data_numbytes,
2923 g_warning("XGetWindowProperty on %#x may have failed\n",
2924 event->dropdataavailable.requestor);
2925 event->dropdataavailable.data = NULL;
2929 GDK_NOTE (DND, g_print("XGetWindowProperty got us %ld bytes\n",
2930 event->dropdataavailable.data_numbytes));
2931 event->dropdataavailable.data =
2932 g_malloc (event->dropdataavailable.data_numbytes);
2933 memcpy (event->dropdataavailable.data,
2934 tmp_charptr, event->dropdataavailable.data_numbytes);
2943 /* Send unknown ClientMessage's on to Gtk for it to use */
2944 event->client.type = GDK_CLIENT_EVENT;
2945 event->client.window = window;
2946 event->client.message_type = xevent->xclient.message_type;
2947 event->client.data_format = xevent->xclient.format;
2948 memcpy(&event->client.data, &xevent->xclient.data,
2949 sizeof(event->client.data));
2956 return_val = return_val && !window_private->destroyed;
2960 /* Print debugging info.
2963 g_print ("mapping notify\n"));
2965 /* Let XLib know that there is a new keyboard mapping.
2967 XRefreshKeyboardMapping (&xevent->xmapping);
2971 /* something else - (e.g., a Xinput event) */
2973 if (window_private &&
2974 (window_private->extension_events != 0) &&
2975 gdk_input_vtable.other_event)
2976 return_val = gdk_input_vtable.other_event(event, xevent, window);
2980 return_val = return_val && !window_private->destroyed;
2987 if (event->any.window)
2988 gdk_window_ref (event->any.window);
2989 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2990 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2991 (event->crossing.subwindow != NULL))
2992 gdk_window_ref (event->crossing.subwindow);
2996 /* Mark this event as having no resources to be freed */
2997 event->any.window = NULL;
2998 event->any.type = GDK_NOTHING;
3002 gdk_window_unref (window);
3009 gdk_event_get_type (Display *display,
3016 if (gdk_event_translate (&event, xevent))
3018 pred = (GdkPredicate*) arg;
3019 return (* pred->func) (&event, pred->data);
3027 gdk_synthesize_click (GdkEvent *event,
3030 GdkEvent temp_event;
3032 g_return_if_fail (event != NULL);
3034 temp_event = *event;
3035 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
3037 gdk_event_put (&temp_event);
3041 *--------------------------------------------------------------
3044 * This is the "atexit" function that makes sure the
3045 * library gets a chance to cleanup.
3052 * The library is un-initialized and the program exits.
3054 *--------------------------------------------------------------
3058 gdk_exit_func (void)
3060 static gboolean in_gdk_exit_func = FALSE;
3062 /* This is to avoid an infinite loop if a program segfaults in
3063 an atexit() handler (and yes, it does happen, especially if a program
3064 has trounced over memory too badly for even g_print to work) */
3065 if(in_gdk_exit_func == TRUE) return;
3066 in_gdk_exit_func = TRUE;
3078 gdk_key_repeat_restore ();
3080 XCloseDisplay (gdk_display);
3086 *--------------------------------------------------------------
3089 * The X error handling routine.
3092 * "display" is the X display the error orignated from.
3093 * "error" is the XErrorEvent that we are handling.
3096 * Either we were expecting some sort of error to occur,
3097 * in which case we set the "gdk_error_code" flag, or this
3098 * error was unexpected, in which case we will print an
3099 * error message and exit. (Since trying to continue will
3100 * most likely simply lead to more errors).
3104 *--------------------------------------------------------------
3108 gdk_x_error (Display *display,
3113 if (gdk_error_warnings)
3115 XGetErrorText (display, error->error_code, buf, 63);
3116 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
3120 error->request_code,
3124 gdk_error_code = -1;
3129 *--------------------------------------------------------------
3132 * The X I/O error handling routine.
3135 * "display" is the X display the error orignated from.
3138 * An X I/O error basically means we lost our connection
3139 * to the X server. There is not much we can do to
3140 * continue, so simply print an error message and exit.
3144 *--------------------------------------------------------------
3148 gdk_x_io_error (Display *display)
3150 g_error ("an x io error occurred");
3155 *--------------------------------------------------------------
3158 * The signal handler.
3161 * "sig_num" is the number of the signal we received.
3164 * The signals we catch are all fatal. So we simply build
3165 * up a nice little error message and print it and exit.
3166 * If in the process of doing so another signal is received
3167 * we notice that we are already exiting and simply kill
3172 *--------------------------------------------------------------
3176 gdk_signal (int sig_num)
3178 static int caught_fatal_sig = 0;
3181 if (caught_fatal_sig)
3182 kill (getpid (), sig_num);
3183 caught_fatal_sig = 1;
3209 sig = "unknown signal";
3213 g_print ("\n** ERROR **: %s caught\n", sig);
3214 #ifdef G_ENABLE_DEBUG
3216 #else /* !G_ENABLE_DEBUG */
3218 #endif /* !G_ENABLE_DEBUG */
3222 gdk_dnd_drag_begin (GdkWindow *initial_window)
3226 GDK_NOTE(DND, g_print("------- STARTING DRAG from %p\n", initial_window));
3228 tev.type = GDK_DRAG_BEGIN;
3229 tev.dragbegin.window = initial_window;
3230 tev.dragbegin.u.allflags = 0;
3231 tev.dragbegin.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3233 gdk_event_put (&tev);
3237 gdk_dnd_drag_enter (Window dest)
3240 GdkEventDropEnter tev;
3242 GdkWindowPrivate *wp;
3244 sev.xclient.type = ClientMessage;
3245 sev.xclient.format = 32;
3246 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3247 sev.xclient.window = dest;
3250 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3251 tev.u.flags.sendreply = 1;
3252 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3254 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3255 if (wp->dnd_drag_data_numtypesavail)
3257 sev.xclient.data.l[0] = wp->xwindow;
3258 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3259 sev.xclient.data.l[1] = tev.u.allflags;
3260 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3261 if (wp->dnd_drag_data_numtypesavail > 1)
3263 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3264 if (wp->dnd_drag_data_numtypesavail > 2)
3266 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3269 sev.xclient.data.l[4] = None;
3272 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3273 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3274 GDK_NOTE (DND, g_print("Sending XdeEnter to %#lx failed\n",
3284 /* The following routines duplicate functionality in Xlib to
3285 * translate from varargs to X's internal opaque XVaNestedList.
3287 * If all vendors have stuck close to the reference implementation,
3288 * then we should hopefully be OK.
3291 /* This needs to match XIMArg as defined in Xlcint.h exactly */
3298 /*************************************************************
3300 * Counts the number of name/value pairs in the vararg list
3305 *************************************************************/
3308 gdk_im_va_count (va_list list)
3313 name = va_arg (list, gchar *);
3317 (void)va_arg (list, gpointer);
3318 name = va_arg (list, gchar *);
3324 /*************************************************************
3325 * gdk_im_va_to_nested:
3326 * Given a varargs list and the result of gdk_im_va_count,
3327 * create a XVaNestedList.
3332 *************************************************************/
3334 static XVaNestedList
3335 gdk_im_va_to_nested (va_list list, guint count)
3345 result = g_new (GdkImArg, count+1);
3348 name = va_arg (list, gchar *);
3352 arg->value = va_arg (list, gpointer);
3354 name = va_arg (list, gchar *);
3359 return (XVaNestedList)result;
3363 *--------------------------------------------------------------
3366 * Begin using input method with XIM Protocol(X11R6 standard)
3369 * "ic" is the "Input Context" which is created by gtk_ic_new.
3370 * The input area is specified with "window".
3373 * The gdk's event handling routine is switched to XIM based routine.
3374 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3375 * and uses XmbLookupString instead of XLookupString.
3379 *--------------------------------------------------------------
3383 gdk_im_begin (GdkIC ic, GdkWindow* window)
3385 GdkICPrivate *private;
3388 g_return_if_fail (ic != NULL);
3389 g_return_if_fail (window);
3391 private = (GdkICPrivate *) ic;
3395 xim_window = window;
3398 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3399 if (xwin != GDK_WINDOW_XWINDOW(window))
3400 XSetICValues (private->xic, XNFocusWindow,
3401 GDK_WINDOW_XWINDOW(window), NULL);
3402 if (private != xim_ic)
3403 XSetICFocus (private->xic);
3408 *--------------------------------------------------------------
3411 * End using input method with XIM Protocol(X11R6 standard)
3416 * The gdk's event handling routine is switched to normal routine.
3417 * User should call this function before ic and window will be destroyed.
3421 *--------------------------------------------------------------
3439 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3441 GdkIMStyle s1, s2, u;
3443 if (style1 == 0) return style2;
3444 if (style2 == 0) return style1;
3445 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3446 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3449 s1 = style1 & GdkIMPreeditMask;
3450 s2 = style2 & GdkIMPreeditMask;
3453 if (u & GdkIMPreeditCallbacks)
3454 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3455 else if (u & GdkIMPreeditPosition)
3456 return (s1 == GdkIMPreeditPosition)? style1:style2;
3457 else if (u & GdkIMPreeditArea)
3458 return (s1 == GdkIMPreeditArea)? style1:style2;
3459 else if (u & GdkIMPreeditNothing)
3460 return (s1 == GdkIMPreeditNothing)? style1:style2;
3462 s1 = style1 & GdkIMStatusMask;
3463 s2 = style2 & GdkIMStatusMask;
3465 if ( u & GdkIMStatusCallbacks)
3466 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3467 else if ( u & GdkIMStatusArea)
3468 return (s1 == GdkIMStatusArea)? style1:style2;
3469 else if ( u & GdkIMStatusNothing)
3470 return (s1 == GdkIMStatusNothing)? style1:style2;
3471 else if ( u & GdkIMStatusNone)
3472 return (s1 == GdkIMStatusNone)? style1:style2;
3474 return 0; /* Get rid of stupid warning */
3478 gdk_im_decide_style (GdkIMStyle supported_style)
3481 GdkIMStyle style, tmp;
3483 g_return_val_if_fail (xim_styles != NULL, 0);
3486 for (i=0; i<xim_styles->count_styles; i++)
3488 tmp = xim_styles->supported_styles[i];
3489 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3490 style = gdk_im_choose_better_style (style, tmp);
3496 gdk_im_set_best_style (GdkIMStyle style)
3498 if (style & GdkIMPreeditMask)
3500 xim_best_allowed_style &= ~GdkIMPreeditMask;
3502 xim_best_allowed_style |= GdkIMPreeditNone;
3503 if (!(style & GdkIMPreeditNone))
3505 xim_best_allowed_style |= GdkIMPreeditNothing;
3506 if (!(style & GdkIMPreeditNothing))
3508 xim_best_allowed_style |= GdkIMPreeditArea;
3509 if (!(style & GdkIMPreeditArea))
3511 xim_best_allowed_style |= GdkIMPreeditPosition;
3512 if (!(style & GdkIMPreeditPosition))
3513 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3518 if (style & GdkIMStatusMask)
3520 xim_best_allowed_style &= ~GdkIMStatusMask;
3522 xim_best_allowed_style |= GdkIMStatusNone;
3523 if (!(style & GdkIMStatusNone))
3525 xim_best_allowed_style |= GdkIMStatusNothing;
3526 if (!(style & GdkIMStatusNothing))
3528 xim_best_allowed_style |= GdkIMStatusArea;
3529 if (!(style & GdkIMStatusArea))
3530 xim_best_allowed_style |= GdkIMStatusCallbacks;
3535 return xim_best_allowed_style;
3539 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3541 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3544 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
3547 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3570 return (xim_im != NULL);
3574 gdk_ic_new (GdkWindow* client_window,
3575 GdkWindow* focus_window,
3576 GdkIMStyle style, ...)
3579 GdkICPrivate *private;
3580 XVaNestedList preedit_attr = NULL;
3583 g_return_val_if_fail (client_window != NULL, NULL);
3584 g_return_val_if_fail (focus_window != NULL, NULL);
3585 g_return_val_if_fail (gdk_im_ready(), NULL);
3587 private = g_new (GdkICPrivate, 1);
3589 va_start (list, style);
3590 count = gdk_im_va_count (list);
3593 va_start (list, style);
3594 preedit_attr = gdk_im_va_to_nested (list, count);
3597 private->style = gdk_im_decide_style (style);
3598 if (private->style != style)
3600 g_warning ("can not create input context with specified input style.");
3605 private->xic = XCreateIC(gdk_im_get (),
3606 XNInputStyle, style,
3607 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3608 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3609 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3612 g_free (preedit_attr);
3620 xim_ic_list = g_list_append (xim_ic_list, private);
3625 gdk_ic_destroy (GdkIC ic)
3627 GdkICPrivate *private;
3629 g_return_if_fail (ic != NULL);
3631 private = (GdkICPrivate *) ic;
3633 if (xim_ic == private)
3636 XDestroyIC (private->xic);
3637 xim_ic_list = g_list_remove (xim_ic_list, private);
3642 gdk_ic_get_style (GdkIC ic)
3644 GdkICPrivate *private;
3646 g_return_val_if_fail (ic != NULL, 0);
3648 private = (GdkICPrivate *) ic;
3650 return private->style;
3654 gdk_ic_set_values (GdkIC ic, ...)
3658 GdkICPrivate *private;
3661 g_return_if_fail (ic != NULL);
3663 private = (GdkICPrivate *) ic;
3665 va_start (list, ic);
3666 count = gdk_im_va_count (list);
3669 va_start (list, ic);
3670 args = gdk_im_va_to_nested (list, count);
3673 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3679 gdk_ic_get_values (GdkIC ic, ...)
3683 GdkICPrivate *private;
3686 g_return_if_fail (ic != NULL);
3688 private = (GdkICPrivate *) ic;
3690 va_start (list, ic);
3691 count = gdk_im_va_count (list);
3694 va_start (list, ic);
3695 args = gdk_im_va_to_nested (list, count);
3698 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3704 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3708 GdkICPrivate *private;
3711 g_return_if_fail (ic != NULL);
3712 g_return_if_fail (target != NULL);
3714 private = (GdkICPrivate *) ic;
3716 va_start (list, target);
3717 count = gdk_im_va_count (list);
3720 va_start (list, target);
3721 attr = gdk_im_va_to_nested (list, count);
3724 XSetICValues (private->xic, target, attr, NULL);
3730 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3734 GdkICPrivate *private;
3737 g_return_if_fail (ic != NULL);
3738 g_return_if_fail (target != NULL);
3740 private = (GdkICPrivate *) ic;
3742 va_start (list, target);
3743 count = gdk_im_va_count (list);
3746 va_start (list, target);
3747 attr = gdk_im_va_to_nested (list, count);
3750 XGetICValues (private->xic, target, attr, NULL);
3756 gdk_ic_get_events (GdkIC ic)
3761 GdkICPrivate *private;
3764 /* From gdkwindow.c */
3765 extern int nevent_masks;
3766 extern int event_mask_table[];
3768 g_return_val_if_fail (ic != NULL, 0);
3770 private = (GdkICPrivate *) ic;
3772 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
3774 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
3779 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3780 if (xmask & event_mask_table [i])
3783 xmask &= ~ event_mask_table [i];
3787 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
3793 gdk_ic_cleanup (void)
3797 GdkICPrivate *private;
3800 for (node = xim_ic_list; node != NULL; node = node->next)
3804 private = (GdkICPrivate *) (node->data);
3805 XDestroyIC (private->xic);
3810 #ifdef G_ENABLE_DEBUG
3811 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3813 g_warning ("Cleaned up %i IC(s)\n", destroyed);
3815 #endif /* G_ENABLE_DEBUG */
3816 g_list_free(xim_ic_list);
3820 #else /* !USE_XIM */
3823 gdk_im_begin (GdkIC ic, GdkWindow* window)
3833 gdk_im_decide_style (GdkIMStyle supported_style)
3835 return GdkIMPreeditNone | GdkIMStatusNone;
3839 gdk_im_set_best_style (GdkIMStyle style)
3841 return GdkIMPreeditNone | GdkIMStatusNone;
3851 gdk_ic_new (GdkWindow* client_window,
3852 GdkWindow* focus_window,
3853 GdkIMStyle style, ...)
3859 gdk_ic_destroy (GdkIC ic)
3864 gdk_ic_get_style (GdkIC ic)
3866 return GdkIMPreeditNone | GdkIMStatusNone;
3870 gdk_ic_set_values (GdkIC ic, ...)
3875 gdk_ic_get_values (GdkIC ic, ...)
3880 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3885 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3890 gdk_ic_get_events (GdkIC ic)
3895 #endif /* USE_XIM */
3900 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3902 static wchar_t wcs[MB_CUR_MAX + 1];
3903 static gchar mbs[MB_CUR_MAX + 1];
3905 wcs[0] = (wchar_t) NULL;
3908 /* The last argument isn't a mistake. The X locale code trims
3909 * the input string to the length of the output string!
3911 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3914 else if (wcs[0] == (wchar_t) NULL)
3917 len = _Xwctomb (mbs, wcs[0]);
3926 #endif /* X_LOCALE */
3929 gdk_dnd_drag_leave (Window dest)
3932 GdkEventDropLeave tev;
3934 GdkWindowPrivate *wp;
3938 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3939 sev.xclient.type = ClientMessage;
3940 sev.xclient.window = dest;
3941 sev.xclient.format = 32;
3942 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3943 sev.xclient.data.l[1] = tev.u.allflags;
3944 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3946 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3947 sev.xclient.data.l[0] = wp->xwindow;
3948 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3949 GDK_NOTE (DND, g_print("Sending XdeLeave to %#lx failed\n",
3951 wp->dnd_drag_accepted = 0;
3956 * when a drop occurs, we go through the list of windows being dragged and
3957 * tell them that it has occurred, so that they can set things up and reply
3961 gdk_dnd_drag_end (Window dest,
3964 GdkWindowPrivate *wp;
3968 tev.dragrequest.type = GDK_DRAG_REQUEST;
3969 tev.dragrequest.drop_coords = coords;
3970 tev.dragrequest.requestor = dest;
3971 tev.dragrequest.u.allflags = 0;
3972 tev.dragrequest.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3973 tev.dragrequest.isdrop = 1;
3975 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3977 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3978 if (wp->dnd_drag_accepted)
3980 tev.dragrequest.window = (GdkWindow *) wp;
3981 tev.dragrequest.u.flags.delete_data = wp->dnd_drag_destructive_op;
3982 tev.dragrequest.timestamp = gdk_dnd.last_drop_time;
3983 tev.dragrequest.data_type =
3984 gdk_atom_name(wp->dnd_drag_data_type);
3986 gdk_event_put(&tev);
3992 gdk_dnd_check_types (GdkWindow *window,
3995 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3997 GdkEventDropEnter event;
3999 g_return_val_if_fail(window != NULL, 0);
4000 g_return_val_if_fail(xevent != NULL, 0);
4001 g_return_val_if_fail(xevent->type == ClientMessage, 0);
4002 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
4004 if(wp->dnd_drop_data_numtypesavail <= 0 ||
4005 !wp->dnd_drop_data_typesavail)
4008 for (i = 2; i <= 4; i++)
4010 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
4012 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
4013 return xevent->xclient.data.l[i];
4017 /* Now we get the extended type list if it's available */
4018 event.u.allflags = xevent->xclient.data.l[1];
4019 if (event.u.flags.extended_typelist)
4021 Atom *exttypes, realtype;
4022 gulong nitems, nbar;
4025 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
4026 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
4027 False, AnyPropertyType, &realtype, &realfmt,
4028 &nitems, &nbar, (unsigned char **) &exttypes)
4032 if (realfmt != (sizeof(Atom) * 8))
4034 g_warning("XdeTypelist property had format of %d instead of the expected %ld, on window %#lx\n",
4035 realfmt, (glong)sizeof(Atom) * 8, xevent->xclient.data.l[0]);
4039 for (i = 0; i <= nitems; i++)
4041 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
4043 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
4056 * used for debugging only
4060 gdk_print_atom (GdkAtom anatom)
4062 gchar *tmpstr = NULL;
4063 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
4064 g_print("Atom %lu has name %s\n", anatom, tmpstr);
4071 * used only by below routine and itself
4074 getchildren (Display *dpy,
4078 Window root, parent, *children, inf = 0;
4080 unsigned int nchildren, i;
4082 unsigned long nitems, after;
4083 unsigned char *data;
4085 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
4088 for (i = 0; !inf && (i < nchildren); i++)
4090 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
4091 AnyPropertyType, &type, &format, &nitems,
4098 for (i = 0; !inf && (i < nchildren); i++)
4099 inf = getchildren (dpy, children[i], WM_STATE);
4101 if (children != None)
4102 XFree ((char *) children);
4108 * find a window with WM_STATE, else return win itself, as per ICCCM
4110 * modification of the XmuClientWindow() routine from X11R6.3
4113 gdk_get_client_window (Display *dpy,
4119 unsigned long nitems, after;
4120 unsigned char *data;
4124 return DefaultRootWindow(dpy);
4126 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
4129 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
4130 &type, &format, &nitems, &after, &data);
4134 inf = getchildren (dpy, win, WM_STATE);
4142 #ifdef WE_HAVE_MOTIF_DROPS_DONE
4144 gdk_drop_get_real_window (GdkWindow *w,
4148 GdkWindow *retval = w;
4149 GdkWindowPrivate *awin;
4151 gint16 myx = *x, myy = *y;
4153 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
4159 for (children = gdk_window_get_children(retval);
4160 children && children->next;
4161 children = children->next)
4163 awin = (GdkWindowPrivate *) children->data;
4164 if ((myx >= awin->x) && (myy >= awin->y)
4165 && (myx < (awin->x + awin->width))
4166 && (myy < (awin->y + awin->height)))
4168 retval = (GdkWindow *) awin;
4182 /* Sends a ClientMessage to all toplevel client windows */
4184 gdk_event_send_clientmessage_toall(GdkEvent *event)
4187 Window *ret_children, ret_root, ret_parent, curwin;
4188 unsigned int ret_nchildren;
4191 g_return_if_fail(event != NULL);
4193 /* Set up our event to send, with the exception of its target window */
4194 sev.xclient.type = ClientMessage;
4195 sev.xclient.display = gdk_display;
4196 sev.xclient.format = event->client.data_format;
4197 sev.xclient.serial = CurrentTime;
4198 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
4199 sev.xclient.message_type = event->client.message_type;
4201 /* OK, we're all set, now let's find some windows to send this to */
4202 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
4203 &ret_children, &ret_nchildren) != True)
4206 /* foreach true child window of the root window, send an event to it */
4207 for(i = 0; i < ret_nchildren; i++) {
4208 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
4209 sev.xclient.window = curwin;
4210 if (!gdk_send_xevent (curwin, False, NoEventMask, &sev))
4211 GDK_NOTE (MISC, g_print("Gdk: Sending client message %ld to %#lx failed\n",
4212 event->client.message_type, curwin));
4215 XFree(ret_children);
4219 gdk_get_display(void)
4221 return (gchar *)XDisplayName (gdk_display_name);
4225 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
4232 gdk_error_warnings = 0;
4233 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
4234 XSync (gdk_display, False);
4235 gdk_error_warnings = 1;
4237 return result && (gdk_error_code != -1);