Hiding the widget with the focus/default
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Cc: timj gtk org
- Subject: Hiding the widget with the focus/default
- Date: Mon, 11 Nov 2002 19:14:52 -0500 (EST)
I discovered a problem while while making GtkInputDialog
multihead-aware.
Consider the following heirarchy
A. GtkInputDialog
\
Vbox
\
B. Device control widgets
|
C. GtkLabel "No devices"
When we move the dialog from Display 1 (several devices) to
Display 2 (no XInput devices), we hide B and show C.
So, the sequence looks like:
unmap A
unrealize A
::screen-changed ... hide B, show C
realize A
map A
Say the focus widget is inside B at the start of the sequence,
then it remains there. But when A is re-realized, the widgets
in C are not rerealized since they are not visible.
This causes the code in gtkwindow.c to send events to the focus
widget to break since there is:
fevent->focus_change.window = g_object_ref (widget->window);
Now, we could simply change this to:
fevent->focus_change.window = widget->window;
if (fevent->focus_change.window)
g_object_ref (fevent->focus_change.window);
But it strikes me as wrong to have the focus on a hidden window,
so I came up with the following patch which unsets the focus
from within widgets when they are hidden.
Unfortunately, we can't make this an invariant, since we need
to support:
create_heirarchy
grab_focus (some_widget_in_heirarchy)
show_all (toplevel);
So, it's just a special-case hack. But it's probably a useful hack?
I'd appreciate it if anyone wanted to review this patch ... it's
actually smaller than it looks since most of it is just code
movement.
Thanks,
Owen
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.333
diff -u -p -r1.333 gtkwidget.c
--- gtk/gtkwidget.c 9 Nov 2002 16:46:24 -0000 1.333
+++ gtk/gtkwidget.c 12 Nov 2002 00:01:00 -0000
@@ -1522,41 +1522,12 @@ gtk_widget_unparent (GtkWidget *widget)
g_object_freeze_notify (G_OBJECT (widget));
nqueue = g_object_notify_queue_freeze (G_OBJECT (widget), _gtk_widget_child_property_notify_context);
- /* unset focused and default children properly, this code
- * should eventually move into some gtk_window_unparent_branch() or
- * similar function.
- */
-
toplevel = gtk_widget_get_toplevel (widget);
- if (GTK_CONTAINER (widget->parent)->focus_child == widget)
- {
- gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), NULL);
-
- if (GTK_WIDGET_TOPLEVEL (toplevel))
- {
- GtkWidget *child;
-
- child = GTK_WINDOW (toplevel)->focus_widget;
-
- while (child && child != widget)
- child = child->parent;
-
- if (child == widget)
- gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
- }
- }
if (GTK_WIDGET_TOPLEVEL (toplevel))
- {
- GtkWidget *child;
-
- child = GTK_WINDOW (toplevel)->default_widget;
-
- while (child && child != widget)
- child = child->parent;
-
- if (child == widget)
- gtk_window_set_default (GTK_WINDOW (toplevel), NULL);
- }
+ _gtk_window_unset_focus_default (GTK_WINDOW (toplevel), widget);
+
+ if (GTK_CONTAINER (widget->parent)->focus_child == widget)
+ gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), NULL);
/* If we are unanchoring the child, we save around the toplevel
* to emit hierarchy changed
@@ -1762,6 +1733,10 @@ gtk_widget_hide (GtkWidget *widget)
if (GTK_WIDGET_VISIBLE (widget))
{
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
+ if (toplevel != widget && GTK_WIDGET_TOPLEVEL (toplevel))
+ _gtk_window_unset_focus_default (GTK_WINDOW (toplevel), widget);
+
g_object_ref (widget);
g_signal_emit (widget, widget_signals[HIDE], 0);
if (!GTK_WIDGET_TOPLEVEL (widget))
@@ -4709,7 +4684,16 @@ gtk_widget_set_child_visible (GtkWidget
if (is_visible)
GTK_PRIVATE_SET_FLAG (widget, GTK_CHILD_VISIBLE);
else
- GTK_PRIVATE_UNSET_FLAG (widget, GTK_CHILD_VISIBLE);
+ {
+ GtkWidget *toplevel;
+
+ GTK_PRIVATE_UNSET_FLAG (widget, GTK_CHILD_VISIBLE);
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (toplevel != widget && GTK_WIDGET_TOPLEVEL (toplevel))
+ _gtk_window_unset_focus_default (GTK_WINDOW (toplevel), widget);
+ }
+
if (widget->parent && GTK_WIDGET_REALIZED (widget->parent))
{
if (GTK_WIDGET_MAPPED (widget->parent) &&
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.232
diff -u -p -r1.232 gtkwindow.c
--- gtk/gtkwindow.c 8 Nov 2002 23:03:36 -0000 1.232
+++ gtk/gtkwindow.c 12 Nov 2002 00:01:00 -0000
@@ -4336,6 +4336,41 @@ gtk_window_real_set_focus (GtkWindow *wi
}
}
+/**
+ * _gtk_window_unset_focus_default:
+ * @window: a #GtkWindow
+ * @widget: a widget inside of @window
+ *
+ * Checks whether the focus and default widgets of @window are
+ * @widget or a descendent of @widget, and if so, unset them.
+ **/
+void
+_gtk_window_unset_focus_default (GtkWindow *window,
+ GtkWidget *widget)
+
+{
+ GtkWidget *child;
+
+ if (GTK_CONTAINER (widget->parent)->focus_child == widget)
+ {
+ child = window->focus_widget;
+
+ while (child && child != widget)
+ child = child->parent;
+
+ if (child == widget)
+ gtk_window_set_focus (GTK_WINDOW (window), NULL);
+ }
+
+ child = window->default_widget;
+
+ while (child && child != widget)
+ child = child->parent;
+
+ if (child == widget)
+ gtk_window_set_default (window, NULL);
+}
+
/*********************************
* Functions related to resizing *
*********************************/
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.67
diff -u -p -r1.67 gtkwindow.h
--- gtk/gtkwindow.h 2 Nov 2002 05:37:04 -0000 1.67
+++ gtk/gtkwindow.h 12 Nov 2002 00:01:00 -0000
@@ -364,6 +364,9 @@ gboolean _gtk_window_activate_key
void _gtk_window_set_has_toplevel_focus (GtkWindow *window,
gboolean has_toplevel_focus);
+void _gtk_window_unset_focus_default (GtkWindow *window,
+ GtkWidget *widget);
+
void _gtk_window_set_is_active (GtkWindow *window,
gboolean is_active);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]