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"
54 #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);
1609 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1616 if (FD_ISSET (connection_number, &readfds))
1618 if (XPending (gdk_display) == 0)
1622 XNoOp (gdk_display);
1623 XFlush (gdk_display);
1638 if (FD_ISSET (input->source, &readfds))
1639 condition |= GDK_INPUT_READ;
1640 if (FD_ISSET (input->source, &writefds))
1641 condition |= GDK_INPUT_WRITE;
1642 if (FD_ISSET (input->source, &exceptfds))
1643 condition |= GDK_INPUT_EXCEPTION;
1645 if (condition && input->function)
1646 (* input->function) (input->data, input->source, condition);
1657 gdk_event_apply_filters (XEvent *xevent,
1661 GdkEventFilter *filter;
1663 GdkFilterReturn result;
1669 filter = (GdkEventFilter *)tmp_list->data;
1671 result = (*filter->function)(xevent, event, filter->data);
1672 if (result != GDK_FILTER_CONTINUE)
1675 tmp_list = tmp_list->next;
1678 return GDK_FILTER_CONTINUE;
1682 gdk_event_translate (GdkEvent *event,
1687 GdkWindowPrivate *window_private;
1688 XComposeStatus compose;
1691 static gchar* buf = NULL;
1692 static gint buf_len= 0;
1700 /* We need to play catch-up with the dnd motion events */
1701 if(gdk_dnd.drag_really && xevent->type == MotionNotify)
1702 while (XCheckTypedEvent(xevent->xany.display,MotionNotify,xevent));
1704 /* Find the GdkWindow that this event occurred in.
1705 * All events occur in some GdkWindow (otherwise, why
1706 * would we be receiving them). It really is an error
1707 * to receive an event for which we cannot find the
1708 * corresponding GdkWindow. We handle events with window=None
1709 * specially - they are generated by XFree86's XInput under
1710 * some circumstances.
1713 if ((xevent->xany.window == None) &&
1714 gdk_input_vtable.window_none_event)
1716 return_val = gdk_input_vtable.window_none_event (event,xevent);
1718 if (return_val >= 0) /* was handled */
1724 window = gdk_window_lookup (xevent->xany.window);
1725 window_private = (GdkWindowPrivate *) window;
1728 gdk_window_ref (window);
1729 else if(gdk_null_window_warnings) /* Special purpose programs that
1730 get events for other windows may
1731 want to disable this */
1732 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1734 /* Check for filters for this window */
1737 GdkFilterReturn result;
1738 result = gdk_event_apply_filters (xevent, event,
1740 ?window_private->filters
1741 :gdk_default_filters);
1743 if (result != GDK_FILTER_CONTINUE)
1745 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1749 /* We do a "manual" conversion of the XEvent to a
1750 * GdkEvent. The structures are mostly the same so
1751 * the conversion is fairly straightforward. We also
1752 * optionally print debugging info regarding events
1756 * During drag & drop you get events where the pointer is
1757 * in other windows. Need to just do finer-grained checking
1759 switch (xevent->type)
1762 /* Lookup the string corresponding to the given keysym.
1768 buf = g_new (gchar, buf_len);
1770 if (xim_using == TRUE && xim_ic)
1774 /* Clear keyval. Depending on status, may not be set */
1775 event->key.keyval = GDK_VoidSymbol;
1776 charcount = XmbLookupString(xim_ic->xic,
1777 &xevent->xkey, buf, buf_len-1,
1778 (KeySym*) &event->key.keyval,
1780 if (status == XBufferOverflow)
1782 /* alloc adequate size of buffer */
1784 g_print("XIM: overflow (required %i)\n", charcount));
1786 while (buf_len <= charcount)
1788 buf = (gchar *) g_realloc (buf, buf_len);
1790 charcount = XmbLookupString (xim_ic->xic,
1791 &xevent->xkey, buf, buf_len-1,
1792 (KeySym*) &event->key.keyval,
1795 if (status == XLookupNone)
1802 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1803 (KeySym*) &event->key.keyval,
1806 charcount = XLookupString (&xevent->xkey, buf, 16,
1807 (KeySym*) &event->key.keyval,
1810 if (charcount > 0 && buf[charcount-1] == '\0')
1813 buf[charcount] = '\0';
1815 /* Print debugging info.
1817 #ifdef G_ENABLE_DEBUG
1818 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1820 g_print ("key press:\twindow: %ld key: %12s %d\n",
1821 xevent->xkey.window - base_id,
1822 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1825 g_print ("\t\tlength: %4d string: \"%s\"\n",
1828 #endif /* G_ENABLE_DEBUG */
1830 event->key.type = GDK_KEY_PRESS;
1831 event->key.window = window;
1832 event->key.time = xevent->xkey.time;
1833 event->key.state = (GdkModifierType) xevent->xkey.state;
1834 event->key.string = g_strdup (buf);
1835 event->key.length = charcount;
1837 return_val = window_private && !window_private->destroyed;
1840 g_free (event->key.string);
1845 /* Lookup the string corresponding to the given keysym.
1847 charcount = XLookupString (&xevent->xkey, buf, 16,
1848 (KeySym*) &event->key.keyval,
1851 /* Print debugging info.
1854 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1855 xevent->xkey.window - base_id,
1856 XKeysymToString (event->key.keyval),
1857 event->key.keyval));
1859 event->key.type = GDK_KEY_RELEASE;
1860 event->key.window = window;
1861 event->key.time = xevent->xkey.time;
1862 event->key.state = (GdkModifierType) xevent->xkey.state;
1863 event->key.length = 0;
1864 event->key.string = NULL;
1866 return_val = window_private && !window_private->destroyed;
1870 /* Print debugging info.
1873 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1874 window_private?window_private->dnd_drag_enabled:0,
1875 xevent->xbutton.window - base_id,
1876 xevent->xbutton.x, xevent->xbutton.y,
1877 xevent->xbutton.button));
1879 if (window_private &&
1880 (window_private->extension_events != 0) &&
1881 gdk_input_ignore_core)
1884 event->button.type = GDK_BUTTON_PRESS;
1885 event->button.window = window;
1886 event->button.time = xevent->xbutton.time;
1887 event->button.x = xevent->xbutton.x;
1888 event->button.y = xevent->xbutton.y;
1889 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1890 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1891 event->button.pressure = 0.5;
1892 event->button.xtilt = 0;
1893 event->button.ytilt = 0;
1894 event->button.state = (GdkModifierType) xevent->xbutton.state;
1895 event->button.button = xevent->xbutton.button;
1896 event->button.source = GDK_SOURCE_MOUSE;
1897 event->button.deviceid = GDK_CORE_POINTER;
1899 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1900 (event->button.window == button_window[1]) &&
1901 (event->button.button == button_number[1]))
1903 gdk_synthesize_click (event, 3);
1905 button_click_time[1] = 0;
1906 button_click_time[0] = 0;
1907 button_window[1] = NULL;
1908 button_window[0] = 0;
1909 button_number[1] = -1;
1910 button_number[0] = -1;
1912 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1913 (event->button.window == button_window[0]) &&
1914 (event->button.button == button_number[0]))
1916 gdk_synthesize_click (event, 2);
1918 button_click_time[1] = button_click_time[0];
1919 button_click_time[0] = event->button.time;
1920 button_window[1] = button_window[0];
1921 button_window[0] = event->button.window;
1922 button_number[1] = button_number[0];
1923 button_number[0] = event->button.button;
1927 button_click_time[1] = 0;
1928 button_click_time[0] = event->button.time;
1929 button_window[1] = NULL;
1930 button_window[0] = event->button.window;
1931 button_number[1] = -1;
1932 button_number[0] = event->button.button;
1935 && window_private->dnd_drag_enabled
1936 && !gdk_dnd.drag_perhaps
1937 && event->button.button == 1
1938 && !gdk_dnd.drag_really)
1940 gdk_dnd.drag_perhaps = 1;
1941 gdk_dnd.dnd_drag_start.x = xevent->xbutton.x_root;
1942 gdk_dnd.dnd_drag_start.y = xevent->xbutton.y_root;
1943 gdk_dnd.real_sw = window_private;
1945 if(gdk_dnd.drag_startwindows)
1947 g_free(gdk_dnd.drag_startwindows);
1948 gdk_dnd.drag_startwindows = NULL;
1950 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1951 gdk_dnd.dnd_grabbed = FALSE;
1954 /* Set motion mask for first DnD'd window, since it
1955 will be the one that is actually dragged */
1956 XWindowAttributes dnd_winattr;
1957 XSetWindowAttributes dnd_setwinattr;
1959 /* We need to get motion events while the button is down, so
1960 we can know whether to really start dragging or not... */
1961 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1964 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1965 dnd_setwinattr.event_mask =
1966 window_private->dnd_drag_eventmask = ButtonMotionMask | ButtonPressMask | ButtonReleaseMask |
1967 EnterWindowMask | LeaveWindowMask | ExposureMask;
1968 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1969 CWEventMask, &dnd_setwinattr);
1972 return_val = window_private && !window_private->destroyed;
1976 /* Print debugging info.
1979 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
1980 window_private?window_private->dnd_drag_enabled:0,
1981 xevent->xbutton.window - base_id,
1982 xevent->xbutton.x, xevent->xbutton.y,
1983 xevent->xbutton.button));
1985 if (window_private &&
1986 (window_private->extension_events != 0) &&
1987 gdk_input_ignore_core)
1990 event->button.type = GDK_BUTTON_RELEASE;
1991 event->button.window = window;
1992 event->button.time = xevent->xbutton.time;
1993 event->button.x = xevent->xbutton.x;
1994 event->button.y = xevent->xbutton.y;
1995 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1996 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1997 event->button.pressure = 0.5;
1998 event->button.xtilt = 0;
1999 event->button.ytilt = 0;
2000 event->button.state = (GdkModifierType) xevent->xbutton.state;
2001 event->button.button = xevent->xbutton.button;
2002 event->button.source = GDK_SOURCE_MOUSE;
2003 event->button.deviceid = GDK_CORE_POINTER;
2005 gdk_dnd.last_drop_time = xevent->xbutton.time;
2006 if(gdk_dnd.drag_perhaps)
2009 XSetWindowAttributes attrs;
2010 /* Reset event mask to pre-drag value, assuming event_mask
2011 doesn't change during drag */
2012 attrs.event_mask = gdk_dnd.real_sw->dnd_drag_savedeventmask;
2013 XChangeWindowAttributes(gdk_display, gdk_dnd.real_sw->xwindow,
2014 CWEventMask, &attrs);
2017 if (gdk_dnd.dnd_grabbed)
2019 gdk_dnd_display_drag_cursor(-2,
2022 XUngrabPointer(gdk_display, CurrentTime);
2023 gdk_dnd.dnd_grabbed = FALSE;
2026 if(gdk_dnd.drag_really)
2029 foo.x = xevent->xbutton.x_root;
2030 foo.y = xevent->xbutton.y_root;
2032 if(gdk_dnd.dnd_drag_target != None)
2033 gdk_dnd_drag_end(gdk_dnd.dnd_drag_target, foo);
2034 gdk_dnd.drag_really = 0;
2036 gdk_dnd.drag_numwindows = 0;
2037 if(gdk_dnd.drag_startwindows)
2039 g_free(gdk_dnd.drag_startwindows);
2040 gdk_dnd.drag_startwindows = NULL;
2043 gdk_dnd.real_sw = NULL;
2046 gdk_dnd.drag_perhaps = 0;
2047 gdk_dnd.dnd_drag_start.x = gdk_dnd.dnd_drag_start.y = 0;
2048 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2049 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2050 gdk_dnd.dnd_drag_curwin = None;
2051 return_val = window_private?TRUE:FALSE;
2053 return_val = window_private && !window_private->destroyed;
2057 /* Print debugging info.
2060 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2061 xevent->xmotion.window - base_id,
2062 xevent->xmotion.x, xevent->xmotion.y,
2063 (xevent->xmotion.is_hint) ? "true" : "false",
2064 gdk_dnd.drag_perhaps, gdk_dnd.drag_really));
2066 if (window_private &&
2067 (window_private->extension_events != 0) &&
2068 gdk_input_ignore_core)
2071 event->motion.type = GDK_MOTION_NOTIFY;
2072 event->motion.window = window;
2073 event->motion.time = xevent->xmotion.time;
2074 event->motion.x = xevent->xmotion.x;
2075 event->motion.y = xevent->xmotion.y;
2076 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2077 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2078 event->motion.pressure = 0.5;
2079 event->motion.xtilt = 0;
2080 event->motion.ytilt = 0;
2081 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2082 event->motion.is_hint = xevent->xmotion.is_hint;
2083 event->motion.source = GDK_SOURCE_MOUSE;
2084 event->motion.deviceid = GDK_CORE_POINTER;
2086 #define IS_IN_ZONE(cx, cy) (cx >= gdk_dnd.dnd_drag_dropzone.x \
2087 && cy >= gdk_dnd.dnd_drag_dropzone.y \
2088 && cx < (gdk_dnd.dnd_drag_dropzone.x + gdk_dnd.dnd_drag_dropzone.width) \
2089 && cy < (gdk_dnd.dnd_drag_dropzone.y + gdk_dnd.dnd_drag_dropzone.height))
2091 if(gdk_dnd.drag_perhaps && gdk_dnd.drag_really
2092 /* && event->motion.is_hint */ /* HINTME */)
2094 /* First, we have to find what window the motion was in... */
2095 /* XXX there has to be a better way to do this, perhaps with
2096 XTranslateCoordinates or XQueryTree - I don't know how,
2097 and this sort of works */
2098 static Window lastwin = None, curwin = None;
2102 Window childwin = gdk_root_window;
2105 /* Interlude - display cursor for the drag ASAP */
2106 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2107 xevent->xmotion.y_root,
2108 gdk_dnd.dnd_drag_target?TRUE:FALSE,
2112 curwin = gdk_root_window;
2113 ox = x = xevent->xmotion.x_root;
2114 oy = y = xevent->xmotion.y_root;
2116 curwin = gdk_window_xid_at_coords(xevent->xmotion.x_root,
2117 xevent->xmotion.y_root,
2118 gdk_dnd.c->xids,TRUE);
2119 XTranslateCoordinates(gdk_display, gdk_root_window, curwin,
2120 x, y, &x, &y, &childwin);
2122 while(childwin != None)
2126 XTranslateCoordinates(gdk_display, curwin, curwin,
2127 x, y, &x, &y, &childwin);
2128 if(childwin != None)
2130 XTranslateCoordinates(gdk_display, curwin, childwin,
2131 x, y, &x, &y, &twin);
2136 g_print("Drag is now in window %#lx, lastwin was %#lx, ddc = %#lx\n",
2137 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2138 if(curwin != gdk_dnd.dnd_drag_curwin && curwin != lastwin)
2140 /* We have left one window and entered another
2141 (do leave & enter bits) */
2142 if(gdk_dnd.dnd_drag_curwin != None)
2143 gdk_dnd_drag_leave(gdk_dnd.dnd_drag_curwin);
2144 gdk_dnd.dnd_drag_curwin = curwin;
2145 gdk_dnd_drag_enter(gdk_dnd.dnd_drag_curwin);
2146 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2147 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2148 gdk_dnd.dnd_drag_target = None;
2150 g_print("curwin = %#lx, lastwin = %#lx, dnd_drag_curwin = %#lx\n",
2151 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2153 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2154 xevent->xmotion.y_root,
2157 else if(gdk_dnd.dnd_drag_dropzone.width > 0
2158 && gdk_dnd.dnd_drag_dropzone.height > 0
2159 && curwin == gdk_dnd.dnd_drag_curwin)
2161 /* Handle all that dropzone stuff - thanks John ;-) */
2162 if (gdk_dnd.dnd_drag_target != None)
2164 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2165 xevent->xmotion.y_root);
2166 gboolean old_in_zone = IS_IN_ZONE(gdk_dnd.dnd_drag_oldpos.x,
2167 gdk_dnd.dnd_drag_oldpos.y);
2169 if (!in_zone && old_in_zone)
2171 /* We were in the drop zone and moved out */
2172 gdk_dnd.dnd_drag_target = None;
2173 gdk_dnd_drag_leave(curwin);
2174 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2175 xevent->xmotion.y_root,
2178 else if (!in_zone && !old_in_zone)
2180 /* We were outside drop zone but in the window
2181 - have to send enter events */
2182 gdk_dnd_drag_enter(curwin);
2183 gdk_dnd.dnd_drag_curwin = curwin;
2184 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2185 gdk_dnd.dnd_drag_target = None;
2189 dnd_drag_curwin = None; */
2193 return_val = window_private && !window_private->destroyed;
2197 /* Print debugging info.
2200 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2201 xevent->xcrossing.window - base_id,
2202 xevent->xcrossing.detail,
2203 xevent->xcrossing.subwindow - base_id));
2205 /* Tell XInput stuff about it if appropriate */
2206 if (window_private &&
2207 (window_private->extension_events != 0) &&
2208 gdk_input_vtable.enter_event)
2209 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2211 event->crossing.type = GDK_ENTER_NOTIFY;
2212 event->crossing.window = window;
2214 /* If the subwindow field of the XEvent is non-NULL, then
2215 * lookup the corresponding GdkWindow.
2217 if (xevent->xcrossing.subwindow != None)
2218 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2220 event->crossing.subwindow = NULL;
2222 /* Translate the crossing detail into Gdk terms.
2224 switch (xevent->xcrossing.detail)
2226 case NotifyInferior:
2227 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2229 case NotifyAncestor:
2230 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2233 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2235 case NotifyNonlinear:
2236 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2238 case NotifyNonlinearVirtual:
2239 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2242 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2246 #ifdef G_ENABLE_DEBUG
2247 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2249 g_print("We may[%d] have a drag into %#lx = %#lx\n",
2250 gdk_dnd.drag_really,
2251 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2253 #endif /* G_ENABLE_DEBUG */
2255 if (gdk_dnd.drag_perhaps && gdk_dnd.drag_really &&
2256 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2258 gdk_dnd.drag_really = 0;
2260 GDK_NOTE (DND, g_print("Ungrabbed\n"));
2262 gdk_dnd.drag_numwindows = 0;
2263 g_free(gdk_dnd.drag_startwindows);
2264 gdk_dnd.drag_startwindows = NULL;
2265 /* We don't want to ungrab the pointer here, or we'll
2266 * start getting spurious enter/leave events */
2268 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2272 return_val = window_private && !window_private->destroyed;
2276 /* Print debugging info.
2279 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2280 xevent->xcrossing.window - base_id,
2281 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2283 event->crossing.type = GDK_LEAVE_NOTIFY;
2284 event->crossing.window = window;
2286 /* If the subwindow field of the XEvent is non-NULL, then
2287 * lookup the corresponding GdkWindow.
2289 if (xevent->xcrossing.subwindow != None)
2290 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2292 event->crossing.subwindow = NULL;
2294 /* Translate the crossing detail into Gdk terms.
2296 switch (xevent->xcrossing.detail)
2298 case NotifyInferior:
2299 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2301 case NotifyAncestor:
2302 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2305 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2307 case NotifyNonlinear:
2308 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2310 case NotifyNonlinearVirtual:
2311 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2314 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2317 #ifdef G_ENABLE_DEBUG
2318 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2320 g_print("We may[%d] have a drag out of %#lx = %#lx\n",
2321 gdk_dnd.drag_really,
2322 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2324 #endif /* G_ENABLE_DEBUG */
2325 if (gdk_dnd.drag_perhaps && !gdk_dnd.drag_really &&
2326 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2329 gdk_dnd_drag_addwindow((GdkWindow *) gdk_dnd.real_sw);
2330 gdk_dnd_drag_begin((GdkWindow *) gdk_dnd.real_sw);
2332 XGrabPointer(gdk_display, gdk_dnd.real_sw->xwindow, False,
2333 ButtonMotionMask | PointerMotionMask |
2334 /* PointerMotionHintMask | */ /* HINTME */
2335 ButtonPressMask | ButtonReleaseMask,
2336 GrabModeAsync, GrabModeAsync, None,
2338 #ifdef G_ENABLE_DEBUG
2339 GDK_NOTE(DND, g_print("xgpret = %d\n", xgpret));
2341 gdk_dnd.dnd_grabbed = TRUE;
2342 gdk_dnd.drag_really = 1;
2343 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2344 xevent->xmotion.y_root,
2348 return_val = window_private && !window_private->destroyed;
2353 /* We only care about focus events that indicate that _this_
2354 * window (not a ancestor or child) got or lost the focus
2356 switch (xevent->xfocus.detail)
2358 case NotifyAncestor:
2359 case NotifyInferior:
2360 case NotifyNonlinear:
2361 /* Print debugging info.
2364 g_print ("focus %s:\t\twindow: %ld\n",
2365 (xevent->xany.type == FocusIn) ? "in" : "out",
2366 xevent->xfocus.window - base_id));
2368 event->focus_change.type = GDK_FOCUS_CHANGE;
2369 event->focus_change.window = window;
2370 event->focus_change.in = (xevent->xany.type == FocusIn);
2372 return_val = window_private && !window_private->destroyed;
2380 /* Print debugging info.
2383 g_print ("keymap notify\n"));
2385 /* Not currently handled */
2389 /* Print debugging info.
2392 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2393 xevent->xexpose.window - base_id, xevent->xexpose.count,
2394 xevent->xexpose.x, xevent->xexpose.y,
2395 xevent->xexpose.width, xevent->xexpose.height));
2397 event->expose.type = GDK_EXPOSE;
2398 event->expose.window = window;
2399 event->expose.area.x = xevent->xexpose.x;
2400 event->expose.area.y = xevent->xexpose.y;
2401 event->expose.area.width = xevent->xexpose.width;
2402 event->expose.area.height = xevent->xexpose.height;
2403 event->expose.count = xevent->xexpose.count;
2405 return_val = window_private && !window_private->destroyed;
2408 case GraphicsExpose:
2409 /* Print debugging info.
2412 g_print ("graphics expose:\tdrawable: %ld\n",
2413 xevent->xgraphicsexpose.drawable - base_id));
2415 event->expose.type = GDK_EXPOSE;
2416 event->expose.window = window;
2417 event->expose.area.x = xevent->xgraphicsexpose.x;
2418 event->expose.area.y = xevent->xgraphicsexpose.y;
2419 event->expose.area.width = xevent->xgraphicsexpose.width;
2420 event->expose.area.height = xevent->xgraphicsexpose.height;
2421 event->expose.count = xevent->xexpose.count;
2423 return_val = window_private && !window_private->destroyed;
2427 /* Print debugging info.
2430 g_print ("no expose:\t\tdrawable: %ld\n",
2431 xevent->xnoexpose.drawable - base_id));
2433 event->no_expose.type = GDK_NO_EXPOSE;
2434 event->no_expose.window = window;
2436 return_val = window_private && !window_private->destroyed;
2439 case VisibilityNotify:
2440 /* Print debugging info.
2442 #ifdef G_ENABLE_DEBUG
2443 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2444 switch (xevent->xvisibility.state)
2446 case VisibilityFullyObscured:
2447 g_print ("visibility notify:\twindow: %ld none\n",
2448 xevent->xvisibility.window - base_id);
2450 case VisibilityPartiallyObscured:
2451 g_print ("visibility notify:\twindow: %ld partial\n",
2452 xevent->xvisibility.window - base_id);
2454 case VisibilityUnobscured:
2455 g_print ("visibility notify:\twindow: %ld full\n",
2456 xevent->xvisibility.window - base_id);
2459 #endif /* G_ENABLE_DEBUG */
2461 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2462 event->visibility.window = window;
2464 switch (xevent->xvisibility.state)
2466 case VisibilityFullyObscured:
2467 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2470 case VisibilityPartiallyObscured:
2471 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2474 case VisibilityUnobscured:
2475 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2479 return_val = window_private && !window_private->destroyed;
2483 /* Not currently handled */
2487 /* Print debugging info.
2490 g_print ("destroy notify:\twindow: %ld\n",
2491 xevent->xdestroywindow.window - base_id));
2493 event->any.type = GDK_DESTROY;
2494 event->any.window = window;
2496 return_val = window_private && !window_private->destroyed;
2498 gdk_window_destroy_notify (window);
2502 /* Print debugging info.
2505 g_print ("unmap notify:\t\twindow: %ld\n",
2506 xevent->xmap.window - base_id));
2508 event->any.type = GDK_UNMAP;
2509 event->any.window = window;
2511 if (xgrab_window == window_private)
2512 xgrab_window = NULL;
2514 return_val = window_private && !window_private->destroyed;
2518 /* Print debugging info.
2521 g_print ("map notify:\t\twindow: %ld\n",
2522 xevent->xmap.window - base_id));
2524 event->any.type = GDK_MAP;
2525 event->any.window = window;
2527 return_val = window_private && !window_private->destroyed;
2530 case ReparentNotify:
2531 /* Print debugging info.
2534 g_print ("reparent notify:\twindow: %ld\n",
2535 xevent->xreparent.window - base_id));
2537 /* Not currently handled */
2540 case ConfigureNotify:
2541 /* Print debugging info.
2543 while ((XPending (gdk_display) > 0) &&
2544 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2545 ConfigureNotify, xevent))
2547 GdkFilterReturn result;
2550 g_print ("configure notify discarded:\twindow: %ld\n",
2551 xevent->xconfigure.window - base_id));
2553 result = gdk_event_apply_filters (xevent, event,
2555 ?window_private->filters
2556 :gdk_default_filters);
2558 /* If the result is GDK_FILTER_REMOVE, there will be
2559 * trouble, but anybody who filtering the Configure events
2560 * better know what they are doing
2562 if (result != GDK_FILTER_CONTINUE)
2564 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2567 /*XSync (gdk_display, 0);*/
2572 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2573 xevent->xconfigure.window - base_id,
2574 xevent->xconfigure.x,
2575 xevent->xconfigure.y,
2576 xevent->xconfigure.width,
2577 xevent->xconfigure.height,
2578 xevent->xconfigure.border_width,
2579 xevent->xconfigure.above - base_id,
2580 xevent->xconfigure.override_redirect));
2584 if ((window_private->extension_events != 0) &&
2585 gdk_input_vtable.configure_event)
2586 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2588 if (window_private->window_type != GDK_WINDOW_CHILD)
2590 event->configure.type = GDK_CONFIGURE;
2591 event->configure.window = window;
2592 event->configure.width = xevent->xconfigure.width;
2593 event->configure.height = xevent->xconfigure.height;
2595 if (!xevent->xconfigure.x &&
2596 !xevent->xconfigure.y &&
2597 !window_private->destroyed)
2601 Window child_window = 0;
2603 if (!XTranslateCoordinates (window_private->xdisplay,
2604 window_private->xwindow,
2609 g_warning ("GdkWindow %ld doesn't share root windows display?",
2610 window_private->xwindow - base_id);
2611 event->configure.x = tx;
2612 event->configure.y = ty;
2616 event->configure.x = xevent->xconfigure.x;
2617 event->configure.y = xevent->xconfigure.y;
2619 window_private->x = event->configure.x;
2620 window_private->y = event->configure.y;
2621 window_private->width = xevent->xconfigure.width;
2622 window_private->height = xevent->xconfigure.height;
2623 if (window_private->resize_count > 1)
2624 window_private->resize_count -= 1;
2626 return_val = !window_private->destroyed;
2631 case PropertyNotify:
2632 /* Print debugging info.
2635 g_print ("property notify:\twindow: %ld\n",
2636 xevent->xproperty.window - base_id));
2638 event->property.type = GDK_PROPERTY_NOTIFY;
2639 event->property.window = window;
2640 event->property.atom = xevent->xproperty.atom;
2641 event->property.time = xevent->xproperty.time;
2642 event->property.state = xevent->xproperty.state;
2644 return_val = window_private && !window_private->destroyed;
2647 case SelectionClear:
2649 g_print ("selection clear:\twindow: %ld\n",
2650 xevent->xproperty.window - base_id));
2652 event->selection.type = GDK_SELECTION_CLEAR;
2653 event->selection.window = window;
2654 event->selection.selection = xevent->xselectionclear.selection;
2655 event->selection.time = xevent->xselectionclear.time;
2657 return_val = window_private && !window_private->destroyed;
2660 case SelectionRequest:
2662 g_print ("selection request:\twindow: %ld\n",
2663 xevent->xproperty.window - base_id));
2665 event->selection.type = GDK_SELECTION_REQUEST;
2666 event->selection.window = window;
2667 event->selection.selection = xevent->xselectionrequest.selection;
2668 event->selection.target = xevent->xselectionrequest.target;
2669 event->selection.property = xevent->xselectionrequest.property;
2670 event->selection.requestor = xevent->xselectionrequest.requestor;
2671 event->selection.time = xevent->xselectionrequest.time;
2673 return_val = window_private && !window_private->destroyed;
2676 case SelectionNotify:
2678 g_print ("selection notify:\twindow: %ld\n",
2679 xevent->xproperty.window - base_id));
2682 event->selection.type = GDK_SELECTION_NOTIFY;
2683 event->selection.window = window;
2684 event->selection.selection = xevent->xselection.selection;
2685 event->selection.target = xevent->xselection.target;
2686 event->selection.property = xevent->xselection.property;
2687 event->selection.time = xevent->xselection.time;
2689 return_val = window_private && !window_private->destroyed;
2692 case ColormapNotify:
2693 /* Print debugging info.
2696 g_print ("colormap notify:\twindow: %ld\n",
2697 xevent->xcolormap.window - base_id));
2699 /* Not currently handled */
2703 /* Print debugging info.
2706 g_print ("client message:\twindow: %ld\n",
2707 xevent->xclient.window - base_id));
2709 /* Client messages are the means of the window manager
2710 * communicating with a program. We'll first check to
2711 * see if this is really the window manager talking
2714 if (xevent->xclient.message_type == gdk_wm_protocols)
2716 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2718 /* The delete window request specifies a window
2719 * to delete. We don't actually destroy the
2720 * window because "it is only a request". (The
2721 * window might contain vital data that the
2722 * program does not want destroyed). Instead
2723 * the event is passed along to the program,
2724 * which should then destroy the window.
2727 /* Print debugging info.
2730 g_print ("delete window:\t\twindow: %ld\n",
2731 xevent->xclient.window - base_id));
2733 event->any.type = GDK_DELETE;
2734 event->any.window = window;
2736 return_val = window_private && !window_private->destroyed;
2738 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2742 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2746 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2748 GDK_NOTE (DND, g_print ("GDK_DROP_ENTER [%d][%d]\n",
2749 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply));
2752 /* Now figure out if we really want this drop...
2753 * If someone is trying funky clipboard stuff, ignore
2756 && window_private->dnd_drop_enabled
2757 && event->dropenter.u.flags.sendreply
2758 && (reptype = gdk_dnd_check_types (window, xevent)))
2762 replyev.xclient.type = ClientMessage;
2763 replyev.xclient.window = xevent->xclient.data.l[0];
2764 replyev.xclient.format = 32;
2765 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2766 replyev.xclient.data.l[0] = window_private->xwindow;
2768 event->dragrequest.u.allflags = 0;
2769 event->dragrequest.u.flags.protocol_version =
2770 DND_PROTOCOL_VERSION;
2771 event->dragrequest.u.flags.willaccept = 1;
2772 event->dragrequest.u.flags.delete_data =
2773 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2775 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2776 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2777 replyev.xclient.data.l[4] = reptype;
2779 if (!gdk_send_xevent (replyev.xclient.window, False,
2780 NoEventMask, &replyev))
2781 GDK_NOTE (DND, g_print("Sending XdeRequest to %#lx failed\n",
2782 replyev.xclient.window));
2784 event->any.type = GDK_DROP_ENTER;
2785 event->any.window = window;
2786 event->dropenter.requestor = replyev.xclient.window;
2787 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2789 GDK_NOTE (DND, g_print("We sent a GDK_DROP_ENTER on to Gtk\n"));
2793 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2795 #ifdef G_ENABLE_DEBUG
2796 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2797 g_print ("GDK_DROP_LEAVE\n");
2800 if (window_private && window_private->dnd_drop_enabled)
2802 event->dropleave.type = GDK_DROP_LEAVE;
2803 event->dropleave.window = window;
2804 event->dropleave.requestor = xevent->xclient.data.l[0];
2805 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2811 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2814 * make sure to only handle requests from the window the cursor is
2817 #ifdef G_ENABLE_DEBUG
2818 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2819 g_print ("GDK_DRAG_REQUEST\n");
2821 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2824 if (window && gdk_dnd.drag_really &&
2825 xevent->xclient.data.l[0] == gdk_dnd.dnd_drag_curwin &&
2826 event->dragrequest.u.flags.sendreply == 0)
2828 /* Got request - do we need to ask user? */
2829 if (!event->dragrequest.u.flags.willaccept
2830 && event->dragrequest.u.flags.senddata)
2833 event->dragrequest.type = GDK_DRAG_REQUEST;
2834 event->dragrequest.window = window;
2835 event->dragrequest.requestor = xevent->xclient.data.l[0];
2836 event->dragrequest.isdrop = 0;
2837 event->dragrequest.drop_coords.x =
2838 event->dragrequest.drop_coords.y = 0;
2841 else if (event->dragrequest.u.flags.willaccept)
2843 window_private->dnd_drag_destructive_op =
2844 event->dragrequest.u.flags.delete_data;
2845 window_private->dnd_drag_accepted = 1;
2846 window_private->dnd_drag_data_type =
2847 xevent->xclient.data.l[4];
2849 gdk_dnd.dnd_drag_target = gdk_dnd.dnd_drag_curwin;
2850 gdk_dnd_display_drag_cursor(-1, -1, TRUE, TRUE);
2852 gdk_dnd.dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2853 gdk_dnd.dnd_drag_dropzone.y =
2854 (xevent->xclient.data.l[2] >> 16) & 65535;
2855 gdk_dnd.dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2856 gdk_dnd.dnd_drag_dropzone.height =
2857 (xevent->xclient.data.l[3] >> 16) & 65535;
2860 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2862 gint tmp_int; Atom tmp_atom;
2864 guchar *tmp_charptr;
2866 #ifdef G_ENABLE_DEBUG
2867 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2868 g_print("GDK_DROP_DATA_AVAIL\n");
2870 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2871 event->dropdataavailable.timestamp = xevent->xclient.data.l[4];
2872 event->dropdataavailable.coords.x =
2873 xevent->xclient.data.l[3] & 0xffff;
2874 event->dropdataavailable.coords.y =
2875 (xevent->xclient.data.l[3] >> 16) & 0xffff;
2877 /* No preview of data ATM */
2878 && event->dropdataavailable.u.flags.isdrop)
2880 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2881 event->dropdataavailable.window = window;
2882 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2883 event->dropdataavailable.data_type =
2884 gdk_atom_name(xevent->xclient.data.l[2]);
2885 if(XGetWindowProperty (gdk_display,
2886 event->dropdataavailable.requestor,
2887 xevent->xclient.data.l[2],
2889 False, XA_PRIMARY, &tmp_atom,
2891 &event->dropdataavailable.data_numbytes,
2896 g_warning("XGetWindowProperty on %#x may have failed\n",
2897 event->dropdataavailable.requestor);
2898 event->dropdataavailable.data = NULL;
2902 GDK_NOTE (DND, g_print("XGetWindowProperty got us %ld bytes\n",
2903 event->dropdataavailable.data_numbytes));
2904 event->dropdataavailable.data =
2905 g_malloc (event->dropdataavailable.data_numbytes);
2906 memcpy (event->dropdataavailable.data,
2907 tmp_charptr, event->dropdataavailable.data_numbytes);
2916 /* Send unknown ClientMessage's on to Gtk for it to use */
2917 event->client.type = GDK_CLIENT_EVENT;
2918 event->client.window = window;
2919 event->client.message_type = xevent->xclient.message_type;
2920 event->client.data_format = xevent->xclient.format;
2921 memcpy(&event->client.data, &xevent->xclient.data,
2922 sizeof(event->client.data));
2929 return_val = return_val && !window_private->destroyed;
2933 /* Print debugging info.
2936 g_print ("mapping notify\n"));
2938 /* Let XLib know that there is a new keyboard mapping.
2940 XRefreshKeyboardMapping (&xevent->xmapping);
2944 /* something else - (e.g., a Xinput event) */
2946 if (window_private &&
2947 (window_private->extension_events != 0) &&
2948 gdk_input_vtable.other_event)
2949 return_val = gdk_input_vtable.other_event(event, xevent, window);
2953 return_val = return_val && !window_private->destroyed;
2960 if (event->any.window)
2961 gdk_window_ref (event->any.window);
2962 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2963 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2964 (event->crossing.subwindow != NULL))
2965 gdk_window_ref (event->crossing.subwindow);
2969 /* Mark this event as having no resources to be freed */
2970 event->any.window = NULL;
2971 event->any.type = GDK_NOTHING;
2975 gdk_window_unref (window);
2982 gdk_event_get_type (Display *display,
2989 if (gdk_event_translate (&event, xevent))
2991 pred = (GdkPredicate*) arg;
2992 return (* pred->func) (&event, pred->data);
3000 gdk_synthesize_click (GdkEvent *event,
3003 GdkEvent temp_event;
3005 g_return_if_fail (event != NULL);
3007 temp_event = *event;
3008 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
3010 gdk_event_put (&temp_event);
3014 *--------------------------------------------------------------
3017 * This is the "atexit" function that makes sure the
3018 * library gets a chance to cleanup.
3025 * The library is un-initialized and the program exits.
3027 *--------------------------------------------------------------
3031 gdk_exit_func (void)
3033 static gboolean in_gdk_exit_func = FALSE;
3035 /* This is to avoid an infinite loop if a program segfaults in
3036 an atexit() handler (and yes, it does happen, especially if a program
3037 has trounced over memory too badly for even g_print to work) */
3038 if(in_gdk_exit_func == TRUE) return;
3039 in_gdk_exit_func = TRUE;
3051 gdk_key_repeat_restore ();
3053 XCloseDisplay (gdk_display);
3059 *--------------------------------------------------------------
3062 * The X error handling routine.
3065 * "display" is the X display the error orignated from.
3066 * "error" is the XErrorEvent that we are handling.
3069 * Either we were expecting some sort of error to occur,
3070 * in which case we set the "gdk_error_code" flag, or this
3071 * error was unexpected, in which case we will print an
3072 * error message and exit. (Since trying to continue will
3073 * most likely simply lead to more errors).
3077 *--------------------------------------------------------------
3081 gdk_x_error (Display *display,
3086 if (gdk_error_warnings)
3088 XGetErrorText (display, error->error_code, buf, 63);
3089 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
3093 error->request_code,
3097 gdk_error_code = -1;
3102 *--------------------------------------------------------------
3105 * The X I/O error handling routine.
3108 * "display" is the X display the error orignated from.
3111 * An X I/O error basically means we lost our connection
3112 * to the X server. There is not much we can do to
3113 * continue, so simply print an error message and exit.
3117 *--------------------------------------------------------------
3121 gdk_x_io_error (Display *display)
3123 g_error ("an x io error occurred");
3128 *--------------------------------------------------------------
3131 * The signal handler.
3134 * "sig_num" is the number of the signal we received.
3137 * The signals we catch are all fatal. So we simply build
3138 * up a nice little error message and print it and exit.
3139 * If in the process of doing so another signal is received
3140 * we notice that we are already exiting and simply kill
3145 *--------------------------------------------------------------
3149 gdk_signal (int sig_num)
3151 static int caught_fatal_sig = 0;
3154 if (caught_fatal_sig)
3155 kill (getpid (), sig_num);
3156 caught_fatal_sig = 1;
3182 sig = "unknown signal";
3186 g_print ("\n** ERROR **: %s caught\n", sig);
3187 #ifdef G_ENABLE_DEBUG
3189 #else /* !G_ENABLE_DEBUG */
3191 #endif /* !G_ENABLE_DEBUG */
3195 gdk_dnd_drag_begin (GdkWindow *initial_window)
3199 GDK_NOTE(DND, g_print("------- STARTING DRAG from %p\n", initial_window));
3201 tev.type = GDK_DRAG_BEGIN;
3202 tev.dragbegin.window = initial_window;
3203 tev.dragbegin.u.allflags = 0;
3204 tev.dragbegin.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3206 gdk_event_put (&tev);
3210 gdk_dnd_drag_enter (Window dest)
3213 GdkEventDropEnter tev;
3215 GdkWindowPrivate *wp;
3217 sev.xclient.type = ClientMessage;
3218 sev.xclient.format = 32;
3219 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3220 sev.xclient.window = dest;
3223 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3224 tev.u.flags.sendreply = 1;
3225 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3227 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3228 if (wp->dnd_drag_data_numtypesavail)
3230 sev.xclient.data.l[0] = wp->xwindow;
3231 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3232 sev.xclient.data.l[1] = tev.u.allflags;
3233 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3234 if (wp->dnd_drag_data_numtypesavail > 1)
3236 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3237 if (wp->dnd_drag_data_numtypesavail > 2)
3239 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3242 sev.xclient.data.l[4] = None;
3245 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3246 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3247 GDK_NOTE (DND, g_print("Sending XdeEnter to %#lx failed\n",
3257 /* The following routines duplicate functionality in Xlib to
3258 * translate from varargs to X's internal opaque XVaNestedList.
3260 * If all vendors have stuck close to the reference implementation,
3261 * then we should hopefully be OK.
3264 /* This needs to match XIMArg as defined in Xlcint.h exactly */
3271 /*************************************************************
3273 * Counts the number of name/value pairs in the vararg list
3278 *************************************************************/
3281 gdk_im_va_count (va_list list)
3286 name = va_arg (list, gchar *);
3290 (void)va_arg (list, gpointer);
3291 name = va_arg (list, gchar *);
3297 /*************************************************************
3298 * gdk_im_va_to_nested:
3299 * Given a varargs list and the result of gdk_im_va_count,
3300 * create a XVaNestedList.
3305 *************************************************************/
3307 static XVaNestedList
3308 gdk_im_va_to_nested (va_list list, guint count)
3318 result = g_new (GdkImArg, count+1);
3321 name = va_arg (list, gchar *);
3325 arg->value = va_arg (list, gpointer);
3327 name = va_arg (list, gchar *);
3332 return (XVaNestedList)result;
3336 *--------------------------------------------------------------
3339 * Begin using input method with XIM Protocol(X11R6 standard)
3342 * "ic" is the "Input Context" which is created by gtk_ic_new.
3343 * The input area is specified with "window".
3346 * The gdk's event handling routine is switched to XIM based routine.
3347 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3348 * and uses XmbLookupString instead of XLookupString.
3352 *--------------------------------------------------------------
3356 gdk_im_begin (GdkIC ic, GdkWindow* window)
3358 GdkICPrivate *private;
3361 g_return_if_fail (ic != NULL);
3362 g_return_if_fail (window);
3364 private = (GdkICPrivate *) ic;
3368 xim_window = window;
3371 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3372 if (xwin != GDK_WINDOW_XWINDOW(window))
3373 XSetICValues (private->xic, XNFocusWindow,
3374 GDK_WINDOW_XWINDOW(window), NULL);
3375 if (private != xim_ic)
3376 XSetICFocus (private->xic);
3381 *--------------------------------------------------------------
3384 * End using input method with XIM Protocol(X11R6 standard)
3389 * The gdk's event handling routine is switched to normal routine.
3390 * User should call this function before ic and window will be destroyed.
3394 *--------------------------------------------------------------
3412 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3414 GdkIMStyle s1, s2, u;
3416 if (style1 == 0) return style2;
3417 if (style2 == 0) return style1;
3418 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3419 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3422 s1 = style1 & GdkIMPreeditMask;
3423 s2 = style2 & GdkIMPreeditMask;
3426 if (u & GdkIMPreeditCallbacks)
3427 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3428 else if (u & GdkIMPreeditPosition)
3429 return (s1 == GdkIMPreeditPosition)? style1:style2;
3430 else if (u & GdkIMPreeditArea)
3431 return (s1 == GdkIMPreeditArea)? style1:style2;
3432 else if (u & GdkIMPreeditNothing)
3433 return (s1 == GdkIMPreeditNothing)? style1:style2;
3435 s1 = style1 & GdkIMStatusMask;
3436 s2 = style2 & GdkIMStatusMask;
3438 if ( u & GdkIMStatusCallbacks)
3439 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3440 else if ( u & GdkIMStatusArea)
3441 return (s1 == GdkIMStatusArea)? style1:style2;
3442 else if ( u & GdkIMStatusNothing)
3443 return (s1 == GdkIMStatusNothing)? style1:style2;
3444 else if ( u & GdkIMStatusNone)
3445 return (s1 == GdkIMStatusNone)? style1:style2;
3447 return 0; /* Get rid of stupid warning */
3451 gdk_im_decide_style (GdkIMStyle supported_style)
3454 GdkIMStyle style, tmp;
3456 g_return_val_if_fail (xim_styles != NULL, 0);
3459 for (i=0; i<xim_styles->count_styles; i++)
3461 tmp = xim_styles->supported_styles[i];
3462 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3463 style = gdk_im_choose_better_style (style, tmp);
3469 gdk_im_set_best_style (GdkIMStyle style)
3471 if (style & GdkIMPreeditMask)
3473 xim_best_allowed_style &= ~GdkIMPreeditMask;
3475 xim_best_allowed_style |= GdkIMPreeditNone;
3476 if (!(style & GdkIMPreeditNone))
3478 xim_best_allowed_style |= GdkIMPreeditNothing;
3479 if (!(style & GdkIMPreeditNothing))
3481 xim_best_allowed_style |= GdkIMPreeditArea;
3482 if (!(style & GdkIMPreeditArea))
3484 xim_best_allowed_style |= GdkIMPreeditPosition;
3485 if (!(style & GdkIMPreeditPosition))
3486 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3491 if (style & GdkIMStatusMask)
3493 xim_best_allowed_style &= ~GdkIMStatusMask;
3495 xim_best_allowed_style |= GdkIMStatusNone;
3496 if (!(style & GdkIMStatusNone))
3498 xim_best_allowed_style |= GdkIMStatusNothing;
3499 if (!(style & GdkIMStatusNothing))
3501 xim_best_allowed_style |= GdkIMStatusArea;
3502 if (!(style & GdkIMStatusArea))
3503 xim_best_allowed_style |= GdkIMStatusCallbacks;
3508 return xim_best_allowed_style;
3512 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3514 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3517 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
3520 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3543 return (xim_im != NULL);
3547 gdk_ic_new (GdkWindow* client_window,
3548 GdkWindow* focus_window,
3549 GdkIMStyle style, ...)
3552 GdkICPrivate *private;
3553 XVaNestedList preedit_attr = NULL;
3556 g_return_val_if_fail (client_window != NULL, NULL);
3557 g_return_val_if_fail (focus_window != NULL, NULL);
3558 g_return_val_if_fail (gdk_im_ready(), NULL);
3560 private = g_new (GdkICPrivate, 1);
3562 va_start (list, style);
3563 count = gdk_im_va_count (list);
3566 va_start (list, style);
3567 preedit_attr = gdk_im_va_to_nested (list, count);
3570 private->style = gdk_im_decide_style (style);
3571 if (private->style != style)
3573 g_warning ("can not create input context with specified input style.");
3578 private->xic = XCreateIC(gdk_im_get (),
3579 XNInputStyle, style,
3580 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3581 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3582 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3585 g_free (preedit_attr);
3593 xim_ic_list = g_list_append (xim_ic_list, private);
3598 gdk_ic_destroy (GdkIC ic)
3600 GdkICPrivate *private;
3602 g_return_if_fail (ic != NULL);
3604 private = (GdkICPrivate *) ic;
3606 if (xim_ic == private)
3609 XDestroyIC (private->xic);
3610 xim_ic_list = g_list_remove (xim_ic_list, private);
3615 gdk_ic_get_style (GdkIC ic)
3617 GdkICPrivate *private;
3619 g_return_val_if_fail (ic != NULL, 0);
3621 private = (GdkICPrivate *) ic;
3623 return private->style;
3627 gdk_ic_set_values (GdkIC ic, ...)
3631 GdkICPrivate *private;
3634 g_return_if_fail (ic != NULL);
3636 private = (GdkICPrivate *) ic;
3638 va_start (list, ic);
3639 count = gdk_im_va_count (list);
3642 va_start (list, ic);
3643 args = gdk_im_va_to_nested (list, count);
3646 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3652 gdk_ic_get_values (GdkIC ic, ...)
3656 GdkICPrivate *private;
3659 g_return_if_fail (ic != NULL);
3661 private = (GdkICPrivate *) ic;
3663 va_start (list, ic);
3664 count = gdk_im_va_count (list);
3667 va_start (list, ic);
3668 args = gdk_im_va_to_nested (list, count);
3671 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3677 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3681 GdkICPrivate *private;
3684 g_return_if_fail (ic != NULL);
3685 g_return_if_fail (target != NULL);
3687 private = (GdkICPrivate *) ic;
3689 va_start (list, target);
3690 count = gdk_im_va_count (list);
3693 va_start (list, target);
3694 attr = gdk_im_va_to_nested (list, count);
3697 XSetICValues (private->xic, target, attr, NULL);
3703 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3707 GdkICPrivate *private;
3710 g_return_if_fail (ic != NULL);
3711 g_return_if_fail (target != NULL);
3713 private = (GdkICPrivate *) ic;
3715 va_start (list, target);
3716 count = gdk_im_va_count (list);
3719 va_start (list, target);
3720 attr = gdk_im_va_to_nested (list, count);
3723 XGetICValues (private->xic, target, attr, NULL);
3729 gdk_ic_get_events (GdkIC ic)
3734 GdkICPrivate *private;
3737 /* From gdkwindow.c */
3738 extern int nevent_masks;
3739 extern int event_mask_table[];
3741 g_return_val_if_fail (ic != NULL, 0);
3743 private = (GdkICPrivate *) ic;
3745 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
3747 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
3752 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3753 if (xmask & event_mask_table [i])
3756 xmask &= ~ event_mask_table [i];
3760 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
3766 gdk_ic_cleanup (void)
3770 GdkICPrivate *private;
3773 for (node = xim_ic_list; node != NULL; node = node->next)
3777 private = (GdkICPrivate *) (node->data);
3778 XDestroyIC (private->xic);
3783 #ifdef G_ENABLE_DEBUG
3784 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3786 g_warning ("Cleaned up %i IC(s)\n", destroyed);
3788 #endif /* G_ENABLE_DEBUG */
3789 g_list_free(xim_ic_list);
3793 #else /* !USE_XIM */
3796 gdk_im_begin (GdkIC ic, GdkWindow* window)
3806 gdk_im_decide_style (GdkIMStyle supported_style)
3808 return GdkIMPreeditNone | GdkIMStatusNone;
3812 gdk_im_set_best_style (GdkIMStyle style)
3814 return GdkIMPreeditNone | GdkIMStatusNone;
3824 gdk_ic_new (GdkWindow* client_window,
3825 GdkWindow* focus_window,
3826 GdkIMStyle style, ...)
3832 gdk_ic_destroy (GdkIC ic)
3837 gdk_ic_get_style (GdkIC ic)
3839 return GdkIMPreeditNone | GdkIMStatusNone;
3843 gdk_ic_set_values (GdkIC ic, ...)
3848 gdk_ic_get_values (GdkIC ic, ...)
3853 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3858 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3863 gdk_ic_get_events (GdkIC ic)
3868 #endif /* USE_XIM */
3873 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3875 static wchar_t wcs[MB_CUR_MAX + 1];
3876 static gchar mbs[MB_CUR_MAX + 1];
3878 wcs[0] = (wchar_t) NULL;
3881 /* The last argument isn't a mistake. The X locale code trims
3882 * the input string to the length of the output string!
3884 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3887 else if (wcs[0] == (wchar_t) NULL)
3890 len = _Xwctomb (mbs, wcs[0]);
3899 #endif /* X_LOCALE */
3902 gdk_dnd_drag_leave (Window dest)
3905 GdkEventDropLeave tev;
3907 GdkWindowPrivate *wp;
3911 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3912 sev.xclient.type = ClientMessage;
3913 sev.xclient.window = dest;
3914 sev.xclient.format = 32;
3915 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3916 sev.xclient.data.l[1] = tev.u.allflags;
3917 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3919 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3920 sev.xclient.data.l[0] = wp->xwindow;
3921 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3922 GDK_NOTE (DND, g_print("Sending XdeLeave to %#lx failed\n",
3924 wp->dnd_drag_accepted = 0;
3929 * when a drop occurs, we go through the list of windows being dragged and
3930 * tell them that it has occurred, so that they can set things up and reply
3934 gdk_dnd_drag_end (Window dest,
3937 GdkWindowPrivate *wp;
3941 tev.dragrequest.type = GDK_DRAG_REQUEST;
3942 tev.dragrequest.drop_coords = coords;
3943 tev.dragrequest.requestor = dest;
3944 tev.dragrequest.u.allflags = 0;
3945 tev.dragrequest.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3946 tev.dragrequest.isdrop = 1;
3948 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3950 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3951 if (wp->dnd_drag_accepted)
3953 tev.dragrequest.window = (GdkWindow *) wp;
3954 tev.dragrequest.u.flags.delete_data = wp->dnd_drag_destructive_op;
3955 tev.dragrequest.timestamp = gdk_dnd.last_drop_time;
3956 tev.dragrequest.data_type =
3957 gdk_atom_name(wp->dnd_drag_data_type);
3959 gdk_event_put(&tev);
3965 gdk_dnd_check_types (GdkWindow *window,
3968 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3970 GdkEventDropEnter event;
3972 g_return_val_if_fail(window != NULL, 0);
3973 g_return_val_if_fail(xevent != NULL, 0);
3974 g_return_val_if_fail(xevent->type == ClientMessage, 0);
3975 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3977 if(wp->dnd_drop_data_numtypesavail <= 0 ||
3978 !wp->dnd_drop_data_typesavail)
3981 for (i = 2; i <= 4; i++)
3983 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3985 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3986 return xevent->xclient.data.l[i];
3990 /* Now we get the extended type list if it's available */
3991 event.u.allflags = xevent->xclient.data.l[1];
3992 if (event.u.flags.extended_typelist)
3994 Atom *exttypes, realtype;
3995 gulong nitems, nbar;
3998 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3999 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
4000 False, AnyPropertyType, &realtype, &realfmt,
4001 &nitems, &nbar, (unsigned char **) &exttypes)
4005 if (realfmt != (sizeof(Atom) * 8))
4007 g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
4008 realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
4012 for (i = 0; i <= nitems; i++)
4014 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
4016 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
4029 * used for debugging only
4033 gdk_print_atom (GdkAtom anatom)
4035 gchar *tmpstr = NULL;
4036 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
4037 g_print("Atom %lu has name %s\n", anatom, tmpstr);
4044 * used only by below routine and itself
4047 getchildren (Display *dpy,
4051 Window root, parent, *children, inf = 0;
4053 unsigned int nchildren, i;
4055 unsigned long nitems, after;
4056 unsigned char *data;
4058 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
4061 for (i = 0; !inf && (i < nchildren); i++)
4063 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
4064 AnyPropertyType, &type, &format, &nitems,
4071 for (i = 0; !inf && (i < nchildren); i++)
4072 inf = getchildren (dpy, children[i], WM_STATE);
4074 if (children != None)
4075 XFree ((char *) children);
4081 * find a window with WM_STATE, else return win itself, as per ICCCM
4083 * modification of the XmuClientWindow() routine from X11R6.3
4086 gdk_get_client_window (Display *dpy,
4092 unsigned long nitems, after;
4093 unsigned char *data;
4097 return DefaultRootWindow(dpy);
4099 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
4102 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
4103 &type, &format, &nitems, &after, &data);
4107 inf = getchildren (dpy, win, WM_STATE);
4115 #ifdef WE_HAVE_MOTIF_DROPS_DONE
4117 gdk_drop_get_real_window (GdkWindow *w,
4121 GdkWindow *retval = w;
4122 GdkWindowPrivate *awin;
4124 gint16 myx = *x, myy = *y;
4126 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
4132 for (children = gdk_window_get_children(retval);
4133 children && children->next;
4134 children = children->next)
4136 awin = (GdkWindowPrivate *) children->data;
4137 if ((myx >= awin->x) && (myy >= awin->y)
4138 && (myx < (awin->x + awin->width))
4139 && (myy < (awin->y + awin->height)))
4141 retval = (GdkWindow *) awin;
4155 /* Sends a ClientMessage to all toplevel client windows */
4157 gdk_event_send_clientmessage_toall(GdkEvent *event)
4160 Window *ret_children, ret_root, ret_parent, curwin;
4161 unsigned int ret_nchildren;
4164 g_return_if_fail(event != NULL);
4166 /* Set up our event to send, with the exception of its target window */
4167 sev.xclient.type = ClientMessage;
4168 sev.xclient.display = gdk_display;
4169 sev.xclient.format = event->client.data_format;
4170 sev.xclient.serial = CurrentTime;
4171 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
4172 sev.xclient.message_type = event->client.message_type;
4174 /* OK, we're all set, now let's find some windows to send this to */
4175 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
4176 &ret_children, &ret_nchildren) != True)
4179 /* foreach true child window of the root window, send an event to it */
4180 for(i = 0; i < ret_nchildren; i++) {
4181 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
4182 sev.xclient.window = curwin;
4183 if (!gdk_send_xevent (curwin, False, NoEventMask, &sev))
4184 GDK_NOTE (MISC, g_print("Gdk: Sending client message %ld to %#lx failed\n",
4185 event->client.message_type, curwin));
4188 XFree(ret_children);
4192 gdk_get_display(void)
4194 return (gchar *)XDisplayName (gdk_display_name);
4198 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
4205 gdk_error_warnings = 0;
4206 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
4207 XSync (gdk_display, False);
4208 gdk_error_warnings = 1;
4210 return result && (gdk_error_code != -1);