diff options
author | Owen Taylor <otaylor@redhat.com> | 2001-04-18 17:57:36 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2001-04-18 17:57:36 +0000 |
commit | ebd3958c0641d82b54f26118155e4669725900e2 (patch) | |
tree | 84649a7517ff992b4c01de6cd79af795255718e9 | |
parent | 2c0b59f70641f6a56380abbc487815e816cb9662 (diff) | |
download | gtk+-ebd3958c0641d82b54f26118155e4669725900e2.tar.gz |
Introduce an extra child of toplevel windows that serves to hold the focus
Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h
gdk/x11/gdkevents-x11.c: Introduce an extra child
of toplevel windows that serves to hold the focus to
avoid events being delivered to embedded windows.
* gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce
some extra variables to clean up code and reduce the
number of casts.
* gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use
guint for 1 bit bit fields, not gboolean.
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 14 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 14 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 14 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 14 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 14 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 14 | ||||
-rw-r--r-- | gdk/x11/gdkevents-x11.c | 158 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 75 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.h | 22 |
10 files changed, 296 insertions, 57 deletions
@@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 28f1c1f726..1d1b3753e2 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 28f1c1f726..1d1b3753e2 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 28f1c1f726..1d1b3753e2 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 28f1c1f726..1d1b3753e2 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 28f1c1f726..1d1b3753e2 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 28f1c1f726..1d1b3753e2 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,17 @@ +Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> + + * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h + gdk/x11/gdkevents-x11.c: Introduce an extra child + of toplevel windows that serves to hold the focus to + avoid events being delivered to embedded windows. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Introduce + some extra variables to clean up code and reduce the + number of casts. + + * gdk/x11/gdkwindow-x11.h (struct _GdkXPositionInfo): Use + guint for 1 bit bit fields, not gboolean. + Wed Apr 18 10:04:23 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtktooltips.c (gtk_tooltips_paint_window): Return FALSE, diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index bcb70be448..22eb7a3179 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -404,6 +404,23 @@ gdk_check_wm_state_changed (GdkWindow *window) } } +#define HAS_FOCUS(window_impl) \ + ((window_impl)->has_focus || (window_impl)->has_pointer_focus) + +static void +generate_focus_event (GdkWindow *window, + gboolean in) +{ + GdkEvent event; + + event.type = GDK_FOCUS_CHANGE; + event.focus_change.window = window; + event.focus_change.send_event = FALSE; + event.focus_change.in = in; + + gdk_event_put (&event); +} + static gint gdk_event_translate (GdkEvent *event, XEvent *xevent, @@ -412,6 +429,7 @@ gdk_event_translate (GdkEvent *event, GdkWindow *window; GdkWindowObject *window_private; + GdkWindowImplX11 *window_impl = NULL; static XComposeStatus compose; KeySym keysym; int charcount; @@ -439,12 +457,7 @@ gdk_event_translate (GdkEvent *event, } window = gdk_window_lookup (xevent->xany.window); - /* FIXME: window might be a GdkPixmap!!! */ - window_private = (GdkWindowObject *) window; - - if (window != NULL) - gdk_window_ref (window); if (_gdk_moveresize_window && (xevent->xany.type == MotionNotify || @@ -468,6 +481,29 @@ gdk_event_translate (GdkEvent *event, return FALSE; } + /* FIXME: window might be a GdkPixmap!!! */ + if (window != NULL) + { + window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl); + + if (xevent->xany.window != GDK_WINDOW_XID (window)) + { + g_assert (xevent->xany.window == window_impl->focus_window); + + switch (xevent->type) + { + case KeyPress: + case KeyRelease: + xevent->xany.window = GDK_WINDOW_XID (window); + break; + default: + return False; + } + } + + gdk_window_ref (window); + } + event->any.window = window; event->any.send_event = xevent->xany.send_event ? TRUE : FALSE; @@ -718,7 +754,20 @@ gdk_event_translate (GdkEvent *event, xevent->xcrossing.window, xevent->xcrossing.detail, xevent->xcrossing.subwindow)); - + + /* Handle focusing (in the case where no window manager is running */ + if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && + xevent->xcrossing.detail != NotifyInferior && + xevent->xcrossing.focus && !window_impl->has_focus) + { + gboolean had_focus = HAS_FOCUS (window_impl); + + window_impl->has_pointer_focus = TRUE; + + if (HAS_FOCUS (window_impl) != had_focus) + generate_focus_event (window, TRUE); + } + /* Tell XInput stuff about it if appropriate */ if (window_private && !GDK_WINDOW_DESTROYED (window) && @@ -792,6 +841,19 @@ gdk_event_translate (GdkEvent *event, xevent->xcrossing.window, xevent->xcrossing.detail, xevent->xcrossing.subwindow)); + /* Handle focusing (in the case where no window manager is running */ + if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && + xevent->xcrossing.detail != NotifyInferior && + xevent->xcrossing.focus && !window_impl->has_focus) + { + 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.type = GDK_LEAVE_NOTIFY; event->crossing.window = window; @@ -853,38 +915,77 @@ gdk_event_translate (GdkEvent *event, break; - case FocusIn: - case FocusOut: /* We only care about focus events that indicate that _this_ * window (not a ancestor or child) got or lost the focus */ - switch (xevent->xfocus.detail) + case FocusIn: + GDK_NOTE (EVENTS, + g_message ("focus in:\t\twindow: %ld", xevent->xfocus.window)); + + if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD) { - case NotifyAncestor: - case NotifyInferior: - case NotifyNonlinear: - GDK_NOTE (EVENTS, - g_message ("focus %s:\t\twindow: %ld", - (xevent->xany.type == FocusIn) ? "in" : "out", - xevent->xfocus.window)); + gboolean had_focus = HAS_FOCUS (window_impl); + switch (xevent->xfocus.detail) + { + case NotifyAncestor: + case NotifyNonlinear: + case NotifyVirtual: + case NotifyNonlinearVirtual: + window_impl->has_focus = TRUE; + break; + case NotifyPointer: + window_impl->has_pointer_focus = TRUE; + break; + case NotifyInferior: + case NotifyPointerRoot: + case NotifyDetailNone: + break; + } + + if (HAS_FOCUS (window_impl) != had_focus) + generate_focus_event (window, TRUE); + } + break; + case FocusOut: + GDK_NOTE (EVENTS, + g_message ("focus out:\t\twindow: %ld", xevent->xfocus.window)); + + if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD) + { + gboolean had_focus = HAS_FOCUS (window_impl); + + switch (xevent->xfocus.detail) + { + case NotifyAncestor: + case NotifyNonlinear: + case NotifyVirtual: + case NotifyNonlinearVirtual: + window_impl->has_focus = FALSE; + break; + case NotifyPointer: + window_impl->has_pointer_focus = FALSE; + break; + case NotifyInferior: + case NotifyPointerRoot: + case NotifyDetailNone: + break; + } + + if (HAS_FOCUS (window_impl) != had_focus) + generate_focus_event (window, FALSE); + } + break; + +#if 0 /* gdk_keyboard_grab() causes following events. These events confuse * the XIM focus, so ignore them. */ if (xevent->xfocus.mode == NotifyGrab || xevent->xfocus.mode == NotifyUngrab) break; - - event->focus_change.type = GDK_FOCUS_CHANGE; - event->focus_change.window = window; - event->focus_change.in = (xevent->xany.type == FocusIn); +#endif - break; - default: - return_val = FALSE; - } - break; - case KeymapNotify: GDK_NOTE (EVENTS, g_message ("keymap notify")); @@ -1381,6 +1482,11 @@ gdk_wm_protocols_filter (GdkXEvent *xev, } else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus) { + GdkWindow *win = event->any.window; + Window focus_win = GDK_WINDOW_IMPL_X11(((GdkWindowObject *)win)->impl)->focus_window; + + XSetInputFocus (GDK_WINDOW_XDISPLAY (win), focus_win, + RevertToParent, xevent->xclient.data.l[1]); } else if ((Atom) xevent->xclient.data.l[0] == gdk_atom_intern ("_NET_WM_PING", FALSE)) { diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 8daa3061ca..e48e83132a 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -171,6 +171,8 @@ gdk_window_impl_x11_finalize (GObject *object) if (!GDK_WINDOW_DESTROYED (wrapper)) { gdk_xid_table_remove (draw_impl->xid); + if (window_impl->focus_window) + gdk_xid_table_remove (window_impl->focus_window); } G_OBJECT_CLASS (parent_class)->finalize (object); @@ -311,6 +313,8 @@ gdk_window_new (GdkWindow *parent, GdkVisual *visual; Window xparent; Visual *xvisual; + Display *xdisplay; + Window xid; XSetWindowAttributes xattributes; long xattributes_mask; @@ -342,7 +346,7 @@ gdk_window_new (GdkWindow *parent, draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); draw_impl->wrapper = GDK_DRAWABLE (window); - draw_impl->xdisplay = GDK_WINDOW_XDISPLAY (parent); + xdisplay = draw_impl->xdisplay = GDK_WINDOW_XDISPLAY (parent); private->parent = (GdkWindowObject *)parent; @@ -489,15 +493,14 @@ gdk_window_new (GdkWindow *parent, gdk_colormap_ref (draw_impl->colormap); } - draw_impl->xid = XCreateWindow (GDK_WINDOW_XDISPLAY (parent), - xparent, - impl->position_info.x, impl->position_info.y, - impl->position_info.width, impl->position_info.height, - 0, depth, class, xvisual, - xattributes_mask, &xattributes); + xid = draw_impl->xid = XCreateWindow (xdisplay, xparent, + impl->position_info.x, impl->position_info.y, + impl->position_info.width, impl->position_info.height, + 0, depth, class, xvisual, + xattributes_mask, &xattributes); gdk_drawable_ref (window); - gdk_xid_table_insert (&GDK_WINDOW_XID (window), window); + gdk_xid_table_insert (&draw_impl->xid, window); gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ? (attributes->cursor) : @@ -509,13 +512,10 @@ gdk_window_new (GdkWindow *parent, switch (GDK_WINDOW_TYPE (private)) { case GDK_WINDOW_DIALOG: - XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - xparent); + XSetTransientForHint (xdisplay, xid, xparent); case GDK_WINDOW_TOPLEVEL: case GDK_WINDOW_TEMP: - XSetWMProtocols (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), + XSetWMProtocols (xdisplay, xid, gdk_wm_window_protocols, 3); break; case GDK_WINDOW_CHILD: @@ -532,12 +532,30 @@ gdk_window_new (GdkWindow *parent, return window; } - + + if (class != InputOnly) + { + /* The focus window is off the visible area, and serves to receive key + * press events so they don't get sent to child windows. + */ + impl->focus_window = XCreateSimpleWindow (xdisplay, xid, + -1, -1, 1, 1, 0, + xattributes.background_pixel, + xattributes.background_pixel); + /* FIXME: probably better to actually track the requested event mask for the toplevel + */ + XSelectInput (xdisplay, impl->focus_window, + KeyPressMask | KeyReleaseMask | FocusChangeMask); + + XMapWindow (xdisplay, impl->focus_window); + gdk_xid_table_insert (&impl->focus_window, window); + } + size_hints.flags = PSize; size_hints.width = impl->width; size_hints.height = impl->height; - wm_hints.flags = InputHint | StateHint | WindowGroupHint; + wm_hints.flags = StateHint | WindowGroupHint; wm_hints.window_group = gdk_leader_window; wm_hints.input = True; wm_hints.initial_state = NormalState; @@ -546,19 +564,14 @@ gdk_window_new (GdkWindow *parent, * attention to PSize, and even if they do, is this the * correct value??? */ - XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - &size_hints); + XSetWMNormalHints (xdisplay, xid, &size_hints); - XSetWMHints (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - &wm_hints); + XSetWMHints (xdisplay, xid, &wm_hints); if (!wm_client_leader_atom) wm_client_leader_atom = gdk_atom_intern ("WM_CLIENT_LEADER", FALSE); - XChangeProperty (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), + XChangeProperty (xdisplay, xid, wm_client_leader_atom, XA_WINDOW, 32, PropModeReplace, (guchar*) &gdk_leader_window, 1); @@ -575,9 +588,7 @@ gdk_window_new (GdkWindow *parent, class_hint = XAllocClassHint (); class_hint->res_name = attributes->wmclass_name; class_hint->res_class = attributes->wmclass_class; - XSetClassHint (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - class_hint); + XSetClassHint (xdisplay, xid, class_hint); XFree (class_hint); } @@ -643,6 +654,8 @@ gdk_window_foreign_new (GdkNativeWindow anid) private->depth = attrs.depth; + _gdk_window_init_position (GDK_WINDOW (private)); + gdk_drawable_ref (window); gdk_xid_table_insert (&GDK_WINDOW_XID (window), window); @@ -700,8 +713,12 @@ _gdk_windowing_window_destroy (GdkWindow *window, void gdk_window_destroy_notify (GdkWindow *window) { + GdkWindowImplX11 *window_impl; + g_return_if_fail (window != NULL); + window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl); + if (!GDK_WINDOW_DESTROYED (window)) { if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN) @@ -711,6 +728,9 @@ gdk_window_destroy_notify (GdkWindow *window) } gdk_xid_table_remove (GDK_WINDOW_XID (window)); + if (window_impl->focus_window) + gdk_xid_table_remove (window_impl->focus_window); + gdk_drawable_unref (window); } @@ -992,8 +1012,7 @@ gdk_window_reparent (GdkWindow *window, g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); - g_return_if_fail (new_parent != NULL); - g_return_if_fail (GDK_IS_WINDOW (new_parent)); + g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent)); if (!new_parent) new_parent = gdk_parent_root; diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 76658b15c6..0aaf0f93c2 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -43,9 +43,9 @@ struct _GdkXPositionInfo gint height; gint x_offset; /* Offsets to add to X coordinates within window */ gint y_offset; /* to get GDK coodinates within window */ - gboolean big : 1; - gboolean mapped : 1; - gboolean no_bg : 1; /* Set when the window background is temporarily + guint big : 1; + guint mapped : 1; + guint no_bg : 1; /* Set when the window background is temporarily * unset during resizing and scaling */ GdkRectangle clip_rect; /* visible rectangle of window */ }; @@ -72,6 +72,22 @@ struct _GdkWindowImplX11 gint height; GdkXPositionInfo position_info; + + /* Set if the window, or any descendent of it, has the focus + */ + guint has_focus : 1; + + /* Set if !window_has_focus, but events are being sent to the + * window because the pointer is in it. (Typically, no window + * manager is running. + */ + guint has_pointer_focus : 1; + + /* We use an extra X window for toplevel windows that we XSetInputFocus() + * to in order to avoid getting keyboard events redirected to subwindows + * that might not even be part of this app + */ + Window focus_window; }; struct _GdkWindowImplX11Class |