From c0f78ae00e839052a66ded3792888e7240821323 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Thu, 6 Jun 2002 15:38:39 +0000 Subject: [PATCH] Add a "is_focus" property indicating whether a widget is the focus widget Fri May 17 17:27:21 2002 Owen Taylor * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" property indicating whether a widget is the focus widget within the toplevel. * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" properties to indicate (separately) the idea of being the part of the toplevel with the input focus and being the active widget. (Needed for full XEMBED compliance.) * gtk/gtkplug.c gtk/gtksocket.c: Update to work in terms of is_active/has_toplevel_focus, and thus handle the active/focused XEMBED distinction correctly. * gtk/gtkplug.c (gtk_plug_realize): Remove FOCUS_CHANGE_MASK, since we don't need it. Fri May 17 18:07:34 2002 Owen Taylor * gtk/gtksocket.c (gtk_socket_add_window): Send XEMBED_EMBEDDED_NOTIFY. * gtk/gtksocket.c: Assume windows without _XEMBED_INFO property want to be mapped, for better current-Qt compatibility. --- ChangeLog | 29 +++++++++ ChangeLog.pre-2-10 | 29 +++++++++ ChangeLog.pre-2-2 | 29 +++++++++ ChangeLog.pre-2-4 | 29 +++++++++ ChangeLog.pre-2-6 | 29 +++++++++ ChangeLog.pre-2-8 | 29 +++++++++ gtk/gtkplug.c | 45 +++++-------- gtk/gtksocket.c | 156 ++++++++++++++++++++++++++------------------- gtk/gtksocket.h | 3 +- gtk/gtkwidget.c | 15 +++++ gtk/gtkwindow.c | 126 ++++++++++++++++++++++++++++++++---- gtk/gtkwindow.h | 10 ++- 12 files changed, 419 insertions(+), 110 deletions(-) diff --git a/ChangeLog b/ChangeLog index e80822f585..6c1a587639 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +Fri May 17 17:27:21 2002 Owen Taylor + + * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" + property indicating whether a widget is the focus + widget within the toplevel. + + * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" + properties to indicate (separately) the idea of + being the part of the toplevel with the input focus + and being the active widget. (Needed for full XEMBED + compliance.) + + * gtk/gtkplug.c gtk/gtksocket.c: Update to work + in terms of is_active/has_toplevel_focus, and thus + handle the active/focused XEMBED distinction + correctly. + + * gtk/gtkplug.c (gtk_plug_realize): Remove + FOCUS_CHANGE_MASK, since we don't need it. + +Fri May 17 18:07:34 2002 Owen Taylor + + * gtk/gtksocket.c (gtk_socket_add_window): Send + XEMBED_EMBEDDED_NOTIFY. + + * gtk/gtksocket.c: Assume windows without _XEMBED_INFO + property want to be mapped, for better + current-Qt compatibility. + Thu Jun 6 17:27:01 2002 Kristian Rietveld * gtk/gtkrbtree.c (_gtk_rbtree_reorder): don't leak the GArray diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index e80822f585..6c1a587639 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,32 @@ +Fri May 17 17:27:21 2002 Owen Taylor + + * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" + property indicating whether a widget is the focus + widget within the toplevel. + + * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" + properties to indicate (separately) the idea of + being the part of the toplevel with the input focus + and being the active widget. (Needed for full XEMBED + compliance.) + + * gtk/gtkplug.c gtk/gtksocket.c: Update to work + in terms of is_active/has_toplevel_focus, and thus + handle the active/focused XEMBED distinction + correctly. + + * gtk/gtkplug.c (gtk_plug_realize): Remove + FOCUS_CHANGE_MASK, since we don't need it. + +Fri May 17 18:07:34 2002 Owen Taylor + + * gtk/gtksocket.c (gtk_socket_add_window): Send + XEMBED_EMBEDDED_NOTIFY. + + * gtk/gtksocket.c: Assume windows without _XEMBED_INFO + property want to be mapped, for better + current-Qt compatibility. + Thu Jun 6 17:27:01 2002 Kristian Rietveld * gtk/gtkrbtree.c (_gtk_rbtree_reorder): don't leak the GArray diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index e80822f585..6c1a587639 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,32 @@ +Fri May 17 17:27:21 2002 Owen Taylor + + * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" + property indicating whether a widget is the focus + widget within the toplevel. + + * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" + properties to indicate (separately) the idea of + being the part of the toplevel with the input focus + and being the active widget. (Needed for full XEMBED + compliance.) + + * gtk/gtkplug.c gtk/gtksocket.c: Update to work + in terms of is_active/has_toplevel_focus, and thus + handle the active/focused XEMBED distinction + correctly. + + * gtk/gtkplug.c (gtk_plug_realize): Remove + FOCUS_CHANGE_MASK, since we don't need it. + +Fri May 17 18:07:34 2002 Owen Taylor + + * gtk/gtksocket.c (gtk_socket_add_window): Send + XEMBED_EMBEDDED_NOTIFY. + + * gtk/gtksocket.c: Assume windows without _XEMBED_INFO + property want to be mapped, for better + current-Qt compatibility. + Thu Jun 6 17:27:01 2002 Kristian Rietveld * gtk/gtkrbtree.c (_gtk_rbtree_reorder): don't leak the GArray diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index e80822f585..6c1a587639 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,32 @@ +Fri May 17 17:27:21 2002 Owen Taylor + + * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" + property indicating whether a widget is the focus + widget within the toplevel. + + * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" + properties to indicate (separately) the idea of + being the part of the toplevel with the input focus + and being the active widget. (Needed for full XEMBED + compliance.) + + * gtk/gtkplug.c gtk/gtksocket.c: Update to work + in terms of is_active/has_toplevel_focus, and thus + handle the active/focused XEMBED distinction + correctly. + + * gtk/gtkplug.c (gtk_plug_realize): Remove + FOCUS_CHANGE_MASK, since we don't need it. + +Fri May 17 18:07:34 2002 Owen Taylor + + * gtk/gtksocket.c (gtk_socket_add_window): Send + XEMBED_EMBEDDED_NOTIFY. + + * gtk/gtksocket.c: Assume windows without _XEMBED_INFO + property want to be mapped, for better + current-Qt compatibility. + Thu Jun 6 17:27:01 2002 Kristian Rietveld * gtk/gtkrbtree.c (_gtk_rbtree_reorder): don't leak the GArray diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index e80822f585..6c1a587639 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,32 @@ +Fri May 17 17:27:21 2002 Owen Taylor + + * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" + property indicating whether a widget is the focus + widget within the toplevel. + + * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" + properties to indicate (separately) the idea of + being the part of the toplevel with the input focus + and being the active widget. (Needed for full XEMBED + compliance.) + + * gtk/gtkplug.c gtk/gtksocket.c: Update to work + in terms of is_active/has_toplevel_focus, and thus + handle the active/focused XEMBED distinction + correctly. + + * gtk/gtkplug.c (gtk_plug_realize): Remove + FOCUS_CHANGE_MASK, since we don't need it. + +Fri May 17 18:07:34 2002 Owen Taylor + + * gtk/gtksocket.c (gtk_socket_add_window): Send + XEMBED_EMBEDDED_NOTIFY. + + * gtk/gtksocket.c: Assume windows without _XEMBED_INFO + property want to be mapped, for better + current-Qt compatibility. + Thu Jun 6 17:27:01 2002 Kristian Rietveld * gtk/gtkrbtree.c (_gtk_rbtree_reorder): don't leak the GArray diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index e80822f585..6c1a587639 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,32 @@ +Fri May 17 17:27:21 2002 Owen Taylor + + * gtk/gtkwindow.c gtk/gtkwidget.c: Add a "is_focus" + property indicating whether a widget is the focus + widget within the toplevel. + + * gtk/gtkwindow.[ch]: Add "is_active" "has_toplevel_focus" + properties to indicate (separately) the idea of + being the part of the toplevel with the input focus + and being the active widget. (Needed for full XEMBED + compliance.) + + * gtk/gtkplug.c gtk/gtksocket.c: Update to work + in terms of is_active/has_toplevel_focus, and thus + handle the active/focused XEMBED distinction + correctly. + + * gtk/gtkplug.c (gtk_plug_realize): Remove + FOCUS_CHANGE_MASK, since we don't need it. + +Fri May 17 18:07:34 2002 Owen Taylor + + * gtk/gtksocket.c (gtk_socket_add_window): Send + XEMBED_EMBEDDED_NOTIFY. + + * gtk/gtksocket.c: Assume windows without _XEMBED_INFO + property want to be mapped, for better + current-Qt compatibility. + Thu Jun 6 17:27:01 2002 Kristian Rietveld * gtk/gtkrbtree.c (_gtk_rbtree_reorder): don't leak the GArray diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index c74c7c4714..25f572dd74 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -504,7 +504,6 @@ gtk_plug_realize (GtkWidget *widget) GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | - GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK); attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP; @@ -681,7 +680,7 @@ gtk_plug_set_focus (GtkWindow *window, /* Ask for focus from embedder */ - if (focus && !window->has_focus) + if (focus && !window->has_toplevel_focus) { send_xembed_message (plug, XEMBED_REQUEST_FOCUS, 0, 0, 0, gtk_get_current_event_time ()); @@ -885,6 +884,9 @@ send_xembed_message (GtkPlug *plug, GdkDisplay *display = gdk_drawable_get_display (plug->socket_window); XEvent xevent; + GTK_NOTE(PLUGSOCKET, + g_message ("GtkPlug: Sending XEMBED message of type %ld", message)); + xevent.xclient.window = GDK_WINDOW_XWINDOW (plug->socket_window); xevent.xclient.type = ClientMessage; xevent.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"); @@ -977,20 +979,20 @@ handle_xembed_message (GtkPlug *plug, glong data2, guint32 time) { + GtkWindow *window = GTK_WINDOW (plug); + GTK_NOTE (PLUGSOCKET, - g_message ("Message of type %ld received", message)); + g_message ("GtkPlug: Message of type %ld received", message)); switch (message) { case XEMBED_EMBEDDED_NOTIFY: break; case XEMBED_WINDOW_ACTIVATE: - GTK_NOTE(PLUGSOCKET, - g_message ("GtkPlug: ACTIVATE received")); + _gtk_window_set_is_active (window, TRUE); break; case XEMBED_WINDOW_DEACTIVATE: - GTK_NOTE(PLUGSOCKET, - g_message ("GtkPlug: DEACTIVATE received")); + _gtk_window_set_is_active (window, FALSE); break; case XEMBED_MODALITY_ON: @@ -1001,6 +1003,7 @@ handle_xembed_message (GtkPlug *plug, break; case XEMBED_FOCUS_IN: + _gtk_window_set_has_toplevel_focus (window, TRUE); switch (detail) { case XEMBED_FOCUS_FIRST: @@ -1010,31 +1013,13 @@ handle_xembed_message (GtkPlug *plug, focus_first_last (plug, GTK_DIR_TAB_BACKWARD); break; case XEMBED_FOCUS_CURRENT: - /* fall through */; + break; } - + break; + case XEMBED_FOCUS_OUT: - { - GtkWidget *widget = GTK_WIDGET (plug); - GdkEvent event; - - event.focus_change.type = GDK_FOCUS_CHANGE; - event.focus_change.window = widget->window; - event.focus_change.send_event = TRUE; - - if (message == XEMBED_FOCUS_IN) - { - event.focus_change.in = TRUE; - GTK_WIDGET_CLASS (parent_class)->focus_in_event (widget, (GdkEventFocus *)&event); - } - else - { - event.focus_change.in = FALSE; - GTK_WIDGET_CLASS (parent_class)->focus_out_event (widget, (GdkEventFocus *)&event); - } - - break; - } + _gtk_window_set_has_toplevel_focus (window, FALSE); + break; case XEMBED_GRAB_KEY: case XEMBED_UNGRAB_KEY: diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c index 7496ef01c7..53a10bae8c 100644 --- a/gtk/gtksocket.c +++ b/gtk/gtksocket.c @@ -25,6 +25,8 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include + #include "gdk/gdkkeysyms.h" #include "gtkmain.h" #include "gtkmarshalers.h" @@ -51,6 +53,8 @@ struct _GtkSocketPrivate static void gtk_socket_class_init (GtkSocketClass *klass); static void gtk_socket_init (GtkSocket *socket); static void gtk_socket_finalize (GObject *object); +static void gtk_socket_notify (GObject *object, + GParamSpec *pspec); static void gtk_socket_realize (GtkWidget *widget); static void gtk_socket_unrealize (GtkWidget *widget); static void gtk_socket_size_request (GtkWidget *widget, @@ -63,11 +67,8 @@ static void gtk_socket_grab_notify (GtkWidget *widget, gboolean was_grabbed); static gboolean gtk_socket_key_press_event (GtkWidget *widget, GdkEventKey *event); -static gboolean gtk_socket_focus_in_event (GtkWidget *widget, - GdkEventFocus *event); -static void gtk_socket_claim_focus (GtkSocket *socket); -static gboolean gtk_socket_focus_out_event (GtkWidget *widget, - GdkEventFocus *event); +static void gtk_socket_claim_focus (GtkSocket *socket, + gboolean send_event); static void gtk_socket_send_configure_event (GtkSocket *socket); static gboolean gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction); @@ -125,6 +126,8 @@ gtk_socket_get_private (GtkSocket *socket) if (!private) { private = g_new0 (GtkSocketPrivate, 1); + private->resize_count = 0; + g_object_set_qdata_full (G_OBJECT (socket), private_quark, private, (GDestroyNotify) g_free); } @@ -183,6 +186,7 @@ gtk_socket_class_init (GtkSocketClass *class) parent_class = gtk_type_class (GTK_TYPE_CONTAINER); gobject_class->finalize = gtk_socket_finalize; + gobject_class->notify = gtk_socket_notify; widget_class->realize = gtk_socket_realize; widget_class->unrealize = gtk_socket_unrealize; @@ -191,8 +195,6 @@ gtk_socket_class_init (GtkSocketClass *class) widget_class->hierarchy_changed = gtk_socket_hierarchy_changed; widget_class->grab_notify = gtk_socket_grab_notify; widget_class->key_press_event = gtk_socket_key_press_event; - widget_class->focus_in_event = gtk_socket_focus_in_event; - widget_class->focus_out_event = gtk_socket_focus_out_event; widget_class->focus = gtk_socket_focus; container_class->remove = gtk_socket_remove; @@ -229,6 +231,7 @@ gtk_socket_init (GtkSocket *socket) socket->focus_in = FALSE; socket->have_size = FALSE; socket->need_map = FALSE; + socket->active = FALSE; socket->accel_group = gtk_accel_group_new (); g_object_set_data (G_OBJECT (socket->accel_group), "gtk-socket", socket); @@ -660,32 +663,60 @@ remove_grabbed_key (GtkSocket *socket, keyval, modifiers); } -static gboolean -toplevel_focus_in_handler (GtkWidget *toplevel, - GdkEventFocus *event, - GtkSocket *socket) +static void +socket_update_focus_in (GtkSocket *socket) { - /* It appears spurious focus in events can occur when - * the window is hidden. So we'll just check to see if - * the window is visible before actually handling the - * event. (Comment from gtkwindow.c) - */ - if (GTK_WIDGET_VISIBLE (toplevel)) - send_xembed_message (socket, XEMBED_WINDOW_ACTIVATE, 0, 0, 0, - gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */ + gboolean focus_in = FALSE; - return FALSE; + if (socket->plug_window) + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (GTK_WIDGET_TOPLEVEL (toplevel) && + GTK_WINDOW (toplevel)->has_toplevel_focus && + gtk_widget_is_focus (GTK_WIDGET (socket))) + focus_in = TRUE; + } + + if (focus_in != socket->focus_in) + { + socket->focus_in = focus_in; + + if (focus_in) + { + send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, + gtk_get_current_event_time ()); + } + else + { + send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0, + gtk_get_current_event_time ()); + + } + } } -static gboolean -toplevel_focus_out_handler (GtkWidget *toplevel, - GdkEventFocus *event, - GtkSocket *socket) +static void +socket_update_active (GtkSocket *socket) { - send_xembed_message (socket, XEMBED_WINDOW_DEACTIVATE, 0, 0, 0, - gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */ + gboolean active = FALSE; - return FALSE; + if (socket->plug_window) + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (GTK_WIDGET_TOPLEVEL (toplevel) && + GTK_WINDOW (toplevel)->is_active) + active = TRUE; + } + + if (active != socket->active) + { + socket->active = active; + + send_xembed_message (socket, + active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE, + 0, 0, 0, + gtk_get_current_event_time ()); + } } static void @@ -703,8 +734,10 @@ gtk_socket_hierarchy_changed (GtkWidget *widget, if (socket->toplevel) { gtk_window_remove_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group); - gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket); - gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket); + g_signal_handlers_disconnect_by_func (socket->toplevel, + (gpointer) socket_update_focus_in, socket); + g_signal_handlers_disconnect_by_func (socket->toplevel, + (gpointer) socket_update_active, socket); } socket->toplevel = toplevel; @@ -712,11 +745,14 @@ gtk_socket_hierarchy_changed (GtkWidget *widget, if (toplevel) { gtk_window_add_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group); - gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event", - GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket); - gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event", - GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket); + g_signal_connect_swapped (socket->toplevel, "notify::has_toplevel_focus", + G_CALLBACK (socket_update_focus_in), socket); + g_signal_connect_swapped (socket->toplevel, "notify::is_active", + G_CALLBACK (socket_update_active), socket); } + + socket_update_focus_in (socket); + socket_update_active (socket); } } @@ -769,39 +805,23 @@ gtk_socket_key_press_event (GtkWidget *widget, return FALSE; } -static gboolean -gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event) +static void +gtk_socket_notify (GObject *object, + GParamSpec *pspec) { - GtkSocket *socket = GTK_SOCKET (widget); + if (!strcmp (pspec->name, "is_focus")) + return; - if (socket->plug_window) - send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, - gtk_get_current_event_time ()); - - return TRUE; -} - -static gboolean -gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event) -{ - GtkSocket *socket = GTK_SOCKET (widget); - if (socket->plug_window) - { - send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0, - gtk_get_current_event_time ()); - } - - socket->focus_in = FALSE; - - return TRUE; + socket_update_focus_in (GTK_SOCKET (object)); } static void -gtk_socket_claim_focus (GtkSocket *socket) +gtk_socket_claim_focus (GtkSocket *socket, + gboolean send_event) { + if (!send_event) + socket->focus_in = TRUE; /* Otherwise, our notify handler will send FOCUS_IN */ - socket->focus_in = TRUE; - /* Oh, the trickery... */ GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS); @@ -841,8 +861,7 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction) send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0, gtk_get_current_event_time ()); - GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); - gtk_widget_grab_focus (widget); + gtk_socket_claim_focus (socket, FALSE); return TRUE; } @@ -916,7 +935,6 @@ gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid, gboolean need_reparent) { - GtkWidget *widget = GTK_WIDGET (socket); GdkDisplay *display = gtk_widget_get_display (widget); gpointer user_data = NULL; @@ -996,7 +1014,7 @@ gtk_socket_add_window (GtkSocket *socket, { /* FIXME, we should probably actually check the state before we started */ - socket->is_mapped = need_reparent ? TRUE : FALSE; + socket->is_mapped = TRUE; } socket->need_map = socket->is_mapped; @@ -1017,6 +1035,11 @@ gtk_socket_add_window (GtkSocket *socket, if (toplevel && GTK_IS_WINDOW (toplevel)) gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid); + send_xembed_message (socket, XEMBED_EMBEDDED_NOTIFY, 0, 0, 0, + gtk_get_current_event_time ()); + socket_update_active (socket); + socket_update_focus_in (socket); + gtk_widget_queue_resize (GTK_WIDGET (socket)); } @@ -1120,6 +1143,9 @@ handle_xembed_message (GtkSocket *socket, glong data2, guint32 time) { + GTK_NOTE (PLUGSOCKET, + g_message ("GtkSocket: Message of type %ld received", message)); + switch (message) { case XEMBED_EMBEDDED_NOTIFY: @@ -1133,7 +1159,7 @@ handle_xembed_message (GtkSocket *socket, break; case XEMBED_REQUEST_FOCUS: - gtk_socket_claim_focus (socket); + gtk_socket_claim_focus (socket, TRUE); break; case XEMBED_FOCUS_NEXT: @@ -1309,7 +1335,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) case FocusIn: if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS) { - gtk_socket_claim_focus (socket); + gtk_socket_claim_focus (socket, TRUE); } return_val = GDK_FILTER_REMOVE; break; diff --git a/gtk/gtksocket.h b/gtk/gtksocket.h index b6859cc8a9..bdc4baecf4 100644 --- a/gtk/gtksocket.h +++ b/gtk/gtksocket.h @@ -62,7 +62,8 @@ struct _GtkSocket guint have_size : 1; guint need_map : 1; guint is_mapped : 1; - + guint active : 1; + GtkAccelGroup *accel_group; GtkWidget *toplevel; }; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index e8a93780e7..379877932d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -131,6 +131,7 @@ enum { PROP_APP_PAINTABLE, PROP_CAN_FOCUS, PROP_HAS_FOCUS, + PROP_IS_FOCUS, PROP_CAN_DEFAULT, PROP_HAS_DEFAULT, PROP_RECEIVES_DEFAULT, @@ -453,6 +454,13 @@ gtk_widget_class_init (GtkWidgetClass *klass) _("Whether the widget has the input focus"), FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_HAS_FOCUS, + g_param_spec_boolean ("is_focus", + _("Is focus"), + _("Whether the widget is the focus widget within the toplevel"), + FALSE, + G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CAN_DEFAULT, g_param_spec_boolean ("can_default", @@ -1142,6 +1150,10 @@ gtk_widget_set_property (GObject *object, if (g_value_get_boolean (value)) gtk_widget_grab_focus (widget); break; + case PROP_IS_FOCUS: + if (g_value_get_boolean (value)) + gtk_widget_grab_focus (widget); + break; case PROP_CAN_DEFAULT: saved_flags = GTK_WIDGET_FLAGS (widget); if (g_value_get_boolean (value)) @@ -1230,6 +1242,9 @@ gtk_widget_get_property (GObject *object, case PROP_HAS_FOCUS: g_value_set_boolean (value, (GTK_WIDGET_HAS_FOCUS (widget) != FALSE)); break; + case PROP_IS_FOCUS: + g_value_set_boolean (value, (gtk_widget_is_focus (widget))); + break; case PROP_CAN_DEFAULT: g_value_set_boolean (value, (GTK_WIDGET_CAN_DEFAULT (widget) != FALSE)); break; diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 78822c462b..70ff43b46c 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -70,6 +70,10 @@ enum { PROP_DESTROY_WITH_PARENT, PROP_ICON, PROP_SCREEN, + + /* Readonly properties */ + PROP_IS_ACTIVE, + PROP_HAS_TOPLEVEL_FOCUS, LAST_ARG }; @@ -504,6 +508,22 @@ gtk_window_class_init (GtkWindowClass *klass) GDK_TYPE_SCREEN, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_IS_ACTIVE, + g_param_spec_boolean ("is_active", + _("Is Active"), + _("Whether the toplevel is the current active window"), + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_HAS_TOPLEVEL_FOCUS, + g_param_spec_boolean ("has_toplevel_focus", + _("Focus in Toplevel"), + _("Whether the input focus is within this GtkWindow"), + FALSE, + G_PARAM_READABLE)); + window_signals[SET_FOCUS] = g_signal_new ("set_focus", G_TYPE_FROM_CLASS (object_class), @@ -770,6 +790,12 @@ gtk_window_get_property (GObject *object, case PROP_SCREEN: g_value_set_object (value, window->screen); break; + case PROP_IS_ACTIVE: + g_value_set_boolean (value, window->is_active); + break; + case PROP_HAS_TOPLEVEL_FOCUS: + g_value_set_boolean (value, window->has_toplevel_focus); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3772,14 +3798,10 @@ gtk_window_focus_in_event (GtkWidget *widget, */ if (GTK_WIDGET_VISIBLE (widget)) { - window->has_focus = TRUE; - - if (window->focus_widget && - window->focus_widget != widget && - !GTK_WIDGET_HAS_FOCUS (window->focus_widget)) - do_focus_change (window->focus_widget, TRUE); + _gtk_window_set_has_toplevel_focus (window, TRUE); + _gtk_window_set_is_active (window, TRUE); } - + return FALSE; } @@ -3789,12 +3811,8 @@ gtk_window_focus_out_event (GtkWidget *widget, { GtkWindow *window = GTK_WINDOW (widget); - window->has_focus = FALSE; - - if (window->focus_widget && - window->focus_widget != widget && - GTK_WIDGET_HAS_FOCUS (window->focus_widget)) - do_focus_change (window->focus_widget, FALSE); + _gtk_window_set_has_toplevel_focus (window, FALSE); + _gtk_window_set_is_active (window, FALSE); return FALSE; } @@ -3934,6 +3952,8 @@ gtk_window_real_set_focus (GtkWindow *window, if (window->has_focus) do_focus_change (window->focus_widget, FALSE); + + g_object_notify (G_OBJECT (window->focus_widget), "is_focus"); } window->focus_widget = focus; @@ -3952,6 +3972,8 @@ gtk_window_real_set_focus (GtkWindow *window, if (window->has_focus) do_focus_change (window->focus_widget, TRUE); + + g_object_notify (G_OBJECT (window->focus_widget), "is_focus"); } if (window->default_widget && @@ -6084,3 +6106,81 @@ _gtk_window_activate_key (GtkWindow *window, else return FALSE; } + +static void +window_update_has_focus (GtkWindow *window) +{ + GtkWidget *widget = GTK_WIDGET (window); + gboolean has_focus = window->has_toplevel_focus && window->is_active; + + if (has_focus != window->has_focus) + { + window->has_focus = has_focus; + + if (has_focus) + { + if (window->focus_widget && + window->focus_widget != widget && + !GTK_WIDGET_HAS_FOCUS (window->focus_widget)) + do_focus_change (window->focus_widget, TRUE); + } + else + { + if (window->focus_widget && + window->focus_widget != widget && + GTK_WIDGET_HAS_FOCUS (window->focus_widget)) + do_focus_change (window->focus_widget, FALSE); + } + } +} + +/** + * _gtk_window_set_is_active: + * @window: a #GtkWindow + * @is_active: %TRUE if the window is in the currently active toplevel + * + * Internal function that sets whether the #GtkWindow is part + * of the currently active toplevel window (taking into account inter-process + * embedding.) + **/ +void +_gtk_window_set_is_active (GtkWindow *window, + gboolean is_active) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + + is_active = is_active != FALSE; + + if (is_active != window->is_active) + { + window->is_active = is_active; + window_update_has_focus (window); + + g_object_notify (G_OBJECT (window), "is_active"); + } +} + +/** + * _gtk_window_set_has_toplevel_focus: + * @window: a #GtkWindow + * @has_toplevel_focus: %TRUE if the in + * + * Internal function that sets whether the keyboard focus for the + * toplevel window (taking into account inter-process embedding.) + **/ +void +_gtk_window_set_has_toplevel_focus (GtkWindow *window, + gboolean has_toplevel_focus) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + + has_toplevel_focus = has_toplevel_focus != FALSE; + + if (has_toplevel_focus != window->has_toplevel_focus) + { + window->has_toplevel_focus = has_toplevel_focus; + window_update_has_focus (window); + + g_object_notify (G_OBJECT (window), "has_toplevel_focus"); + } +} diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 0251131be3..9dff5d7205 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -98,7 +98,10 @@ struct _GtkWindow guint decorated : 1; guint type_hint : 3; /* GdkWindowTypeHint */ - guint gravity : 5; /* GdkGravity */ + guint gravity : 5; /* GdkGravity */ + + guint is_active : 1; + guint has_toplevel_focus : 1; guint frame_left; guint frame_top; @@ -344,6 +347,11 @@ GtkWindowGroup *_gtk_window_get_group (GtkWindow *window); gboolean _gtk_window_activate_key (GtkWindow *window, GdkEventKey *event); +void _gtk_window_set_has_toplevel_focus (GtkWindow *window, + gboolean has_toplevel_focus); +void _gtk_window_set_is_active (GtkWindow *window, + gboolean is_active); + typedef void (*GtkWindowKeysForeachFunc) (GtkWindow *window, guint keyval, GdkModifierType modifiers,