Commit ebd3958c authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor
Browse files

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.
parent 2c0b59f7
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,
......
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,
......
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,
......
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,
......
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,
......
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,
......
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,
......
......@@ -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))
{
......
......@@ -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;
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment