1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "../config.h"
20 /* If you don't want to use gdk's signal handlers define this */
21 /* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */
23 #include <X11/Xlocale.h>
34 #ifdef HAVE_SYS_SELECT_H
35 #include <sys/select.h>
36 #endif /* HAVE_SYS_SELECT_H_ */
38 #define XLIB_ILLEGAL_ACCESS
39 #include <X11/Xatom.h>
42 #include <X11/Xutil.h>
43 #include <X11/Xmu/WinUtil.h>
45 #include <X11/Xresource.h>
47 #include <X11/cursorfont.h>
49 #include "gdkprivate.h"
53 #include "gdkkeysyms.h"
57 #ifndef X_GETTIMEOFDAY
58 #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
59 #endif /* X_GETTIMEOFDAY */
62 #define DOUBLE_CLICK_TIME 250
63 #define TRIPLE_CLICK_TIME 500
64 #define DOUBLE_CLICK_DIST 5
65 #define TRIPLE_CLICK_DIST 5
69 # define SELECT_MASK fd_set
75 # define SELECT_MASK void
77 # define SELECT_MASK int
82 typedef struct _GdkInput GdkInput;
83 typedef struct _GdkPredicate GdkPredicate;
89 GdkInputCondition condition;
90 GdkInputFunction function;
92 GdkDestroyNotify destroy;
102 * Private function declarations
105 static GdkEvent *gdk_event_new (void);
106 static gint gdk_event_wait (void);
107 static gint gdk_event_apply_filters (XEvent *xevent,
110 static gint gdk_event_translate (GdkEvent *event,
113 static Bool gdk_event_get_type (Display *display,
117 static void gdk_synthesize_click (GdkEvent *event,
120 static void gdk_dnd_drag_begin (GdkWindow *initial_window);
121 static void gdk_dnd_drag_enter (Window dest);
122 static void gdk_dnd_drag_leave (Window dest);
123 static void gdk_dnd_drag_end (Window dest,
125 static GdkAtom gdk_dnd_check_types (GdkWindow *window,
128 static void gdk_print_atom (GdkAtom anatom);
132 * old junk from offix, we might use it though so leave it
134 Window gdk_get_client_window (Display *dpy,
136 #ifdef WE_HAVE_MOTIF_DROPS_DONE
137 static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
141 static void gdk_exit_func (void);
142 static int gdk_x_error (Display *display,
144 static int gdk_x_io_error (Display *display);
145 static RETSIGTYPE gdk_signal (int signum);
149 static GdkIM gdk_im_get (void);
150 static gint gdk_im_open (XrmDatabase db,
153 static void gdk_im_close (void);
154 static void gdk_ic_cleanup (void);
157 /* Private variable declarations
159 static int initialized = 0; /* 1 if the library is initialized,
162 static int connection_number = 0; /* The file descriptor number of our
163 * connection to the X server. This
164 * is used so that we may determine
165 * when events are pending by using
166 * the "select" system call.
170 static struct timeval start; /* The time at which the library was
173 static struct timeval timer; /* Timeout interval to use in the call
174 * to "select". This is used in
175 * conjunction with "timerp" to create
176 * a maximum time to wait for an event
179 static struct timeval *timerp; /* The actual timer passed to "select"
180 * This may be NULL, in which case
181 * "select" will block until an event
184 static guint32 timer_val; /* The timeout length as specified by
185 * the user in milliseconds.
187 static GList *inputs; /* A list of the input file descriptors
188 * that we care about. Each list node
189 * contains a GdkInput struct that describes
190 * when we are interested in the specified
191 * file descriptor. That is, when it is
192 * available for read, write or has an
195 static guint32 button_click_time[2]; /* The last 2 button click times. Used
196 * to determine if the latest button click
197 * is part of a double or triple click.
199 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
200 * Also used to determine if the latest button
201 * click is part of a double or triple click.
203 static guint button_number[2]; /* The last 2 buttons to be pressed.
205 static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds the
210 static gint xim_using; /* using XIM Protocol if TRUE */
211 static GdkIM xim_im; /* global IM */
212 static XIMStyles* xim_styles; /* im supports these styles */
213 static XIMStyle xim_best_allowed_style;
214 static GdkICPrivate *xim_ic; /* currently using IC */
215 static GdkWindow* xim_window; /* currently using Widow */
216 static GList* xim_ic_list;
220 #define OTHER_XEVENT_BUFSIZE 4
221 static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
222 static int other_xevent_i = 0;
223 static GList *putback_events = NULL;
225 static gulong base_id;
226 static gint autorepeat;
228 #ifdef G_ENABLE_DEBUG
229 static GDebugKey gdk_debug_keys[] = {
230 {"events", GDK_DEBUG_EVENTS},
231 {"misc", GDK_DEBUG_MISC},
232 {"dnd", GDK_DEBUG_DND},
233 {"color-context", GDK_DEBUG_COLOR_CONTEXT},
234 {"xim", GDK_DEBUG_XIM}
236 #endif /* G_ENABLE_DEBUG */
239 *--------------------------------------------------------------
242 * Initialize the library for use.
245 * "argc" is the number of arguments.
246 * "argv" is an array of strings.
249 * "argc" and "argv" are modified to reflect any arguments
250 * which were not handled. (Such arguments should either
251 * be handled by the application or dismissed).
254 * The library is initialized.
256 *--------------------------------------------------------------
263 XKeyboardState keyboard_state;
266 XClassHint *class_hint;
267 int argc_orig = *argc;
270 gboolean debug_set = FALSE;
272 argv_orig = malloc ((argc_orig + 1) * sizeof (char*));
273 for (i = 0; i < argc_orig; i++)
274 argv_orig[i] = g_strdup ((*argv)[i]);
275 argv_orig[argc_orig] = NULL;
277 X_GETTIMEOFDAY (&start);
279 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
280 signal (SIGHUP, gdk_signal);
281 signal (SIGINT, gdk_signal);
282 signal (SIGQUIT, gdk_signal);
283 signal (SIGBUS, gdk_signal);
284 signal (SIGSEGV, gdk_signal);
285 signal (SIGPIPE, gdk_signal);
286 signal (SIGTERM, gdk_signal);
289 gdk_display_name = NULL;
291 XSetErrorHandler (gdk_x_error);
292 XSetIOErrorHandler (gdk_x_io_error);
299 gdk_progname = (*argv)[0];
301 for (i = 1; i < *argc;)
303 if ((*argv)[i] == NULL)
306 #ifdef G_ENABLE_DEBUG
307 if (strcmp ("--gdk-debug", (*argv)[i]) == 0)
311 if ((i + 1) < *argc && (*argv)[i + 1])
313 gdk_debug_flags = g_parse_debug_string ((*argv)[i+1],
315 sizeof(gdk_debug_keys) / sizeof(GDebugKey));
317 (*argv)[i + 1] = NULL;
321 #endif G_ENABLE_DEBUG
322 else if (strcmp ("--display", (*argv)[i]) == 0)
326 if ((i + 1) < *argc && (*argv)[i + 1])
328 gdk_display_name = g_strdup ((*argv)[i + 1]);
329 (*argv)[i + 1] = NULL;
333 else if (strcmp ("--sync", (*argv)[i]) == 0)
338 else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
341 gdk_use_xshm = FALSE;
343 else if (strcmp ("--name", (*argv)[i]) == 0)
345 if ((i + 1) < *argc && (*argv)[i + 1])
348 gdk_progname = (*argv)[i];
352 else if (strcmp ("--class", (*argv)[i]) == 0)
354 if ((i + 1) < *argc && (*argv)[i + 1])
357 gdk_progclass = (*argv)[i];
362 else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
364 if ((i + 1) < *argc && (*argv)[i + 1])
367 gdk_input_gxid_host = ((*argv)[i]);
371 else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
373 if ((i + 1) < *argc && (*argv)[i + 1])
376 gdk_input_gxid_port = atoi ((*argv)[i]);
382 else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
384 if ((i + 1) < *argc && (*argv)[i + 1])
387 if (strcmp ("none", (*argv)[i]) == 0)
388 gdk_im_set_best_style (GdkIMPreeditNone);
389 else if (strcmp ("nothing", (*argv)[i]) == 0)
390 gdk_im_set_best_style (GdkIMPreeditNothing);
391 else if (strcmp ("area", (*argv)[i]) == 0)
392 gdk_im_set_best_style (GdkIMPreeditArea);
393 else if (strcmp ("position", (*argv)[i]) == 0)
394 gdk_im_set_best_style (GdkIMPreeditPosition);
395 else if (strcmp ("callbacks", (*argv)[i]) == 0)
396 gdk_im_set_best_style (GdkIMPreeditCallbacks);
399 else if (strcmp ("--xim-status", (*argv)[i]) == 0)
401 if ((i + 1) < *argc && (*argv)[i + 1])
404 if (strcmp ("none", (*argv)[i]) == 0)
405 gdk_im_set_best_style (GdkIMStatusNone);
406 else if (strcmp ("nothing", (*argv)[i]) == 0)
407 gdk_im_set_best_style (GdkIMStatusNothing);
408 else if (strcmp ("area", (*argv)[i]) == 0)
409 gdk_im_set_best_style (GdkIMStatusArea);
410 else if (strcmp ("callbacks", (*argv)[i]) == 0)
411 gdk_im_set_best_style (GdkIMStatusCallbacks);
419 for (i = 1; i < *argc; i++)
421 for (k = i; k < *argc; k++)
422 if ((*argv)[k] != NULL)
428 for (j = i + k; j < *argc; j++)
429 (*argv)[j-k] = (*argv)[j];
436 gdk_progname = "<unknown>";
441 gchar *debug_string = getenv("GDK_DEBUG");
442 if (debug_string != NULL)
443 gdk_debug_flags = g_parse_debug_string (debug_string,
445 sizeof(gdk_debug_keys) / sizeof(GDebugKey));
448 gdk_display = XOpenDisplay (gdk_display_name);
451 g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
455 /* This is really crappy. We have to look into the display structure
456 * to find the base resource id. This is only needed for recording
457 * and playback of events.
459 /* base_id = RESOURCE_BASE; */
461 GDK_NOTE (EVENTS, g_print ("base id: %lu\n", base_id));
463 connection_number = ConnectionNumber (gdk_display);
465 g_print ("connection number: %d\n", connection_number));
468 XSynchronize (gdk_display, True);
470 gdk_screen = DefaultScreen (gdk_display);
471 gdk_root_window = RootWindow (gdk_display, gdk_screen);
473 gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
474 10, 10, 10, 10, 0, 0 , 0);
475 class_hint = XAllocClassHint();
476 class_hint->res_name = gdk_progname;
477 if (gdk_progclass == NULL)
479 gdk_progclass = g_strdup (gdk_progname);
480 gdk_progclass[0] = toupper (gdk_progclass[0]);
482 class_hint->res_class = gdk_progclass;
483 XSetClassHint(gdk_display, gdk_leader_window, class_hint);
484 XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
487 gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
488 gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
489 gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
490 gdk_wm_window_protocols[0] = gdk_wm_delete_window;
491 gdk_wm_window_protocols[1] = gdk_wm_take_focus;
492 gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
494 gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
495 gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
496 gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
497 gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
498 gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
499 gdk_dnd.gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
500 gdk_dnd.gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
502 XGetKeyboardControl (gdk_display, &keyboard_state);
503 autorepeat = keyboard_state.global_auto_repeat;
509 button_click_time[0] = 0;
510 button_click_time[1] = 0;
511 button_window[0] = NULL;
512 button_window[1] = NULL;
513 button_number[0] = -1;
514 button_number[1] = -1;
516 if (ATEXIT (gdk_exit_func))
517 g_warning ("unable to register exit function");
525 /* initialize XIM Protocol variables */
529 if (!(xim_best_allowed_style & GdkIMPreeditMask))
530 gdk_im_set_best_style (GdkIMPreeditCallbacks);
531 if (!(xim_best_allowed_style & GdkIMStatusMask))
532 gdk_im_set_best_style (GdkIMStatusCallbacks);
534 xim_window = (GdkWindow*)NULL;
536 gdk_im_open (NULL, NULL, NULL);
537 if (gdk_im_get () == NULL)
538 g_warning ("unable to open input method.");
545 *--------------------------------------------------------------
548 * Restores the library to an un-itialized state and exits
549 * the program using the "exit" system call.
552 * "errorcode" is the error value to pass to "exit".
555 * Allocated structures are freed and the program exits
560 *--------------------------------------------------------------
564 gdk_exit (int errorcode)
566 /* de-initialisation is done by the gdk_exit_funct(),
567 no need to do this here (Alex J.) */
572 *--------------------------------------------------------------
581 *--------------------------------------------------------------
587 if (!setlocale (LC_ALL,""))
588 g_print ("locale not supported by C library\n");
590 if (!XSupportsLocale ())
592 g_print ("locale not supported by Xlib, locale set to C\n");
593 setlocale (LC_ALL, "C");
596 if (!XSetLocaleModifiers (""))
598 g_print ("can not set locale modifiers\n");
601 return setlocale (LC_ALL,NULL);
605 *--------------------------------------------------------------
608 * Returns the number of events pending on the queue.
609 * These events have already been read from the server
615 * Returns the number of events on XLib's event queue.
619 *--------------------------------------------------------------
623 gdk_events_pending ()
628 result = XPending (gdk_display);
630 tmp_list = putback_events;
634 tmp_list = tmp_list->next;
641 *--------------------------------------------------------------
642 * gdk_event_get_graphics_expose
644 * Waits for a GraphicsExpose or NoExpose event
649 * For GraphicsExpose events, returns a pointer to the event
650 * converted into a GdkEvent Otherwise, returns NULL.
654 *-------------------------------------------------------------- */
657 graphics_expose_predicate (Display *display,
661 GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
663 g_return_val_if_fail (private != NULL, False);
665 if ((xevent->xany.window == private->xwindow) &&
666 ((xevent->xany.type == GraphicsExpose) ||
667 (xevent->xany.type == NoExpose)))
674 gdk_event_get_graphics_expose (GdkWindow *window)
679 g_return_val_if_fail (window != NULL, NULL);
681 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
683 if (xevent.xany.type == GraphicsExpose)
685 event = gdk_event_new ();
687 if (gdk_event_translate (event, &xevent))
690 gdk_event_free (event);
697 *--------------------------------------------------------------
700 * Gets the next event.
705 * If an event was received that we care about, returns
706 * a pointer to that event, to be freed with gdk_event_free.
707 * Otherwise, returns NULL. This function will also return
708 * before an event is received if the timeout interval
713 *--------------------------------------------------------------
726 temp_list = putback_events;
729 temp_event = temp_list->data;
731 if ((* pred) (temp_event, data))
734 *event = *temp_event;
735 putback_events = g_list_remove_link (putback_events, temp_list);
736 g_list_free (temp_list);
740 temp_list = temp_list->next;
743 event_pred.func = pred;
744 event_pred.data = data;
746 if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
748 return gdk_event_translate (event, &xevent);
754 event = putback_events->data;
756 temp_list = putback_events;
757 putback_events = g_list_remove_link (putback_events, temp_list);
758 g_list_free_1 (temp_list);
763 /* Wait for an event to occur or the timeout to elapse.
764 * If an event occurs "gdk_event_wait" will return TRUE.
765 * If the timeout elapses "gdk_event_wait" will return
768 if (gdk_event_wait ())
770 /* If we get here we can rest assurred that an event
771 * has occurred. Read it.
775 if (xim_using && xim_window)
777 { /* don't dispatch events used by IM */
778 XNextEvent (gdk_display, &xevent);
779 filter_status = XFilterEvent (&xevent,
780 GDK_WINDOW_XWINDOW (xim_window));
781 } while (filter_status == True);
783 XNextEvent (gdk_display, &xevent);
785 XNextEvent (gdk_display, &xevent);
787 event = gdk_event_new ();
789 event->any.type = GDK_NOTHING;
790 event->any.window = NULL;
791 event->any.send_event = FALSE;
792 event->any.send_event = xevent.xany.send_event;
794 if (gdk_event_translate (event, &xevent))
797 gdk_event_free (event);
804 gdk_event_put (GdkEvent *event)
808 g_return_if_fail (event != NULL);
810 new_event = gdk_event_copy (event);
812 putback_events = g_list_prepend (putback_events, new_event);
816 *--------------------------------------------------------------
819 * Copy a event structure into new storage.
822 * "event" is the event struct to copy.
825 * A new event structure. Free it with gdk_event_free.
828 * The reference count of the window in the event is increased.
830 *--------------------------------------------------------------
833 static GMemChunk *event_chunk;
840 if (event_chunk == NULL)
841 event_chunk = g_mem_chunk_new ("events",
846 new_event = g_chunk_new (GdkEvent, event_chunk);
852 gdk_event_copy (GdkEvent *event)
856 g_return_val_if_fail (event != NULL, NULL);
858 new_event = gdk_event_new ();
861 gdk_window_ref (new_event->any.window);
863 switch (event->any.type)
866 case GDK_KEY_RELEASE:
867 new_event->key.string = g_strdup (event->key.string);
870 case GDK_ENTER_NOTIFY:
871 case GDK_LEAVE_NOTIFY:
872 if (event->crossing.subwindow != NULL)
873 gdk_window_ref (event->crossing.subwindow);
876 case GDK_DROP_DATA_AVAIL:
877 new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
878 new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
879 memcpy (new_event->dropdataavailable.data,
880 event->dropdataavailable.data,
881 event->dropdataavailable.data_numbytes);
892 *--------------------------------------------------------------
895 * Free a event structure obtained from gdk_event_copy. Do not use
896 * with other event structures.
899 * "event" is the event struct to free.
904 * The reference count of the window in the event is decreased and
905 * might be freed, too.
907 *-------------------------------------------------------------- */
910 gdk_event_free (GdkEvent *event)
912 g_assert (event_chunk != NULL);
913 g_return_if_fail (event != NULL);
915 if (event->any.window)
916 gdk_window_unref (event->any.window);
918 switch (event->any.type)
921 case GDK_KEY_RELEASE:
922 g_free (event->key.string);
925 case GDK_ENTER_NOTIFY:
926 case GDK_LEAVE_NOTIFY:
927 if (event->crossing.subwindow != NULL)
928 gdk_window_unref (event->crossing.subwindow);
931 case GDK_DROP_DATA_AVAIL:
932 g_free (event->dropdataavailable.data_type);
933 g_free (event->dropdataavailable.data);
936 case GDK_DRAG_REQUEST:
937 g_free (event->dragrequest.data_type);
944 g_mem_chunk_free (event_chunk, event);
948 *--------------------------------------------------------------
949 * gdk_set_show_events
951 * Turns on/off the showing of events.
954 * "show_events" is a boolean describing whether or
955 * not to show the events gdk receives.
960 * When "show_events" is TRUE, calls to "gdk_event_get"
961 * will output debugging informatin regarding the event
962 * received to stdout.
964 *--------------------------------------------------------------
968 gdk_set_show_events (int show_events)
971 gdk_debug_flags |= GDK_DEBUG_EVENTS;
973 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
977 gdk_set_use_xshm (gint use_xshm)
979 gdk_use_xshm = use_xshm;
983 gdk_get_show_events ()
985 return gdk_debug_flags & GDK_DEBUG_EVENTS;
995 *--------------------------------------------------------------
998 * Get the number of milliseconds since the library was
1004 * The time since the library was initialized is returned.
1005 * This time value is accurate to milliseconds even though
1006 * a more accurate time down to the microsecond could be
1011 *--------------------------------------------------------------
1018 struct timeval elapsed;
1019 guint32 milliseconds;
1021 X_GETTIMEOFDAY (&end);
1023 if (start.tv_usec > end.tv_usec)
1025 end.tv_usec += 1000000;
1028 elapsed.tv_sec = end.tv_sec - start.tv_sec;
1029 elapsed.tv_usec = end.tv_usec - start.tv_usec;
1031 milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1033 return milliseconds;
1037 *--------------------------------------------------------------
1040 * Returns the current timer.
1045 * Returns the current timer interval. This interval is
1046 * in units of milliseconds.
1050 *--------------------------------------------------------------
1060 *--------------------------------------------------------------
1063 * Sets the timer interval.
1066 * "milliseconds" is the new value for the timer.
1071 * Calls to "gdk_event_get" will last for a maximum
1072 * of time of "milliseconds". However, a value of 0
1073 * milliseconds will cause "gdk_event_get" to block
1074 * indefinately until an event is received.
1076 *--------------------------------------------------------------
1080 gdk_timer_set (guint32 milliseconds)
1082 timer_val = milliseconds;
1083 timer.tv_sec = milliseconds / 1000;
1084 timer.tv_usec = (milliseconds % 1000) * 1000;
1095 gdk_timer_disable ()
1101 gdk_input_add_full (gint source,
1102 GdkInputCondition condition,
1103 GdkInputFunction function,
1105 GdkDestroyNotify destroy)
1107 static gint next_tag = 1;
1120 if ((input->source == source) && (input->condition == condition))
1123 (input->destroy) (input->data);
1124 input->function = function;
1126 input->destroy = destroy;
1133 input = g_new (GdkInput, 1);
1134 input->tag = next_tag++;
1135 input->source = source;
1136 input->condition = condition;
1137 input->function = function;
1139 input->destroy = destroy;
1142 inputs = g_list_prepend (inputs, input);
1149 gdk_input_add (gint source,
1150 GdkInputCondition condition,
1151 GdkInputFunction function,
1154 return gdk_input_add_interp (source, condition, function, data, NULL);
1158 gdk_input_remove (gint tag)
1169 if (input->tag == tag)
1172 (input->destroy) (input->data);
1177 list->next->prev = list->prev;
1179 list->prev->next = list->next;
1181 inputs = list->next;
1183 temp_list->next = NULL;
1184 temp_list->prev = NULL;
1186 g_free (temp_list->data);
1187 g_list_free (temp_list);
1196 *--------------------------------------------------------------
1199 * Grabs the pointer to a specific window
1202 * "window" is the window which will receive the grab
1203 * "owner_events" specifies whether events will be reported as is,
1204 * or relative to "window"
1205 * "event_mask" masks only interesting events
1206 * "confine_to" limits the cursor movement to the specified window
1207 * "cursor" changes the cursor for the duration of the grab
1208 * "time" specifies the time
1213 * requires a corresponding call to gdk_pointer_ungrab
1215 *--------------------------------------------------------------
1219 gdk_pointer_grab (GdkWindow * window,
1221 GdkEventMask event_mask,
1222 GdkWindow * confine_to,
1226 /* From gdkwindow.c */
1227 extern int nevent_masks;
1228 extern int event_mask_table[];
1231 GdkWindowPrivate *window_private;
1232 GdkWindowPrivate *confine_to_private;
1233 GdkCursorPrivate *cursor_private;
1240 g_return_val_if_fail (window != NULL, 0);
1242 window_private = (GdkWindowPrivate*) window;
1243 confine_to_private = (GdkWindowPrivate*) confine_to;
1244 cursor_private = (GdkCursorPrivate*) cursor;
1246 xwindow = window_private->xwindow;
1248 if (!confine_to || confine_to_private->destroyed)
1251 xconfine_to = confine_to_private->xwindow;
1256 xcursor = cursor_private->xcursor;
1260 for (i = 0; i < nevent_masks; i++)
1262 if (event_mask & (1 << (i + 1)))
1263 xevent_mask |= event_mask_table[i];
1266 if (((GdkWindowPrivate *)window)->extension_events &&
1267 gdk_input_vtable.grab_pointer)
1268 return_val = gdk_input_vtable.grab_pointer (window,
1274 return_val = Success;
1276 if (return_val == Success)
1278 if (!window_private->destroyed)
1279 return_val = XGrabPointer (window_private->xdisplay,
1283 GrabModeAsync, GrabModeAsync,
1288 return_val = AlreadyGrabbed;
1291 if (return_val == GrabSuccess)
1292 xgrab_window = window_private;
1298 *--------------------------------------------------------------
1299 * gdk_pointer_ungrab
1301 * Releases any pointer grab
1309 *--------------------------------------------------------------
1313 gdk_pointer_ungrab (guint32 time)
1315 if (gdk_input_vtable.ungrab_pointer)
1316 gdk_input_vtable.ungrab_pointer (time);
1318 XUngrabPointer (gdk_display, time);
1319 xgrab_window = NULL;
1323 *--------------------------------------------------------------
1324 * gdk_pointer_is_grabbed
1326 * Tell wether there is an active x pointer grab in effect
1334 *--------------------------------------------------------------
1338 gdk_pointer_is_grabbed (void)
1340 return xgrab_window != NULL;
1344 *--------------------------------------------------------------
1347 * Grabs the keyboard to a specific window
1350 * "window" is the window which will receive the grab
1351 * "owner_events" specifies whether events will be reported as is,
1352 * or relative to "window"
1353 * "time" specifies the time
1358 * requires a corresponding call to gdk_keyboard_ungrab
1360 *--------------------------------------------------------------
1364 gdk_keyboard_grab (GdkWindow * window,
1368 GdkWindowPrivate *window_private;
1371 g_return_val_if_fail (window != NULL, 0);
1373 window_private = (GdkWindowPrivate*) window;
1374 xwindow = window_private->xwindow;
1376 if (!window_private->destroyed)
1377 return XGrabKeyboard (window_private->xdisplay,
1380 GrabModeAsync, GrabModeAsync,
1383 return AlreadyGrabbed;
1387 *--------------------------------------------------------------
1388 * gdk_keyboard_ungrab
1390 * Releases any keyboard grab
1398 *--------------------------------------------------------------
1402 gdk_keyboard_ungrab (guint32 time)
1404 XUngrabKeyboard (gdk_display, time);
1408 *--------------------------------------------------------------
1411 * Return the width of the screen.
1419 *--------------------------------------------------------------
1427 return_val = DisplayWidth (gdk_display, gdk_screen);
1433 *--------------------------------------------------------------
1436 * Return the height of the screen.
1444 *--------------------------------------------------------------
1448 gdk_screen_height ()
1452 return_val = DisplayHeight (gdk_display, gdk_screen);
1458 gdk_key_repeat_disable ()
1460 XAutoRepeatOff (gdk_display);
1464 gdk_key_repeat_restore ()
1467 XAutoRepeatOn (gdk_display);
1469 XAutoRepeatOff (gdk_display);
1474 *--------------------------------------------------------------
1477 * Flushes the Xlib output buffer and then waits
1478 * until all requests have been received and processed
1479 * by the X server. The only real use for this function
1480 * is in dealing with XShm.
1488 *--------------------------------------------------------------
1493 XSync (gdk_display, False);
1500 XBell(gdk_display, 100);
1505 *--------------------------------------------------------------
1508 * Waits until an event occurs or the timer runs out.
1513 * Returns TRUE if an event is ready to be read and FALSE
1514 * if the timer ran out.
1518 *--------------------------------------------------------------
1526 GdkInputCondition condition;
1527 SELECT_MASK readfds;
1528 SELECT_MASK writefds;
1529 SELECT_MASK exceptfds;
1533 /* If there are no events pending we will wait for an event.
1534 * The time we wait is dependant on the "timer". If no timer
1535 * has been specified then we'll block until an event arrives.
1536 * If a timer has been specified we'll block until an event
1537 * arrives or the timer expires. (This is all done using the
1538 * "select" system call).
1541 if (XPending (gdk_display) == 0)
1544 FD_ZERO (&writefds);
1545 FD_ZERO (&exceptfds);
1547 FD_SET (connection_number, &readfds);
1548 max_input = connection_number;
1556 if (input->condition & GDK_INPUT_READ)
1557 FD_SET (input->source, &readfds);
1558 if (input->condition & GDK_INPUT_WRITE)
1559 FD_SET (input->source, &writefds);
1560 if (input->condition & GDK_INPUT_EXCEPTION)
1561 FD_SET (input->source, &exceptfds);
1563 max_input = MAX (max_input, input->source);
1566 nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1573 if (FD_ISSET (connection_number, &readfds))
1575 if (XPending (gdk_display) == 0)
1579 XNoOp (gdk_display);
1580 XFlush (gdk_display);
1595 if (FD_ISSET (input->source, &readfds))
1596 condition |= GDK_INPUT_READ;
1597 if (FD_ISSET (input->source, &writefds))
1598 condition |= GDK_INPUT_WRITE;
1599 if (FD_ISSET (input->source, &exceptfds))
1600 condition |= GDK_INPUT_EXCEPTION;
1602 if (condition && input->function)
1603 (* input->function) (input->data, input->source, condition);
1614 gdk_event_apply_filters (XEvent *xevent,
1618 GdkEventFilter *filter;
1620 GdkFilterReturn result;
1626 filter = (GdkEventFilter *)tmp_list->data;
1628 result = (*filter->function)(xevent, event, filter->data);
1629 if (result != GDK_FILTER_CONTINUE)
1632 tmp_list = tmp_list->next;
1635 return GDK_FILTER_CONTINUE;
1639 gdk_event_translate (GdkEvent *event,
1644 GdkWindowPrivate *window_private;
1645 XComposeStatus compose;
1648 static gchar* buf = NULL;
1649 static gint buf_len= 0;
1655 /* Are static variables used for this purpose thread-safe? */
1656 static GdkPoint dnd_drag_start = {0,0},
1657 dnd_drag_oldpos = {0,0};
1658 static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
1659 static gint dnd_drag_perhaps = 0;
1660 static gboolean dnd_grabbed = FALSE;
1661 static GdkWindowPrivate *real_sw = NULL;
1662 static Window dnd_drag_curwin = None, dnd_drag_target = None;
1666 /* Find the GdkWindow that this event occurred in.
1667 * All events occur in some GdkWindow (otherwise, why
1668 * would we be receiving them). It really is an error
1669 * to receive an event for which we cannot find the
1670 * corresponding GdkWindow. We handle events with window=None
1671 * specially - they are generated by XFree86's XInput under
1672 * some circumstances.
1675 if ((xevent->xany.window == None) &&
1676 gdk_input_vtable.window_none_event)
1678 return_val = gdk_input_vtable.window_none_event (event,xevent);
1680 if (return_val >= 0) /* was handled */
1686 window = gdk_window_lookup (xevent->xany.window);
1687 window_private = (GdkWindowPrivate *) window;
1690 g_warning ("%#lx -> NULL\n", xevent->xany.window);
1692 gdk_window_ref (window);
1695 /* Check for filters for this window */
1699 GdkFilterReturn result;
1700 result = gdk_event_apply_filters (xevent, event, window_private->filters);
1702 if (result != GDK_FILTER_CONTINUE)
1704 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1708 /* We do a "manual" conversion of the XEvent to a
1709 * GdkEvent. The structures are mostly the same so
1710 * the conversion is fairly straightforward. We also
1711 * optionally print debugging info regarding events
1715 * During drag & drop you get events where the pointer is
1716 * in other windows. Need to just do finer-grained checking
1718 switch (xevent->type)
1721 /* Lookup the string corresponding to the given keysym.
1727 buf = g_new (gchar, buf_len);
1729 if (xim_using == TRUE && xim_ic)
1733 /* Clear keyval. Depending on status, may not be set */
1734 event->key.keyval = GDK_VoidSymbol;
1735 charcount = XmbLookupString(xim_ic->xic,
1736 &xevent->xkey, buf, buf_len-1,
1737 (KeySym*) &event->key.keyval,
1739 if (status == XBufferOverflow)
1741 /* alloc adequate size of buffer */
1743 g_print("XIM: overflow (required %i)\n", charcount));
1745 while (buf_len <= charcount)
1747 buf = (gchar *) g_realloc (buf, buf_len);
1749 charcount = XmbLookupString (xim_ic->xic,
1750 &xevent->xkey, buf, buf_len-1,
1751 (KeySym*) &event->key.keyval,
1754 if (status == XLookupNone)
1761 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1762 (KeySym*) &event->key.keyval,
1765 charcount = XLookupString (&xevent->xkey, buf, 16,
1766 (KeySym*) &event->key.keyval,
1769 if (charcount > 0 && buf[charcount-1] == '\0')
1772 buf[charcount] = '\0';
1774 /* Print debugging info.
1776 #ifdef G_ENABLE_DEBUG
1777 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1779 g_print ("key press:\twindow: %ld key: %12s %d\n",
1780 xevent->xkey.window - base_id,
1781 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1784 g_print ("\t\tlength: %4d string: \"%s\"\n",
1787 #endif /* G_ENABLE_DEBUG */
1789 event->key.type = GDK_KEY_PRESS;
1790 event->key.window = window;
1791 event->key.time = xevent->xkey.time;
1792 event->key.state = (GdkModifierType) xevent->xkey.state;
1793 event->key.string = g_strdup (buf);
1794 event->key.length = charcount;
1796 return_val = window_private && !window_private->destroyed;
1799 g_free (event->key.string);
1804 /* Lookup the string corresponding to the given keysym.
1806 charcount = XLookupString (&xevent->xkey, buf, 16,
1807 (KeySym*) &event->key.keyval,
1810 /* Print debugging info.
1813 g_print ("key release:\t\twindow: %ld key: %12s %d\n",
1814 xevent->xkey.window - base_id,
1815 XKeysymToString (event->key.keyval),
1816 event->key.keyval));
1818 event->key.type = GDK_KEY_RELEASE;
1819 event->key.window = window;
1820 event->key.time = xevent->xkey.time;
1821 event->key.state = (GdkModifierType) xevent->xkey.state;
1822 event->key.length = 0;
1823 event->key.string = NULL;
1825 return_val = window_private && !window_private->destroyed;
1829 /* Print debugging info.
1832 g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
1833 window_private?window_private->dnd_drag_enabled:0,
1834 xevent->xbutton.window - base_id,
1835 xevent->xbutton.x, xevent->xbutton.y,
1836 xevent->xbutton.button));
1838 if (window_private &&
1839 (window_private->extension_events != 0) &&
1840 gdk_input_ignore_core)
1843 event->button.type = GDK_BUTTON_PRESS;
1844 event->button.window = window;
1845 event->button.time = xevent->xbutton.time;
1846 event->button.x = xevent->xbutton.x;
1847 event->button.y = xevent->xbutton.y;
1848 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1849 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1850 event->button.pressure = 0.5;
1851 event->button.xtilt = 0;
1852 event->button.ytilt = 0;
1853 event->button.state = (GdkModifierType) xevent->xbutton.state;
1854 event->button.button = xevent->xbutton.button;
1855 event->button.source = GDK_SOURCE_MOUSE;
1856 event->button.deviceid = GDK_CORE_POINTER;
1858 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1859 (event->button.window == button_window[1]) &&
1860 (event->button.button == button_number[1]))
1862 gdk_synthesize_click (event, 3);
1864 button_click_time[1] = 0;
1865 button_click_time[0] = 0;
1866 button_window[1] = NULL;
1867 button_window[0] = 0;
1868 button_number[1] = -1;
1869 button_number[0] = -1;
1871 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1872 (event->button.window == button_window[0]) &&
1873 (event->button.button == button_number[0]))
1875 gdk_synthesize_click (event, 2);
1877 button_click_time[1] = button_click_time[0];
1878 button_click_time[0] = event->button.time;
1879 button_window[1] = button_window[0];
1880 button_window[0] = event->button.window;
1881 button_number[1] = button_number[0];
1882 button_number[0] = event->button.button;
1886 button_click_time[1] = 0;
1887 button_click_time[0] = event->button.time;
1888 button_window[1] = NULL;
1889 button_window[0] = event->button.window;
1890 button_number[1] = -1;
1891 button_number[0] = event->button.button;
1894 && window_private->dnd_drag_enabled
1895 && !dnd_drag_perhaps
1896 && !gdk_dnd.drag_really)
1898 dnd_drag_perhaps = 1;
1899 dnd_drag_start.x = xevent->xbutton.x_root;
1900 dnd_drag_start.y = xevent->xbutton.y_root;
1901 real_sw = window_private;
1903 if(gdk_dnd.drag_startwindows)
1905 g_free(gdk_dnd.drag_startwindows);
1906 gdk_dnd.drag_startwindows = NULL;
1908 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1909 dnd_grabbed = FALSE;
1912 /* Set motion mask for first DnD'd window, since it
1913 will be the one that is actually dragged */
1914 XWindowAttributes dnd_winattr;
1915 XSetWindowAttributes dnd_setwinattr;
1917 /* We need to get motion events while the button is down, so
1918 we can know whether to really start dragging or not... */
1919 XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1922 window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1923 dnd_setwinattr.event_mask =
1924 window_private->dnd_drag_eventmask = ButtonMotionMask | EnterWindowMask | LeaveWindowMask;
1925 XChangeWindowAttributes(gdk_display, window_private->xwindow,
1926 CWEventMask, &dnd_setwinattr);
1929 return_val = window_private && !window_private->destroyed;
1933 /* Print debugging info.
1936 g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
1937 window_private?window_private->dnd_drag_enabled:0,
1938 xevent->xbutton.window - base_id,
1939 xevent->xbutton.x, xevent->xbutton.y,
1940 xevent->xbutton.button));
1942 if (window_private &&
1943 (window_private->extension_events != 0) &&
1944 gdk_input_ignore_core)
1947 event->button.type = GDK_BUTTON_RELEASE;
1948 event->button.window = window;
1949 event->button.time = xevent->xbutton.time;
1950 event->button.x = xevent->xbutton.x;
1951 event->button.y = xevent->xbutton.y;
1952 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1953 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1954 event->button.pressure = 0.5;
1955 event->button.xtilt = 0;
1956 event->button.ytilt = 0;
1957 event->button.state = (GdkModifierType) xevent->xbutton.state;
1958 event->button.button = xevent->xbutton.button;
1959 event->button.source = GDK_SOURCE_MOUSE;
1960 event->button.deviceid = GDK_CORE_POINTER;
1962 if(dnd_drag_perhaps)
1965 XSetWindowAttributes attrs;
1966 /* Reset event mask to pre-drag value, assuming event_mask
1967 doesn't change during drag */
1968 attrs.event_mask = real_sw->dnd_drag_savedeventmask;
1969 XChangeWindowAttributes(gdk_display, real_sw->xwindow,
1970 CWEventMask, &attrs);
1975 XUngrabPointer(gdk_display, CurrentTime);
1976 dnd_grabbed = FALSE;
1979 if(gdk_dnd.drag_really)
1982 foo.x = xevent->xbutton.x_root;
1983 foo.y = xevent->xbutton.y_root;
1985 if(dnd_drag_target != None)
1986 gdk_dnd_drag_end(dnd_drag_target, foo);
1987 gdk_dnd.drag_really = 0;
1989 gdk_dnd.drag_numwindows = 0;
1990 if(gdk_dnd.drag_startwindows)
1992 g_free(gdk_dnd.drag_startwindows);
1993 gdk_dnd.drag_startwindows = NULL;
1999 dnd_drag_perhaps = 0;
2000 dnd_drag_start.x = dnd_drag_start.y = 0;
2001 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2002 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2003 dnd_drag_curwin = None;
2004 return_val = window_private?TRUE:FALSE;
2006 return_val = window_private && !window_private->destroyed;
2010 /* Print debugging info.
2013 g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
2014 xevent->xmotion.window - base_id,
2015 xevent->xmotion.x, xevent->xmotion.y,
2016 (xevent->xmotion.is_hint) ? "true" : "false",
2017 dnd_drag_perhaps, gdk_dnd.drag_really));
2019 if (window_private &&
2020 (window_private->extension_events != 0) &&
2021 gdk_input_ignore_core)
2024 event->motion.type = GDK_MOTION_NOTIFY;
2025 event->motion.window = window;
2026 event->motion.time = xevent->xmotion.time;
2027 event->motion.x = xevent->xmotion.x;
2028 event->motion.y = xevent->xmotion.y;
2029 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2030 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2031 event->motion.pressure = 0.5;
2032 event->motion.xtilt = 0;
2033 event->motion.ytilt = 0;
2034 event->motion.state = (GdkModifierType) xevent->xmotion.state;
2035 event->motion.is_hint = xevent->xmotion.is_hint;
2036 event->motion.source = GDK_SOURCE_MOUSE;
2037 event->motion.deviceid = GDK_CORE_POINTER;
2039 #define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
2040 && cy >= dnd_drag_dropzone.y \
2041 && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
2042 && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
2044 if(dnd_drag_perhaps && gdk_dnd.drag_really)
2046 /* First, we have to find what window the motion was in... */
2047 /* XXX there has to be a better way to do this, perhaps with
2048 XTranslateCoordinates or XQueryTree - I don't know how,
2049 and this sort of works */
2050 static Window lastwin = None, curwin = None, twin;
2051 Window childwin = gdk_root_window;
2054 curwin = gdk_root_window;
2055 ox = x = xevent->xmotion.x_root;
2056 oy = y = xevent->xmotion.y_root;
2057 while(childwin != None)
2061 XTranslateCoordinates(gdk_display, curwin, curwin,
2062 x, y, &x, &y, &childwin);
2063 if(childwin != None)
2065 XTranslateCoordinates(gdk_display, curwin, childwin,
2066 x, y, &x, &y, &twin);
2070 g_print("Drag is now in window %#lx, lastwin was %#lx, ddc = %#lx\n",
2071 curwin, lastwin, dnd_drag_curwin));
2072 if(curwin != dnd_drag_curwin && curwin != lastwin)
2074 /* We have left one window and entered another
2075 (do leave & enter bits) */
2076 if(dnd_drag_curwin != None)
2077 gdk_dnd_drag_leave(dnd_drag_curwin);
2078 dnd_drag_curwin = curwin;
2079 gdk_dnd_drag_enter(dnd_drag_curwin);
2080 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2081 dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
2082 dnd_drag_target = None;
2084 g_print("curwin = %#lx, lastwin = %#lx, dnd_drag_curwin = %#lx\n",
2085 curwin, lastwin, dnd_drag_curwin));
2087 XChangeActivePointerGrab(gdk_display,
2089 ButtonPressMask | ButtonReleaseMask,
2090 gdk_dnd.gdk_cursor_dragdefault,
2093 else if(dnd_drag_dropzone.width > 0
2094 && dnd_drag_dropzone.height > 0
2095 && curwin == dnd_drag_curwin)
2097 /* Handle all that dropzone stuff - thanks John ;-) */
2098 if (dnd_drag_target != None)
2100 gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2101 xevent->xmotion.y_root);
2102 gboolean old_in_zone = IS_IN_ZONE(dnd_drag_oldpos.x,
2105 if (!in_zone && old_in_zone)
2107 /* We were in the drop zone and moved out */
2108 dnd_drag_target = None;
2109 gdk_dnd_drag_leave(curwin);
2111 else if (!in_zone && !old_in_zone)
2113 /* We were outside drop zone but in the window
2114 - have to send enter events */
2115 gdk_dnd_drag_enter(curwin);
2116 dnd_drag_curwin = curwin;
2117 dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
2118 dnd_drag_target = None;
2122 dnd_drag_curwin = None; */
2126 return_val = window_private && !window_private->destroyed;
2130 /* Print debugging info.
2133 g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2134 xevent->xcrossing.window - base_id,
2135 xevent->xcrossing.detail,
2136 xevent->xcrossing.subwindow - base_id));
2138 /* Tell XInput stuff about it if appropriate */
2139 if (window_private &&
2140 (window_private->extension_events != 0) &&
2141 gdk_input_vtable.enter_event)
2142 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2144 event->crossing.type = GDK_ENTER_NOTIFY;
2145 event->crossing.window = window;
2147 /* If the subwindow field of the XEvent is non-NULL, then
2148 * lookup the corresponding GdkWindow.
2150 if (xevent->xcrossing.subwindow != None)
2151 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2153 event->crossing.subwindow = NULL;
2155 /* Translate the crossing detail into Gdk terms.
2157 switch (xevent->xcrossing.detail)
2159 case NotifyInferior:
2160 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2162 case NotifyAncestor:
2163 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2166 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2168 case NotifyNonlinear:
2169 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2171 case NotifyNonlinearVirtual:
2172 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2175 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2179 if ((gdk_debug_flags & GDK_DEBUG_DND) & dnd_drag_perhaps)
2181 g_print("We may[%d] have a drag into %#lx = %#lx\n",
2182 gdk_dnd.drag_really,
2183 xevent->xcrossing.window, real_sw->xwindow);
2186 if (dnd_drag_perhaps && gdk_dnd.drag_really &&
2187 (xevent->xcrossing.window == real_sw->xwindow))
2189 gdk_dnd.drag_really = 0;
2191 GDK_NOTE (DND, g_print("Ungrabbed\n"));
2193 gdk_dnd.drag_numwindows = 0;
2194 g_free(gdk_dnd.drag_startwindows);
2195 gdk_dnd.drag_startwindows = NULL;
2196 /* We don't want to ungrab the pointer here, or we'll
2197 * start getting spurious enter/leave events */
2198 XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2201 return_val = window_private && !window_private->destroyed;
2205 /* Print debugging info.
2208 g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
2209 xevent->xcrossing.window - base_id,
2210 xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2212 event->crossing.type = GDK_LEAVE_NOTIFY;
2213 event->crossing.window = window;
2215 /* If the subwindow field of the XEvent is non-NULL, then
2216 * lookup the corresponding GdkWindow.
2218 if (xevent->xcrossing.subwindow != None)
2219 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2221 event->crossing.subwindow = NULL;
2223 /* Translate the crossing detail into Gdk terms.
2225 switch (xevent->xcrossing.detail)
2227 case NotifyInferior:
2228 event->crossing.detail = GDK_NOTIFY_INFERIOR;
2230 case NotifyAncestor:
2231 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2234 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2236 case NotifyNonlinear:
2237 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2239 case NotifyNonlinearVirtual:
2240 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2243 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2246 if ((gdk_debug_flags & GDK_DEBUG_DND) & dnd_drag_perhaps)
2248 g_print("We may[%d] have a drag out of %#lx = %#lx\n",
2249 gdk_dnd.drag_really,
2250 xevent->xcrossing.window, real_sw->xwindow);
2252 if (dnd_drag_perhaps && !gdk_dnd.drag_really &&
2253 (xevent->xcrossing.window == real_sw->xwindow))
2255 gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
2256 gdk_dnd_drag_begin((GdkWindow *) real_sw);
2257 XGrabPointer(gdk_display, real_sw->xwindow, False,
2259 ButtonPressMask | ButtonReleaseMask,
2260 GrabModeAsync, GrabModeAsync, gdk_root_window,
2261 gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
2263 gdk_dnd.drag_really = 1;
2266 return_val = window_private && !window_private->destroyed;
2271 /* We only care about focus events that indicate that _this_
2272 * window (not a ancestor or child) got or lost the focus
2274 switch (xevent->xfocus.detail)
2276 case NotifyAncestor:
2277 case NotifyInferior:
2278 case NotifyNonlinear:
2279 /* Print debugging info.
2282 g_print ("focus %s:\t\twindow: %ld\n",
2283 (xevent->xany.type == FocusIn) ? "in" : "out",
2284 xevent->xfocus.window - base_id));
2286 event->focus_change.type = GDK_FOCUS_CHANGE;
2287 event->focus_change.window = window;
2288 event->focus_change.in = (xevent->xany.type == FocusIn);
2290 return_val = window_private && !window_private->destroyed;
2298 /* Print debugging info.
2301 g_print ("keymap notify\n"));
2303 /* Not currently handled */
2307 /* Print debugging info.
2310 g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
2311 xevent->xexpose.window - base_id, xevent->xexpose.count,
2312 xevent->xexpose.x, xevent->xexpose.y,
2313 xevent->xexpose.width, xevent->xexpose.height));
2315 event->expose.type = GDK_EXPOSE;
2316 event->expose.window = window;
2317 event->expose.area.x = xevent->xexpose.x;
2318 event->expose.area.y = xevent->xexpose.y;
2319 event->expose.area.width = xevent->xexpose.width;
2320 event->expose.area.height = xevent->xexpose.height;
2321 event->expose.count = xevent->xexpose.count;
2323 return_val = window_private && !window_private->destroyed;
2326 case GraphicsExpose:
2327 /* Print debugging info.
2330 g_print ("graphics expose:\tdrawable: %ld\n",
2331 xevent->xgraphicsexpose.drawable - base_id));
2333 event->expose.type = GDK_EXPOSE;
2334 event->expose.window = window;
2335 event->expose.area.x = xevent->xgraphicsexpose.x;
2336 event->expose.area.y = xevent->xgraphicsexpose.y;
2337 event->expose.area.width = xevent->xgraphicsexpose.width;
2338 event->expose.area.height = xevent->xgraphicsexpose.height;
2339 event->expose.count = xevent->xexpose.count;
2341 return_val = window_private && !window_private->destroyed;
2345 /* Print debugging info.
2348 g_print ("no expose:\t\tdrawable: %ld\n",
2349 xevent->xnoexpose.drawable - base_id));
2351 event->no_expose.type = GDK_NO_EXPOSE;
2352 event->no_expose.window = window;
2354 return_val = window_private && !window_private->destroyed;
2357 case VisibilityNotify:
2358 /* Print debugging info.
2360 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2361 switch (xevent->xvisibility.state)
2363 case VisibilityFullyObscured:
2364 g_print ("visibility notify:\twindow: %ld none\n",
2365 xevent->xvisibility.window - base_id);
2367 case VisibilityPartiallyObscured:
2368 g_print ("visibility notify:\twindow: %ld partial\n",
2369 xevent->xvisibility.window - base_id);
2371 case VisibilityUnobscured:
2372 g_print ("visibility notify:\twindow: %ld full\n",
2373 xevent->xvisibility.window - base_id);
2377 event->visibility.type = GDK_VISIBILITY_NOTIFY;
2378 event->visibility.window = window;
2380 switch (xevent->xvisibility.state)
2382 case VisibilityFullyObscured:
2383 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2386 case VisibilityPartiallyObscured:
2387 event->visibility.state = GDK_VISIBILITY_PARTIAL;
2390 case VisibilityUnobscured:
2391 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2395 return_val = window_private && !window_private->destroyed;
2399 /* Not currently handled */
2403 /* Print debugging info.
2406 g_print ("destroy notify:\twindow: %ld\n",
2407 xevent->xdestroywindow.window - base_id));
2409 event->any.type = GDK_DESTROY;
2410 event->any.window = window;
2412 return_val = window_private && !window_private->destroyed;
2414 gdk_window_destroy_notify (window);
2418 /* Print debugging info.
2421 g_print ("unmap notify:\t\twindow: %ld\n",
2422 xevent->xmap.window - base_id));
2424 event->any.type = GDK_UNMAP;
2425 event->any.window = window;
2427 if (xgrab_window == window_private)
2428 xgrab_window = NULL;
2430 return_val = window_private && !window_private->destroyed;
2434 /* Print debugging info.
2437 g_print ("map notify:\t\twindow: %ld\n",
2438 xevent->xmap.window - base_id));
2440 event->any.type = GDK_MAP;
2441 event->any.window = window;
2443 return_val = window_private && !window_private->destroyed;
2446 case ReparentNotify:
2447 /* Print debugging info.
2450 g_print ("reparent notify:\twindow: %ld\n",
2451 xevent->xreparent.window - base_id));
2453 /* Not currently handled */
2456 case ConfigureNotify:
2457 /* Print debugging info.
2459 while ((XPending (gdk_display) > 0) &&
2460 XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2461 ConfigureNotify, xevent))
2462 /*XSync (gdk_display, 0)*/;
2465 g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d\n",
2466 xevent->xconfigure.window - base_id,
2467 xevent->xconfigure.x,
2468 xevent->xconfigure.y,
2469 xevent->xconfigure.width,
2470 xevent->xconfigure.height,
2471 xevent->xconfigure.border_width,
2472 xevent->xconfigure.above - base_id,
2473 xevent->xconfigure.override_redirect));
2477 if ((window_private->extension_events != 0) &&
2478 gdk_input_vtable.configure_event)
2479 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2481 if (window_private->window_type != GDK_WINDOW_CHILD)
2483 event->configure.type = GDK_CONFIGURE;
2484 event->configure.window = window;
2485 event->configure.width = xevent->xconfigure.width;
2486 event->configure.height = xevent->xconfigure.height;
2488 if (!xevent->xconfigure.x &&
2489 !xevent->xconfigure.y)
2493 Window child_window = 0;
2495 if (!XTranslateCoordinates (window_private->xdisplay,
2496 window_private->xwindow,
2501 g_warning ("GdkWindow %ld doesn't share root windows display?",
2502 window_private->xwindow - base_id);
2503 event->configure.x = tx;
2504 event->configure.y = ty;
2508 event->configure.x = xevent->xconfigure.x;
2509 event->configure.y = xevent->xconfigure.y;
2511 window_private->x = event->configure.x;
2512 window_private->y = event->configure.y;
2513 window_private->width = xevent->xconfigure.width;
2514 window_private->height = xevent->xconfigure.height;
2515 if (window_private->resize_count > 1)
2516 window_private->resize_count -= 1;
2518 return_val = !window_private->destroyed;
2523 case PropertyNotify:
2524 /* Print debugging info.
2527 g_print ("property notify:\twindow: %ld\n",
2528 xevent->xproperty.window - base_id));
2530 event->property.type = GDK_PROPERTY_NOTIFY;
2531 event->property.window = window;
2532 event->property.atom = xevent->xproperty.atom;
2533 event->property.time = xevent->xproperty.time;
2534 event->property.state = xevent->xproperty.state;
2536 return_val = window_private && !window_private->destroyed;
2539 case SelectionClear:
2541 g_print ("selection clear:\twindow: %ld\n",
2542 xevent->xproperty.window - base_id));
2544 event->selection.type = GDK_SELECTION_CLEAR;
2545 event->selection.window = window;
2546 event->selection.selection = xevent->xselectionclear.selection;
2547 event->selection.time = xevent->xselectionclear.time;
2549 return_val = window_private && !window_private->destroyed;
2552 case SelectionRequest:
2554 g_print ("selection request:\twindow: %ld\n",
2555 xevent->xproperty.window - base_id));
2557 event->selection.type = GDK_SELECTION_REQUEST;
2558 event->selection.window = window;
2559 event->selection.selection = xevent->xselectionrequest.selection;
2560 event->selection.target = xevent->xselectionrequest.target;
2561 event->selection.property = xevent->xselectionrequest.property;
2562 event->selection.requestor = xevent->xselectionrequest.requestor;
2563 event->selection.time = xevent->xselectionrequest.time;
2565 return_val = window_private && !window_private->destroyed;
2568 case SelectionNotify:
2570 g_print ("selection notify:\twindow: %ld\n",
2571 xevent->xproperty.window - base_id));
2574 event->selection.type = GDK_SELECTION_NOTIFY;
2575 event->selection.window = window;
2576 event->selection.selection = xevent->xselection.selection;
2577 event->selection.target = xevent->xselection.target;
2578 event->selection.property = xevent->xselection.property;
2579 event->selection.time = xevent->xselection.time;
2581 return_val = window_private && !window_private->destroyed;
2584 case ColormapNotify:
2585 /* Print debugging info.
2588 g_print ("colormap notify:\twindow: %ld\n",
2589 xevent->xcolormap.window - base_id));
2591 /* Not currently handled */
2595 /* Print debugging info.
2598 g_print ("client message:\twindow: %ld\n",
2599 xevent->xclient.window - base_id));
2601 /* Client messages are the means of the window manager
2602 * communicating with a program. We'll first check to
2603 * see if this is really the window manager talking
2606 if (xevent->xclient.message_type == gdk_wm_protocols)
2608 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2610 /* The delete window request specifies a window
2611 * to delete. We don't actually destroy the
2612 * window because "it is only a request". (The
2613 * window might contain vital data that the
2614 * program does not want destroyed). Instead
2615 * the event is passed along to the program,
2616 * which should then destroy the window.
2619 /* Print debugging info.
2622 g_print ("delete window:\t\twindow: %ld\n",
2623 xevent->xclient.window - base_id));
2625 event->any.type = GDK_DELETE;
2626 event->any.window = window;
2628 return_val = window_private && !window_private->destroyed;
2630 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2634 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2638 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2640 GDK_NOTE (DND, g_print ("GDK_DROP_ENTER [%d][%d]\n",
2641 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply));
2644 /* Now figure out if we really want this drop...
2645 * If someone is trying funky clipboard stuff, ignore
2648 && window_private->dnd_drop_enabled
2649 && event->dropenter.u.flags.sendreply
2650 && (reptype = gdk_dnd_check_types (window, xevent)))
2654 replyev.xclient.type = ClientMessage;
2655 replyev.xclient.window = xevent->xclient.data.l[0];
2656 replyev.xclient.format = 32;
2657 replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2658 replyev.xclient.data.l[0] = window_private->xwindow;
2660 event->dragrequest.u.allflags = 0;
2661 event->dragrequest.u.flags.protocol_version =
2662 DND_PROTOCOL_VERSION;
2663 event->dragrequest.u.flags.willaccept = 1;
2664 event->dragrequest.u.flags.delete_data =
2665 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2667 replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2668 replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2669 replyev.xclient.data.l[4] = reptype;
2671 XSendEvent (gdk_display, replyev.xclient.window,
2672 False, NoEventMask, &replyev);
2674 event->any.type = GDK_DROP_ENTER;
2675 event->any.window = window;
2676 event->dropenter.requestor = replyev.xclient.window;
2677 event->dropenter.u.allflags = xevent->xclient.data.l[1];
2679 GDK_NOTE (DND, g_print("We sent a GDK_DROP_ENTER on to Gtk\n"));
2683 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2685 #ifdef G_ENABLE_DEBUG
2686 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2687 g_print ("GDK_DROP_LEAVE\n");
2690 if (window_private && window_private->dnd_drop_enabled)
2692 event->dropleave.type = GDK_DROP_LEAVE;
2693 event->dropleave.window = window;
2694 event->dropleave.requestor = xevent->xclient.data.l[0];
2695 event->dropleave.u.allflags = xevent->xclient.data.l[1];
2701 else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2704 * make sure to only handle requests from the window the cursor is
2707 #ifdef G_ENABLE_DEBUG
2708 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2709 g_print ("GDK_DRAG_REQUEST\n");
2711 event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2714 if (window && gdk_dnd.drag_really &&
2715 xevent->xclient.data.l[0] == dnd_drag_curwin &&
2716 event->dragrequest.u.flags.sendreply == 0)
2718 /* Got request - do we need to ask user? */
2719 if (!event->dragrequest.u.flags.willaccept
2720 && event->dragrequest.u.flags.senddata)
2723 event->dragrequest.type = GDK_DRAG_REQUEST;
2724 event->dragrequest.window = window;
2725 event->dragrequest.requestor = xevent->xclient.data.l[0];
2726 event->dragrequest.isdrop = 0;
2727 event->dragrequest.drop_coords.x =
2728 event->dragrequest.drop_coords.y = 0;
2731 else if (event->dragrequest.u.flags.willaccept)
2733 window_private->dnd_drag_destructive_op =
2734 event->dragrequest.u.flags.delete_data;
2735 window_private->dnd_drag_accepted = 1;
2736 window_private->dnd_drag_data_type =
2737 xevent->xclient.data.l[4];
2739 dnd_drag_target = dnd_drag_curwin;
2740 XChangeActivePointerGrab (gdk_display,
2744 EnterWindowMask | LeaveWindowMask,
2745 gdk_dnd.gdk_cursor_dragok,
2748 dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2749 dnd_drag_dropzone.y =
2750 (xevent->xclient.data.l[2] >> 16) & 65535;
2751 dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2752 dnd_drag_dropzone.height =
2753 (xevent->xclient.data.l[3] >> 16) & 65535;
2756 else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2758 gint tmp_int; Atom tmp_atom;
2760 guchar *tmp_charptr;
2762 #ifdef G_ENABLE_DEBUG
2763 if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2764 g_print("GDK_DROP_DATA_AVAIL\n");
2766 event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2768 /* No preview of data ATM */
2769 && event->dropdataavailable.u.flags.isdrop)
2771 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2772 event->dropdataavailable.window = window;
2773 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2774 event->dropdataavailable.data_type =
2775 gdk_atom_name(xevent->xclient.data.l[2]);
2776 if(XGetWindowProperty (gdk_display,
2777 event->dropdataavailable.requestor,
2778 xevent->xclient.data.l[2],
2780 False, XA_PRIMARY, &tmp_atom,
2782 &event->dropdataavailable.data_numbytes,
2787 g_warning("XGetWindowProperty on %#x may have failed\n",
2788 event->dropdataavailable.requestor);
2789 event->dropdataavailable.data = NULL;
2793 GDK_NOTE (DND, g_print("XGetWindowProperty got us %ld bytes\n",
2794 event->dropdataavailable.data_numbytes));
2795 event->dropdataavailable.data =
2796 g_malloc (event->dropdataavailable.data_numbytes);
2797 memcpy (event->dropdataavailable.data,
2798 tmp_charptr, event->dropdataavailable.data_numbytes);
2807 /* Send unknown ClientMessage's on to Gtk for it to use */
2808 event->client.type = GDK_CLIENT_EVENT;
2809 event->client.window = window;
2810 event->client.message_type = xevent->xclient.message_type;
2811 event->client.data_format = xevent->xclient.format;
2812 memcpy(&event->client.data, &xevent->xclient.data,
2813 sizeof(event->client.data));
2820 return_val = return_val && !window_private->destroyed;
2824 /* Print debugging info.
2827 g_print ("mapping notify\n"));
2829 /* Let XLib know that there is a new keyboard mapping.
2831 XRefreshKeyboardMapping (&xevent->xmapping);
2835 /* something else - (e.g., a Xinput event) */
2837 if (window_private &&
2838 (window_private->extension_events != 0) &&
2839 gdk_input_vtable.other_event)
2840 return_val = gdk_input_vtable.other_event(event, xevent, window);
2844 if (return_val < 0) /* not an XInput event, convert */
2846 event->other.type = GDK_OTHER_EVENT;
2847 event->other.window = window;
2848 event->other.xevent = (GdkXEvent *)&other_xevent[other_xevent_i];
2849 memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
2850 other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
2854 return_val = return_val && !window_private->destroyed;
2861 if (event->any.window)
2862 gdk_window_ref (event->any.window);
2863 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2864 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2865 (event->crossing.subwindow != NULL))
2866 gdk_window_ref (event->crossing.subwindow);
2870 /* Mark this event as having no resources to be freed */
2871 event->any.window = NULL;
2872 event->any.type = GDK_NOTHING;
2876 gdk_window_unref (window);
2883 gdk_event_get_type (Display *display,
2890 if (gdk_event_translate (&event, xevent))
2892 pred = (GdkPredicate*) arg;
2893 return (* pred->func) (&event, pred->data);
2901 gdk_synthesize_click (GdkEvent *event,
2904 GdkEvent temp_event;
2906 g_return_if_fail (event != NULL);
2908 temp_event = *event;
2909 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2911 gdk_event_put (&temp_event);
2915 *--------------------------------------------------------------
2918 * This is the "atexit" function that makes sure the
2919 * library gets a chance to cleanup.
2926 * The library is un-initialized and the program exits.
2928 *--------------------------------------------------------------
2934 static gboolean in_gdk_exit_func = FALSE;
2936 /* This is to avoid an infinite loop if a program segfaults in
2937 an atexit() handler (and yes, it does happen, especially if a program
2938 has trounced over memory too badly for even g_print to work) */
2939 if(in_gdk_exit_func == TRUE) return;
2940 in_gdk_exit_func = TRUE;
2952 gdk_key_repeat_restore ();
2954 XCloseDisplay (gdk_display);
2960 *--------------------------------------------------------------
2963 * The X error handling routine.
2966 * "display" is the X display the error orignated from.
2967 * "error" is the XErrorEvent that we are handling.
2970 * Either we were expecting some sort of error to occur,
2971 * in which case we set the "gdk_error_code" flag, or this
2972 * error was unexpected, in which case we will print an
2973 * error message and exit. (Since trying to continue will
2974 * most likely simply lead to more errors).
2978 *--------------------------------------------------------------
2982 gdk_x_error (Display *display,
2987 if (gdk_error_warnings)
2989 XGetErrorText (display, error->error_code, buf, 63);
2990 g_error ("%s", buf);
2993 gdk_error_code = -1;
2998 *--------------------------------------------------------------
3001 * The X I/O error handling routine.
3004 * "display" is the X display the error orignated from.
3007 * An X I/O error basically means we lost our connection
3008 * to the X server. There is not much we can do to
3009 * continue, so simply print an error message and exit.
3013 *--------------------------------------------------------------
3017 gdk_x_io_error (Display *display)
3019 g_error ("an x io error occurred");
3024 *--------------------------------------------------------------
3027 * The signal handler.
3030 * "sig_num" is the number of the signal we received.
3033 * The signals we catch are all fatal. So we simply build
3034 * up a nice little error message and print it and exit.
3035 * If in the process of doing so another signal is received
3036 * we notice that we are already exiting and simply kill
3041 *--------------------------------------------------------------
3045 gdk_signal (int sig_num)
3047 static int caught_fatal_sig = 0;
3050 if (caught_fatal_sig)
3051 kill (getpid (), sig_num);
3052 caught_fatal_sig = 1;
3078 sig = "unknown signal";
3082 g_print ("\n** ERROR **: %s caught\n", sig);
3087 gdk_dnd_drag_begin (GdkWindow *initial_window)
3089 GdkEventDragBegin tev;
3090 tev.type = GDK_DRAG_BEGIN;
3091 tev.window = initial_window;
3093 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3095 gdk_event_put ((GdkEvent *) &tev);
3099 gdk_dnd_drag_enter (Window dest)
3102 GdkEventDropEnter tev;
3104 GdkWindowPrivate *wp;
3106 sev.xclient.type = ClientMessage;
3107 sev.xclient.format = 32;
3108 sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3109 sev.xclient.window = dest;
3112 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3113 tev.u.flags.sendreply = 1;
3114 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3116 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3117 if (wp->dnd_drag_data_numtypesavail)
3119 sev.xclient.data.l[0] = wp->xwindow;
3120 tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3121 sev.xclient.data.l[1] = tev.u.allflags;
3122 sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3123 if (wp->dnd_drag_data_numtypesavail > 1)
3125 sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3126 if (wp->dnd_drag_data_numtypesavail > 2)
3128 sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3131 sev.xclient.data.l[4] = None;
3134 sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3135 XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
3145 *--------------------------------------------------------------
3148 * Begin using input method with XIM Protocol(X11R6 standard)
3151 * "ic" is the "Input Context" which is created by gtk_ic_new.
3152 * The input area is specified with "window".
3155 * The gdk's event handling routine is switched to XIM based routine.
3156 * XIM based routine uses XFilterEvent to get rid of events used by IM,
3157 * and uses XmbLookupString instead of XLookupString.
3161 *--------------------------------------------------------------
3165 gdk_im_begin (GdkIC ic, GdkWindow* window)
3167 GdkICPrivate *private;
3170 g_return_if_fail (ic != NULL);
3171 g_return_if_fail (window);
3173 private = (GdkICPrivate *) ic;
3177 xim_window = window;
3180 XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3181 if (xwin != GDK_WINDOW_XWINDOW(window))
3182 XSetICValues (private->xic, XNFocusWindow,
3183 GDK_WINDOW_XWINDOW(window), NULL);
3184 if (private != xim_ic)
3185 XSetICFocus (private->xic);
3190 *--------------------------------------------------------------
3193 * End using input method with XIM Protocol(X11R6 standard)
3198 * The gdk's event handling routine is switched to normal routine.
3199 * User should call this function before ic and window will be destroyed.
3203 *--------------------------------------------------------------
3221 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
3223 GdkIMStyle s1, s2, u;
3225 if (style1 == 0) return style2;
3226 if (style2 == 0) return style1;
3227 if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3228 == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3231 s1 = style1 & GdkIMPreeditMask;
3232 s2 = style2 & GdkIMPreeditMask;
3235 if (u & GdkIMPreeditCallbacks)
3236 return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3237 else if (u & GdkIMPreeditPosition)
3238 return (s1 == GdkIMPreeditPosition)? style1:style2;
3239 else if (u & GdkIMPreeditArea)
3240 return (s1 == GdkIMPreeditArea)? style1:style2;
3241 else if (u & GdkIMPreeditNothing)
3242 return (s1 == GdkIMPreeditNothing)? style1:style2;
3244 s1 = style1 & GdkIMStatusMask;
3245 s2 = style2 & GdkIMStatusMask;
3247 if ( u & GdkIMStatusCallbacks)
3248 return (s1 == GdkIMStatusCallbacks)? style1:style2;
3249 else if ( u & GdkIMStatusArea)
3250 return (s1 == GdkIMStatusArea)? style1:style2;
3251 else if ( u & GdkIMStatusNothing)
3252 return (s1 == GdkIMStatusNothing)? style1:style2;
3253 else if ( u & GdkIMStatusNone)
3254 return (s1 == GdkIMStatusNone)? style1:style2;
3256 return 0; /* Get rid of stupid warning */
3260 gdk_im_decide_style (GdkIMStyle supported_style)
3263 GdkIMStyle style, tmp;
3265 g_return_val_if_fail (xim_styles != NULL, 0);
3268 for (i=0; i<xim_styles->count_styles; i++)
3270 tmp = xim_styles->supported_styles[i];
3271 if (tmp == (tmp & supported_style & xim_best_allowed_style))
3272 style = gdk_im_choose_better_style (style, tmp);
3278 gdk_im_set_best_style (GdkIMStyle style)
3280 if (style & GdkIMPreeditMask)
3282 xim_best_allowed_style &= ~GdkIMPreeditMask;
3284 xim_best_allowed_style |= GdkIMPreeditNone;
3285 if (!(style & GdkIMPreeditNone))
3287 xim_best_allowed_style |= GdkIMPreeditNothing;
3288 if (!(style & GdkIMPreeditNothing))
3290 xim_best_allowed_style |= GdkIMPreeditArea;
3291 if (!(style & GdkIMPreeditArea))
3293 xim_best_allowed_style |= GdkIMPreeditPosition;
3294 if (!(style & GdkIMPreeditPosition))
3295 xim_best_allowed_style |= GdkIMPreeditCallbacks;
3300 if (style & GdkIMStatusMask)
3302 xim_best_allowed_style &= ~GdkIMStatusMask;
3304 xim_best_allowed_style |= GdkIMStatusNone;
3305 if (!(style & GdkIMStatusNone))
3307 xim_best_allowed_style |= GdkIMStatusNothing;
3308 if (!(style & GdkIMStatusNothing))
3310 xim_best_allowed_style |= GdkIMStatusArea;
3311 if (!(style & GdkIMStatusArea))
3312 xim_best_allowed_style |= GdkIMStatusCallbacks;
3317 return xim_best_allowed_style;
3321 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3323 xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3326 g_warning ("Don\'t open IM.");
3329 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3352 return (xim_im != NULL);
3356 gdk_ic_new (GdkWindow* client_window,
3357 GdkWindow* focus_window,
3358 GdkIMStyle style, ...)
3361 GdkICPrivate *private;
3362 XVaNestedList preedit_attr;
3364 g_return_val_if_fail (client_window != NULL, NULL);
3365 g_return_val_if_fail (focus_window != NULL, NULL);
3366 g_return_val_if_fail (gdk_im_ready(), NULL);
3368 private = g_new (GdkICPrivate, 1);
3370 va_start (list, style);
3371 preedit_attr = (XVaNestedList) & (va_arg (list, void *));
3374 private->style = gdk_im_decide_style (style);
3375 if (private->style != style)
3377 g_warning ("can not create input context with specified input style.");
3382 private->xic = XCreateIC(gdk_im_get (),
3383 XNInputStyle, style,
3384 XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3385 XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
3386 preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3394 xim_ic_list = g_list_append (xim_ic_list, private);
3399 gdk_ic_destroy (GdkIC ic)
3401 GdkICPrivate *private;
3403 g_return_if_fail (ic != NULL);
3405 private = (GdkICPrivate *) ic;
3407 if (xim_ic == private)
3410 XDestroyIC (private->xic);
3411 xim_ic_list = g_list_remove (xim_ic_list, private);
3415 gdk_ic_get_style (GdkIC ic)
3417 GdkICPrivate *private;
3419 g_return_val_if_fail (ic != NULL, 0);
3421 private = (GdkICPrivate *) ic;
3423 return private->style;
3427 gdk_ic_set_values (GdkIC ic, ...)
3431 GdkICPrivate *private;
3433 g_return_if_fail (ic != NULL);
3435 private = (GdkICPrivate *) ic;
3437 va_start (list, ic);
3438 args = (XVaNestedList) & (va_arg (list, void *));
3441 XSetICValues (private->xic, XNVaNestedList, args, NULL);
3445 gdk_ic_get_values (GdkIC ic, ...)
3449 GdkICPrivate *private;
3451 g_return_if_fail (ic != NULL);
3453 private = (GdkICPrivate *) ic;
3455 va_start (list, ic);
3456 args = (XVaNestedList) & (va_arg (list, void *));
3459 XGetICValues (private->xic, XNVaNestedList, args, NULL);
3463 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3467 GdkICPrivate *private;
3469 g_return_if_fail (ic != NULL);
3470 g_return_if_fail (target != NULL);
3472 private = (GdkICPrivate *) ic;
3474 va_start (list, target);
3475 attr = (XVaNestedList) & (va_arg (list, void *));
3478 XSetICValues (private->xic, target, attr, NULL);
3482 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3486 GdkICPrivate *private;
3488 g_return_if_fail (ic != NULL);
3489 g_return_if_fail (target != NULL);
3491 private = (GdkICPrivate *) ic;
3493 va_start (list, target);
3494 attr = (XVaNestedList) & (va_arg (list, void *));
3497 XGetICValues (private->xic, target, attr, NULL);
3501 gdk_ic_get_events (GdkIC ic)
3506 GdkICPrivate *private;
3509 /* From gdkwindow.c */
3510 extern int nevent_masks;
3511 extern int event_mask_table[];
3513 g_return_val_if_fail (ic != NULL, 0);
3515 private = (GdkICPrivate *) ic;
3517 XGetICValues (private->xic, XNFilterEvents, &xmask, NULL);
3520 for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3521 if (xmask & event_mask_table [i])
3524 xmask &= ~ event_mask_table [i];
3528 g_warning ("ic requires the events not supported by the application (%04lx)", xmask);
3534 gdk_ic_cleanup (void)
3538 GdkICPrivate *private;
3541 for (node = xim_ic_list; node != NULL; node = node->next)
3545 private = (GdkICPrivate *) (node->data);
3546 XDestroyIC (private->xic);
3551 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3553 g_warning ("Cleaned up %i IC(s)\n", destroyed);
3555 g_list_free(xim_ic_list);
3559 #else /* !USE_XIM */
3562 gdk_im_begin (GdkIC ic, GdkWindow* window)
3572 gdk_im_decide_style (GdkIMStyle supported_style)
3574 return GdkIMPreeditNone | GdkIMStatusNone;
3578 gdk_im_set_best_style (GdkIMStyle style)
3580 return GdkIMPreeditNone | GdkIMStatusNone;
3590 gdk_ic_new (GdkWindow* client_window,
3591 GdkWindow* focus_window,
3592 GdkIMStyle style, ...)
3598 gdk_ic_destroy (GdkIC ic)
3603 gdk_ic_get_style (GdkIC ic)
3605 return GdkIMPreeditNone | GdkIMStatusNone;
3609 gdk_ic_set_values (GdkIC ic, ...)
3614 gdk_ic_get_values (GdkIC ic, ...)
3619 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3624 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3629 gdk_ic_get_events (GdkIC ic)
3634 #endif /* USE_XIM */
3639 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3641 static wchar_t wcs[MB_CUR_MAX + 1];
3642 static gchar mbs[MB_CUR_MAX + 1];
3644 wcs[0] = (wchar_t) NULL;
3647 len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3650 else if (wcs[0] == (wchar_t) NULL)
3653 len = _Xwctomb (mbs, wcs[0]);
3662 #endif /* X_LOCALE */
3665 gdk_dnd_drag_leave (Window dest)
3668 GdkEventDropLeave tev;
3670 GdkWindowPrivate *wp;
3674 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3675 sev.xclient.type = ClientMessage;
3676 sev.xclient.window = dest;
3677 sev.xclient.format = 32;
3678 sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3679 sev.xclient.data.l[1] = tev.u.allflags;
3680 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3682 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3683 sev.xclient.data.l[0] = wp->xwindow;
3684 XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
3685 wp->dnd_drag_accepted = 0;
3690 * when a drop occurs, we go through the list of windows being dragged and
3691 * tell them that it has occurred, so that they can set things up and reply
3695 gdk_dnd_drag_end (Window dest,
3698 GdkWindowPrivate *wp;
3699 GdkEventDragRequest tev;
3702 tev.type = GDK_DRAG_REQUEST;
3703 tev.drop_coords = coords;
3704 tev.requestor = dest;
3706 tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3709 for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3711 wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3712 if (wp->dnd_drag_accepted)
3714 tev.window = (GdkWindow *) wp;
3715 tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
3717 gdk_atom_name(wp->dnd_drag_data_type);
3719 gdk_event_put((GdkEvent *) &tev);
3725 gdk_dnd_check_types (GdkWindow *window,
3728 GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3730 GdkEventDropEnter event;
3732 g_return_val_if_fail(window != NULL, 0);
3733 g_return_val_if_fail(xevent != NULL, 0);
3734 g_return_val_if_fail(xevent->type == ClientMessage, 0);
3735 g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3737 if(wp->dnd_drop_data_numtypesavail <= 0 ||
3738 !wp->dnd_drop_data_typesavail)
3741 for (i = 2; i <= 4; i++)
3743 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3745 if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3746 return xevent->xclient.data.l[i];
3750 /* Now we get the extended type list if it's available */
3751 event.u.allflags = xevent->xclient.data.l[1];
3752 if (event.u.flags.extended_typelist)
3754 Atom *exttypes, realtype;
3755 gulong nitems, nbar;
3758 if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3759 gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
3760 False, AnyPropertyType, &realtype, &realfmt,
3761 &nitems, &nbar, (unsigned char **) &exttypes)
3765 if (realfmt != (sizeof(Atom) * 8))
3767 g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
3768 realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
3772 for (i = 0; i <= nitems; i++)
3774 for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3776 if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
3789 * used for debugging only
3793 gdk_print_atom (GdkAtom anatom)
3795 gchar *tmpstr = NULL;
3796 tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
3797 g_print("Atom %lu has name %s\n", anatom, tmpstr);
3804 * used only by below routine and itself
3807 getchildren (Display *dpy,
3811 Window root, parent, *children, inf = 0;
3813 unsigned int nchildren, i;
3815 unsigned long nitems, after;
3816 unsigned char *data;
3818 if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
3821 for (i = 0; !inf && (i < nchildren); i++)
3823 XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
3824 AnyPropertyType, &type, &format, &nitems,
3831 for (i = 0; !inf && (i < nchildren); i++)
3832 inf = getchildren (dpy, children[i], WM_STATE);
3834 if (children != None)
3835 XFree ((char *) children);
3841 * find a window with WM_STATE, else return win itself, as per ICCCM
3843 * modification of the XmuClientWindow() routine from X11R6.3
3846 gdk_get_client_window (Display *dpy,
3852 unsigned long nitems, after;
3853 unsigned char *data;
3857 return DefaultRootWindow(dpy);
3859 if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
3862 XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
3863 &type, &format, &nitems, &after, &data);
3867 inf = getchildren (dpy, win, WM_STATE);
3875 #ifdef WE_HAVE_MOTIF_DROPS_DONE
3877 gdk_drop_get_real_window (GdkWindow *w,
3881 GdkWindow *retval = w;
3882 GdkWindowPrivate *awin;
3884 gint16 myx = *x, myy = *y;
3886 g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
3892 for (children = gdk_window_get_children(retval);
3893 children && children->next;
3894 children = children->next)
3896 awin = (GdkWindowPrivate *) children->data;
3897 if ((myx >= awin->x) && (myy >= awin->y)
3898 && (myx < (awin->x + awin->width))
3899 && (myy < (awin->y + awin->height)))
3901 retval = (GdkWindow *) awin;
3915 /* Sends a ClientMessage to all toplevel client windows */
3917 gdk_event_send_clientmessage_toall(GdkEvent *event)
3920 Window *ret_children, ret_root, ret_parent, curwin;
3921 unsigned int ret_nchildren;
3924 g_return_if_fail(event != NULL);
3926 /* Set up our event to send, with the exception of its target window */
3927 sev.xclient.type = ClientMessage;
3928 sev.xclient.display = gdk_display;
3929 sev.xclient.format = event->client.data_format;
3930 sev.xclient.serial = CurrentTime;
3931 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
3932 sev.xclient.message_type = event->client.message_type;
3934 /* OK, we're all set, now let's find some windows to send this to */
3935 if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
3936 &ret_children, &ret_nchildren) != True)
3939 /* foreach true child window of the root window, send an event to it */
3940 for(i = 0; i < ret_nchildren; i++) {
3941 curwin = gdk_get_client_window(gdk_display, ret_children[i]);
3942 sev.xclient.window = curwin;
3943 XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
3946 XFree(ret_children);
3950 gdk_get_display(void)
3952 return (gchar *)XDisplayName (gdk_display_name);