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"
53 #include "gdkkeysyms.h"
56 #ifndef X_GETTIMEOFDAY
57 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
58 #endif /* X_GETTIMEOFDAY */
61 #define DOUBLE_CLICK_TIME 250
62 #define TRIPLE_CLICK_TIME 500
63 #define DOUBLE_CLICK_DIST 5
64 #define TRIPLE_CLICK_DIST 5
68 # define SELECT_MASK fd_set
74 # define SELECT_MASK void
76 # define SELECT_MASK int
81 typedef struct _GdkInput GdkInput;
82 typedef struct _GdkPredicate GdkPredicate;
88 GdkInputCondition condition;
89 GdkInputFunction function;
91 GdkDestroyNotify destroy;
101 * Private function declarations
104 static GdkEvent *gdk_event_new (void);
105 static gint gdk_event_wait (void);
106 static gint gdk_event_apply_filters (XEvent *xevent,
109 static gint gdk_event_translate (GdkEvent *event,
112 static Bool gdk_event_get_type (Display *display,
116 static void gdk_synthesize_click (GdkEvent *event,
119 static void gdk_dnd_drag_begin (GdkWindow *initial_window);
120 static void gdk_dnd_drag_enter (Window dest);
121 static void gdk_dnd_drag_leave (Window dest);
122 static void gdk_dnd_drag_end (Window dest,
124 static GdkAtom gdk_dnd_check_types (GdkWindow *window,
127 static void gdk_print_atom (GdkAtom anatom);
130 #ifndef HAVE_XCONVERTCASE
131 static void gdkx_XConvertCase (KeySym symbol,
134 #define XConvertCase gdkx_XConvertCase
138 * old junk from offix, we might use it though so leave it
140 Window gdk_get_client_window (Display *dpy,
142 #ifdef WE_HAVE_MOTIF_DROPS_DONE
143 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
147 static void gdk_exit_func (void);
148 static int gdk_x_error (Display *display,
150 static int gdk_x_io_error (Display *display);
151 static RETSIGTYPE gdk_signal (int signum);
155 static guint gdk_im_va_count (va_list list);
156 static XVaNestedList gdk_im_va_to_nested (va_list list,
159 static GdkIM gdk_im_get (void);
160 static gint gdk_im_open (XrmDatabase db,
163 static void gdk_im_close (void);
164 static void gdk_ic_cleanup (void);
168 /* Private variable declarations
170 static int gdk_initialized = 0; /* 1 if the library is initialized,
173 static int connection_number = 0; /* The file descriptor number of our
174 * connection to the X server. This
175 * is used so that we may determine
176 * when events are pending by using
177 * the "select" system call.
181 static struct timeval start; /* The time at which the library was
184 static struct timeval timer; /* Timeout interval to use in the call
185 * to "select". This is used in
186 * conjunction with "timerp" to create
187 * a maximum time to wait for an event
190 static struct timeval *timerp; /* The actual timer passed to "select"
191 * This may be NULL, in which case
192 * "select" will block until an event
195 static guint32 timer_val; /* The timeout length as specified by
196 * the user in milliseconds.
198 static GList *inputs; /* A list of the input file descriptors
199 * that we care about. Each list node
200 * contains a GdkInput struct that describes
201 * when we are interested in the specified
202 * file descriptor. That is, when it is
203 * available for read, write or has an
206 static guint32 button_click_time[2]; /* The last 2 button click times. Used
207 * to determine if the latest button click
208 * is part of a double or triple click.
210 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
211 * Also used to determine if the latest button
212 * click is part of a double or triple click.
214 static guint button_number[2]; /* The last 2 buttons to be pressed.
216 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
221 static gint xim_using; /* using XIM Protocol if TRUE */
222 static GdkIM xim_im; /* global IM */
223 static XIMStyles* xim_styles; /* im supports these styles */
224 static XIMStyle xim_best_allowed_style;
225 static GdkICPrivate *xim_ic; /* currently using IC */
226 static GdkWindow* xim_window; /* currently using Widow */
227 static GList* xim_ic_list;
231 static GList *putback_events = NULL;
233 static gulong base_id;
234 static gint autorepeat;
236 #ifdef G_ENABLE_DEBUG
237 static GDebugKey gdk_debug_keys[] = {
238 {"events", GDK_DEBUG_EVENTS},
239 {"misc", GDK_DEBUG_MISC},
240 {"dnd", GDK_DEBUG_DND},
241 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
242 {"xim", GDK_DEBUG_XIM}
245 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
247 #endif /* G_ENABLE_DEBUG */
250 *--------------------------------------------------------------
253 * Initialize the library for use.
256 * "argc" is the number of arguments.
257 * "argv" is an array of strings.
260 * "argc" and "argv" are modified to reflect any arguments
261 * which were not handled. (Such arguments should either
262 * be handled by the application or dismissed).
265 * The library is initialized.
267 *--------------------------------------------------------------
274 XKeyboardState keyboard_state;
277 XClassHint *class_hint;
278 gchar **argv_orig = NULL;
288 argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
289 for (i = 0; i < argc_orig; i++)
290 argv_orig[i] = g_strdup ((*argv)[i]);
291 argv_orig[argc_orig] = NULL;
294 X_GETTIMEOFDAY (&start);
296 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
297 signal (SIGHUP, gdk_signal);
298 signal (SIGINT, gdk_signal);
299 signal (SIGQUIT, gdk_signal);
300 signal (SIGBUS, gdk_signal);
301 signal (SIGSEGV, gdk_signal);
302 signal (SIGPIPE, gdk_signal);
303 signal (SIGTERM, gdk_signal);
306 gdk_display_name = NULL;
308 XSetErrorHandler (gdk_x_error);
309 XSetIOErrorHandler (gdk_x_io_error);
313 #ifdef G_ENABLE_DEBUG
315 gchar *debug_string = getenv("GDK_DEBUG");
316 if (debug_string != NULL)
317 gdk_debug_flags = g_parse_debug_string (debug_string,
321 #endif /* G_ENABLE_DEBUG */
329 d = strrchr((*argv)[0],'/');
331 g_set_prgname (d + 1);
333 g_set_prgname ((*argv)[0]);
336 for (i = 1; i < *argc;)
338 #ifdef G_ENABLE_DEBUG
339 if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
340 (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
342 gchar *equal_pos = strchr ((*argv)[i], '=');
344 if (equal_pos != NULL)
346 gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
350 else if ((i + 1) < *argc && (*argv)[i + 1])
352 gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
360 else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
361 (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
363 gchar *equal_pos = strchr ((*argv)[i], '=');
365 if (equal_pos != NULL)
367 gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
371 else if ((i + 1) < *argc && (*argv)[i + 1])
373 gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
382 #endif /* G_ENABLE_DEBUG */
383 if (strcmp ("--display", (*argv)[i]) == 0)
387 if ((i + 1) < *argc && (*argv)[i + 1])
389 gdk_display_name = g_strdup ((*argv)[i + 1]);
390 (*argv)[i + 1] = NULL;
394 else if (strcmp ("--sync", (*argv)[i]) == 0)
399 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
402 gdk_use_xshm = FALSE;
404 else if (strcmp ("--name", (*argv)[i]) == 0)
406 if ((i + 1) < *argc && (*argv)[i + 1])
409 g_set_prgname ((*argv)[i]);
413 else if (strcmp ("--class", (*argv)[i]) == 0)
415 if ((i + 1) < *argc && (*argv)[i + 1])
418 gdk_progclass = (*argv)[i];
423 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
425 if ((i + 1) < *argc && (*argv)[i + 1])
428 gdk_input_gxid_host = ((*argv)[i]);
432 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
434 if ((i + 1) < *argc && (*argv)[i + 1])
437 gdk_input_gxid_port = atoi ((*argv)[i]);
443 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
445 if ((i + 1) < *argc && (*argv)[i + 1])
448 if (strcmp ("none", (*argv)[i]) == 0)
449 gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
450 else if (strcmp ("nothing", (*argv)[i]) == 0)
451 gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
452 else if (strcmp ("area", (*argv)[i]) == 0)
453 gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
454 else if (strcmp ("position", (*argv)[i]) == 0)
455 gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
456 else if (strcmp ("callbacks", (*argv)[i]) == 0)
457 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
460 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
462 if ((i + 1) < *argc && (*argv)[i + 1])
465 if (strcmp ("none", (*argv)[i]) == 0)
466 gdk_im_set_best_style (GDK_IM_STATUS_NONE);
467 else if (strcmp ("nothing", (*argv)[i]) == 0)
468 gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
469 else if (strcmp ("area", (*argv)[i]) == 0)
470 gdk_im_set_best_style (GDK_IM_STATUS_AREA);
471 else if (strcmp ("callbacks", (*argv)[i]) == 0)
472 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
480 for (i = 1; i < *argc; i++)
482 for (k = i; k < *argc; k++)
483 if ((*argv)[k] != NULL)
489 for (j = i + k; j < *argc; j++)
490 (*argv)[j-k] = (*argv)[j];
497 g_set_prgname ("<unknown>");
500 GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));
502 gdk_display = XOpenDisplay (gdk_display_name);
505 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
509 /* This is really crappy. We have to look into the display structure
510 * to find the base resource id. This is only needed for recording
511 * and playback of events.
513 /* base_id = RESOURCE_BASE; */
515 GDK_NOTE (EVENTS, g_message ("base id: %lu", base_id));
517 connection_number = ConnectionNumber (gdk_display);
519 g_message ("connection number: %d", connection_number));
522 XSynchronize (gdk_display, True);
524 gdk_screen = DefaultScreen (gdk_display);
525 gdk_root_window = RootWindow (gdk_display, gdk_screen);
527 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
528 10, 10, 10, 10, 0, 0 , 0);
529 class_hint = XAllocClassHint();
530 class_hint->res_name = g_get_prgname ();
531 if (gdk_progclass == NULL)
533 gdk_progclass = g_strdup (g_get_prgname ());
534 gdk_progclass[0] = toupper (gdk_progclass[0]);
536 class_hint->res_class = gdk_progclass;
537 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
538 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
541 for (i = 0; i < argc_orig; i++)
542 g_free(argv_orig[i]);
545 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
546 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
547 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
548 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
549 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
550 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
552 gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
553 gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
554 gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
555 gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
556 gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
557 gdk_dnd.c->gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
558 gdk_dnd.c->gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
560 XGetKeyboardControl (gdk_display, &keyboard_state);
561 autorepeat = keyboard_state.global_auto_repeat;
567 button_click_time[0] = 0;
568 button_click_time[1] = 0;
569 button_window[0] = NULL;
570 button_window[1] = NULL;
571 button_number[0] = -1;
572 button_number[1] = -1;
574 g_atexit (gdk_exit_func);
582 /* initialize XIM Protocol variables */
586 if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
587 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
588 if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
589 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
591 xim_window = (GdkWindow*)NULL;
593 gdk_im_open (NULL, NULL, NULL);
600 *--------------------------------------------------------------
603 * Restores the library to an un-itialized state and exits
604 * the program using the "exit" system call.
607 * "errorcode" is the error value to pass to "exit".
610 * Allocated structures are freed and the program exits
615 *--------------------------------------------------------------
619 gdk_exit (int errorcode)
621 /* de-initialisation is done by the gdk_exit_funct(),
622 no need to do this here (Alex J.) */
627 *--------------------------------------------------------------
636 *--------------------------------------------------------------
640 gdk_set_locale (void)
642 if (!setlocale (LC_ALL,""))
643 g_message ("locale not supported by C library");
645 if (!XSupportsLocale ())
647 g_message ("locale not supported by Xlib, locale set to C");
648 setlocale (LC_ALL, "C");
651 if (!XSetLocaleModifiers (""))
653 g_message ("can not set locale modifiers");
656 return setlocale (LC_ALL,NULL);
660 *--------------------------------------------------------------
663 * Returns the number of events pending on the queue.
664 * These events have already been read from the server
670 * Returns the number of events on XLib's event queue.
674 *--------------------------------------------------------------
678 gdk_events_pending (void)
683 result = XPending (gdk_display);
685 tmp_list = putback_events;
689 tmp_list = tmp_list->next;
696 *--------------------------------------------------------------
697 * gdk_event_get_graphics_expose
699 * Waits for a GraphicsExpose or NoExpose event
704 * For GraphicsExpose events, returns a pointer to the event
705 * converted into a GdkEvent Otherwise, returns NULL.
709 *-------------------------------------------------------------- */
712 graphics_expose_predicate (Display *display,
716 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
718 g_return_val_if_fail (private != NULL, False);
720 if ((xevent->xany.window == private->xwindow) &&
721 ((xevent->xany.type == GraphicsExpose) ||
722 (xevent->xany.type == NoExpose)))
729 gdk_event_get_graphics_expose (GdkWindow *window)
734 g_return_val_if_fail (window != NULL, NULL);
736 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
738 if (xevent.xany.type == GraphicsExpose)
740 event = gdk_event_new ();
742 if (gdk_event_translate (event, &xevent))
745 gdk_event_free (event);
752 *--------------------------------------------------------------
755 * Gets the next event.
760 * If an event was received that we care about, returns
761 * a pointer to that event, to be freed with gdk_event_free.
762 * Otherwise, returns NULL. This function will also return
763 * before an event is received if the timeout interval
768 *--------------------------------------------------------------
781 temp_list = putback_events;
784 temp_event = temp_list->data;
786 if ((* pred) (temp_event, data))
789 *event = *temp_event;
790 putback_events = g_list_remove_link (putback_events, temp_list);
791 g_list_free (temp_list);
795 temp_list = temp_list->next;
798 event_pred.func = pred;
799 event_pred.data = data;
801 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
803 return gdk_event_translate (event, &xevent);
809 event = putback_events->data;
811 temp_list = putback_events;
812 putback_events = g_list_remove_link (putback_events, temp_list);
813 g_list_free_1 (temp_list);
818 /* Wait for an event to occur or the timeout to elapse.
819 * If an event occurs "gdk_event_wait" will return TRUE.
820 * If the timeout elapses "gdk_event_wait" will return
823 if (gdk_event_wait ())
825 /* If we get here we can rest assurred that an event
826 * has occurred. Read it.
830 if (xim_using && xim_window)
832 { /* don't dispatch events used by IM */
833 XNextEvent (gdk_display, &xevent);
834 filter_status = XFilterEvent (&xevent,
835 GDK_WINDOW_XWINDOW (xim_window));
836 } while (filter_status == True);
838 XNextEvent (gdk_display, &xevent);
840 XNextEvent (gdk_display, &xevent);
842 event = gdk_event_new ();
844 event->any.type = GDK_NOTHING;
845 event->any.window = NULL;
846 event->any.send_event = FALSE;
847 event->any.send_event = xevent.xany.send_event;
849 if (gdk_event_translate (event, &xevent))
852 gdk_event_free (event);
859 gdk_event_put (GdkEvent *event)
863 g_return_if_fail (event != NULL);
865 new_event = gdk_event_copy (event);
867 putback_events = g_list_prepend (putback_events, new_event);
871 *--------------------------------------------------------------
874 * Copy a event structure into new storage.
877 * "event" is the event struct to copy.
880 * A new event structure. Free it with gdk_event_free.
883 * The reference count of the window in the event is increased.
885 *--------------------------------------------------------------
888 static GMemChunk *event_chunk;
895 if (event_chunk == NULL)
896 event_chunk = g_mem_chunk_new ("events",
901 new_event = g_chunk_new (GdkEvent, event_chunk);
907 gdk_event_copy (GdkEvent *event)
911 g_return_val_if_fail (event != NULL, NULL);
913 new_event = gdk_event_new ();
916 gdk_window_ref (new_event->any.window);
918 switch (event->any.type)
921 case GDK_KEY_RELEASE:
922 new_event->key.string = g_strdup (event->key.string);
925 case GDK_ENTER_NOTIFY:
926 case GDK_LEAVE_NOTIFY:
927 if (event->crossing.subwindow != NULL)
928 gdk_window_ref (event->crossing.subwindow);
931 case GDK_DROP_DATA_AVAIL:
932 new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
933 new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
934 memcpy (new_event->dropdataavailable.data,
935 event->dropdataavailable.data,
936 event->dropdataavailable.data_numbytes);
947 *--------------------------------------------------------------
950 * Free a event structure obtained from gdk_event_copy. Do not use
951 * with other event structures.
954 * "event" is the event struct to free.
959 * The reference count of the window in the event is decreased and
960 * might be freed, too.
962 *-------------------------------------------------------------- */
965 gdk_event_free (GdkEvent *event)
967 g_assert (event_chunk != NULL);
968 g_return_if_fail (event != NULL);
970 if (event->any.window)
971 gdk_window_unref (event->any.window);
973 switch (event->any.type)
976 case GDK_KEY_RELEASE:
977 g_free (event->key.string);
980 case GDK_ENTER_NOTIFY:
981 case GDK_LEAVE_NOTIFY:
982 if (event->crossing.subwindow != NULL)
983 gdk_window_unref (event->crossing.subwindow);
986 case GDK_DROP_DATA_AVAIL:
987 g_free (event->dropdataavailable.data_type);
988 g_free (event->dropdataavailable.data);
991 case GDK_DRAG_REQUEST:
992 g_free (event->dragrequest.data_type);
999 g_mem_chunk_free (event_chunk, event);
1003 *--------------------------------------------------------------
1004 * gdk_set_show_events
1006 * Turns on/off the showing of events.
1009 * "show_events" is a boolean describing whether or
1010 * not to show the events gdk receives.
1015 * When "show_events" is TRUE, calls to "gdk_event_get"
1016 * will output debugging informatin regarding the event
1017 * received to stdout.
1019 *--------------------------------------------------------------
1023 gdk_set_show_events (int show_events)
1026 gdk_debug_flags |= GDK_DEBUG_EVENTS;
1028 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1032 gdk_set_use_xshm (gint use_xshm)
1034 gdk_use_xshm = use_xshm;
1038 gdk_get_show_events (void)
1040 return gdk_debug_flags & GDK_DEBUG_EVENTS;
1044 gdk_get_use_xshm (void)
1046 return gdk_use_xshm;
1050 *--------------------------------------------------------------
1053 * Get the number of milliseconds since the library was
1059 * The time since the library was initialized is returned.
1060 * This time value is accurate to milliseconds even though
1061 * a more accurate time down to the microsecond could be
1066 *--------------------------------------------------------------
1073 struct timeval elapsed;
1074 guint32 milliseconds;
1076 X_GETTIMEOFDAY (&end);
1078 if (start.tv_usec > end.tv_usec)
1080 end.tv_usec += 1000000;
1083 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1084 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1086 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1088 return milliseconds;
1092 *--------------------------------------------------------------
1095 * Returns the current timer.
1100 * Returns the current timer interval. This interval is
1101 * in units of milliseconds.
1105 *--------------------------------------------------------------
1109 gdk_timer_get (void)
1115 *--------------------------------------------------------------
1118 * Sets the timer interval.
1121 * "milliseconds" is the new value for the timer.
1126 * Calls to "gdk_event_get" will last for a maximum
1127 * of time of "milliseconds". However, a value of 0
1128 * milliseconds will cause "gdk_event_get" to block
1129 * indefinately until an event is received.
1131 *--------------------------------------------------------------
1135 gdk_timer_set (guint32 milliseconds)
1137 timer_val = milliseconds;
1138 timer.tv_sec = milliseconds / 1000;
1139 timer.tv_usec = (milliseconds % 1000) * 1000;
1144 gdk_timer_enable (void)
1150 gdk_timer_disable (void)
1156 gdk_input_add_full (gint source,
1157 GdkInputCondition condition,
1158 GdkInputFunction function,
1160 GdkDestroyNotify destroy)
1162 static gint next_tag = 1;
1175 if ((input->source == source) && (input->condition == condition))
1178 (input->destroy) (input->data);
1179 input->function = function;
1181 input->destroy = destroy;
1188 input = g_new (GdkInput, 1);
1189 input->tag = next_tag++;
1190 input->source = source;
1191 input->condition = condition;
1192 input->function = function;
1194 input->destroy = destroy;
1197 inputs = g_list_prepend (inputs, input);
1204 gdk_input_add (gint source,
1205 GdkInputCondition condition,
1206 GdkInputFunction function,
1209 return gdk_input_add_interp (source, condition, function, data, NULL);
1213 gdk_input_remove (gint tag)
1223 if (input->tag == tag)
1226 (input->destroy) (input->data);
1228 input->tag = 0; /* do not free it here */
1229 input->condition = 0; /* it's done in gdk_event_wait */
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 (gdk_input_vtable.grab_pointer)
1310 return_val = gdk_input_vtable.grab_pointer (window,
1316 return_val = Success;
1318 if (return_val == Success)
1320 if (!window_private->destroyed)
1321 return_val = XGrabPointer (window_private->xdisplay,
1325 GrabModeAsync, GrabModeAsync,
1330 return_val = AlreadyGrabbed;
1333 if (return_val == GrabSuccess)
1334 xgrab_window = window_private;
1340 *--------------------------------------------------------------
1341 * gdk_pointer_ungrab
1343 * Releases any pointer grab
1351 *--------------------------------------------------------------
1355 gdk_pointer_ungrab (guint32 time)
1357 if (gdk_input_vtable.ungrab_pointer)
1358 gdk_input_vtable.ungrab_pointer (time);
1360 XUngrabPointer (gdk_display, time);
1361 xgrab_window = NULL;
1365 *--------------------------------------------------------------
1366 * gdk_pointer_is_grabbed
1368 * Tell wether there is an active x pointer grab in effect
1376 *--------------------------------------------------------------
1380 gdk_pointer_is_grabbed (void)
1382 return xgrab_window != NULL;
1386 *--------------------------------------------------------------
1389 * Grabs the keyboard to a specific window
1392 * "window" is the window which will receive the grab
1393 * "owner_events" specifies whether events will be reported as is,
1394 * or relative to "window"
1395 * "time" specifies the time
1400 * requires a corresponding call to gdk_keyboard_ungrab
1402 *--------------------------------------------------------------
1406 gdk_keyboard_grab (GdkWindow * window,
1410 GdkWindowPrivate *window_private;
1413 g_return_val_if_fail (window != NULL, 0);
1415 window_private = (GdkWindowPrivate*) window;
1416 xwindow = window_private->xwindow;
1418 if (!window_private->destroyed)
1419 return XGrabKeyboard (window_private->xdisplay,
1422 GrabModeAsync, GrabModeAsync,
1425 return AlreadyGrabbed;
1429 *--------------------------------------------------------------
1430 * gdk_keyboard_ungrab
1432 * Releases any keyboard grab
1440 *--------------------------------------------------------------
1444 gdk_keyboard_ungrab (guint32 time)
1446 XUngrabKeyboard (gdk_display, time);
1450 *--------------------------------------------------------------
1453 * Return the width of the screen.
1461 *--------------------------------------------------------------
1465 gdk_screen_width (void)
1469 return_val = DisplayWidth (gdk_display, gdk_screen);
1475 *--------------------------------------------------------------
1478 * Return the height of the screen.
1486 *--------------------------------------------------------------
1490 gdk_screen_height (void)
1494 return_val = DisplayHeight (gdk_display, gdk_screen);
1500 *--------------------------------------------------------------
1501 * gdk_screen_width_mm
1503 * Return the width of the screen in millimeters.
1511 *--------------------------------------------------------------
1515 gdk_screen_width_mm (void)
1519 return_val = DisplayWidthMM (gdk_display, gdk_screen);
1525 *--------------------------------------------------------------
1528 * Return the height of the screen in millimeters.
1536 *--------------------------------------------------------------
1540 gdk_screen_height_mm (void)
1544 return_val = DisplayHeightMM (gdk_display, gdk_screen);
1550 gdk_key_repeat_disable (void)
1552 XAutoRepeatOff (gdk_display);
1556 gdk_key_repeat_restore (void)
1559 XAutoRepeatOn (gdk_display);
1561 XAutoRepeatOff (gdk_display);
1566 *--------------------------------------------------------------
1569 * Flushes the Xlib output buffer and then waits
1570 * until all requests have been received and processed
1571 * by the X server. The only real use for this function
1572 * is in dealing with XShm.
1580 *--------------------------------------------------------------
1583 void gdk_flush (void)
1585 XSync (gdk_display, False);
1592 XBell(gdk_display, 100);
1597 *--------------------------------------------------------------
1600 * Waits until an event occurs or the timer runs out.
1605 * Returns TRUE if an event is ready to be read and FALSE
1606 * if the timer ran out.
1610 *--------------------------------------------------------------
1614 gdk_event_wait (void)
1619 GdkInputCondition condition;
1620 SELECT_MASK readfds;
1621 SELECT_MASK writefds;
1622 SELECT_MASK exceptfds;
1626 /* If there are no events pending we will wait for an event.
1627 * The time we wait is dependant on the "timer". If no timer
1628 * has been specified then we'll block until an event arrives.
1629 * If a timer has been specified we'll block until an event
1630 * arrives or the timer expires. (This is all done using the
1631 * "select" system call).
1634 if (XPending (gdk_display) == 0)
1637 FD_ZERO (&writefds);
1638 FD_ZERO (&exceptfds);
1640 FD_SET (connection_number, &readfds);
1641 max_input = connection_number;
1650 if (input->condition & GDK_INPUT_READ)
1651 FD_SET (input->source, &readfds);
1652 if (input->condition & GDK_INPUT_WRITE)
1653 FD_SET (input->source, &writefds);
1654 if (input->condition & GDK_INPUT_EXCEPTION)
1655 FD_SET (input->source, &exceptfds);
1657 max_input = MAX (max_input, input->source);
1660 else /* free removed inputs */
1665 list->next->prev = list->prev;
1667 list->prev->next = list->next;
1669 inputs = list->next;
1673 temp_list->next = NULL;
1674 temp_list->prev = NULL;
1676 g_free (temp_list->data);
1677 g_list_free (temp_list);
1682 if (gdk_using_threads)
1684 gdk_select_waiting = TRUE;
1686 FD_SET (gdk_threads_pipe[0], &readfds);
1687 max_input = MAX (max_input, gdk_threads_pipe[0]);
1688 gdk_threads_leave ();
1692 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1695 if (gdk_using_threads)
1698 gdk_threads_enter ();
1699 gdk_select_waiting = FALSE;
1701 if (FD_ISSET (gdk_threads_pipe[0], &readfds))
1702 read (gdk_threads_pipe[0], &c, 1);
1711 if (FD_ISSET (connection_number, &readfds))
1713 if (XPending (gdk_display) == 0)
1717 XNoOp (gdk_display);
1718 XFlush (gdk_display);
1733 if (FD_ISSET (input->source, &readfds))
1734 condition |= GDK_INPUT_READ;
1735 if (FD_ISSET (input->source, &writefds))
1736 condition |= GDK_INPUT_WRITE;
1737 if (FD_ISSET (input->source, &exceptfds))
1738 condition |= GDK_INPUT_EXCEPTION;
1740 if (condition && input->function)
1741 (* input->function) (input->data, input->source, condition);
1752 gdk_event_apply_filters (XEvent *xevent,
1756 GdkEventFilter *filter;
1758 GdkFilterReturn result;
1764 filter = (GdkEventFilter *)tmp_list->data;
1766 result = (*filter->function)(xevent, event, filter->data);
1767 if (result != GDK_FILTER_CONTINUE)
1770 tmp_list = tmp_list->next;
1773 return GDK_FILTER_CONTINUE;
1777 gdk_event_translate (GdkEvent *event,
1782 GdkWindowPrivate *window_private;
1783 static XComposeStatus compose;
1787 static gchar* buf = NULL;
1788 static gint buf_len= 0;
1796 /* We need to play catch-up with the dnd motion events */
1797 if(gdk_dnd.drag_really && xevent->type == MotionNotify)
1798 while (XCheckTypedEvent(xevent->xany.display,MotionNotify,xevent));
1800 /* Find the GdkWindow that this event occurred in.
1801 * All events occur in some GdkWindow (otherwise, why
1802 * would we be receiving them). It really is an error
1803 * to receive an event for which we cannot find the
1804 * corresponding GdkWindow. We handle events with window=None
1805 * specially - they are generated by XFree86's XInput under
1806 * some circumstances.
1809 if ((xevent->xany.window == None) &&
1810 gdk_input_vtable.window_none_event)
1812 return_val = gdk_input_vtable.window_none_event (event,xevent);
1814 if (return_val >= 0) /* was handled */
1820 window = gdk_window_lookup (xevent->xany.window);
1821 window_private = (GdkWindowPrivate *) window;
1824 gdk_window_ref (window);
1825 else if (gdk_null_window_warnings)
1827 /* Special purpose programs that
1828 * get events for other windows may
1829 * want to disable this
1831 g_warning ("xwindow(%#lx) lookup reveals NULL", xevent->xany.window);
1834 /* Check for filters for this window */
1837 GdkFilterReturn result;
1838 result = gdk_event_apply_filters (xevent, event,
1840 ?window_private->filters
1841 :gdk_default_filters);
1843 if (result != GDK_FILTER_CONTINUE)
1845 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1849 /* We do a "manual" conversion of the XEvent to a
1850 * GdkEvent. The structures are mostly the same so
1851 * the conversion is fairly straightforward. We also
1852 * optionally print debugging info regarding events
1856 * During drag & drop you get events where the pointer is
1857 * in other windows. Need to just do finer-grained checking
1859 switch (xevent->type)
1862 /* Lookup the string corresponding to the given keysym.
1868 buf = g_new (gchar, buf_len);
1870 keysym = GDK_VoidSymbol;
1872 if (xim_using == TRUE && xim_ic)
1876 /* Clear keyval. Depending on status, may not be set */
1877 charcount = XmbLookupString(xim_ic->xic,
1878 &xevent->xkey, buf, buf_len-1,
1880 if (status == XBufferOverflow)
1882 /* alloc adequate size of buffer */
1884 g_message("XIM: overflow (required %i)", charcount));
1886 while (buf_len <= charcount)
1888 buf = (gchar *) g_realloc (buf, buf_len);
1890 charcount = XmbLookupString (xim_ic->xic,
1891 &xevent->xkey, buf, buf_len-1,
1894 if (status == XLookupNone)
1901 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1904 charcount = XLookupString (&xevent->xkey, buf, 16,
1907 event->key.keyval = keysym;
1909 if (charcount > 0 && buf[charcount-1] == '\0')
1912 buf[charcount] = '\0';
1914 /* Print debugging info.
1916 #ifdef G_ENABLE_DEBUG
1917 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1919 g_message ("key press:\twindow: %ld key: %12s %d",
1920 xevent->xkey.window - base_id,
1921 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1924 g_message ("\t\tlength: %4d string: \"%s\"",
1927 #endif /* G_ENABLE_DEBUG */
1929 event->key.type = GDK_KEY_PRESS;
1930 event->key.window = window;
1931 event->key.time = xevent->xkey.time;
1932 event->key.state = (GdkModifierType) xevent->xkey.state;
1933 event->key.string = g_strdup (buf);
1934 event->key.length = charcount;
1936 return_val = window_private && !window_private->destroyed;
1939 g_free (event->key.string);
1944 /* Lookup the string corresponding to the given keysym.
1946 keysym = GDK_VoidSymbol;
1947 charcount = XLookupString (&xevent->xkey, buf, 16,
1949 event->key.keyval = keysym;
1951 /* Print debugging info.
1954 g_message ("key release:\t\twindow: %ld key: %12s %d",
1955 xevent->xkey.window - base_id,
1956 XKeysymToString (event->key.keyval),
1957 event->key.keyval));
1959 event->key.type = GDK_KEY_RELEASE;
1960 event->key.window = window;
1961 event->key.time = xevent->xkey.time;
1962 event->key.state = (GdkModifierType) xevent->xkey.state;
1963 event->key.length = 0;
1964 event->key.string = NULL;
1966 return_val = window_private && !window_private->destroyed;
1970 /* Print debugging info.
1973 g_message ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d",
1974 window_private?window_private->dnd_drag_enabled:0,
1975 xevent->xbutton.window - base_id,
1976 xevent->xbutton.x, xevent->xbutton.y,
1977 xevent->xbutton.button));
1979 if (window_private &&
1980 (window_private->extension_events != 0) &&
1981 gdk_input_ignore_core)
1984 event->button.type = GDK_BUTTON_PRESS;
1985 event->button.window = window;
1986 event->button.time = xevent->xbutton.time;
1987 event->button.x = xevent->xbutton.x;
1988 event->button.y = xevent->xbutton.y;
1989 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1990 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1991 event->button.pressure = 0.5;
1992 event->button.xtilt = 0;
1993 event->button.ytilt = 0;
1994 event->button.state = (GdkModifierType) xevent->xbutton.state;
1995 event->button.button = xevent->xbutton.button;
1996 event->button.source = GDK_SOURCE_MOUSE;
1997 event->button.deviceid = GDK_CORE_POINTER;
1999 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
2000 (event->button.window == button_window[1]) &&
2001 (event->button.button == button_number[1]))
2003 gdk_synthesize_click (event, 3);
2005 button_click_time[1] = 0;
2006 button_click_time[0] = 0;
2007 button_window[1] = NULL;
2008 button_window[0] = 0;
2009 button_number[1] = -1;
2010 button_number[0] = -1;
2012 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
2013 (event->button.window == button_window[0]) &&
2014 (event->button.button == button_number[0]))
2016 gdk_synthesize_click (event, 2);
2018 button_click_time[1] = button_click_time[0];
2019 button_click_time[0] = event->button.time;
2020 button_window[1] = button_window[0];
2021 button_window[0] = event->button.window;
2022 button_number[1] = button_number[0];
2023 button_number[0] = event->button.button;
2027 button_click_time[1] = 0;
2028 button_click_time[0] = event->button.time;
2029 button_window[1] = NULL;
2030 button_window[0] = event->button.window;
2031 button_number[1] = -1;
2032 button_number[0] = event->button.button;
2035 && window_private->dnd_drag_enabled
2036 && !gdk_dnd.drag_perhaps
2037 && event->button.button == 1
2038 && !gdk_dnd.drag_really)
2040 gdk_dnd.drag_perhaps = 1;
2041 gdk_dnd.dnd_drag_start.x = xevent->xbutton.x_root;
2042 gdk_dnd.dnd_drag_start.y = xevent->xbutton.y_root;
2043 gdk_dnd.real_sw = window_private;
2045 if(gdk_dnd.drag_startwindows)
2047 g_free(gdk_dnd.drag_startwindows);
2048 gdk_dnd.drag_startwindows = NULL;
2050 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
2051 gdk_dnd.dnd_grabbed = FALSE;
2054 /* Set motion mask for first DnD'd window, since it
2055 will be the one that is actually dragged */
2056 XWindowAttributes dnd_winattr;
2057 XSetWindowAttributes dnd_setwinattr;
2059 /* We need to get motion events while the button is down, so
2060 we can know whether to really start dragging or not... */
2061 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
2064 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
2065 dnd_setwinattr.event_mask =
2066 window_private->dnd_drag_eventmask = ButtonMotionMask | ButtonPressMask | ButtonReleaseMask |
2067 EnterWindowMask | LeaveWindowMask | ExposureMask;
2068 XChangeWindowAttributes(gdk_display, window_private->xwindow,
2069 CWEventMask, &dnd_setwinattr);
2072 return_val = window_private && !window_private->destroyed;
2076 /* Print debugging info.
2079 g_message ("button release[%d]:\twindow: %ld x,y: %d %d button: %d",
2080 window_private?window_private->dnd_drag_enabled:0,
2081 xevent->xbutton.window - base_id,
2082 xevent->xbutton.x, xevent->xbutton.y,
2083 xevent->xbutton.button));
2085 if (window_private &&
2086 (window_private->extension_events != 0) &&
2087 gdk_input_ignore_core)
2090 event->button.type = GDK_BUTTON_RELEASE;
2091 event->button.window = window;
2092 event->button.time = xevent->xbutton.time;
2093 event->button.x = xevent->xbutton.x;
2094 event->button.y = xevent->xbutton.y;
2095 event->button.x_root = (gfloat)xevent->xbutton.x_root;
2096 event->button.y_root = (gfloat)xevent->xbutton.y_root;
2097 event->button.pressure = 0.5;
2098 event->button.xtilt = 0;
2099 event->button.ytilt = 0;
2100 event->button.state = (GdkModifierType) xevent->xbutton.state;
2101 event->button.button = xevent->xbutton.button;
2102 event->button.source = GDK_SOURCE_MOUSE;
2103 event->button.deviceid = GDK_CORE_POINTER;
2105 gdk_dnd.last_drop_time = xevent->xbutton.time;
2106 if(gdk_dnd.drag_perhaps)
2109 XSetWindowAttributes attrs;
2110 /* Reset event mask to pre-drag value, assuming event_mask
2111 doesn't change during drag */
2112 attrs.event_mask = gdk_dnd.real_sw->dnd_drag_savedeventmask;
2113 XChangeWindowAttributes(gdk_display, gdk_dnd.real_sw->xwindow,
2114 CWEventMask, &attrs);
2117 if (gdk_dnd.dnd_grabbed)
2119 gdk_dnd_display_drag_cursor(-2,
2122 XUngrabPointer(gdk_display, CurrentTime);
2123 gdk_dnd.dnd_grabbed = FALSE;
2126 if(gdk_dnd.drag_really)
2129 foo.x = xevent->xbutton.x_root;
2130 foo.y = xevent->xbutton.y_root;
2132 if(gdk_dnd.dnd_drag_target != None)
2133 gdk_dnd_drag_end(gdk_dnd.dnd_drag_target, foo);
2134 gdk_dnd.drag_really = 0;
2136 gdk_dnd.drag_numwindows = 0;
2137 if(gdk_dnd.drag_startwindows)
2139 g_free(gdk_dnd.drag_startwindows);
2140 gdk_dnd.drag_startwindows = NULL;
2143 gdk_dnd.real_sw = NULL;
2146 gdk_dnd.drag_perhaps = 0;
2147 gdk_dnd.dnd_drag_start.x = gdk_dnd.dnd_drag_start.y = 0;
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_curwin = None;
2151 return_val = window_private?TRUE:FALSE;
2153 return_val = window_private && !window_private->destroyed;
2157 /* Print debugging info.
2160 g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d",
2161 xevent->xmotion.window - base_id,
2162 xevent->xmotion.x, xevent->xmotion.y,
2163 (xevent->xmotion.is_hint) ? "true" : "false",
2164 gdk_dnd.drag_perhaps, gdk_dnd.drag_really));
2166 if (window_private &&
2167 (window_private->extension_events != 0) &&
2168 gdk_input_ignore_core)
2171 event->motion.type = GDK_MOTION_NOTIFY;
2172 event->motion.window = window;
2173 event->motion.time = xevent->xmotion.time;
2174 event->motion.x = xevent->xmotion.x;
2175 event->motion.y = xevent->xmotion.y;
2176 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2177 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2178 event->motion.pressure = 0.5;
2179 event->motion.xtilt = 0;
2180 event->motion.ytilt = 0;
2181 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2182 event->motion.is_hint = xevent->xmotion.is_hint;
2183 event->motion.source = GDK_SOURCE_MOUSE;
2184 event->motion.deviceid = GDK_CORE_POINTER;
2186 #define IS_IN_ZONE(cx, cy) (cx >= gdk_dnd.dnd_drag_dropzone.x \
2187 && cy >= gdk_dnd.dnd_drag_dropzone.y \
2188 && cx < (gdk_dnd.dnd_drag_dropzone.x + gdk_dnd.dnd_drag_dropzone.width) \
2189 && cy < (gdk_dnd.dnd_drag_dropzone.y + gdk_dnd.dnd_drag_dropzone.height))
2191 if(gdk_dnd.drag_perhaps && gdk_dnd.drag_really
2192 /* && event->motion.is_hint */ /* HINTME */)
2194 /* First, we have to find what window the motion was in... */
2195 /* XXX there has to be a better way to do this, perhaps with
2196 XTranslateCoordinates or XQueryTree - I don't know how,
2197 and this sort of works */
2198 static Window lastwin = None, curwin = None;
2202 Window childwin = gdk_root_window;
2205 /* Interlude - display cursor for the drag ASAP */
2206 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2207 xevent->xmotion.y_root,
2208 gdk_dnd.dnd_drag_target?TRUE:FALSE,
2212 curwin = gdk_root_window;
2213 ox = x = xevent->xmotion.x_root;
2214 oy = y = xevent->xmotion.y_root;
2216 curwin = gdk_window_xid_at_coords(xevent->xmotion.x_root,
2217 xevent->xmotion.y_root,
2218 gdk_dnd.c->xids,TRUE);
2219 XTranslateCoordinates(gdk_display, gdk_root_window, curwin,
2220 x, y, &x, &y, &childwin);
2222 while(childwin != None)
2226 XTranslateCoordinates(gdk_display, curwin, curwin,
2227 x, y, &x, &y, &childwin);
2228 if(childwin != None)
2230 XTranslateCoordinates(gdk_display, curwin, childwin,
2231 x, y, &x, &y, &twin);
2236 g_message("Drag is now in window %#lx, lastwin was %#lx, ddc = %#lx",
2237 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2238 if(curwin != gdk_dnd.dnd_drag_curwin && curwin != lastwin)
2240 /* We have left one window and entered another
2241 (do leave & enter bits) */
2242 if(gdk_dnd.dnd_drag_curwin != None)
2243 gdk_dnd_drag_leave(gdk_dnd.dnd_drag_curwin);
2244 gdk_dnd.dnd_drag_curwin = curwin;
2245 gdk_dnd_drag_enter(gdk_dnd.dnd_drag_curwin);
2246 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2247 gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2248 gdk_dnd.dnd_drag_target = None;
2250 g_message("curwin = %#lx, lastwin = %#lx, dnd_drag_curwin = %#lx",
2251 curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2253 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2254 xevent->xmotion.y_root,
2257 else if(gdk_dnd.dnd_drag_dropzone.width > 0
2258 && gdk_dnd.dnd_drag_dropzone.height > 0
2259 && curwin == gdk_dnd.dnd_drag_curwin)
2261 /* Handle all that dropzone stuff - thanks John ;-) */
2262 if (gdk_dnd.dnd_drag_target != None)
2264 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2265 xevent->xmotion.y_root);
2266 gboolean old_in_zone = IS_IN_ZONE(gdk_dnd.dnd_drag_oldpos.x,
2267 gdk_dnd.dnd_drag_oldpos.y);
2269 if (!in_zone && old_in_zone)
2271 /* We were in the drop zone and moved out */
2272 gdk_dnd.dnd_drag_target = None;
2273 gdk_dnd_drag_leave(curwin);
2274 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2275 xevent->xmotion.y_root,
2278 else if (!in_zone && !old_in_zone)
2280 /* We were outside drop zone but in the window
2281 - have to send enter events */
2282 gdk_dnd_drag_enter(curwin);
2283 gdk_dnd.dnd_drag_curwin = curwin;
2284 gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2285 gdk_dnd.dnd_drag_target = None;
2289 dnd_drag_curwin = None; */
2293 return_val = window_private && !window_private->destroyed;
2297 /* Print debugging info.
2300 g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
2301 xevent->xcrossing.window - base_id,
2302 xevent->xcrossing.detail,
2303 xevent->xcrossing.subwindow - base_id));
2305 /* Tell XInput stuff about it if appropriate */
2306 if (window_private &&
2307 (window_private->extension_events != 0) &&
2308 gdk_input_vtable.enter_event)
2309 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2311 event->crossing.type = GDK_ENTER_NOTIFY;
2312 event->crossing.window = window;
2314 /* If the subwindow field of the XEvent is non-NULL, then
2315 * lookup the corresponding GdkWindow.
2317 if (xevent->xcrossing.subwindow != None)
2318 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2320 event->crossing.subwindow = NULL;
2322 event->crossing.time = xevent->xcrossing.time;
2323 event->crossing.x = xevent->xcrossing.x;
2324 event->crossing.y = xevent->xcrossing.y;
2325 event->crossing.x_root = xevent->xcrossing.x_root;
2326 event->crossing.y_root = xevent->xcrossing.y_root;
2328 /* Translate the crossing mode into Gdk terms.
2330 switch (xevent->xcrossing.mode)
2333 event->crossing.mode = GDK_CROSSING_NORMAL;
2336 event->crossing.mode = GDK_CROSSING_GRAB;
2339 event->crossing.mode = GDK_CROSSING_UNGRAB;
2343 /* Translate the crossing detail into Gdk terms.
2345 switch (xevent->xcrossing.detail)
2347 case NotifyInferior:
2348 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2350 case NotifyAncestor:
2351 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2354 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2356 case NotifyNonlinear:
2357 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2359 case NotifyNonlinearVirtual:
2360 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2363 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2367 event->crossing.focus = xevent->xcrossing.focus;
2368 event->crossing.state = xevent->xcrossing.state;
2370 #ifdef G_ENABLE_DEBUG
2371 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2373 g_message("We may[%d] have a drag into %#lx = %#lx",
2374 gdk_dnd.drag_really,
2375 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2377 #endif /* G_ENABLE_DEBUG */
2379 if (gdk_dnd.drag_perhaps && gdk_dnd.drag_really &&
2380 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2383 gdk_dnd.drag_really = 0;
2385 GDK_NOTE (DND, g_message("Ungrabbed"));
2387 gdk_dnd.drag_numwindows = 0;
2388 g_free(gdk_dnd.drag_startwindows);
2389 gdk_dnd.drag_startwindows = NULL;
2390 /* We don't want to ungrab the pointer here, or we'll
2391 * start getting spurious enter/leave events */
2394 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2398 return_val = window_private && !window_private->destroyed;
2402 /* Print debugging info.
2405 g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
2406 xevent->xcrossing.window - base_id,
2407 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2409 event->crossing.type = GDK_LEAVE_NOTIFY;
2410 event->crossing.window = window;
2412 /* If the subwindow field of the XEvent is non-NULL, then
2413 * lookup the corresponding GdkWindow.
2415 if (xevent->xcrossing.subwindow != None)
2416 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2418 event->crossing.subwindow = NULL;
2420 event->crossing.time = xevent->xcrossing.time;
2421 event->crossing.x = xevent->xcrossing.x;
2422 event->crossing.y = xevent->xcrossing.y;
2423 event->crossing.x_root = xevent->xcrossing.x_root;
2424 event->crossing.y_root = xevent->xcrossing.y_root;
2426 /* Translate the crossing mode into Gdk terms.
2428 switch (xevent->xcrossing.mode)
2431 event->crossing.mode = GDK_CROSSING_NORMAL;
2434 event->crossing.mode = GDK_CROSSING_GRAB;
2437 event->crossing.mode = GDK_CROSSING_UNGRAB;
2441 /* Translate the crossing detail into Gdk terms.
2443 switch (xevent->xcrossing.detail)
2445 case NotifyInferior:
2446 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2448 case NotifyAncestor:
2449 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2452 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2454 case NotifyNonlinear:
2455 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2457 case NotifyNonlinearVirtual:
2458 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2461 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2465 event->crossing.focus = xevent->xcrossing.focus;
2466 event->crossing.state = xevent->xcrossing.state;
2468 #ifdef G_ENABLE_DEBUG
2469 if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2471 g_message("We may[%d] have a drag out of %#lx = %#lx",
2472 gdk_dnd.drag_really,
2473 xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2475 #endif /* G_ENABLE_DEBUG */
2476 if (gdk_dnd.drag_perhaps && !gdk_dnd.drag_really &&
2477 (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2480 gdk_dnd_drag_addwindow((GdkWindow *) gdk_dnd.real_sw);
2481 gdk_dnd_drag_begin((GdkWindow *) gdk_dnd.real_sw);
2483 XGrabPointer(gdk_display, gdk_dnd.real_sw->xwindow, False,
2484 ButtonMotionMask | PointerMotionMask |
2485 /* PointerMotionHintMask | */ /* HINTME */
2486 ButtonPressMask | ButtonReleaseMask,
2487 GrabModeAsync, GrabModeAsync, None,
2489 #ifdef G_ENABLE_DEBUG
2490 GDK_NOTE(DND, g_message("xgpret = %d", xgpret));
2492 gdk_dnd.dnd_grabbed = TRUE;
2493 gdk_dnd.drag_really = 1;
2494 gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2495 xevent->xmotion.y_root,
2499 return_val = window_private && !window_private->destroyed;
2504 /* We only care about focus events that indicate that _this_
2505 * window (not a ancestor or child) got or lost the focus
2507 switch (xevent->xfocus.detail)
2509 case NotifyAncestor:
2510 case NotifyInferior:
2511 case NotifyNonlinear:
2512 /* Print debugging info.
2515 g_message ("focus %s:\t\twindow: %ld",
2516 (xevent->xany.type == FocusIn) ? "in" : "out",
2517 xevent->xfocus.window - base_id));
2519 event->focus_change.type = GDK_FOCUS_CHANGE;
2520 event->focus_change.window = window;
2521 event->focus_change.in = (xevent->xany.type == FocusIn);
2523 return_val = window_private && !window_private->destroyed;
2531 /* Print debugging info.
2534 g_message ("keymap notify"));
2536 /* Not currently handled */
2540 /* Print debugging info.
2543 g_message ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d",
2544 xevent->xexpose.window - base_id, xevent->xexpose.count,
2545 xevent->xexpose.x, xevent->xexpose.y,
2546 xevent->xexpose.width, xevent->xexpose.height));
2548 event->expose.type = GDK_EXPOSE;
2549 event->expose.window = window;
2550 event->expose.area.x = xevent->xexpose.x;
2551 event->expose.area.y = xevent->xexpose.y;
2552 event->expose.area.width = xevent->xexpose.width;
2553 event->expose.area.height = xevent->xexpose.height;
2554 event->expose.count = xevent->xexpose.count;
2556 return_val = window_private && !window_private->destroyed;
2559 case GraphicsExpose:
2560 /* Print debugging info.
2563 g_message ("graphics expose:\tdrawable: %ld",
2564 xevent->xgraphicsexpose.drawable - base_id));
2566 event->expose.type = GDK_EXPOSE;
2567 event->expose.window = window;
2568 event->expose.area.x = xevent->xgraphicsexpose.x;
2569 event->expose.area.y = xevent->xgraphicsexpose.y;
2570 event->expose.area.width = xevent->xgraphicsexpose.width;
2571 event->expose.area.height = xevent->xgraphicsexpose.height;
2572 event->expose.count = xevent->xexpose.count;
2574 return_val = window_private && !window_private->destroyed;
2578 /* Print debugging info.
2581 g_message ("no expose:\t\tdrawable: %ld",
2582 xevent->xnoexpose.drawable - base_id));
2584 event->no_expose.type = GDK_NO_EXPOSE;
2585 event->no_expose.window = window;
2587 return_val = window_private && !window_private->destroyed;
2590 case VisibilityNotify:
2591 /* Print debugging info.
2593 #ifdef G_ENABLE_DEBUG
2594 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2595 switch (xevent->xvisibility.state)
2597 case VisibilityFullyObscured:
2598 g_message ("visibility notify:\twindow: %ld none",
2599 xevent->xvisibility.window - base_id);
2601 case VisibilityPartiallyObscured:
2602 g_message ("visibility notify:\twindow: %ld partial",
2603 xevent->xvisibility.window - base_id);
2605 case VisibilityUnobscured:
2606 g_message ("visibility notify:\twindow: %ld full",
2607 xevent->xvisibility.window - base_id);
2610 #endif /* G_ENABLE_DEBUG */
2612 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2613 event->visibility.window = window;
2615 switch (xevent->xvisibility.state)
2617 case VisibilityFullyObscured:
2618 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2621 case VisibilityPartiallyObscured:
2622 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2625 case VisibilityUnobscured:
2626 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2630 return_val = window_private && !window_private->destroyed;
2634 /* Not currently handled */
2638 /* Print debugging info.
2641 g_message ("destroy notify:\twindow: %ld",
2642 xevent->xdestroywindow.window - base_id));
2644 event->any.type = GDK_DESTROY;
2645 event->any.window = window;
2647 return_val = window_private && !window_private->destroyed;
2649 if(window && window_private->xwindow != GDK_ROOT_WINDOW())
2650 gdk_window_destroy_notify (window);
2654 /* Print debugging info.
2657 g_message ("unmap notify:\t\twindow: %ld",
2658 xevent->xmap.window - base_id));
2660 event->any.type = GDK_UNMAP;
2661 event->any.window = window;
2663 if (xgrab_window == window_private)
2664 xgrab_window = NULL;
2666 return_val = window_private && !window_private->destroyed;
2670 /* Print debugging info.
2673 g_message ("map notify:\t\twindow: %ld",
2674 xevent->xmap.window - base_id));
2676 event->any.type = GDK_MAP;
2677 event->any.window = window;
2679 return_val = window_private && !window_private->destroyed;
2682 case ReparentNotify:
2683 /* Print debugging info.
2686 g_message ("reparent notify:\twindow: %ld",
2687 xevent->xreparent.window - base_id));
2689 /* Not currently handled */
2692 case ConfigureNotify:
2693 /* Print debugging info.
2695 while ((XPending (gdk_display) > 0) &&
2696 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2697 ConfigureNotify, xevent))
2699 GdkFilterReturn result;
2702 g_message ("configure notify discarded:\twindow: %ld",
2703 xevent->xconfigure.window - base_id));
2705 result = gdk_event_apply_filters (xevent, event,
2707 ?window_private->filters
2708 :gdk_default_filters);
2710 /* If the result is GDK_FILTER_REMOVE, there will be
2711 * trouble, but anybody who filtering the Configure events
2712 * better know what they are doing
2714 if (result != GDK_FILTER_CONTINUE)
2716 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
2719 /*XSync (gdk_display, 0);*/
2724 g_message ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d",
2725 xevent->xconfigure.window - base_id,
2726 xevent->xconfigure.x,
2727 xevent->xconfigure.y,
2728 xevent->xconfigure.width,
2729 xevent->xconfigure.height,
2730 xevent->xconfigure.border_width,
2731 xevent->xconfigure.above - base_id,
2732 xevent->xconfigure.override_redirect));
2736 if ((window_private->extension_events != 0) &&
2737 gdk_input_vtable.configure_event)
2738 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2740 if (window_private->window_type != GDK_WINDOW_CHILD)
2742 event->configure.type = GDK_CONFIGURE;
2743 event->configure.window = window;
2744 event->configure.width = xevent->xconfigure.width;
2745 event->configure.height = xevent->xconfigure.height;
2747 if (!xevent->xconfigure.x &&
2748 !xevent->xconfigure.y &&
2749 !window_private->destroyed)
2753 Window child_window = 0;
2755 if (!XTranslateCoordinates (window_private->xdisplay,
2756 window_private->xwindow,
2761 g_warning ("GdkWindow %ld doesn't share root windows display?",
2762 window_private->xwindow - base_id);
2763 event->configure.x = tx;
2764 event->configure.y = ty;
2768 event->configure.x = xevent->xconfigure.x;
2769 event->configure.y = xevent->xconfigure.y;
2771 window_private->x = event->configure.x;
2772 window_private->y = event->configure.y;
2773 window_private->width = xevent->xconfigure.width;
2774 window_private->height = xevent->xconfigure.height;
2775 if (window_private->resize_count > 1)
2776 window_private->resize_count -= 1;
2778 return_val = !window_private->destroyed;
2783 case PropertyNotify:
2784 /* Print debugging info.
2787 g_message ("property notify:\twindow: %ld",
2788 xevent->xproperty.window - base_id));
2790 event->property.type = GDK_PROPERTY_NOTIFY;
2791 event->property.window = window;
2792 event->property.atom = xevent->xproperty.atom;
2793 event->property.time = xevent->xproperty.time;
2794 event->property.state = xevent->xproperty.state;
2796 return_val = window_private && !window_private->destroyed;
2799 case SelectionClear:
2801 g_message ("selection clear:\twindow: %ld",
2802 xevent->xproperty.window - base_id));
2804 event->selection.type = GDK_SELECTION_CLEAR;
2805 event->selection.window = window;
2806 event->selection.selection = xevent->xselectionclear.selection;
2807 event->selection.time = xevent->xselectionclear.time;
2809 return_val = window_private && !window_private->destroyed;
2812 case SelectionRequest:
2814 g_message ("selection request:\twindow: %ld",
2815 xevent->xproperty.window - base_id));
2817 event->selection.type = GDK_SELECTION_REQUEST;
2818 event->selection.window = window;
2819 event->selection.selection = xevent->xselectionrequest.selection;
2820 event->selection.target = xevent->xselectionrequest.target;
2821 event->selection.property = xevent->xselectionrequest.property;
2822 event->selection.requestor = xevent->xselectionrequest.requestor;
2823 event->selection.time = xevent->xselectionrequest.time;
2825 return_val = window_private && !window_private->destroyed;
2828 case SelectionNotify:
2830 g_message ("selection notify:\twindow: %ld",
2831 xevent->xproperty.window - base_id));
2834 event->selection.type = GDK_SELECTION_NOTIFY;
2835 event->selection.window = window;
2836 event->selection.selection = xevent->xselection.selection;
2837 event->selection.target = xevent->xselection.target;
2838 event->selection.property = xevent->xselection.property;
2839 event->selection.time = xevent->xselection.time;
2841 return_val = window_private && !window_private->destroyed;
2844 case ColormapNotify:
2845 /* Print debugging info.
2848 g_message ("colormap notify:\twindow: %ld",
2849 xevent->xcolormap.window - base_id));
2851 /* Not currently handled */
2855 /* Print debugging info.
2858 g_message ("client message:\twindow: %ld",
2859 xevent->xclient.window - base_id));
2861 /* Client messages are the means of the window manager
2862 * communicating with a program. We'll first check to
2863 * see if this is really the window manager talking
2866 if (xevent->xclient.message_type == gdk_wm_protocols)
2868 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2870 /* The delete window request specifies a window
2871 * to delete. We don't actually destroy the
2872 * window because "it is only a request". (The
2873 * window might contain vital data that the
2874 * program does not want destroyed). Instead
2875 * the event is passed along to the program,
2876 * which should then destroy the window.
2879 /* Print debugging info.
2882 g_message ("delete window:\t\twindow: %ld",
2883 xevent->xclient.window - base_id));
2885 event->any.type = GDK_DELETE;
2886 event->any.window = window;
2888 return_val = window_private && !window_private->destroyed;
2890 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2894 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2898 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2900 GDK_NOTE (DND, g_message ("GDK_DROP_ENTER [%d][%d]",
2901 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply));
2904 /* Now figure out if we really want this drop...
2905 * If someone is trying funky clipboard stuff, ignore
2908 && window_private->dnd_drop_enabled
2909 && event->dropenter.u.flags.sendreply
2910 && (reptype = gdk_dnd_check_types (window, xevent)))
2914 replyev.xclient.type = ClientMessage;
2915 replyev.xclient.window = xevent->xclient.data.l[0];
2916 replyev.xclient.format = 32;
2917 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2918 replyev.xclient.data.l[0] = window_private->xwindow;
2920 event->dragrequest.u.allflags = 0;
2921 event->dragrequest.u.flags.protocol_version =
2922 DND_PROTOCOL_VERSION;
2923 event->dragrequest.u.flags.willaccept = 1;
2924 event->dragrequest.u.flags.delete_data =
2925 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2927 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2928 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2929 replyev.xclient.data.l[4] = reptype;
2931 if (!gdk_send_xevent (replyev.xclient.window, False,
2932 NoEventMask, &replyev))
2933 GDK_NOTE (DND, g_message("Sending XdeRequest to %#lx failed",
2934 replyev.xclient.window));
2936 event->any.type = GDK_DROP_ENTER;
2937 event->any.window = window;
2938 event->dropenter.requestor = replyev.xclient.window;
2939 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2941 GDK_NOTE (DND, g_message("We sent a GDK_DROP_ENTER on to Gtk"));
2945 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2947 #ifdef G_ENABLE_DEBUG
2948 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2949 g_message ("GDK_DROP_LEAVE");
2952 if (window_private && window_private->dnd_drop_enabled)
2954 event->dropleave.type = GDK_DROP_LEAVE;
2955 event->dropleave.window = window;
2956 event->dropleave.requestor = xevent->xclient.data.l[0];
2957 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2963 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2966 * make sure to only handle requests from the window the cursor is
2969 #ifdef G_ENABLE_DEBUG
2970 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2971 g_message ("GDK_DRAG_REQUEST");
2973 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2976 if (window && gdk_dnd.drag_really &&
2977 xevent->xclient.data.l[0] == gdk_dnd.dnd_drag_curwin &&
2978 event->dragrequest.u.flags.sendreply == 0)
2980 /* Got request - do we need to ask user? */
2981 if (!event->dragrequest.u.flags.willaccept
2982 && event->dragrequest.u.flags.senddata)
2985 event->dragrequest.type = GDK_DRAG_REQUEST;
2986 event->dragrequest.window = window;
2987 event->dragrequest.requestor = xevent->xclient.data.l[0];
2988 event->dragrequest.isdrop = 0;
2989 event->dragrequest.drop_coords.x =
2990 event->dragrequest.drop_coords.y = 0;
2993 else if (event->dragrequest.u.flags.willaccept)
2995 window_private->dnd_drag_destructive_op =
2996 event->dragrequest.u.flags.delete_data;
2997 window_private->dnd_drag_accepted = 1;
2998 window_private->dnd_drag_data_type =
2999 xevent->xclient.data.l[4];
3001 gdk_dnd.dnd_drag_target = gdk_dnd.dnd_drag_curwin;
3002 gdk_dnd_display_drag_cursor(-1, -1, TRUE, TRUE);
3004 gdk_dnd.dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
3005 gdk_dnd.dnd_drag_dropzone.y =
3006 (xevent->xclient.data.l[2] >> 16) & 65535;
3007 gdk_dnd.dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
3008 gdk_dnd.dnd_drag_dropzone.height =
3009 (xevent->xclient.data.l[3] >> 16) & 65535;
3012 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
3014 gint tmp_int; Atom tmp_atom;
3016 guchar *tmp_charptr;
3018 #ifdef G_ENABLE_DEBUG
3019 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
3020 g_message("GDK_DROP_DATA_AVAIL");
3022 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
3023 event->dropdataavailable.timestamp = xevent->xclient.data.l[4];
3024 event->dropdataavailable.coords.x =
3025 xevent->xclient.data.l[3] & 0xffff;
3026 event->dropdataavailable.coords.y =
3027 (xevent->xclient.data.l[3] >> 16) & 0xffff;
3029 /* No preview of data ATM */
3030 && event->dropdataavailable.u.flags.isdrop)
3032 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
3033 event->dropdataavailable.window = window;
3034 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
3035 event->dropdataavailable.data_type =
3036 gdk_atom_name(xevent->xclient.data.l[2]);
3037 if(XGetWindowProperty (gdk_display,
3038 event->dropdataavailable.requestor,
3039 xevent->xclient.data.l[2],
3041 False, XA_PRIMARY, &tmp_atom,
3043 &event->dropdataavailable.data_numbytes,
3048 g_warning("XGetWindowProperty on %#x may have failed\n",
3049 event->dropdataavailable.requestor);
3050 event->dropdataavailable.data = NULL;
3054 GDK_NOTE (DND, g_message("XGetWindowProperty got us %ld bytes",
3055 event->dropdataavailable.data_numbytes));
3056 event->dropdataavailable.data =
3057 g_malloc (event->dropdataavailable.data_numbytes);
3058 memcpy (event->dropdataavailable.data,
3059 tmp_charptr, event->dropdataavailable.data_numbytes);
3068 /* Send unknown ClientMessage's on to Gtk for it to use */
3069 event->client.type = GDK_CLIENT_EVENT;
3070 event->client.window = window;
3071 event->client.message_type = xevent->xclient.message_type;
3072 event->client.data_format = xevent->xclient.format;
3073 memcpy(&event->client.data, &xevent->xclient.data,
3074 sizeof(event->client.data));
3081 return_val = return_val && !window_private->destroyed;
3085 /* Print debugging info.
3088 g_message ("mapping notify"));
3090 /* Let XLib know that there is a new keyboard mapping.
3092 XRefreshKeyboardMapping (&xevent->xmapping);
3096 /* something else - (e.g., a Xinput event) */
3098 if (window_private &&
3099 (window_private->extension_events != 0) &&
3100 gdk_input_vtable.other_event)
3101 return_val = gdk_input_vtable.other_event(event, xevent, window);
3105 return_val = return_val && !window_private->destroyed;
3112 if (event->any.window)
3113 gdk_window_ref (event->any.window);
3114 if (((event->any.type == GDK_ENTER_NOTIFY) ||
3115 (event->any.type == GDK_LEAVE_NOTIFY)) &&
3116 (event->crossing.subwindow != NULL))
3117 gdk_window_ref (event->crossing.subwindow);
3121 /* Mark this event as having no resources to be freed */
3122 event->any.window = NULL;
3123 event->any.type = GDK_NOTHING;
3127 gdk_window_unref (window);
3134 gdk_event_get_type (Display *display,
3141 if (gdk_event_translate (&event, xevent))
3143 pred = (GdkPredicate*) arg;
3144 return (* pred->func) (&event, pred->data);
3152 gdk_synthesize_click (GdkEvent *event,
3155 GdkEvent temp_event;
3157 g_return_if_fail (event != NULL);
3159 temp_event = *event;
3160 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
3162 gdk_event_put (&temp_event);
3166 *--------------------------------------------------------------
3169 * This is the "atexit" function that makes sure the
3170 * library gets a chance to cleanup.
3177 * The library is un-initialized and the program exits.
3179 *--------------------------------------------------------------
3183 gdk_exit_func (void)
3185 static gboolean in_gdk_exit_func = FALSE;
3187 /* This is to avoid an infinite loop if a program segfaults in
3188 an atexit() handler (and yes, it does happen, especially if a program
3189 has trounced over memory too badly for even g_message to work) */
3190 if (in_gdk_exit_func == TRUE)
3192 in_gdk_exit_func = TRUE;
3194 if (gdk_initialized)
3204 gdk_key_repeat_restore ();
3206 XCloseDisplay (gdk_display);
3207 gdk_initialized = 0;
3212 *--------------------------------------------------------------
3215 * The X error handling routine.
3218 * "display" is the X display the error orignated from.
3219 * "error" is the XErrorEvent that we are handling.
3222 * Either we were expecting some sort of error to occur,
3223 * in which case we set the "gdk_error_code" flag, or this
3224 * error was unexpected, in which case we will print an
3225 * error message and exit. (Since trying to continue will
3226 * most likely simply lead to more errors).
3230 *--------------------------------------------------------------
3234 gdk_x_error (Display *display,
3239 if (gdk_error_warnings)
3241 XGetErrorText (display, error->error_code, buf, 63);
3242 g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
3246 error->request_code,
3250 gdk_error_code = -1;
3255 *--------------------------------------------------------------
3258 * The X I/O error handling routine.
3261 * "display" is the X display the error orignated from.
3264 * An X I/O error basically means we lost our connection
3265 * to the X server. There is not much we can do to
3266 * continue, so simply print an error message and exit.
3270 *--------------------------------------------------------------
3274 gdk_x_io_error (Display *display)
3276 g_error ("an x io error occurred");
3281 *--------------------------------------------------------------
3284 * The signal handler.
3287 * "sig_num" is the number of the signal we received.
3290 * The signals we catch are all fatal. So we simply build
3291 * up a nice little error message and print it and exit.
3292 * If in the process of doing so another signal is received
3293 * we notice that we are already exiting and simply kill
3298 *--------------------------------------------------------------
3302 gdk_signal (int sig_num)
3304 static int caught_fatal_sig = 0;
3307 if (caught_fatal_sig)
3308 kill (getpid (), sig_num);
3309 caught_fatal_sig = 1;
3335 sig = "unknown signal";
3339 g_message ("\n** ERROR **: %s caught", sig);
3340 #ifdef G_ENABLE_DEBUG
3342 #else /* !G_ENABLE_DEBUG */
3344 #endif /* !G_ENABLE_DEBUG */
3348 gdk_dnd_drag_begin (GdkWindow *initial_window)
3352 GDK_NOTE(DND, g_message("------- STARTING DRAG from %p", initial_window));
3354 tev.type = GDK_DRAG_BEGIN;
3355 tev.dragbegin.window = initial_window;
3356 tev.dragbegin.u.allflags = 0;
3357 tev.dragbegin.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3359 gdk_event_put (&tev);
3363 gdk_dnd_drag_enter (Window dest)
3366 GdkEventDropEnter tev;
3368 GdkWindowPrivate *wp;
3370 sev.xclient.type = ClientMessage;
3371 sev.xclient.format = 32;
3372 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3373 sev.xclient.window = dest;
3376 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3377 tev.u.flags.sendreply = 1;
3378 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3380 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3381 if (wp->dnd_drag_data_numtypesavail)
3383 sev.xclient.data.l[0] = wp->xwindow;
3384 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3385 sev.xclient.data.l[1] = tev.u.allflags;
3386 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3387 if (wp->dnd_drag_data_numtypesavail > 1)
3389 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3390 if (wp->dnd_drag_data_numtypesavail > 2)
3392 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3395 sev.xclient.data.l[4] = None;
3398 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3399 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
3400 GDK_NOTE (DND, g_message("Sending XdeEnter to %#lx failed",
3410 /* The following routines duplicate functionality in Xlib to
3411 * translate from varargs to X's internal opaque XVaNestedList.
3413 * If all vendors have stuck close to the reference implementation,
3414 * then we should hopefully be OK.
3417 /* This needs to match XIMArg as defined in Xlcint.h exactly */
3424 /*************************************************************
3426 * Counts the number of name/value pairs in the vararg list
3431 *************************************************************/
3434 gdk_im_va_count (va_list list)
3439 name = va_arg (list, gchar *);
3443 (void)va_arg (list, gpointer);
3444 name = va_arg (list, gchar *);
3450 /*************************************************************
3451 * gdk_im_va_to_nested:
3452 * Given a varargs list and the result of gdk_im_va_count,
3453 * create a XVaNestedList.
3458 *************************************************************/
3460 static XVaNestedList
3461 gdk_im_va_to_nested (va_list list, guint count)
3471 result = g_new (GdkImArg, count+1);
3474 name = va_arg (list, gchar *);
3478 arg->value = va_arg (list, gpointer);
3480 name = va_arg (list, gchar *);
3485 return (XVaNestedList)result;
3489 *--------------------------------------------------------------
3492 * Begin using input method with XIM Protocol(X11R6 standard)
3495 * "ic" is the "Input Context" which is created by gtk_ic_new.
3496 * The input area is specified with "window".
3499 * The gdk's event handling routine is switched to XIM based routine.
3500 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3501 * and uses XmbLookupString instead of XLookupString.
3505 *--------------------------------------------------------------
3509 gdk_im_begin (GdkIC ic, GdkWindow* window)
3511 GdkICPrivate *private;
3514 g_return_if_fail (ic != NULL);
3515 g_return_if_fail (window);
3517 private = (GdkICPrivate *) ic;
3521 xim_window = window;
3524 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3525 if (xwin != GDK_WINDOW_XWINDOW(window))
3526 XSetICValues (private->xic, XNFocusWindow,
3527 GDK_WINDOW_XWINDOW(window), NULL);
3528 if (private != xim_ic)
3529 XSetICFocus (private->xic);
3534 *--------------------------------------------------------------
3537 * End using input method with XIM Protocol(X11R6 standard)
3542 * The gdk's event handling routine is switched to normal routine.
3543 * User should call this function before ic and window will be destroyed.
3547 *--------------------------------------------------------------
3565 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3567 GdkIMStyle s1, s2, u;
3569 if (style1 == 0) return style2;
3570 if (style2 == 0) return style1;
3571 if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
3572 == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
3575 s1 = style1 & GDK_IM_PREEDIT_MASK;
3576 s2 = style2 & GDK_IM_PREEDIT_MASK;
3579 if (u & GDK_IM_PREEDIT_CALLBACKS)
3580 return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
3581 else if (u & GDK_IM_PREEDIT_POSITION)
3582 return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
3583 else if (u & GDK_IM_PREEDIT_AREA)
3584 return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
3585 else if (u & GDK_IM_PREEDIT_NOTHING)
3586 return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
3588 s1 = style1 & GDK_IM_STATUS_MASK;
3589 s2 = style2 & GDK_IM_STATUS_MASK;
3591 if ( u & GDK_IM_STATUS_CALLBACKS)
3592 return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
3593 else if ( u & GDK_IM_STATUS_AREA)
3594 return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
3595 else if ( u & GDK_IM_STATUS_NOTHING)
3596 return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
3597 else if ( u & GDK_IM_STATUS_NONE)
3598 return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
3600 return 0; /* Get rid of stupid warning */
3604 gdk_im_decide_style (GdkIMStyle supported_style)
3607 GdkIMStyle style, tmp;
3609 g_return_val_if_fail (xim_styles != NULL, 0);
3612 for (i=0; i<xim_styles->count_styles; i++)
3614 tmp = xim_styles->supported_styles[i];
3615 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3616 style = gdk_im_choose_better_style (style, tmp);
3622 gdk_im_set_best_style (GdkIMStyle style)
3624 if (style & GDK_IM_PREEDIT_MASK)
3626 xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
3628 xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
3629 if (!(style & GDK_IM_PREEDIT_NONE))
3631 xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
3632 if (!(style & GDK_IM_PREEDIT_NOTHING))
3634 xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
3635 if (!(style & GDK_IM_PREEDIT_AREA))
3637 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
3638 if (!(style & GDK_IM_PREEDIT_POSITION))
3639 xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
3644 if (style & GDK_IM_STATUS_MASK)
3646 xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
3648 xim_best_allowed_style |= GDK_IM_STATUS_NONE;
3649 if (!(style & GDK_IM_STATUS_NONE))
3651 xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
3652 if (!(style & GDK_IM_STATUS_NOTHING))
3654 xim_best_allowed_style |= GDK_IM_STATUS_AREA;
3655 if (!(style & GDK_IM_STATUS_AREA))
3656 xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
3661 return xim_best_allowed_style;
3665 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3667 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3670 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
3673 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3696 return (xim_im != NULL);
3700 gdk_ic_new (GdkWindow* client_window,
3701 GdkWindow* focus_window,
3702 GdkIMStyle style, ...)
3705 GdkICPrivate *private;
3706 XVaNestedList preedit_attr = NULL;
3709 g_return_val_if_fail (client_window != NULL, NULL);
3710 g_return_val_if_fail (focus_window != NULL, NULL);
3711 g_return_val_if_fail (gdk_im_ready(), NULL);
3713 private = g_new (GdkICPrivate, 1);
3715 va_start (list, style);
3716 count = gdk_im_va_count (list);
3719 va_start (list, style);
3720 preedit_attr = gdk_im_va_to_nested (list, count);
3723 private->style = gdk_im_decide_style (style);
3724 if (private->style != style)
3726 g_warning ("can not create input context with specified input style.");
3731 private->xic = XCreateIC(gdk_im_get (),
3732 XNInputStyle, style,
3733 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3734 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3735 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3738 g_free (preedit_attr);
3746 xim_ic_list = g_list_append (xim_ic_list, private);
3751 gdk_ic_destroy (GdkIC ic)
3753 GdkICPrivate *private;
3755 g_return_if_fail (ic != NULL);
3757 private = (GdkICPrivate *) ic;
3759 if (xim_ic == private)
3762 XDestroyIC (private->xic);
3763 xim_ic_list = g_list_remove (xim_ic_list, private);
3768 gdk_ic_get_style (GdkIC ic)
3770 GdkICPrivate *private;
3772 g_return_val_if_fail (ic != NULL, 0);
3774 private = (GdkICPrivate *) ic;
3776 return private->style;
3780 gdk_ic_set_values (GdkIC ic, ...)
3784 GdkICPrivate *private;
3787 g_return_if_fail (ic != NULL);
3789 private = (GdkICPrivate *) ic;
3791 va_start (list, ic);
3792 count = gdk_im_va_count (list);
3795 va_start (list, ic);
3796 args = gdk_im_va_to_nested (list, count);
3799 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3805 gdk_ic_get_values (GdkIC ic, ...)
3809 GdkICPrivate *private;
3812 g_return_if_fail (ic != NULL);
3814 private = (GdkICPrivate *) ic;
3816 va_start (list, ic);
3817 count = gdk_im_va_count (list);
3820 va_start (list, ic);
3821 args = gdk_im_va_to_nested (list, count);
3824 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3830 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3834 GdkICPrivate *private;
3837 g_return_if_fail (ic != NULL);
3838 g_return_if_fail (target != NULL);
3840 private = (GdkICPrivate *) ic;
3842 va_start (list, target);
3843 count = gdk_im_va_count (list);
3846 va_start (list, target);
3847 attr = gdk_im_va_to_nested (list, count);
3850 XSetICValues (private->xic, target, attr, NULL);
3856 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3860 GdkICPrivate *private;
3863 g_return_if_fail (ic != NULL);
3864 g_return_if_fail (target != NULL);
3866 private = (GdkICPrivate *) ic;
3868 va_start (list, target);
3869 count = gdk_im_va_count (list);
3872 va_start (list, target);
3873 attr = gdk_im_va_to_nested (list, count);
3876 XGetICValues (private->xic, target, attr, NULL);
3882 gdk_ic_get_events (GdkIC ic)
3887 GdkICPrivate *private;
3890 /* From gdkwindow.c */
3891 extern int nevent_masks;
3892 extern int event_mask_table[];
3894 g_return_val_if_fail (ic != NULL, 0);
3896 private = (GdkICPrivate *) ic;
3898 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
3900 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
3905 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3906 if (xmask & event_mask_table [i])
3909 xmask &= ~ event_mask_table [i];
3913 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
3919 gdk_ic_cleanup (void)
3923 GdkICPrivate *private;
3926 for (node = xim_ic_list; node != NULL; node = node->next)
3930 private = (GdkICPrivate *) (node->data);
3931 XDestroyIC (private->xic);
3936 #ifdef G_ENABLE_DEBUG
3937 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3939 g_warning ("Cleaned up %i IC(s)\n", destroyed);
3941 #endif /* G_ENABLE_DEBUG */
3942 g_list_free(xim_ic_list);
3946 #else /* !USE_XIM */
3949 gdk_im_begin (GdkIC ic, GdkWindow* window)
3959 gdk_im_decide_style (GdkIMStyle supported_style)
3961 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
3965 gdk_im_set_best_style (GdkIMStyle style)
3967 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
3977 gdk_ic_new (GdkWindow* client_window,
3978 GdkWindow* focus_window,
3979 GdkIMStyle style, ...)
3985 gdk_ic_destroy (GdkIC ic)
3990 gdk_ic_get_style (GdkIC ic)
3992 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
3996 gdk_ic_set_values (GdkIC ic, ...)
4001 gdk_ic_get_values (GdkIC ic, ...)
4006 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
4011 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
4016 gdk_ic_get_events (GdkIC ic)
4021 #endif /* USE_XIM */
4026 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
4028 static wchar_t wcs[MB_CUR_MAX + 1];
4029 static gchar mbs[MB_CUR_MAX + 1];
4031 wcs[0] = (wchar_t) NULL;
4034 /* The last argument isn't a mistake. The X locale code trims
4035 * the input string to the length of the output string!
4037 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
4040 else if (wcs[0] == (wchar_t) NULL)
4043 len = _Xwctomb (mbs, wcs[0]);
4052 #endif /* X_LOCALE */
4055 gdk_dnd_drag_leave (Window dest)
4058 GdkEventDropLeave tev;
4060 GdkWindowPrivate *wp;
4064 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
4065 sev.xclient.type = ClientMessage;
4066 sev.xclient.window = dest;
4067 sev.xclient.format = 32;
4068 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
4069 sev.xclient.data.l[1] = tev.u.allflags;
4070 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
4072 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
4073 sev.xclient.data.l[0] = wp->xwindow;
4074 if (!gdk_send_xevent (dest, False, StructureNotifyMask, &sev))
4075 GDK_NOTE (DND, g_message("Sending XdeLeave to %#lx failed",
4077 wp->dnd_drag_accepted = 0;
4082 * when a drop occurs, we go through the list of windows being dragged and
4083 * tell them that it has occurred, so that they can set things up and reply
4087 gdk_dnd_drag_end (Window dest,
4090 GdkWindowPrivate *wp;
4094 tev.dragrequest.type = GDK_DRAG_REQUEST;
4095 tev.dragrequest.drop_coords = coords;
4096 tev.dragrequest.requestor = dest;
4097 tev.dragrequest.u.allflags = 0;
4098 tev.dragrequest.u.flags.protocol_version = DND_PROTOCOL_VERSION;
4099 tev.dragrequest.isdrop = 1;
4101 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
4103 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
4104 if (wp->dnd_drag_accepted)
4106 tev.dragrequest.window = (GdkWindow *) wp;
4107 tev.dragrequest.u.flags.delete_data = wp->dnd_drag_destructive_op;
4108 tev.dragrequest.timestamp = gdk_dnd.last_drop_time;
4109 tev.dragrequest.data_type =
4110 gdk_atom_name(wp->dnd_drag_data_type);
4112 gdk_event_put(&tev);
4118 gdk_dnd_check_types (GdkWindow *window,
4121 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
4123 GdkEventDropEnter event;
4125 g_return_val_if_fail(window != NULL, 0);
4126 g_return_val_if_fail(xevent != NULL, 0);
4127 g_return_val_if_fail(xevent->type == ClientMessage, 0);
4128 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
4130 if(wp->dnd_drop_data_numtypesavail <= 0 ||
4131 !wp->dnd_drop_data_typesavail)
4134 for (i = 2; i <= 4; i++)
4136 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
4138 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
4139 return xevent->xclient.data.l[i];
4143 /* Now we get the extended type list if it's available */
4144 event.u.allflags = xevent->xclient.data.l[1];
4145 if (event.u.flags.extended_typelist)
4147 Atom *exttypes, realtype;
4148 gulong nitems, nbar;
4151 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
4152 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
4153 False, AnyPropertyType, &realtype, &realfmt,
4154 &nitems, &nbar, (unsigned char **) &exttypes)
4158 if (realfmt != (sizeof(Atom) * 8))
4160 g_warning("XdeTypelist property had format of %d instead of the expected %ld, on window %#lx\n",
4161 realfmt, (glong)sizeof(Atom) * 8, xevent->xclient.data.l[0]);
4165 for (i = 0; i <= nitems; i++)
4167 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
4169 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
4182 * used for debugging only
4186 gdk_print_atom (GdkAtom anatom)
4188 gchar *tmpstr = NULL;
4189 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
4190 g_message("Atom %lu has name %s", anatom, tmpstr);
4197 * used only by below routine and itself
4200 getchildren (Display *dpy,
4204 Window root, parent, *children, inf = 0;
4206 unsigned int nchildren, i;
4208 unsigned long nitems, after;
4209 unsigned char *data;
4211 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
4214 for (i = 0; !inf && (i < nchildren); i++)
4216 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
4217 AnyPropertyType, &type, &format, &nitems,
4224 for (i = 0; !inf && (i < nchildren); i++)
4225 inf = getchildren (dpy, children[i], WM_STATE);
4227 if (children != None)
4228 XFree ((char *) children);
4234 * find a window with WM_STATE, else return win itself, as per ICCCM
4236 * modification of the XmuClientWindow() routine from X11R6.3
4239 gdk_get_client_window (Display *dpy,
4245 unsigned long nitems, after;
4246 unsigned char *data;
4250 return DefaultRootWindow(dpy);
4252 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
4255 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
4256 &type, &format, &nitems, &after, &data);
4260 inf = getchildren (dpy, win, WM_STATE);
4268 #ifdef WE_HAVE_MOTIF_DROPS_DONE
4270 gdk_drop_get_real_window (GdkWindow *w,
4274 GdkWindow *retval = w;
4275 GdkWindowPrivate *awin;
4277 gint16 myx = *x, myy = *y;
4279 g_return_val_if_fail (w != NULL && x != NULL && y != NULL, NULL);
4285 for (children = gdk_window_get_children(retval);
4286 children && children->next;
4287 children = children->next)
4289 awin = (GdkWindowPrivate *) children->data;
4290 if ((myx >= awin->x) && (myy >= awin->y)
4291 && (myx < (awin->x + awin->width))
4292 && (myy < (awin->y + awin->height)))
4294 retval = (GdkWindow *) awin;
4308 /* Sends a ClientMessage to all toplevel client windows */
4310 gdk_event_send_clientmessage_toall (GdkEvent *event)
4313 Window *ret_children, ret_root, ret_parent, curwin;
4314 unsigned int ret_nchildren;
4317 g_return_if_fail(event != NULL);
4319 /* Set up our event to send, with the exception of its target window */
4320 sev.xclient.type = ClientMessage;
4321 sev.xclient.display = gdk_display;
4322 sev.xclient.format = event->client.data_format;
4323 sev.xclient.serial = CurrentTime;
4324 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
4325 sev.xclient.message_type = event->client.message_type;
4327 /* OK, we're all set, now let's find some windows to send this to */
4328 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
4329 &ret_children, &ret_nchildren) != True)
4332 /* foreach true child window of the root window, send an event to it */
4333 for(i = 0; i < ret_nchildren; i++) {
4334 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
4335 sev.xclient.window = curwin;
4336 if (!gdk_send_xevent (curwin, False, NoEventMask, &sev))
4337 GDK_NOTE (MISC, g_message ("Sending client message %ld to %#lx failed",
4338 event->client.message_type, curwin));
4341 XFree(ret_children);
4345 gdk_get_display(void)
4347 return (gchar *)XDisplayName (gdk_display_name);
4351 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
4358 gdk_error_warnings = 0;
4359 result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
4360 XSync (gdk_display, False);
4361 gdk_error_warnings = 1;
4363 return result && (gdk_error_code != -1);
4366 #ifndef HAVE_XCONVERTCASE
4367 /* compatibility function from X11R6.3, since XConvertCase is not
4368 * supplied by X11R5.
4371 gdkx_XConvertCase (KeySym symbol,
4375 register KeySym sym = symbol;
4377 g_return_if_fail (lower != NULL);
4378 g_return_if_fail (upper != NULL);
4385 #if defined (GDK_A) && defined (GDK_Ooblique)
4386 case 0: /* Latin 1 */
4387 if ((sym >= GDK_A) && (sym <= GDK_Z))
4388 *lower += (GDK_a - GDK_A);
4389 else if ((sym >= GDK_a) && (sym <= GDK_z))
4390 *upper -= (GDK_a - GDK_A);
4391 else if ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis))
4392 *lower += (GDK_agrave - GDK_Agrave);
4393 else if ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis))
4394 *upper -= (GDK_agrave - GDK_Agrave);
4395 else if ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn))
4396 *lower += (GDK_oslash - GDK_Ooblique);
4397 else if ((sym >= GDK_oslash) && (sym <= GDK_thorn))
4398 *upper -= (GDK_oslash - GDK_Ooblique);
4402 #if defined (GDK_Aogonek) && defined (GDK_tcedilla)
4403 case 1: /* Latin 2 */
4404 /* Assume the KeySym is a legal value (ignore discontinuities) */
4405 if (sym == GDK_Aogonek)
4406 *lower = GDK_aogonek;
4407 else if (sym >= GDK_Lstroke && sym <= GDK_Sacute)
4408 *lower += (GDK_lstroke - GDK_Lstroke);
4409 else if (sym >= GDK_Scaron && sym <= GDK_Zacute)
4410 *lower += (GDK_scaron - GDK_Scaron);
4411 else if (sym >= GDK_Zcaron && sym <= GDK_Zabovedot)
4412 *lower += (GDK_zcaron - GDK_Zcaron);
4413 else if (sym == GDK_aogonek)
4414 *upper = GDK_Aogonek;
4415 else if (sym >= GDK_lstroke && sym <= GDK_sacute)
4416 *upper -= (GDK_lstroke - GDK_Lstroke);
4417 else if (sym >= GDK_scaron && sym <= GDK_zacute)
4418 *upper -= (GDK_scaron - GDK_Scaron);
4419 else if (sym >= GDK_zcaron && sym <= GDK_zabovedot)
4420 *upper -= (GDK_zcaron - GDK_Zcaron);
4421 else if (sym >= GDK_Racute && sym <= GDK_Tcedilla)
4422 *lower += (GDK_racute - GDK_Racute);
4423 else if (sym >= GDK_racute && sym <= GDK_tcedilla)
4424 *upper -= (GDK_racute - GDK_Racute);
4428 #if defined (GDK_Hstroke) && defined (GDK_Cabovedot)
4429 case 2: /* Latin 3 */
4430 /* Assume the KeySym is a legal value (ignore discontinuities) */
4431 if (sym >= GDK_Hstroke && sym <= GDK_Hcircumflex)
4432 *lower += (GDK_hstroke - GDK_Hstroke);
4433 else if (sym >= GDK_Gbreve && sym <= GDK_Jcircumflex)
4434 *lower += (GDK_gbreve - GDK_Gbreve);
4435 else if (sym >= GDK_hstroke && sym <= GDK_hcircumflex)
4436 *upper -= (GDK_hstroke - GDK_Hstroke);
4437 else if (sym >= GDK_gbreve && sym <= GDK_jcircumflex)
4438 *upper -= (GDK_gbreve - GDK_Gbreve);
4439 else if (sym >= GDK_Cabovedot && sym <= GDK_Scircumflex)
4440 *lower += (GDK_cabovedot - GDK_Cabovedot);
4441 else if (sym >= GDK_cabovedot && sym <= GDK_scircumflex)
4442 *upper -= (GDK_cabovedot - GDK_Cabovedot);
4446 #if defined (GDK_Rcedilla) && defined (GDK_Amacron)
4447 case 3: /* Latin 4 */
4448 /* Assume the KeySym is a legal value (ignore discontinuities) */
4449 if (sym >= GDK_Rcedilla && sym <= GDK_Tslash)
4450 *lower += (GDK_rcedilla - GDK_Rcedilla);
4451 else if (sym >= GDK_rcedilla && sym <= GDK_tslash)
4452 *upper -= (GDK_rcedilla - GDK_Rcedilla);
4453 else if (sym == GDK_ENG)
4455 else if (sym == GDK_eng)
4457 else if (sym >= GDK_Amacron && sym <= GDK_Umacron)
4458 *lower += (GDK_amacron - GDK_Amacron);
4459 else if (sym >= GDK_amacron && sym <= GDK_umacron)
4460 *upper -= (GDK_amacron - GDK_Amacron);
4464 #if defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
4465 case 6: /* Cyrillic */
4466 /* Assume the KeySym is a legal value (ignore discontinuities) */
4467 if (sym >= GDK_Serbian_DJE && sym <= GDK_Serbian_DZE)
4468 *lower -= (GDK_Serbian_DJE - GDK_Serbian_dje);
4469 else if (sym >= GDK_Serbian_dje && sym <= GDK_Serbian_dze)
4470 *upper += (GDK_Serbian_DJE - GDK_Serbian_dje);
4471 else if (sym >= GDK_Cyrillic_YU && sym <= GDK_Cyrillic_HARDSIGN)
4472 *lower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
4473 else if (sym >= GDK_Cyrillic_yu && sym <= GDK_Cyrillic_hardsign)
4474 *upper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
4476 #endif /* CYRILLIC */
4478 #if defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
4480 /* Assume the KeySym is a legal value (ignore discontinuities) */
4481 if (sym >= GDK_Greek_ALPHAaccent && sym <= GDK_Greek_OMEGAaccent)
4482 *lower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
4483 else if (sym >= GDK_Greek_alphaaccent && sym <= GDK_Greek_omegaaccent &&
4484 sym != GDK_Greek_iotaaccentdieresis &&
4485 sym != GDK_Greek_upsilonaccentdieresis)
4486 *upper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
4487 else if (sym >= GDK_Greek_ALPHA && sym <= GDK_Greek_OMEGA)
4488 *lower += (GDK_Greek_alpha - GDK_Greek_ALPHA);
4489 else if (sym >= GDK_Greek_alpha && sym <= GDK_Greek_omega &&
4490 sym != GDK_Greek_finalsmallsigma)
4491 *upper -= (GDK_Greek_alpha - GDK_Greek_ALPHA);
4499 gdk_keyval_name (guint keyval)
4501 return XKeysymToString (keyval);
4505 gdk_keyval_from_name (const gchar *keyval_name)
4507 g_return_val_if_fail (keyval_name != NULL, 0);
4509 return XStringToKeysym (keyval_name);
4513 gdk_keyval_to_upper (guint keyval)
4517 KeySym lower_val = 0;
4518 KeySym upper_val = 0;
4520 XConvertCase (keyval, &lower_val, &upper_val);
4527 gdk_keyval_to_lower (guint keyval)
4531 KeySym lower_val = 0;
4532 KeySym upper_val = 0;
4534 XConvertCase (keyval, &lower_val, &upper_val);
4541 gdk_keyval_is_upper (guint keyval)
4545 KeySym lower_val = 0;
4546 KeySym upper_val = 0;
4548 XConvertCase (keyval, &lower_val, &upper_val);
4549 return upper_val == keyval;
4555 gdk_keyval_is_lower (guint keyval)
4559 KeySym lower_val = 0;
4560 KeySym upper_val = 0;
4562 XConvertCase (keyval, &lower_val, &upper_val);
4563 return lower_val == keyval;