if (xevent.xany.type == GraphicsExpose)
{
- event = _gdk_event_new ();
+ event = gdk_event_new (GDK_NOTHING);
if (gdk_event_translate (GDK_WINDOW_DISPLAY (window), event,
&xevent, TRUE))
*
* Adds a filter to be called when X ClientMessage events are received.
*
+ * Since: 2.2
**/
void
gdk_display_add_client_message_filter (GdkDisplay *display,
gdk_event_put (&event);
}
+static void
+set_screen_from_root (GdkDisplay *display,
+ GdkEvent *event,
+ Window xrootwin)
+{
+ GdkScreen *screen;
+
+ screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
+ g_assert (screen);
+
+ gdk_event_set_screen (event, screen);
+}
+
+static void
+translate_key_event (GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+ gunichar c = 0;
+ guchar buf[7];
+
+ event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ event->key.keyval = GDK_VoidSymbol;
+
+ gdk_keymap_translate_keyboard_state (keymap,
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->key.string = NULL;
+
+ if (event->key.keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->key.keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->key.state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->key.string = g_memdup ("\0\0", 2);
+ event->key.length = 1;
+ buf[0] = '\0';
+ goto out;
+ }
+ else if (c >= '3' && c <= '7') c -= ('3' - '\033');
+ else if (c == '8') c = '\177';
+ else if (c == '/') c = '_' & 0x1F;
+ }
+
+ len = g_unichar_to_utf8 (c, buf);
+ buf[len] = '\0';
+
+ event->key.string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->key.string)
+ event->key.length = bytes_written;
+ }
+ else if (event->key.keyval == GDK_Escape)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\033");
+ }
+ else if (event->key.keyval == GDK_Return ||
+ event->key.keyval == GDK_KP_Enter)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\r");
+ }
+
+ if (!event->key.string)
+ {
+ event->key.length = 0;
+ event->key.string = g_strdup ("");
+ }
+
+ out:
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("%s:\t\twindow: %ld key: %12s %d",
+ event->type == GDK_KEY_PRESS ? "key press " : "key release",
+ xevent->xkey.window,
+ event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
+ event->key.keyval);
+
+ if (event->key.length > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ event->key.length, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+}
+
+/* Return the window this has to do with, if any, rather
+ * than the frame or root window that was selecting
+ * for substructure
+ */
+static Window
+get_real_window (XEvent *event)
+{
+ switch (event->type)
+ {
+ case CreateNotify:
+ return event->xcreatewindow.window;
+
+ case DestroyNotify:
+ return event->xdestroywindow.window;
+
+ case UnmapNotify:
+ return event->xunmap.window;
+
+ case MapNotify:
+ return event->xmap.window;
+
+ case MapRequest:
+ return event->xmaprequest.window;
+
+ case ReparentNotify:
+ return event->xreparent.window;
+
+ case ConfigureNotify:
+ return event->xconfigure.window;
+
+ case ConfigureRequest:
+ return event->xconfigurerequest.window;
+
+ case GravityNotify:
+ return event->xgravity.window;
+
+ case CirculateNotify:
+ return event->xcirculate.window;
+
+ case CirculateRequest:
+ return event->xcirculaterequest.window;
+
+ default:
+ return event->xany.window;
+ }
+}
+
+#ifdef G_ENABLE_DEBUG
+static const char notify_modes[][18] = {
+ "NotifyNormal",
+ "NotifyGrab",
+ "NotifyUngrab",
+ "NotifyWhileGrabbed"
+};
+
+static const char notify_details[][22] = {
+ "NotifyAncestor",
+ "NotifyVirtual",
+ "NotifyInferior",
+ "NotifyNonlinear",
+ "NotifyNonlinearVirtual",
+ "NotifyPointer",
+ "NotifyPointerRoot",
+ "NotifyDetailNone"
+};
+#endif
+
static gboolean
gdk_event_translate (GdkDisplay *display,
GdkEvent *event,
GdkWindow *window;
GdkWindowObject *window_private;
+ GdkWindow *filter_window;
GdkWindowImplX11 *window_impl = NULL;
- static XComposeStatus compose;
- KeySym keysym;
- int charcount;
- char buf[16];
gint return_val;
gint xoffset, yoffset;
GdkScreen *screen = NULL;
GdkScreenX11 *screen_x11 = NULL;
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+ Window xwindow;
return_val = FALSE;
return_val = FALSE;
}
- /* Find the GdkWindow that this event occurred in. */
+ /* Find the GdkWindow that this event relates to.
+ * Basically this means substructure events
+ * are reported same as structure events
+ */
+ xwindow = get_real_window (xevent);
- window = gdk_window_lookup_for_display (display, xevent->xany.window);
+ window = gdk_window_lookup_for_display (display, xwindow);
window_private = (GdkWindowObject *) window;
+ /* We always run the filters for the window where the event
+ * is delivered, not the window that it relates to
+ */
+ if (xevent->xany.window == xwindow)
+ filter_window = window;
+ else
+ filter_window = gdk_window_lookup_for_display (display, xevent->xany.window);
+
if (window)
{
screen = GDK_WINDOW_SCREEN (window);
if (GDK_IS_WINDOW (window))
{
window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
-
- if (xevent->xany.window != GDK_WINDOW_XID (window))
+
+ /* Move key events on focus window to the real toplevel, and
+ * filter out all other events on focus window
+ */
+ if (xwindow == window_impl->focus_window)
{
- g_assert (xevent->xany.window == window_impl->focus_window);
-
switch (xevent->type)
{
case KeyPress:
case KeyRelease:
- xevent->xany.window = GDK_WINDOW_XID (window);
+ xwindow = GDK_WINDOW_XID (window);
+ xevent->xany.window = xwindow;
break;
default:
return FALSE;
goto done;
}
}
- else if (window_private)
+ else if (filter_window)
{
/* Apply per-window filters */
+ GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
GdkFilterReturn result;
- result = gdk_event_apply_filters (xevent, event,
- window_private->filters);
-
- if (result != GDK_FILTER_CONTINUE)
+
+ if (filter_private->filters)
{
- return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
- goto done;
+ g_object_ref (filter_window);
+
+ result = gdk_event_apply_filters (xevent, event,
+ filter_private->filters);
+
+ g_object_unref (filter_window);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
}
}
if (screen_x11 && screen_x11->wmspec_check_window != None &&
- xevent->xany.window == screen_x11->wmspec_check_window)
+ xwindow == screen_x11->wmspec_check_window)
{
if (xevent->type == DestroyNotify)
{
return_val = FALSE;
break;
}
-
- /* Lookup the string corresponding to the given keysym.
- */
-
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- if (charcount > 0 && buf[charcount-1] == '\0')
- charcount --;
- else
- buf[charcount] = '\0';
-
-#ifdef G_ENABLE_DEBUG
- if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
- {
- g_message ("key press:\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
- event->key.keyval);
- if (charcount > 0)
- g_message ("\t\tlength: %4d string: \"%s\"",
- charcount, buf);
- }
-#endif /* G_ENABLE_DEBUG */
-
- event->key.type = GDK_KEY_PRESS;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.string = g_strdup (buf);
- event->key.length = charcount;
-
- /* bits 13 and 14 in the "state" field are the keyboard group */
-#define KEYBOARD_GROUP_SHIFT 13
-#define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
-
- event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
-
+ translate_key_event (display, event, xevent);
break;
-
+
case KeyRelease:
if (window_private == NULL)
{
break;
}
- /* Lookup the string corresponding to the given keysym.
- */
-
/* Emulate detectable auto-repeat by checking to see
* if the next event is a key press with the same
* keycode and timestamp, and if so, ignoring the event.
if (next_event.type == KeyPress &&
next_event.xkey.keycode == xevent->xkey.keycode &&
next_event.xkey.time == xevent->xkey.time)
- break;
+ {
+ return_val = FALSE;
+ break;
+ }
}
-
- keysym = GDK_VoidSymbol;
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- GDK_NOTE (EVENTS,
- g_message ("key release:\t\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- XKeysymToString (event->key.keyval),
- event->key.keyval));
-
- event->key.type = GDK_KEY_RELEASE;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.length = 0;
- event->key.string = NULL;
-
- event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
+ translate_key_event (display, event, xevent);
break;
case ButtonPress:
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
event->scroll.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xbutton.root);
+
break;
default:
event->button.button = xevent->xbutton.button;
event->button.device = display->core_pointer;
+ set_screen_from_root (display, event, xevent->xbutton.root);
+
_gdk_event_button_generate (display, event);
break;
}
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
event->button.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xbutton.root);
break;
event->motion.is_hint = xevent->xmotion.is_hint;
event->motion.device = display->core_pointer;
+ set_screen_from_root (display, event, xevent->xmotion.root);
+
break;
case EnterNotify:
if (window &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
xevent->xcrossing.detail != NotifyInferior &&
- xevent->xcrossing.focus && !window_impl->has_focus)
+ xevent->xcrossing.focus && !window_impl->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (window_impl);
-
+
window_impl->has_pointer_focus = TRUE;
if (HAS_FOCUS (window_impl) != had_focus)
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
+ set_screen_from_root (display, event, xevent->xcrossing.root);
+
/* Translate the crossing mode into Gdk terms.
*/
switch (xevent->xcrossing.mode)
if (window &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
xevent->xcrossing.detail != NotifyInferior &&
- xevent->xcrossing.focus && !window_impl->has_focus)
+ xevent->xcrossing.focus && !window_impl->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (window_impl);
window_impl->has_pointer_focus = FALSE;
-
+
if (HAS_FOCUS (window_impl) != had_focus)
generate_focus_event (window, FALSE);
}
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
+ set_screen_from_root (display, event, xevent->xcrossing.root);
+
/* Translate the crossing mode into Gdk terms.
*/
switch (xevent->xcrossing.mode)
*/
case FocusIn:
GDK_NOTE (EVENTS,
- g_message ("focus in:\t\twindow: %ld", xevent->xfocus.window));
+ g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
{
case NotifyNonlinear:
case NotifyVirtual:
case NotifyNonlinearVirtual:
+ window_impl->has_focus_window = TRUE;
/* We pretend that the focus moves to the grab
* window, so we pay attention to NotifyGrab
* NotifyUngrab, and ignore NotifyWhileGrabbed
break;
case FocusOut:
GDK_NOTE (EVENTS,
- g_message ("focus out:\t\twindow: %ld", xevent->xfocus.window));
-
+ g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
{
gboolean had_focus = HAS_FOCUS (window_impl);
case NotifyNonlinear:
case NotifyVirtual:
case NotifyNonlinearVirtual:
+ window_impl->has_focus_window = FALSE;
if (xevent->xfocus.mode != NotifyWhileGrabbed)
window_impl->has_focus = FALSE;
break;
: xevent->xconfigure.event != xevent->xconfigure.window
? " (discarding substructure)"
: ""));
+ if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
+ _gdk_x11_screen_size_changed (screen, xevent);
+
if (window &&
xevent->xconfigure.event == xevent->xconfigure.window &&
!GDK_WINDOW_DESTROYED (window) &&
continue;
}
- event = _gdk_event_new ();
+ event = gdk_event_new (GDK_NOTHING);
- event->any.type = GDK_NOTHING;
event->any.window = NULL;
event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
}
/**
- * gdk_event_send_client_message_for_display :
- * @display : the #GdkDisplay for the window where the message is to be sent.
- * @event : the #GdkEvent to send, which should be a #GdkEventClient.
- * @winid : the window to send the X ClientMessage event to.
+ * gdk_event_send_client_message_for_display:
+ * @display: the #GdkDisplay for the window where the message is to be sent.
+ * @event: the #GdkEvent to send, which should be a #GdkEventClient.
+ * @winid: the window to send the X ClientMessage event to.
*
* Sends an X ClientMessage event to a given window.
*
* This could be used for communicating between different applications,
* though the amount of data is limited to 20 bytes.
*
- * Returns : non-zero on success.
+ * Returns: non-zero on success.
+ *
+ * Since: 2.2
*/
gboolean
gdk_event_send_client_message_for_display (GdkDisplay *display,
/**
* gdk_screen_broadcast_client_message:
- * @screen : the #GdkScreen where the event will be broadcasted.
- * @event : the #GdkEvent.
+ * @screen: the #GdkScreen where the event will be broadcasted.
+ * @event: the #GdkEvent.
*
* Sends an X ClientMessage event to all toplevel windows on @screen.
*
* as described in the Inter-Client Communication Conventions Manual (ICCCM).
* If no windows are found with the WM_STATE property set, the message is
* sent to all children of the root window.
+ *
+ * Since: 2.2
*/
void
_gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
}
+/**
+ * gdk_x11_screen_get_window_manager_name:
+ * @screen: a #GdkScreen
+ *
+ * Returns the name of the window manager for @screen.
+ *
+ * Return value: the name of the window manager screen @screen, or
+ * "unknown" if the window manager is unknown. The string is owned by GDK
+ * and should not be freed.
+ *
+ * Since: 2.2
+ **/
const char*
gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
{
/**
* gdk_x11_screen_supports_net_wm_hint:
- * @screen : the relevant #GdkScreen.
+ * @screen: the relevant #GdkScreen.
* @property: a property atom.
*
* This function is specific to the X11 backend of GDK, and indicates
* whether the window manager supports a certain hint from the
* Extended Window Manager Hints Specification. You can find this
- * specification on http://www.freedesktop.org.
+ * specification on
+ * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
*
* When using this function, keep in mind that the window manager
* can change over time; so you shouldn't use this function in
* a window manager change.
*
* Return value: %TRUE if the window manager supports @property
+ *
+ * Since: 2.2
**/
gboolean
gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
* FIXME needs a list of valid settings here, or a link to
* more information.
*
- * Returns : %TRUE if the setting existed and a value was stored
+ * Returns: %TRUE if the setting existed and a value was stored
* in @value, %FALSE otherwise.
+ *
+ * Since: 2.2
**/
gboolean
gdk_screen_get_setting (GdkScreen *screen,