1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "../config.h"
20 /* If you don't want to use gdk's signal handlers define this */
21 /* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */
23 #include <X11/Xlocale.h>
34 #ifdef HAVE_SYS_SELECT_H
35 #include <sys/select.h>
36 #endif /* HAVE_SYS_SELECT_H_ */
38 #define XLIB_ILLEGAL_ACCESS
39 #include <X11/Xatom.h>
42 #include <X11/Xutil.h>
43 #include <X11/Xmu/WinUtil.h>
45 #include <X11/Xresource.h>
47 #include <X11/cursorfont.h>
49 #include "gdkprivate.h"
53 #include "gdkkeysyms.h"
57 #ifndef X_GETTIMEOFDAY
58 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
59 #endif /* X_GETTIMEOFDAY */
62 #define DOUBLE_CLICK_TIME 250
63 #define TRIPLE_CLICK_TIME 500
64 #define DOUBLE_CLICK_DIST 5
65 #define TRIPLE_CLICK_DIST 5
69 # define SELECT_MASK fd_set
75 # define SELECT_MASK void
77 # define SELECT_MASK int
82 typedef struct _GdkInput GdkInput;
83 typedef struct _GdkPredicate GdkPredicate;
89 GdkInputCondition condition;
90 GdkInputFunction function;
92 GdkDestroyNotify destroy;
102 * Private function declarations
105 static GdkEvent *gdk_event_new (void);
106 static gint gdk_event_wait (void);
107 static gint gdk_event_apply_filters (XEvent *xevent,
110 static gint gdk_event_translate (GdkEvent *event,
113 static Bool gdk_event_get_type (Display *display,
117 static void gdk_synthesize_click (GdkEvent *event,
120 static void gdk_dnd_drag_begin (GdkWindow *initial_window);
121 static void gdk_dnd_drag_enter (Window dest);
122 static void gdk_dnd_drag_leave (Window dest);
123 static void gdk_dnd_drag_end (Window dest,
125 static GdkAtom gdk_dnd_check_types (GdkWindow *window,
128 static void gdk_print_atom (GdkAtom anatom);
132 * old junk from offix, we might use it though so leave it
134 Window gdk_get_client_window (Display *dpy,
136 #ifdef WE_HAVE_MOTIF_DROPS_DONE
137 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
141 static void gdk_exit_func (void);
142 static int gdk_x_error (Display *display,
144 static int gdk_x_io_error (Display *display);
145 static RETSIGTYPE gdk_signal (int signum);
149 static guint gdk_im_va_count (va_list list);
150 static XVaNestedList gdk_im_va_to_nested (va_list list,
153 static GdkIM gdk_im_get (void);
154 static gint gdk_im_open (XrmDatabase db,
157 static void gdk_im_close (void);
158 static void gdk_ic_cleanup (void);
162 /* Private variable declarations
164 static int initialized = 0; /* 1 if the library is initialized,
167 static int connection_number = 0; /* The file descriptor number of our
168 * connection to the X server. This
169 * is used so that we may determine
170 * when events are pending by using
171 * the "select" system call.
175 static struct timeval start; /* The time at which the library was
178 static struct timeval timer; /* Timeout interval to use in the call
179 * to "select". This is used in
180 * conjunction with "timerp" to create
181 * a maximum time to wait for an event
184 static struct timeval *timerp; /* The actual timer passed to "select"
185 * This may be NULL, in which case
186 * "select" will block until an event
189 static guint32 timer_val; /* The timeout length as specified by
190 * the user in milliseconds.
192 static GList *inputs; /* A list of the input file descriptors
193 * that we care about. Each list node
194 * contains a GdkInput struct that describes
195 * when we are interested in the specified
196 * file descriptor. That is, when it is
197 * available for read, write or has an
200 static guint32 button_click_time[2]; /* The last 2 button click times. Used
201 * to determine if the latest button click
202 * is part of a double or triple click.
204 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
205 * Also used to determine if the latest button
206 * click is part of a double or triple click.
208 static guint button_number[2]; /* The last 2 buttons to be pressed.
210 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
215 static gint xim_using; /* using XIM Protocol if TRUE */
216 static GdkIM xim_im; /* global IM */
217 static XIMStyles* xim_styles; /* im supports these styles */
218 static XIMStyle xim_best_allowed_style;
219 static GdkICPrivate *xim_ic; /* currently using IC */
220 static GdkWindow* xim_window; /* currently using Widow */
221 static GList* xim_ic_list;
225 #define OTHER_XEVENT_BUFSIZE 4
226 static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
227 static int other_xevent_i = 0;
228 static GList *putback_events = NULL;
230 static gulong base_id;
231 static gint autorepeat;
233 #ifdef G_ENABLE_DEBUG
234 static GDebugKey gdk_debug_keys[] = {
235 {"events", GDK_DEBUG_EVENTS},
236 {"misc", GDK_DEBUG_MISC},
237 {"dnd", GDK_DEBUG_DND},
238 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
239 {"xim", GDK_DEBUG_XIM}
242 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
244 #endif /* G_ENABLE_DEBUG */
247 *--------------------------------------------------------------
250 * Initialize the library for use.
253 * "argc" is the number of arguments.
254 * "argv" is an array of strings.
257 * "argc" and "argv" are modified to reflect any arguments
258 * which were not handled. (Such arguments should either
259 * be handled by the application or dismissed).
262 * The library is initialized.
264 *--------------------------------------------------------------
271 XKeyboardState keyboard_state;
274 XClassHint *class_hint;
275 gint argc_orig = *argc;
278 argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
279 for (i = 0; i < argc_orig; i++)
280 argv_orig[i] = g_strdup ((*argv)[i]);
281 argv_orig[argc_orig] = NULL;
283 X_GETTIMEOFDAY (&start);
285 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
286 signal (SIGHUP, gdk_signal);
287 signal (SIGINT, gdk_signal);
288 signal (SIGQUIT, gdk_signal);
289 signal (SIGBUS, gdk_signal);
290 signal (SIGSEGV, gdk_signal);
291 signal (SIGPIPE, gdk_signal);
292 signal (SIGTERM, gdk_signal);
295 gdk_display_name = NULL;
297 XSetErrorHandler (gdk_x_error);
298 XSetIOErrorHandler (gdk_x_io_error);
302 #ifdef G_ENABLE_DEBUG
304 gchar *debug_string = getenv("GDK_DEBUG");
305 if (debug_string != NULL)
306 gdk_debug_flags = g_parse_debug_string (debug_string,
310 #endif /* G_ENABLE_DEBUG */
318 d = strrchr((*argv)[0],'/');
320 gdk_progname = g_strdup (d + 1);
322 gdk_progname = g_strdup ((*argv)[0]);
324 g_print ("Gdk: progname: \"%s\"\n", gdk_progname));
327 for (i = 1; i < *argc;)
329 #ifdef G_ENABLE_DEBUG
330 if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
331 (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
333 gchar *equal_pos = strchr ((*argv)[i], '=');
335 if (equal_pos != NULL)
337 gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
341 else if ((i + 1) < *argc && (*argv)[i + 1])
343 gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
351 else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
352 (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
354 gchar *equal_pos = strchr ((*argv)[i], '=');
356 if (equal_pos != NULL)
358 gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
362 else if ((i + 1) < *argc && (*argv)[i + 1])
364 gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
373 #endif /* G_ENABLE_DEBUG */
374 if (strcmp ("--display", (*argv)[i]) == 0)
378 if ((i + 1) < *argc && (*argv)[i + 1])
380 gdk_display_name = g_strdup ((*argv)[i + 1]);
381 (*argv)[i + 1] = NULL;
385 else if (strcmp ("--sync", (*argv)[i]) == 0)
390 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
393 gdk_use_xshm = FALSE;
395 else if (strcmp ("--name", (*argv)[i]) == 0)
397 if ((i + 1) < *argc && (*argv)[i + 1])
400 gdk_progname = (*argv)[i];
404 else if (strcmp ("--class", (*argv)[i]) == 0)
406 if ((i + 1) < *argc && (*argv)[i + 1])
409 gdk_progclass = (*argv)[i];
414 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
416 if ((i + 1) < *argc && (*argv)[i + 1])
419 gdk_input_gxid_host = ((*argv)[i]);
423 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
425 if ((i + 1) < *argc && (*argv)[i + 1])
428 gdk_input_gxid_port = atoi ((*argv)[i]);
434 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
436 if ((i + 1) < *argc && (*argv)[i + 1])
439 if (strcmp ("none", (*argv)[i]) == 0)
440 gdk_im_set_best_style (GdkIMPreeditNone);
441 else if (strcmp ("nothing", (*argv)[i]) == 0)
442 gdk_im_set_best_style (GdkIMPreeditNothing);
443 else if (strcmp ("area", (*argv)[i]) == 0)
444 gdk_im_set_best_style (GdkIMPreeditArea);
445 else if (strcmp ("position", (*argv)[i]) == 0)
446 gdk_im_set_best_style (GdkIMPreeditPosition);
447 else if (strcmp ("callbacks", (*argv)[i]) == 0)
448 gdk_im_set_best_style (GdkIMPreeditCallbacks);
451 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
453 if ((i + 1) < *argc && (*argv)[i + 1])
456 if (strcmp ("none", (*argv)[i]) == 0)
457 gdk_im_set_best_style (GdkIMStatusNone);
458 else if (strcmp ("nothing", (*argv)[i]) == 0)
459 gdk_im_set_best_style (GdkIMStatusNothing);
460 else if (strcmp ("area", (*argv)[i]) == 0)
461 gdk_im_set_best_style (GdkIMStatusArea);
462 else if (strcmp ("callbacks", (*argv)[i]) == 0)
463 gdk_im_set_best_style (GdkIMStatusCallbacks);
471 for (i = 1; i < *argc; i++)
473 for (k = i; k < *argc; k++)
474 if ((*argv)[k] != NULL)
480 for (j = i + k; j < *argc; j++)
481 (*argv)[j-k] = (*argv)[j];
488 gdk_progname = "<unknown>";
491 gdk_display = XOpenDisplay (gdk_display_name);
494 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
498 /* This is really crappy. We have to look into the display structure
499 * to find the base resource id. This is only needed for recording
500 * and playback of events.
502 /* base_id = RESOURCE_BASE; */
504 GDK_NOTE (EVENTS, g_print ("base id: %lu\n", base_id));
506 connection_number = ConnectionNumber (gdk_display);
508 g_print ("Gdk: connection number: %d\n", connection_number));
511 XSynchronize (gdk_display, True);
513 gdk_screen = DefaultScreen (gdk_display);
514 gdk_root_window = RootWindow (gdk_display, gdk_screen);
516 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
517 10, 10, 10, 10, 0, 0 , 0);
518 class_hint = XAllocClassHint();
519 class_hint->res_name = gdk_progname;
520 if (gdk_progclass == NULL)
522 gdk_progclass = g_strdup (gdk_progname);
523 gdk_progclass[0] = toupper (gdk_progclass[0]);
525 class_hint->res_class = gdk_progclass;
526 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
527 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
530 for (i = 0; i < argc_orig; i++)
531 g_free(argv_orig[i]);
534 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
535 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
536 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
537 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
538 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
539 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
541 gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
542 gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
543 gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
544 gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
545 gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
546 gdk_dnd.c->gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
547 gdk_dnd.c->gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
549 XGetKeyboardControl (gdk_display, &keyboard_state);
550 autorepeat = keyboard_state.global_auto_repeat;
556 button_click_time[0] = 0;
557 button_click_time[1] = 0;
558 button_window[0] = NULL;
559 button_window[1] = NULL;
560 button_number[0] = -1;
561 button_number[1] = -1;
563 if (ATEXIT (gdk_exit_func))
564 g_warning ("unable to register exit function");
572 /* initialize XIM Protocol variables */
576 if (!(xim_best_allowed_style & GdkIMPreeditMask))
577 gdk_im_set_best_style (GdkIMPreeditCallbacks);
578 if (!(xim_best_allowed_style & GdkIMStatusMask))
579 gdk_im_set_best_style (GdkIMStatusCallbacks);
581 xim_window = (GdkWindow*)NULL;
583 gdk_im_open (NULL, NULL, NULL);
590 *--------------------------------------------------------------
593 * Restores the library to an un-itialized state and exits
594 * the program using the "exit" system call.
597 * "errorcode" is the error value to pass to "exit".
600 * Allocated structures are freed and the program exits
605 *--------------------------------------------------------------
609 gdk_exit (int errorcode)
611 /* de-initialisation is done by the gdk_exit_funct(),
612 no need to do this here (Alex J.) */
617 *--------------------------------------------------------------
626 *--------------------------------------------------------------
632 if (!setlocale (LC_ALL,""))
633 g_print ("locale not supported by C library\n");
635 if (!XSupportsLocale ())
637 g_print ("locale not supported by Xlib, locale set to C\n");
638 setlocale (LC_ALL, "C");
641 if (!XSetLocaleModifiers (""))
643 g_print ("can not set locale modifiers\n");
646 return setlocale (LC_ALL,NULL);
650 *--------------------------------------------------------------
653 * Returns the number of events pending on the queue.
654 * These events have already been read from the server
660 * Returns the number of events on XLib's event queue.
664 *--------------------------------------------------------------
668 gdk_events_pending ()
673 result = XPending (gdk_display);
675 tmp_list = putback_events;
679 tmp_list = tmp_list->next;
686 *--------------------------------------------------------------
687 * gdk_event_get_graphics_expose
689 * Waits for a GraphicsExpose or NoExpose event
694 * For GraphicsExpose events, returns a pointer to the event
695 * converted into a GdkEvent Otherwise, returns NULL.
699 *-------------------------------------------------------------- */
702 graphics_expose_predicate (Display *display,
706 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
708 g_return_val_if_fail (private != NULL, False);
710 if ((xevent->xany.window == private->xwindow) &&
711 ((xevent->xany.type == GraphicsExpose) ||
712 (xevent->xany.type == NoExpose)))
719 gdk_event_get_graphics_expose (GdkWindow *window)
724 g_return_val_if_fail (window != NULL, NULL);
726 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
728 if (xevent.xany.type == GraphicsExpose)
730 event = gdk_event_new ();
732 if (gdk_event_translate (event, &xevent))
735 gdk_event_free (event);
742 *--------------------------------------------------------------
745 * Gets the next event.
750 * If an event was received that we care about, returns
751 * a pointer to that event, to be freed with gdk_event_free.
752 * Otherwise, returns NULL. This function will also return
753 * before an event is received if the timeout interval
758 *--------------------------------------------------------------
771 temp_list = putback_events;
774 temp_event = temp_list->data;
776 if ((* pred) (temp_event, data))
779 *event = *temp_event;
780 putback_events = g_list_remove_link (putback_events, temp_list);
781 g_list_free (temp_list);
785 temp_list = temp_list->next;
788 event_pred.func = pred;
789 event_pred.data = data;
791 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
793 return gdk_event_translate (event, &xevent);
799 event = putback_events->data;
801 temp_list = putback_events;
802 putback_events = g_list_remove_link (putback_events, temp_list);
803 g_list_free_1 (temp_list);
808 /* Wait for an event to occur or the timeout to elapse.
809 * If an event occurs "gdk_event_wait" will return TRUE.
810 * If the timeout elapses "gdk_event_wait" will return
813 if (gdk_event_wait ())
815 /* If we get here we can rest assurred that an event
816 * has occurred. Read it.
820 if (xim_using && xim_window)
822 { /* don't dispatch events used by IM */
823 XNextEvent (gdk_display, &xevent);
824 filter_status = XFilterEvent (&xevent,
825 GDK_WINDOW_XWINDOW (xim_window));
826 } while (filter_status == True);
828 XNextEvent (gdk_display, &xevent);
830 XNextEvent (gdk_display, &xevent);
832 event = gdk_event_new ();
834 event->any.type = GDK_NOTHING;
835 event->any.window = NULL;
836 event->any.send_event = FALSE;
837 event->any.send_event = xevent.xany.send_event;
839 if (gdk_event_translate (event, &xevent))
842 gdk_event_free (event);
849 gdk_event_put (GdkEvent *event)
853 g_return_if_fail (event != NULL);
855 new_event = gdk_event_copy (event);
857 putback_events = g_list_prepend (putback_events, new_event);
861 *--------------------------------------------------------------
864 * Copy a event structure into new storage.
867 * "event" is the event struct to copy.
870 * A new event structure. Free it with gdk_event_free.
873 * The reference count of the window in the event is increased.
875 *--------------------------------------------------------------
878 static GMemChunk *event_chunk;
885 if (event_chunk == NULL)
886 event_chunk = g_mem_chunk_new ("events",
891 new_event = g_chunk_new (GdkEvent, event_chunk);
897 gdk_event_copy (GdkEvent *event)
901 g_return_val_if_fail (event != NULL, NULL);
903 new_event = gdk_event_new ();
906 gdk_window_ref (new_event->any.window);
908 switch (event->any.type)
911 case GDK_KEY_RELEASE:
912 new_event->key.string = g_strdup (event->key.string);
915 case GDK_ENTER_NOTIFY:
916 case GDK_LEAVE_NOTIFY:
917 if (event->crossing.subwindow != NULL)
918 gdk_window_ref (event->crossing.subwindow);
921 case GDK_DROP_DATA_AVAIL:
922 new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
923 new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
924 memcpy (new_event->dropdataavailable.data,
925 event->dropdataavailable.data,
926 event->dropdataavailable.data_numbytes);
937 *--------------------------------------------------------------
940 * Free a event structure obtained from gdk_event_copy. Do not use
941 * with other event structures.
944 * "event" is the event struct to free.
949 * The reference count of the window in the event is decreased and
950 * might be freed, too.
952 *-------------------------------------------------------------- */
955 gdk_event_free (GdkEvent *event)
957 g_assert (event_chunk != NULL);
958 g_return_if_fail (event != NULL);
960 if (event->any.window)
961 gdk_window_unref (event->any.window);
963 switch (event->any.type)
966 case GDK_KEY_RELEASE:
967 g_free (event->key.string);
970 case GDK_ENTER_NOTIFY:
971 case GDK_LEAVE_NOTIFY:
972 if (event->crossing.subwindow != NULL)
973 gdk_window_unref (event->crossing.subwindow);
976 case GDK_DROP_DATA_AVAIL:
977 g_free (event->dropdataavailable.data_type);
978 g_free (event->dropdataavailable.data);
981 case GDK_DRAG_REQUEST:
982 g_free (event->dragrequest.data_type);
989 g_mem_chunk_free (event_chunk, event);
993 *--------------------------------------------------------------
994 * gdk_set_show_events
996 * Turns on/off the showing of events.
999 * "show_events" is a boolean describing whether or
1000 * not to show the events gdk receives.
1005 * When "show_events" is TRUE, calls to "gdk_event_get"
1006 * will output debugging informatin regarding the event
1007 * received to stdout.
1009 *--------------------------------------------------------------
1013 gdk_set_show_events (int show_events)
1016 gdk_debug_flags |= GDK_DEBUG_EVENTS;
1018 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1022 gdk_set_use_xshm (gint use_xshm)
1024 gdk_use_xshm = use_xshm;
1028 gdk_get_show_events ()
1030 return gdk_debug_flags & GDK_DEBUG_EVENTS;
1036 return gdk_use_xshm;
1040 *--------------------------------------------------------------
1043 * Get the number of milliseconds since the library was
1049 * The time since the library was initialized is returned.
1050 * This time value is accurate to milliseconds even though
1051 * a more accurate time down to the microsecond could be
1056 *--------------------------------------------------------------
1063 struct timeval elapsed;
1064 guint32 milliseconds;
1066 X_GETTIMEOFDAY (&end);
1068 if (start.tv_usec > end.tv_usec)
1070 end.tv_usec += 1000000;
1073 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1074 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1076 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1078 return milliseconds;
1082 *--------------------------------------------------------------
1085 * Returns the current timer.
1090 * Returns the current timer interval. This interval is
1091 * in units of milliseconds.
1095 *--------------------------------------------------------------
1105 *--------------------------------------------------------------
1108 * Sets the timer interval.
1111 * "milliseconds" is the new value for the timer.
1116 * Calls to "gdk_event_get" will last for a maximum
1117 * of time of "milliseconds". However, a value of 0
1118 * milliseconds will cause "gdk_event_get" to block
1119 * indefinately until an event is received.
1121 *--------------------------------------------------------------
1125 gdk_timer_set (guint32 milliseconds)
1127 timer_val = milliseconds;
1128 timer.tv_sec = milliseconds / 1000;
1129 timer.tv_usec = (milliseconds % 1000) * 1000;
1140 gdk_timer_disable ()
1146 gdk_input_add_full (gint source,
1147 GdkInputCondition condition,
1148 GdkInputFunction function,
1150 GdkDestroyNotify destroy)
1152 static gint next_tag = 1;
1165 if ((input->source == source) && (input->condition == condition))
1168 (input->destroy) (input->data);
1169 input->function = function;
1171 input->destroy = destroy;
1178 input = g_new (GdkInput, 1);
1179 input->tag = next_tag++;
1180 input->source = source;
1181 input->condition = condition;
1182 input->function = function;
1184 input->destroy = destroy;
1187 inputs = g_list_prepend (inputs, input);
1194 gdk_input_add (gint source,
1195 GdkInputCondition condition,
1196 GdkInputFunction function,
1199 return gdk_input_add_interp (source, condition, function, data, NULL);
1203 gdk_input_remove (gint tag)
1214 if (input->tag == tag)
1217 (input->destroy) (input->data);
1222 list->next->prev = list->prev;
1224 list->prev->next = list->next;
1226 inputs = list->next;
1228 temp_list->next = NULL;
1229 temp_list->prev = NULL;
1231 g_free (temp_list->data);
1232 g_list_free (temp_list);
1241 *--------------------------------------------------------------
1244 * Grabs the pointer to a specific window
1247 * "window" is the window which will receive the grab
1248 * "owner_events" specifies whether events will be reported as is,
1249 * or relative to "window"
1250 * "event_mask" masks only interesting events
1251 * "confine_to" limits the cursor movement to the specified window
1252 * "cursor" changes the cursor for the duration of the grab
1253 * "time" specifies the time
1258 * requires a corresponding call to gdk_pointer_ungrab
1260 *--------------------------------------------------------------
1264 gdk_pointer_grab (GdkWindow * window,
1266 GdkEventMask event_mask,
1267 GdkWindow * confine_to,
1271 /* From gdkwindow.c */
1272 extern int nevent_masks;
1273 extern int event_mask_table[];
1276 GdkWindowPrivate *window_private;
1277 GdkWindowPrivate *confine_to_private;
1278 GdkCursorPrivate *cursor_private;
1285 g_return_val_if_fail (window != NULL, 0);
1287 window_private = (GdkWindowPrivate*) window;
1288 confine_to_private = (GdkWindowPrivate*) confine_to;
1289 cursor_private = (GdkCursorPrivate*) cursor;
1291 xwindow = window_private->xwindow;
1293 if (!confine_to || confine_to_private->destroyed)
1296 xconfine_to = confine_to_private->xwindow;
1301 xcursor = cursor_private->xcursor;
1305 for (i = 0; i < nevent_masks; i++)
1307 if (event_mask & (1 << (i + 1)))
1308 xevent_mask |= event_mask_table[i];
1311 if (((GdkWindowPrivate *)window)->extension_events &&
1312 gdk_input_vtable.grab_pointer)
1313 return_val = gdk_input_vtable.grab_pointer (window,
1319 return_val = Success;
1321 if (return_val == Success)
1323 if (!window_private->destroyed)
1324 return_val = XGrabPointer (window_private->xdisplay,
1328 GrabModeAsync, GrabModeAsync,
1333 return_val = AlreadyGrabbed;
1336 if (return_val == GrabSuccess)
1337 xgrab_window = window_private;
1343 *--------------------------------------------------------------
1344 * gdk_pointer_ungrab
1346 * Releases any pointer grab
1354 *--------------------------------------------------------------
1358 gdk_pointer_ungrab (guint32 time)
1360 if (gdk_input_vtable.ungrab_pointer)
1361 gdk_input_vtable.ungrab_pointer (time);
1363 XUngrabPointer (gdk_display, time);
1364 xgrab_window = NULL;
1368 *--------------------------------------------------------------
1369 * gdk_pointer_is_grabbed
1371 * Tell wether there is an active x pointer grab in effect
1379 *--------------------------------------------------------------
1383 gdk_pointer_is_grabbed (void)
1385 return xgrab_window != NULL;
1389 *--------------------------------------------------------------
1392 * Grabs the keyboard to a specific window
1395 * "window" is the window which will receive the grab
1396 * "owner_events" specifies whether events will be reported as is,
1397 * or relative to "window"
1398 * "time" specifies the time
1403 * requires a corresponding call to gdk_keyboard_ungrab
1405 *--------------------------------------------------------------
1409 gdk_keyboard_grab (GdkWindow * window,
1413 GdkWindowPrivate *window_private;
1416 g_return_val_if_fail (window != NULL, 0);
1418 window_private = (GdkWindowPrivate*) window;
1419 xwindow = window_private->xwindow;
1421 if (!window_private->destroyed)
1422 return XGrabKeyboard (window_private->xdisplay,
1425 GrabModeAsync, GrabModeAsync,
1428 return AlreadyGrabbed;
1432 *--------------------------------------------------------------
1433 * gdk_keyboard_ungrab
1435 * Releases any keyboard grab
1443 *--------------------------------------------------------------
1447 gdk_keyboard_ungrab (guint32 time)
1449 XUngrabKeyboard (gdk_display, time);
1453 *--------------------------------------------------------------
1456 * Return the width of the screen.
1464 *--------------------------------------------------------------
1472 return_val = DisplayWidth (gdk_display, gdk_screen);
1478 *--------------------------------------------------------------
1481 * Return the height of the screen.
1489 *--------------------------------------------------------------
1493 gdk_screen_height ()
1497 return_val = DisplayHeight (gdk_display, gdk_screen);
1503 gdk_key_repeat_disable ()
1505 XAutoRepeatOff (gdk_display);
1509 gdk_key_repeat_restore ()
1512 XAutoRepeatOn (gdk_display);
1514 XAutoRepeatOff (gdk_display);
1519 *--------------------------------------------------------------
1522 * Flushes the Xlib output buffer and then waits
1523 * until all requests have been received and processed
1524 * by the X server. The only real use for this function
1525 * is in dealing with XShm.
1533 *--------------------------------------------------------------
1538 XSync (gdk_display, False);
1545 XBell(gdk_display, 100);
1550 *--------------------------------------------------------------
1553 * Waits until an event occurs or the timer runs out.
1558 * Returns TRUE if an event is ready to be read and FALSE
1559 * if the timer ran out.
1563 *--------------------------------------------------------------
1571 GdkInputCondition condition;
1572 SELECT_MASK readfds;
1573 SELECT_MASK writefds;
1574 SELECT_MASK exceptfds;
1578 /* If there are no events pending we will wait for an event.
1579 * The time we wait is dependant on the "timer". If no timer
1580 * has been specified then we'll block until an event arrives.
1581 * If a timer has been specified we'll block until an event
1582 * arrives or the timer expires. (This is all done using the
1583 * "select" system call).
1586 if (XPending (gdk_display) == 0)
1589 FD_ZERO (&writefds);
1590 FD_ZERO (&exceptfds);
1592 FD_SET (connection_number, &readfds);
1593 max_input = connection_number;
1601 if (input->condition & GDK_INPUT_READ)
1602 FD_SET (input->source, &readfds);
1603 if (input->condition & GDK_INPUT_WRITE)
1604 FD_SET (input->source, &writefds);
1605 if (input->condition & GDK_INPUT_EXCEPTION)
1606 FD_SET (input->source, &exceptfds);
1608 max_input = MAX (max_input, input->source);
1611 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1618 if (FD_ISSET (connection_number, &readfds))
1620 if (XPending (gdk_display) == 0)
1624 XNoOp (gdk_display);
1625 XFlush (gdk_display);
1640 if (FD_ISSET (input->source, &readfds))
1641 condition |= GDK_INPUT_READ;
1642 if (FD_ISSET (input->source, &writefds))
1643 condition |= GDK_INPUT_WRITE;
1644 if (FD_ISSET (input->source, &exceptfds))
1645 condition |= GDK_INPUT_EXCEPTION;
1647 if (condition && input->function)
1648 (* input->function) (input->data, input->source, condition);
1659 gdk_event_apply_filters (XEvent *xevent,
1663 GdkEventFilter *filter;
1665 GdkFilterReturn result;
1671 filter = (GdkEventFilter *)tmp_list->data;
1673 result = (*filter->function)(xevent, event, filter->data);
1674 if (result != GDK_FILTER_CONTINUE)
1677 tmp_list = tmp_list->next;
1680 return GDK_FILTER_CONTINUE;
1684 gdk_event_translate (GdkEvent *event,
1689 GdkWindowPrivate *window_private;
1690 XComposeStatus compose;
1693 static gchar* buf = NULL;
1694 static gint buf_len= 0;
1702 /* We need to play catch-up with the dnd motion events */
1703 if(gdk_dnd.drag_really && xevent->type == MotionNotify)
1704 while (XCheckTypedEvent(xevent->xany.display,MotionNotify,xevent));
1706 /* Find the GdkWindow that this event occurred in.
1707 * All events occur in some GdkWindow (otherwise, why
1708 * would we be receiving them). It really is an error
1709 * to receive an event for which we cannot find the
1710 * corresponding GdkWindow. We handle events with window=None
1711 * specially - they are generated by XFree86's XInput under
1712 * some circumstances.
1715 if ((xevent->xany.window == None) &&
1716 gdk_input_vtable.window_none_event)
1718 return_val = gdk_input_vtable.window_none_event (event,xevent);
1720 if (return_val >= 0) /* was handled */
1726 window = gdk_window_lookup (xevent->xany.window);
1727 window_private = (GdkWindowPrivate *) window;
1730 gdk_window_ref (window);
1731 else if(gdk_null_window_warnings) /* Special purpose programs that
1732 get events for other windows may
1733 want to disable this */
1734 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1736 /* Check for filters for this window */
1739 GdkFilterReturn result;
1740 result = gdk_event_apply_filters (xevent, event,
1742 ?window_private->filters
1743 :gdk_default_filters);
1745 if (result != GDK_FILTER_CONTINUE)
1747 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1751 /* We do a "manual" conversion of the XEvent to a
1752 * GdkEvent. The structures are mostly the same so
1753 * the conversion is fairly straightforward. We also
1754 * optionally print debugging info regarding events
1758 * During drag & drop you get events where the pointer is
1759 * in other windows. Need to just do finer-grained checking
1761 switch (xevent->type)
1764 /* Lookup the string corresponding to the given keysym.
1770 buf = g_new (gchar, buf_len);
1772 if (xim_using == TRUE && xim_ic)
1776 /* Clear keyval. Depending on status, may not be set */
1777 event->key.keyval = GDK_VoidSymbol;
1778 charcount = XmbLookupString(xim_ic->xic,
1779 &xevent->xkey, buf, buf_len-1,
1780 (KeySym*) &event->key.keyval,
1782 if (status == XBufferOverflow)
1784 /* alloc adequate size of buffer */
1786 g_print("XIM: overflow (required %i)\n", charcount));
1788 while (buf_len <= charcount)
1790 buf = (gchar *) g_realloc (buf, buf_len);
1792 charcount = XmbLookupString (xim_ic->xic,
1793 &xevent->xkey, buf, buf_len-1,
1794 (KeySym*) &event->key.keyval,
1797 if (status == XLookupNone)
1804 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1805 (KeySym*) &event->key.keyval,
1808 charcount = XLookupString (&xevent->xkey, buf, 16,
1809 (KeySym*) &event->key.keyval,
1812 if (charcount > 0 && buf[charcount-1] == '\0')
1815 buf[charcount] = '\0';
1817 /* Print debugging info.
1819 #ifdef G_ENABLE_DEBUG
1820 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1822 g_print ("key press:\twindow: %ld key: %12s %d\n",
1823 xevent->xkey.window - base_id,
1824 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1827 g_print ("\t\tlength: %4d string: \"%s\"\n",
1830 #endif /* G_ENABLE_DEBUG */
1832 event->key.type = GDK_KEY_PRESS;
1833 event->key.window = window;
1834 event->key.time = xevent->xkey.time;
1835 event->key.state = (GdkModifierType) xevent->xkey.state;
1836 event->key.string = g_strdup (buf);
1837 event->key.length = charcount;
1839 return_val = window_private && !window_private->destroyed;
1842 g_free (event->key.string);
1847 /* Lookup the string corresponding to the given keysym.
1849 charcount = XLookupString (&xevent->xkey, buf, 16,
1850 (KeySym*) &event->key.keyval,
1853 /* Print debugging info.
1856 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1857 xevent->xkey.window - base_id,
1858 XKeysymToString (event->key.keyval),
1859 event->key.keyval));
1861 event->key.type = GDK_KEY_RELEASE;
1862 event->key.window = window;
1863 event->key.time = xevent->xkey.time;
1864 event->key.state = (GdkModifierType) xevent->xkey.state;
1865 event->key.length = 0;
1866 event->key.string = NULL;
1868 return_val = window_private && !window_private->destroyed;
1872 /* Print debugging info.
1875 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1876 window_private?window_private->dnd_drag_enabled:0,
1877 xevent->xbutton.window - base_id,
1878 xevent->xbutton.x, xevent->xbutton.y,
1879 xevent->xbutton.button));
1881 if (window_private &&
1882 (window_private->extension_events != 0) &&
1883 gdk_input_ignore_core)
1886 event->button.type = GDK_BUTTON_PRESS;
1887 event->button.window = window;
1888 event->button.time = xevent->xbutton.time;
1889 event->button.x = xevent->xbutton.x;
1890 event->button.y = xevent->xbutton.y;
1891 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1892 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1893 event->button.pressure = 0.5;
1894 event->button.xtilt = 0;
1895 event->button.ytilt = 0;
1896 event->button.state = (GdkModifierType) xevent->xbutton.state;
1897 event->button.button = xevent->xbutton.button;
1898 event->button.source = GDK_SOURCE_MOUSE;
1899 event->button.deviceid = GDK_CORE_POINTER;
1901 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1902 (event->button.window == button_window[1]) &&
1903 (event->button.button == button_number[1]))
1905 gdk_synthesize_click (event, 3);
1907 button_click_time[1] = 0;
1908 button_click_time[0] = 0;
1909 button_window[1] = NULL;
1910 button_window[0] = 0;
1911 button_number[1] = -1;
1912 button_number[0] = -1;
1914 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1915 (event->button.window == button_window[0]) &&
1916 (event->button.button == button_number[0]))
1918 gdk_synthesize_click (event, 2);
1920 button_click_time[1] = button_click_time[0];
1921 button_click_time[0] = event->button.time;
1922 button_window[1] = button_window[0];
1923 button_window[0] = event->button.window;
1924 button_number[1] = button_number[0];
1925 button_number[0] = event->button.button;
1929 button_click_time[1] = 0;
1930 button_click_time[0] = event->button.time;
1931 button_window[1] = NULL;
1932 button_window[0] = event->button.window;
1933 button_number[1] = -1;
1934 button_number[0] = event->button.button;
1937 && window_private->dnd_drag_enabled
1938 && !gdk_dnd.drag_perhaps
1939 && event->button.button == 1
1940 && !gdk_dnd.drag_really)
1942 gdk_dnd.drag_perhaps = 1;
1943 gdk_dnd.dnd_drag_start.x = xevent->xbutton.x_root;
1944 gdk_dnd.dnd_drag_start.y = xevent->xbutton.y_root;
1945 gdk_dnd.real_sw = window_private;
1947 if(gdk_dnd.drag_startwindows)
1949 g_free(gdk_dnd.drag_startwindows);
1950 gdk_dnd.drag_startwindows = NULL;
1952 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1953 gdk_dnd.dnd_grabbed = FALSE;
1956 /* Set motion mask for first DnD'd window, since it
1957 will be the one that is actually dragged */
1958 XWindowAttributes dnd_winattr;
1959 XSetWindowAttributes dnd_setwinattr;
1961 /* We need to get motion events while the button is down, so
1962 we can know whether to really start dragging or not... */
1963 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1966 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1967 dnd_setwinattr.event_mask =
1968 window_private->dnd_drag_eventmask = ButtonMotionMask | ButtonPressMask | ButtonReleaseMask |
1969 EnterWindowMask | LeaveWindowMask;
1970 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1971 CWEventMask, &dnd_setwinattr);
1974 return_val = window_private && !window_private->destroyed;
1978 /* Print debugging info.
1981 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
1982 window_private?window_private->dnd_drag_enabled:0,
1983 xevent->xbutton.window - base_id,
1984 xevent->xbutton.x, xevent->xbutton.y,
1985 xevent->xbutton.button));
1987 if (window_private &&
1988 (window_private->extension_events != 0) &&
1989 gdk_input_ignore_core)
1992 event->button.type = GDK_BUTTON_RELEASE;
1993 event->button.window = window;
1994 event->button.time = xevent->xbutton.time;
1995 event->button.x = xevent->xbutton.x;
1996 event->button.y = xevent->xbutton.y;
1997 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1998 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1999 event->button.pressure = 0.5;
2000 event->button.xtilt = 0;
2001 event->button.ytilt = 0;
2002 event->button.state = (GdkModifierType) xevent->xbutton.state;
2003 event->button.button = xevent->xbutton.button;
2004 event->button.source = GDK_SOURCE_MOUSE;
2005 event->button.deviceid = GDK_CORE_POINTER;
2007 gdk_dnd.last_drop_time = xevent->xbutton.time;
2008 if(gdk_dnd.drag_perhaps)
2011 XSetWindowAttributes attrs;
2012 /* Reset event mask to pre-drag value, assuming event_mask
2013 doesn't change during drag */
2014 attrs.event_mask = gdk_dnd.real_sw->dnd_drag_savedeventmask;
2015 XChangeWindowAttributes(gdk_display, gdk_dnd.real_sw->xwindow,
2016 CWEventMask, &attrs);
2019 if (gdk_dnd.dnd_grabbed)
2021 gdk_dnd_display_drag_cursor(-2,
2024 XUngrabPointer(gdk_display, CurrentTime);
2025 gdk_dnd.dnd_grabbed = FALSE;
2028 if(gdk_dnd.drag_really)
2031 foo.x = xevent->xbutton.x_root;
2032 foo.y = xevent->xbutton.y_root;
2034 if(gdk_dnd.dnd_drag_target != None)
2035 gdk_dnd_drag_end(gdk_dnd.dnd_drag_target, foo);
2036 gdk_dnd.drag_really = 0;
2038 gdk_dnd.drag_numwindows = 0;
2039 if(gdk_dnd.drag_startwindows)
2041 g_free(gdk_dnd.drag_startwindows);
2042 gdk_dnd.drag_startwindows = NULL;
2045 gdk_dnd.real_sw = NULL;
2048 gdk_dnd.drag_perhaps = 0;
2049 gdk_dnd.dnd_drag_start.x = gdk_dnd.dnd_drag_start.y = 0;
2050 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2051 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2052 gdk_dnd.dnd_drag_curwin = None;
2053 return_val = window_private?TRUE:FALSE;
2055 return_val = window_private && !window_private->destroyed;
2059 /* Print debugging info.
2062 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2063 xevent->xmotion.window - base_id,
2064 xevent->xmotion.x, xevent->xmotion.y,
2065 (xevent->xmotion.is_hint) ? "true" : "false",
2066 gdk_dnd.drag_perhaps, gdk_dnd.drag_really));
2068 if (window_private &&
2069 (window_private->extension_events != 0) &&
2070 gdk_input_ignore_core)
2073 event->motion.type = GDK_MOTION_NOTIFY;
2074 event->motion.window = window;
2075 event->motion.time = xevent->xmotion.time;
2076 event->motion.x = xevent->xmotion.x;
2077 event->motion.y = xevent->xmotion.y;
2078 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2079 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2080 event->motion.pressure = 0.5;
2081 event->motion.xtilt = 0;
2082 event->motion.ytilt = 0;
2083 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2084 event->motion.is_hint = xevent->xmotion.is_hint;
2085 event->motion.source = GDK_SOURCE_MOUSE;
2086 event->motion.deviceid = GDK_CORE_POINTER;
2088 #define IS_IN_ZONE(cx, cy) (cx >= gdk_dnd.dnd_drag_dropzone.x \
2089 && cy >= gdk_dnd.dnd_drag_dropzone.y \
2090 && cx < (gdk_dnd.dnd_drag_dropzone.x + gdk_dnd.dnd_drag_dropzone.width) \
2091 && cy < (gdk_dnd.dnd_drag_dropzone.y + gdk_dnd.dnd_drag_dropzone.height))
2093 if(gdk_dnd.drag_perhaps && gdk_dnd.drag_really
2094 /* && event->motion.is_hint */ /* HINTME */)
2096 /* First, we have to find what window the motion was in... */
2097 /* XXX there has to be a better way to do this, perhaps with
2098 XTranslateCoordinates or XQueryTree - I don't know how,
2099 and this sort of works */
2100 static Window lastwin = None, curwin = None;
2104 Window childwin = gdk_root_window;
2107 /* Interlude - display cursor for the drag ASAP */
2108 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2109 xevent->xmotion.y_root,
2110 gdk_dnd.dnd_drag_target?TRUE:FALSE,
2114 curwin = gdk_root_window;
2115 ox = x = xevent->xmotion.x_root;
2116 oy = y = xevent->xmotion.y_root;
2118 curwin = gdk_window_xid_at_coords(xevent->xmotion.x_root,
2119 xevent->xmotion.y_root,
2120 gdk_dnd.c->xids,TRUE);
2121 XTranslateCoordinates(gdk_display, gdk_root_window, curwin,
2122 x, y, &x, &y, &childwin);
2124 while(childwin != None)
2128 XTranslateCoordinates(gdk_display, curwin, curwin,
2129 x, y, &x, &y, &childwin);
2130 if(childwin != None)
2132 XTranslateCoordinates(gdk_display, curwin, childwin,
2133 x, y, &x, &y, &twin);
2138 g_print("Drag is now in window %#lx, lastwin was %#lx, ddc = %#lx\n",
2139 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2140 if(curwin != gdk_dnd.dnd_drag_curwin && curwin != lastwin)
2142 /* We have left one window and entered another
2143 (do leave & enter bits) */
2144 if(gdk_dnd.dnd_drag_curwin != None)
2145 gdk_dnd_drag_leave(gdk_dnd.dnd_drag_curwin);
2146 gdk_dnd.dnd_drag_curwin = curwin;
2147 gdk_dnd_drag_enter(gdk_dnd.dnd_drag_curwin);
2148 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2149 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2150 gdk_dnd.dnd_drag_target = None;
2152 g_print("curwin = %#lx, lastwin = %#lx, dnd_drag_curwin = %#lx\n",
2153 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2155 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2156 xevent->xmotion.y_root,
2159 else if(gdk_dnd.dnd_drag_dropzone.width > 0
2160 && gdk_dnd.dnd_drag_dropzone.height > 0
2161 && curwin == gdk_dnd.dnd_drag_curwin)
2163 /* Handle all that dropzone stuff - thanks John ;-) */
2164 if (gdk_dnd.dnd_drag_target != None)
2166 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2167 xevent->xmotion.y_root);
2168 gboolean old_in_zone = IS_IN_ZONE(gdk_dnd.dnd_drag_oldpos.x,
2169 gdk_dnd.dnd_drag_oldpos.y);
2171 if (!in_zone && old_in_zone)
2173 /* We were in the drop zone and moved out */
2174 gdk_dnd.dnd_drag_target = None;
2175 gdk_dnd_drag_leave(curwin);
2176 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2177 xevent->xmotion.y_root,
2180 else if (!in_zone && !old_in_zone)
2182 /* We were outside drop zone but in the window
2183 - have to send enter events */
2184 gdk_dnd_drag_enter(curwin);
2185 gdk_dnd.dnd_drag_curwin = curwin;
2186 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2187 gdk_dnd.dnd_drag_target = None;
2191 dnd_drag_curwin = None; */
2195 return_val = window_private && !window_private->destroyed;
2199 /* Print debugging info.
2202 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2203 xevent->xcrossing.window - base_id,
2204 xevent->xcrossing.detail,
2205 xevent->xcrossing.subwindow - base_id));
2207 /* Tell XInput stuff about it if appropriate */
2208 if (window_private &&
2209 (window_private->extension_events != 0) &&
2210 gdk_input_vtable.enter_event)
2211 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2213 event->crossing.type = GDK_ENTER_NOTIFY;
2214 event->crossing.window = window;
2216 /* If the subwindow field of the XEvent is non-NULL, then
2217 * lookup the corresponding GdkWindow.
2219 if (xevent->xcrossing.subwindow != None)
2220 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2222 event->crossing.subwindow = NULL;
2224 /* Translate the crossing detail into Gdk terms.
2226 switch (xevent->xcrossing.detail)
2228 case NotifyInferior:
2229 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2231 case NotifyAncestor:
2232 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2235 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2237 case NotifyNonlinear:
2238 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2240 case NotifyNonlinearVirtual:
2241 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2244 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2248 #ifdef G_ENABLE_DEBUG
2249 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2251 g_print("We may[%d] have a drag into %#lx = %#lx\n",
2252 gdk_dnd.drag_really,
2253 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2255 #endif /* G_ENABLE_DEBUG */
2257 if (gdk_dnd.drag_perhaps && gdk_dnd.drag_really &&
2258 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2260 gdk_dnd.drag_really = 0;
2262 GDK_NOTE (DND, g_print("Ungrabbed\n"));
2264 gdk_dnd.drag_numwindows = 0;
2265 g_free(gdk_dnd.drag_startwindows);
2266 gdk_dnd.drag_startwindows = NULL;
2267 /* We don't want to ungrab the pointer here, or we'll
2268 * start getting spurious enter/leave events */
2270 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2274 return_val = window_private && !window_private->destroyed;
2278 /* Print debugging info.
2281 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2282 xevent->xcrossing.window - base_id,
2283 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2285 event->crossing.type = GDK_LEAVE_NOTIFY;
2286 event->crossing.window = window;
2288 /* If the subwindow field of the XEvent is non-NULL, then
2289 * lookup the corresponding GdkWindow.
2291 if (xevent->xcrossing.subwindow != None)
2292 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2294 event->crossing.subwindow = NULL;
2296 /* Translate the crossing detail into Gdk terms.
2298 switch (xevent->xcrossing.detail)
2300 case NotifyInferior:
2301 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2303 case NotifyAncestor:
2304 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2307 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2309 case NotifyNonlinear:
2310 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2312 case NotifyNonlinearVirtual:
2313 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2316 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2319 #ifdef G_ENABLE_DEBUG
2320 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2322 g_print("We may[%d] have a drag out of %#lx = %#lx\n",
2323 gdk_dnd.drag_really,
2324 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2326 #endif /* G_ENABLE_DEBUG */
2327 if (gdk_dnd.drag_perhaps && !gdk_dnd.drag_really &&
2328 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2331 gdk_dnd_drag_addwindow((GdkWindow *) gdk_dnd.real_sw);
2332 gdk_dnd_drag_begin((GdkWindow *) gdk_dnd.real_sw);
2334 XGrabPointer(gdk_display, gdk_dnd.real_sw->xwindow, False,
2335 ButtonMotionMask | PointerMotionMask |
2336 /* PointerMotionHintMask | */ /* HINTME */
2337 ButtonPressMask | ButtonReleaseMask,
2338 GrabModeAsync, GrabModeAsync, gdk_root_window,
2340 #ifdef G_ENABLE_DEBUG
2341 GDK_NOTE(DND, g_print("xgpret = %d\n", xgpret));
2343 gdk_dnd.dnd_grabbed = TRUE;
2344 gdk_dnd.drag_really = 1;
2345 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2346 xevent->xmotion.y_root,
2350 return_val = window_private && !window_private->destroyed;
2355 /* We only care about focus events that indicate that _this_
2356 * window (not a ancestor or child) got or lost the focus
2358 switch (xevent->xfocus.detail)
2360 case NotifyAncestor:
2361 case NotifyInferior:
2362 case NotifyNonlinear:
2363 /* Print debugging info.
2366 g_print ("focus %s:\t\twindow: %ld\n",
2367 (xevent->xany.type == FocusIn) ? "in" : "out",
2368 xevent->xfocus.window - base_id));
2370 event->focus_change.type = GDK_FOCUS_CHANGE;
2371 event->focus_change.window = window;
2372 event->focus_change.in = (xevent->xany.type == FocusIn);
2374 return_val = window_private && !window_private->destroyed;
2382 /* Print debugging info.
2385 g_print ("keymap notify\n"));
2387 /* Not currently handled */
2391 /* Print debugging info.
2394 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2395 xevent->xexpose.window - base_id, xevent->xexpose.count,
2396 xevent->xexpose.x, xevent->xexpose.y,
2397 xevent->xexpose.width, xevent->xexpose.height));
2399 event->expose.type = GDK_EXPOSE;
2400 event->expose.window = window;
2401 event->expose.area.x = xevent->xexpose.x;
2402 event->expose.area.y = xevent->xexpose.y;
2403 event->expose.area.width = xevent->xexpose.width;
2404 event->expose.area.height = xevent->xexpose.height;
2405 event->expose.count = xevent->xexpose.count;
2407 return_val = window_private && !window_private->destroyed;
2410 case GraphicsExpose:
2411 /* Print debugging info.
2414 g_print ("graphics expose:\tdrawable: %ld\n",
2415 xevent->xgraphicsexpose.drawable - base_id));
2417 event->expose.type = GDK_EXPOSE;
2418 event->expose.window = window;
2419 event->expose.area.x = xevent->xgraphicsexpose.x;
2420 event->expose.area.y = xevent->xgraphicsexpose.y;
2421 event->expose.area.width = xevent->xgraphicsexpose.width;
2422 event->expose.area.height = xevent->xgraphicsexpose.height;
2423 event->expose.count = xevent->xexpose.count;
2425 return_val = window_private && !window_private->destroyed;
2429 /* Print debugging info.
2432 g_print ("no expose:\t\tdrawable: %ld\n",
2433 xevent->xnoexpose.drawable - base_id));
2435 event->no_expose.type = GDK_NO_EXPOSE;
2436 event->no_expose.window = window;
2438 return_val = window_private && !window_private->destroyed;
2441 case VisibilityNotify:
2442 /* Print debugging info.
2444 #ifdef G_ENABLE_DEBUG
2445 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2446 switch (xevent->xvisibility.state)
2448 case VisibilityFullyObscured:
2449 g_print ("visibility notify:\twindow: %ld none\n",
2450 xevent->xvisibility.window - base_id);
2452 case VisibilityPartiallyObscured:
2453 g_print ("visibility notify:\twindow: %ld partial\n",
2454 xevent->xvisibility.window - base_id);
2456 case VisibilityUnobscured:
2457 g_print ("visibility notify:\twindow: %ld full\n",
2458 xevent->xvisibility.window - base_id);
2461 #endif /* G_ENABLE_DEBUG */
2463 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2464 event->visibility.window = window;
2466 switch (xevent->xvisibility.state)
2468 case VisibilityFullyObscured:
2469 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2472 case VisibilityPartiallyObscured:
2473 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2476 case VisibilityUnobscured:
2477 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2481 return_val = window_private && !window_private->destroyed;
2485 /* Not currently handled */
2489 /* Print debugging info.
2492 g_print ("destroy notify:\twindow: %ld\n",
2493 xevent->xdestroywindow.window - base_id));
2495 event->any.type = GDK_DESTROY;
2496 event->any.window = window;
2498 return_val = window_private && !window_private->destroyed;
2500 gdk_window_destroy_notify (window);
2504 /* Print debugging info.
2507 g_print ("unmap notify:\t\twindow: %ld\n",
2508 xevent->xmap.window - base_id));
2510 event->any.type = GDK_UNMAP;
2511 event->any.window = window;
2513 if (xgrab_window == window_private)
2514 xgrab_window = NULL;
2516 return_val = window_private && !window_private->destroyed;
2520 /* Print debugging info.
2523 g_print ("map notify:\t\twindow: %ld\n",
2524 xevent->xmap.window - base_id));
2526 event->any.type = GDK_MAP;
2527 event->any.window = window;
2529 return_val = window_private && !window_private->destroyed;
2532 case ReparentNotify:
2533 /* Print debugging info.
2536 g_print ("reparent notify:\twindow: %ld\n",
2537 xevent->xreparent.window - base_id));
2539 /* Not currently handled */
2542 case ConfigureNotify:
2543 /* Print debugging info.
2545 while ((XPending (gdk_display) > 0) &&
2546 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2547 ConfigureNotify, xevent))
2549 g_print ("configure notify discarded:\twindow: %ld\n",
2550 xevent->xconfigure.window - base_id));
2551 /*XSync (gdk_display, 0);*/
2554 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2555 xevent->xconfigure.window - base_id,
2556 xevent->xconfigure.x,
2557 xevent->xconfigure.y,
2558 xevent->xconfigure.width,
2559 xevent->xconfigure.height,
2560 xevent->xconfigure.border_width,
2561 xevent->xconfigure.above - base_id,
2562 xevent->xconfigure.override_redirect));
2566 if ((window_private->extension_events != 0) &&
2567 gdk_input_vtable.configure_event)
2568 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2570 if (window_private->window_type != GDK_WINDOW_CHILD)
2572 event->configure.type = GDK_CONFIGURE;
2573 event->configure.window = window;
2574 event->configure.width = xevent->xconfigure.width;
2575 event->configure.height = xevent->xconfigure.height;
2577 if (!xevent->xconfigure.x &&
2578 !xevent->xconfigure.y &&
2579 !window_private->destroyed)
2583 Window child_window = 0;
2585 if (!XTranslateCoordinates (window_private->xdisplay,
2586 window_private->xwindow,
2591 g_warning ("GdkWindow %ld doesn't share root windows display?",
2592 window_private->xwindow - base_id);
2593 event->configure.x = tx;
2594 event->configure.y = ty;
2598 event->configure.x = xevent->xconfigure.x;
2599 event->configure.y = xevent->xconfigure.y;
2601 window_private->x = event->configure.x;
2602 window_private->y = event->configure.y;
2603 window_private->width = xevent->xconfigure.width;
2604 window_private->height = xevent->xconfigure.height;
2605 if (window_private->resize_count > 1)
2606 window_private->resize_count -= 1;
2608 return_val = !window_private->destroyed;
2613 case PropertyNotify:
2614 /* Print debugging info.
2617 g_print ("property notify:\twindow: %ld\n",
2618 xevent->xproperty.window - base_id));
2620 event->property.type = GDK_PROPERTY_NOTIFY;
2621 event->property.window = window;
2622 event->property.atom = xevent->xproperty.atom;
2623 event->property.time = xevent->xproperty.time;
2624 event->property.state = xevent->xproperty.state;
2626 return_val = window_private && !window_private->destroyed;
2629 case SelectionClear:
2631 g_print ("selection clear:\twindow: %ld\n",
2632 xevent->xproperty.window - base_id));
2634 event->selection.type = GDK_SELECTION_CLEAR;
2635 event->selection.window = window;
2636 event->selection.selection = xevent->xselectionclear.selection;
2637 event->selection.time = xevent->xselectionclear.time;
2639 return_val = window_private && !window_private->destroyed;
2642 case SelectionRequest:
2644 g_print ("selection request:\twindow: %ld\n",
2645 xevent->xproperty.window - base_id));
2647 event->selection.type = GDK_SELECTION_REQUEST;
2648 event->selection.window = window;
2649 event->selection.selection = xevent->xselectionrequest.selection;
2650 event->selection.target = xevent->xselectionrequest.target;
2651 event->selection.property = xevent->xselectionrequest.property;
2652 event->selection.requestor = xevent->xselectionrequest.requestor;
2653 event->selection.time = xevent->xselectionrequest.time;
2655 return_val = window_private && !window_private->destroyed;
2658 case SelectionNotify:
2660 g_print ("selection notify:\twindow: %ld\n",
2661 xevent->xproperty.window - base_id));
2664 event->selection.type = GDK_SELECTION_NOTIFY;
2665 event->selection.window = window;
2666 event->selection.selection = xevent->xselection.selection;
2667 event->selection.target = xevent->xselection.target;
2668 event->selection.property = xevent->xselection.property;
2669 event->selection.time = xevent->xselection.time;
2671 return_val = window_private && !window_private->destroyed;
2674 case ColormapNotify:
2675 /* Print debugging info.
2678 g_print ("colormap notify:\twindow: %ld\n",
2679 xevent->xcolormap.window - base_id));
2681 /* Not currently handled */
2685 /* Print debugging info.
2688 g_print ("client message:\twindow: %ld\n",
2689 xevent->xclient.window - base_id));
2691 /* Client messages are the means of the window manager
2692 * communicating with a program. We'll first check to
2693 * see if this is really the window manager talking
2696 if (xevent->xclient.message_type == gdk_wm_protocols)
2698 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2700 /* The delete window request specifies a window
2701 * to delete. We don't actually destroy the
2702 * window because "it is only a request". (The
2703 * window might contain vital data that the
2704 * program does not want destroyed). Instead
2705 * the event is passed along to the program,
2706 * which should then destroy the window.
2709 /* Print debugging info.
2712 g_print ("delete window:\t\twindow: %ld\n",
2713 xevent->xclient.window - base_id));
2715 event->any.type = GDK_DELETE;
2716 event->any.window = window;
2718 return_val = window_private && !window_private->destroyed;
2720 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2724 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2728 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2730 GDK_NOTE (DND, g_print ("GDK_DROP_ENTER [%d][%d]\n",
2731 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply));
2734 /* Now figure out if we really want this drop...
2735 * If someone is trying funky clipboard stuff, ignore
2738 && window_private->dnd_drop_enabled
2739 && event->dropenter.u.flags.sendreply
2740 && (reptype = gdk_dnd_check_types (window, xevent)))
2744 replyev.xclient.type = ClientMessage;
2745 replyev.xclient.window = xevent->xclient.data.l[0];
2746 replyev.xclient.format = 32;
2747 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2748 replyev.xclient.data.l[0] = window_private->xwindow;
2750 event->dragrequest.u.allflags = 0;
2751 event->dragrequest.u.flags.protocol_version =
2752 DND_PROTOCOL_VERSION;
2753 event->dragrequest.u.flags.willaccept = 1;
2754 event->dragrequest.u.flags.delete_data =
2755 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2757 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2758 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2759 replyev.xclient.data.l[4] = reptype;
2761 if (!gdk_send_xevent (replyev.xclient.window, False,
2762 NoEventMask, &replyev))
2763 GDK_NOTE (DND, g_print("Sending XdeRequest to %#lx failed\n",
2764 replyev.xclient.window));
2766 event->any.type = GDK_DROP_ENTER;
2767 event->any.window = window;
2768 event->dropenter.requestor = replyev.xclient.window;
2769 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2771 GDK_NOTE (DND, g_print("We sent a GDK_DROP_ENTER on to Gtk\n"));
2775 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2777 #ifdef G_ENABLE_DEBUG
2778 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2779 g_print ("GDK_DROP_LEAVE\n");
2782 if (window_private && window_private->dnd_drop_enabled)
2784 event->dropleave.type = GDK_DROP_LEAVE;
2785 event->dropleave.window = window;
2786 event->dropleave.requestor = xevent->xclient.data.l[0];
2787 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2793 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2796 * make sure to only handle requests from the window the cursor is
2799 #ifdef G_ENABLE_DEBUG
2800 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2801 g_print ("GDK_DRAG_REQUEST\n");
2803 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2806 if (window && gdk_dnd.drag_really &&
2807 xevent->xclient.data.l[0] == gdk_dnd.dnd_drag_curwin &&
2808 event->dragrequest.u.flags.sendreply == 0)
2810 /* Got request - do we need to ask user? */
2811 if (!event->dragrequest.u.flags.willaccept
2812 && event->dragrequest.u.flags.senddata)
2815 event->dragrequest.type = GDK_DRAG_REQUEST;
2816 event->dragrequest.window = window;
2817 event->dragrequest.requestor = xevent->xclient.data.l[0];
2818 event->dragrequest.isdrop = 0;
2819 event->dragrequest.drop_coords.x =
2820 event->dragrequest.drop_coords.y = 0;
2823 else if (event->dragrequest.u.flags.willaccept)
2825 window_private->dnd_drag_destructive_op =
2826 event->dragrequest.u.flags.delete_data;
2827 window_private->dnd_drag_accepted = 1;
2828 window_private->dnd_drag_data_type =
2829 xevent->xclient.data.l[4];
2831 gdk_dnd.dnd_drag_target = gdk_dnd.dnd_drag_curwin;
2832 gdk_dnd_display_drag_cursor(-1, -1, TRUE, TRUE);
2834 gdk_dnd.dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2835 gdk_dnd.dnd_drag_dropzone.y =
2836 (xevent->xclient.data.l[2] >> 16) & 65535;
2837 gdk_dnd.dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2838 gdk_dnd.dnd_drag_dropzone.height =
2839 (xevent->xclient.data.l[3] >> 16) & 65535;
2842 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2844 gint tmp_int; Atom tmp_atom;
2846 guchar *tmp_charptr;
2848 #ifdef G_ENABLE_DEBUG
2849 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2850 g_print("GDK_DROP_DATA_AVAIL\n");
2852 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2853 event->dropdataavailable.timestamp = xevent->xclient.data.l[4];
2854 event->dropdataavailable.coords.x =
2855 xevent->xclient.data.l[3] & 0xffff;
2856 event->dropdataavailable.coords.y =
2857 (xevent->xclient.data.l[3] >> 16) & 0xffff;
2859 /* No preview of data ATM */
2860 && event->dropdataavailable.u.flags.isdrop)
2862 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2863 event->dropdataavailable.window = window;
2864 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2865 event->dropdataavailable.data_type =
2866 gdk_atom_name(xevent->xclient.data.l[2]);
2867 if(XGetWindowProperty (gdk_display,
2868 event->dropdataavailable.requestor,
2869 xevent->xclient.data.l[2],
2871 False, XA_PRIMARY, &tmp_atom,
2873 &event->dropdataavailable.data_numbytes,
2878 g_warning("XGetWindowProperty on %#x may have failed\n",
2879 event->dropdataavailable.requestor);
2880 event->dropdataavailable.data = NULL;
2884 GDK_NOTE (DND, g_print("XGetWindowProperty got us %ld bytes\n",
2885 event->dropdataavailable.data_numbytes));
2886 event->dropdataavailable.data =
2887 g_malloc (event->dropdataavailable.data_numbytes);
2888 memcpy (event->dropdataavailable.data,
2889 tmp_charptr, event->dropdataavailable.data_numbytes);
2898 /* Send unknown ClientMessage's on to Gtk for it to use */
2899 event->client.type = GDK_CLIENT_EVENT;
2900 event->client.window = window;
2901 event->client.message_type = xevent->xclient.message_type;
2902 event->client.data_format = xevent->xclient.format;
2903 memcpy(&event->client.data, &xevent->xclient.data,
2904 sizeof(event->client.data));
2911 return_val = return_val && !window_private->destroyed;
2915 /* Print debugging info.
2918 g_print ("mapping notify\n"));
2920 /* Let XLib know that there is a new keyboard mapping.
2922 XRefreshKeyboardMapping (&xevent->xmapping);
2926 /* something else - (e.g., a Xinput event) */
2928 if (window_private &&
2929 (window_private->extension_events != 0) &&
2930 gdk_input_vtable.other_event)
2931 return_val = gdk_input_vtable.other_event(event, xevent, window);
2935 if (return_val < 0) /* not an XInput event, convert */
2937 event->other.type = GDK_OTHER_EVENT;
2938 event->other.window = window;
2939 event->other.xevent = (GdkXEvent *)&other_xevent[other_xevent_i];
2940 memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
2941 other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
2945 return_val = return_val && !window_private->destroyed;
2952 if (event->any.window)
2953 gdk_window_ref (event->any.window);
2954 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2955 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2956 (event->crossing.subwindow != NULL))
2957 gdk_window_ref (event->crossing.subwindow);
2961 /* Mark this event as having no resources to be freed */
2962 event->any.window = NULL;
2963 event->any.type = GDK_NOTHING;
2967 gdk_window_unref (window);
2974 gdk_event_get_type (Display *display,
2981 if (gdk_event_translate (&event, xevent))
2983 pred = (GdkPredicate*) arg;
2984 return (* pred->func) (&event, pred->data);
2992 gdk_synthesize_click (GdkEvent *event,
2995 GdkEvent temp_event;
2997 g_return_if_fail (event != NULL);
2999 temp_event = *event;
3000 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
3002 gdk_event_put (&temp_event);
3006 *--------------------------------------------------------------
3009 * This is the "atexit" function that makes sure the
3010 * library gets a chance to cleanup.
3017 * The library is un-initialized and the program exits.
3019 *--------------------------------------------------------------
3025 static gboolean in_gdk_exit_func = FALSE;
3027 /* This is to avoid an infinite loop if a program segfaults in
3028 an atexit() handler (and yes, it does happen, especially if a program
3029 has trounced over memory too badly for even g_print to work) */
3030 if(in_gdk_exit_func == TRUE) return;
3031 in_gdk_exit_func = TRUE;
3043 gdk_key_repeat_restore ();
3045 XCloseDisplay (gdk_display);
3051 *--------------------------------------------------------------
3054 * The X error handling routine.
3057 * "display" is the X display the error orignated from.
3058 * "error" is the XErrorEvent that we are handling.
3061 * Either we were expecting some sort of error to occur,
3062 * in which case we set the "gdk_error_code" flag, or this
3063 * error was unexpected, in which case we will print an
3064 * error message and exit. (Since trying to continue will
3065 * most likely simply lead to more errors).
3069 *--------------------------------------------------------------
3073 gdk_x_error (Display *display,
3078 if (gdk_error_warnings)
3080 XGetErrorText (display, error->error_code, buf, 63);
3081 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
3085 error->request_code,
3089 gdk_error_code = -1;
3094 *--------------------------------------------------------------
3097 * The X I/O error handling routine.
3100 * "display" is the X display the error orignated from.
3103 * An X I/O error basically means we lost our connection
3104 * to the X server. There is not much we can do to
3105 * continue, so simply print an error message and exit.
3109 *--------------------------------------------------------------
3113 gdk_x_io_error (Display *display)
3115 g_error ("an x io error occurred");
3120 *--------------------------------------------------------------
3123 * The signal handler.
3126 * "sig_num" is the number of the signal we received.
3129 * The signals we catch are all fatal. So we simply build
3130 * up a nice little error message and print it and exit.
3131 * If in the process of doing so another signal is received
3132 * we notice that we are already exiting and simply kill
3137 *--------------------------------------------------------------
3141 gdk_signal (int sig_num)
3143 static int caught_fatal_sig = 0;
3146 if (caught_fatal_sig)
3147 kill (getpid (), sig_num);
3148 caught_fatal_sig = 1;
3174 sig = "unknown signal";
3178 g_print ("\n** ERROR **: %s caught\n", sig);
3179 #ifdef G_ENABLE_DEBUG
3181 #else /* !G_ENABLE_DEBUG */
3183 #endif /* !G_ENABLE_DEBUG */
3187 gdk_dnd_drag_begin (GdkWindow *initial_window)
3191 GDK_NOTE(DND, g_print("------- STARTING DRAG from %p\n", initial_window));
3193 tev.type = GDK_DRAG_BEGIN;
3194 tev.dragbegin.window = initial_window;
3195 tev.dragbegin.u.allflags = 0;
3196 tev.dragbegin.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3198 gdk_event_put (&tev);
3202 gdk_dnd_drag_enter (Window dest)
3205 GdkEventDropEnter tev;
3207 GdkWindowPrivate *wp;
3209 sev.xclient.type = ClientMessage;
3210 sev.xclient.format = 32;
3211 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3212 sev.xclient.window = dest;
3215 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3216 tev.u.flags.sendreply = 1;
3217 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3219 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3220 if (wp->dnd_drag_data_numtypesavail)
3222 sev.xclient.data.l[0] = wp->xwindow;
3223 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3224 sev.xclient.data.l[1] = tev.u.allflags;
3225 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3226 if (wp->dnd_drag_data_numtypesavail > 1)
3228 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3229 if (wp->dnd_drag_data_numtypesavail > 2)
3231 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3234 sev.xclient.data.l[4] = None;
3237 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3238 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3239 GDK_NOTE (DND, g_print("Sending XdeEnter to %#lx failed\n",
3249 /* The following routines duplicate functionality in Xlib to
3250 * translate from varargs to X's internal opaque XVaNestedList.
3252 * If all vendors have stuck close to the reference implementation,
3253 * then we should hopefully be OK.
3256 /* This needs to match XIMArg as defined in Xlcint.h exactly */
3263 /*************************************************************
3265 * Counts the number of name/value pairs in the vararg list
3270 *************************************************************/
3273 gdk_im_va_count (va_list list)
3278 name = va_arg (list, gchar *);
3282 (void)va_arg (list, gpointer);
3283 name = va_arg (list, gchar *);
3289 /*************************************************************
3290 * gdk_im_va_to_nested:
3291 * Given a varargs list and the result of gdk_im_va_count,
3292 * create a XVaNestedList.
3297 *************************************************************/
3299 static XVaNestedList
3300 gdk_im_va_to_nested (va_list list, guint count)
3310 result = g_new (GdkImArg, count+1);
3313 name = va_arg (list, gchar *);
3317 arg->value = va_arg (list, gpointer);
3319 name = va_arg (list, gchar *);
3324 return (XVaNestedList)result;
3328 *--------------------------------------------------------------
3331 * Begin using input method with XIM Protocol(X11R6 standard)
3334 * "ic" is the "Input Context" which is created by gtk_ic_new.
3335 * The input area is specified with "window".
3338 * The gdk's event handling routine is switched to XIM based routine.
3339 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3340 * and uses XmbLookupString instead of XLookupString.
3344 *--------------------------------------------------------------
3348 gdk_im_begin (GdkIC ic, GdkWindow* window)
3350 GdkICPrivate *private;
3353 g_return_if_fail (ic != NULL);
3354 g_return_if_fail (window);
3356 private = (GdkICPrivate *) ic;
3360 xim_window = window;
3363 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3364 if (xwin != GDK_WINDOW_XWINDOW(window))
3365 XSetICValues (private->xic, XNFocusWindow,
3366 GDK_WINDOW_XWINDOW(window), NULL);
3367 if (private != xim_ic)
3368 XSetICFocus (private->xic);
3373 *--------------------------------------------------------------
3376 * End using input method with XIM Protocol(X11R6 standard)
3381 * The gdk's event handling routine is switched to normal routine.
3382 * User should call this function before ic and window will be destroyed.
3386 *--------------------------------------------------------------
3404 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3406 GdkIMStyle s1, s2, u;
3408 if (style1 == 0) return style2;
3409 if (style2 == 0) return style1;
3410 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3411 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3414 s1 = style1 & GdkIMPreeditMask;
3415 s2 = style2 & GdkIMPreeditMask;
3418 if (u & GdkIMPreeditCallbacks)
3419 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3420 else if (u & GdkIMPreeditPosition)
3421 return (s1 == GdkIMPreeditPosition)? style1:style2;
3422 else if (u & GdkIMPreeditArea)
3423 return (s1 == GdkIMPreeditArea)? style1:style2;
3424 else if (u & GdkIMPreeditNothing)
3425 return (s1 == GdkIMPreeditNothing)? style1:style2;
3427 s1 = style1 & GdkIMStatusMask;
3428 s2 = style2 & GdkIMStatusMask;
3430 if ( u & GdkIMStatusCallbacks)
3431 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3432 else if ( u & GdkIMStatusArea)
3433 return (s1 == GdkIMStatusArea)? style1:style2;
3434 else if ( u & GdkIMStatusNothing)
3435 return (s1 == GdkIMStatusNothing)? style1:style2;
3436 else if ( u & GdkIMStatusNone)
3437 return (s1 == GdkIMStatusNone)? style1:style2;
3439 return 0; /* Get rid of stupid warning */
3443 gdk_im_decide_style (GdkIMStyle supported_style)
3446 GdkIMStyle style, tmp;
3448 g_return_val_if_fail (xim_styles != NULL, 0);
3451 for (i=0; i<xim_styles->count_styles; i++)
3453 tmp = xim_styles->supported_styles[i];
3454 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3455 style = gdk_im_choose_better_style (style, tmp);
3461 gdk_im_set_best_style (GdkIMStyle style)
3463 if (style & GdkIMPreeditMask)
3465 xim_best_allowed_style &= ~GdkIMPreeditMask;
3467 xim_best_allowed_style |= GdkIMPreeditNone;
3468 if (!(style & GdkIMPreeditNone))
3470 xim_best_allowed_style |= GdkIMPreeditNothing;
3471 if (!(style & GdkIMPreeditNothing))
3473 xim_best_allowed_style |= GdkIMPreeditArea;
3474 if (!(style & GdkIMPreeditArea))
3476 xim_best_allowed_style |= GdkIMPreeditPosition;
3477 if (!(style & GdkIMPreeditPosition))
3478 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3483 if (style & GdkIMStatusMask)
3485 xim_best_allowed_style &= ~GdkIMStatusMask;
3487 xim_best_allowed_style |= GdkIMStatusNone;
3488 if (!(style & GdkIMStatusNone))
3490 xim_best_allowed_style |= GdkIMStatusNothing;
3491 if (!(style & GdkIMStatusNothing))
3493 xim_best_allowed_style |= GdkIMStatusArea;
3494 if (!(style & GdkIMStatusArea))
3495 xim_best_allowed_style |= GdkIMStatusCallbacks;
3500 return xim_best_allowed_style;
3504 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3506 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3509 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
3512 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3535 return (xim_im != NULL);
3539 gdk_ic_new (GdkWindow* client_window,
3540 GdkWindow* focus_window,
3541 GdkIMStyle style, ...)
3544 GdkICPrivate *private;
3545 XVaNestedList preedit_attr = NULL;
3548 g_return_val_if_fail (client_window != NULL, NULL);
3549 g_return_val_if_fail (focus_window != NULL, NULL);
3550 g_return_val_if_fail (gdk_im_ready(), NULL);
3552 private = g_new (GdkICPrivate, 1);
3554 va_start (list, style);
3555 count = gdk_im_va_count (list);
3558 va_start (list, style);
3559 preedit_attr = gdk_im_va_to_nested (list, count);
3562 private->style = gdk_im_decide_style (style);
3563 if (private->style != style)
3565 g_warning ("can not create input context with specified input style.");
3570 private->xic = XCreateIC(gdk_im_get (),
3571 XNInputStyle, style,
3572 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3573 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3574 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3577 g_free (preedit_attr);
3585 xim_ic_list = g_list_append (xim_ic_list, private);
3590 gdk_ic_destroy (GdkIC ic)
3592 GdkICPrivate *private;
3594 g_return_if_fail (ic != NULL);
3596 private = (GdkICPrivate *) ic;
3598 if (xim_ic == private)
3601 XDestroyIC (private->xic);
3602 xim_ic_list = g_list_remove (xim_ic_list, private);
3607 gdk_ic_get_style (GdkIC ic)
3609 GdkICPrivate *private;
3611 g_return_val_if_fail (ic != NULL, 0);
3613 private = (GdkICPrivate *) ic;
3615 return private->style;
3619 gdk_ic_set_values (GdkIC ic, ...)
3623 GdkICPrivate *private;
3626 g_return_if_fail (ic != NULL);
3628 private = (GdkICPrivate *) ic;
3630 va_start (list, ic);
3631 count = gdk_im_va_count (list);
3634 va_start (list, ic);
3635 args = gdk_im_va_to_nested (list, count);
3638 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3644 gdk_ic_get_values (GdkIC ic, ...)
3648 GdkICPrivate *private;
3651 g_return_if_fail (ic != NULL);
3653 private = (GdkICPrivate *) ic;
3655 va_start (list, ic);
3656 count = gdk_im_va_count (list);
3659 va_start (list, ic);
3660 args = gdk_im_va_to_nested (list, count);
3663 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3669 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3673 GdkICPrivate *private;
3676 g_return_if_fail (ic != NULL);
3677 g_return_if_fail (target != NULL);
3679 private = (GdkICPrivate *) ic;
3681 va_start (list, target);
3682 count = gdk_im_va_count (list);
3685 va_start (list, target);
3686 attr = gdk_im_va_to_nested (list, count);
3689 XSetICValues (private->xic, target, attr, NULL);
3695 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3699 GdkICPrivate *private;
3702 g_return_if_fail (ic != NULL);
3703 g_return_if_fail (target != NULL);
3705 private = (GdkICPrivate *) ic;
3707 va_start (list, target);
3708 count = gdk_im_va_count (list);
3711 va_start (list, target);
3712 attr = gdk_im_va_to_nested (list, count);
3715 XGetICValues (private->xic, target, attr, NULL);
3721 gdk_ic_get_events (GdkIC ic)
3726 GdkICPrivate *private;
3729 /* From gdkwindow.c */
3730 extern int nevent_masks;
3731 extern int event_mask_table[];
3733 g_return_val_if_fail (ic != NULL, 0);
3735 private = (GdkICPrivate *) ic;
3737 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
3739 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
3744 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3745 if (xmask & event_mask_table [i])
3748 xmask &= ~ event_mask_table [i];
3752 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
3758 gdk_ic_cleanup (void)
3762 GdkICPrivate *private;
3765 for (node = xim_ic_list; node != NULL; node = node->next)
3769 private = (GdkICPrivate *) (node->data);
3770 XDestroyIC (private->xic);
3775 #ifdef G_ENABLE_DEBUG
3776 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3778 g_warning ("Cleaned up %i IC(s)\n", destroyed);
3780 #endif /* G_ENABLE_DEBUG */
3781 g_list_free(xim_ic_list);
3785 #else /* !USE_XIM */
3788 gdk_im_begin (GdkIC ic, GdkWindow* window)
3798 gdk_im_decide_style (GdkIMStyle supported_style)
3800 return GdkIMPreeditNone | GdkIMStatusNone;
3804 gdk_im_set_best_style (GdkIMStyle style)
3806 return GdkIMPreeditNone | GdkIMStatusNone;
3816 gdk_ic_new (GdkWindow* client_window,
3817 GdkWindow* focus_window,
3818 GdkIMStyle style, ...)
3824 gdk_ic_destroy (GdkIC ic)
3829 gdk_ic_get_style (GdkIC ic)
3831 return GdkIMPreeditNone | GdkIMStatusNone;
3835 gdk_ic_set_values (GdkIC ic, ...)
3840 gdk_ic_get_values (GdkIC ic, ...)
3845 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3850 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3855 gdk_ic_get_events (GdkIC ic)
3860 #endif /* USE_XIM */
3865 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3867 static wchar_t wcs[MB_CUR_MAX + 1];
3868 static gchar mbs[MB_CUR_MAX + 1];
3870 wcs[0] = (wchar_t) NULL;
3873 /* The last argument isn't a mistake. The X locale code trims
3874 * the input string to the length of the output string!
3876 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3879 else if (wcs[0] == (wchar_t) NULL)
3882 len = _Xwctomb (mbs, wcs[0]);
3891 #endif /* X_LOCALE */
3894 gdk_dnd_drag_leave (Window dest)
3897 GdkEventDropLeave tev;
3899 GdkWindowPrivate *wp;
3903 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3904 sev.xclient.type = ClientMessage;
3905 sev.xclient.window = dest;
3906 sev.xclient.format = 32;
3907 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3908 sev.xclient.data.l[1] = tev.u.allflags;
3909 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3911 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3912 sev.xclient.data.l[0] = wp->xwindow;
3913 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3914 GDK_NOTE (DND, g_print("Sending XdeLeave to %#lx failed\n",
3916 wp->dnd_drag_accepted = 0;
3921 * when a drop occurs, we go through the list of windows being dragged and
3922 * tell them that it has occurred, so that they can set things up and reply
3926 gdk_dnd_drag_end (Window dest,
3929 GdkWindowPrivate *wp;
3933 tev.dragrequest.type = GDK_DRAG_REQUEST;
3934 tev.dragrequest.drop_coords = coords;
3935 tev.dragrequest.requestor = dest;
3936 tev.dragrequest.u.allflags = 0;
3937 tev.dragrequest.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3938 tev.dragrequest.isdrop = 1;
3940 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3942 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3943 if (wp->dnd_drag_accepted)
3945 tev.dragrequest.window = (GdkWindow *) wp;
3946 tev.dragrequest.u.flags.delete_data = wp->dnd_drag_destructive_op;
3947 tev.dragrequest.timestamp = gdk_dnd.last_drop_time;
3948 tev.dragrequest.data_type =
3949 gdk_atom_name(wp->dnd_drag_data_type);
3951 gdk_event_put(&tev);
3957 gdk_dnd_check_types (GdkWindow *window,
3960 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3962 GdkEventDropEnter event;
3964 g_return_val_if_fail(window != NULL, 0);
3965 g_return_val_if_fail(xevent != NULL, 0);
3966 g_return_val_if_fail(xevent->type == ClientMessage, 0);
3967 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3969 if(wp->dnd_drop_data_numtypesavail <= 0 ||
3970 !wp->dnd_drop_data_typesavail)
3973 for (i = 2; i <= 4; i++)
3975 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3977 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3978 return xevent->xclient.data.l[i];
3982 /* Now we get the extended type list if it's available */
3983 event.u.allflags = xevent->xclient.data.l[1];
3984 if (event.u.flags.extended_typelist)
3986 Atom *exttypes, realtype;
3987 gulong nitems, nbar;
3990 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3991 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
3992 False, AnyPropertyType, &realtype, &realfmt,
3993 &nitems, &nbar, (unsigned char **) &exttypes)
3997 if (realfmt != (sizeof(Atom) * 8))
3999 g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
4000 realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
4004 for (i = 0; i <= nitems; i++)
4006 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
4008 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
4021 * used for debugging only
4025 gdk_print_atom (GdkAtom anatom)
4027 gchar *tmpstr = NULL;
4028 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
4029 g_print("Atom %lu has name %s\n", anatom, tmpstr);
4036 * used only by below routine and itself
4039 getchildren (Display *dpy,
4043 Window root, parent, *children, inf = 0;
4045 unsigned int nchildren, i;
4047 unsigned long nitems, after;
4048 unsigned char *data;
4050 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
4053 for (i = 0; !inf && (i < nchildren); i++)
4055 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
4056 AnyPropertyType, &type, &format, &nitems,
4063 for (i = 0; !inf && (i < nchildren); i++)
4064 inf = getchildren (dpy, children[i], WM_STATE);
4066 if (children != None)
4067 XFree ((char *) children);
4073 * find a window with WM_STATE, else return win itself, as per ICCCM
4075 * modification of the XmuClientWindow() routine from X11R6.3
4078 gdk_get_client_window (Display *dpy,
4084 unsigned long nitems, after;
4085 unsigned char *data;
4089 return DefaultRootWindow(dpy);
4091 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
4094 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
4095 &type, &format, &nitems, &after, &data);
4099 inf = getchildren (dpy, win, WM_STATE);
4107 #ifdef WE_HAVE_MOTIF_DROPS_DONE
4109 gdk_drop_get_real_window (GdkWindow *w,
4113 GdkWindow *retval = w;
4114 GdkWindowPrivate *awin;
4116 gint16 myx = *x, myy = *y;
4118 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
4124 for (children = gdk_window_get_children(retval);
4125 children && children->next;
4126 children = children->next)
4128 awin = (GdkWindowPrivate *) children->data;
4129 if ((myx >= awin->x) && (myy >= awin->y)
4130 && (myx < (awin->x + awin->width))
4131 && (myy < (awin->y + awin->height)))
4133 retval = (GdkWindow *) awin;
4147 /* Sends a ClientMessage to all toplevel client windows */
4149 gdk_event_send_clientmessage_toall(GdkEvent *event)
4152 Window *ret_children, ret_root, ret_parent, curwin;
4153 unsigned int ret_nchildren;
4156 g_return_if_fail(event != NULL);
4158 /* Set up our event to send, with the exception of its target window */
4159 sev.xclient.type = ClientMessage;
4160 sev.xclient.display = gdk_display;
4161 sev.xclient.format = event->client.data_format;
4162 sev.xclient.serial = CurrentTime;
4163 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
4164 sev.xclient.message_type = event->client.message_type;
4166 /* OK, we're all set, now let's find some windows to send this to */
4167 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
4168 &ret_children, &ret_nchildren) != True)
4171 /* foreach true child window of the root window, send an event to it */
4172 for(i = 0; i < ret_nchildren; i++) {
4173 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
4174 sev.xclient.window = curwin;
4175 if (!gdk_send_xevent (curwin, False, NoEventMask, &sev))
4176 GDK_NOTE (MISC, g_print("Gdk: Sending client message %ld to %#lx failed\n",
4177 event->client.message_type, curwin));
4180 XFree(ret_children);
4184 gdk_get_display(void)
4186 return (gchar *)XDisplayName (gdk_display_name);
4190 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
4197 gdk_error_warnings = 0;
4198 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
4199 XSync (gdk_display, False);
4200 gdk_error_warnings = 1;
4202 return result && (gdk_error_code != -1);