Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cc1b701cdf | |||
| b29661a8ce | |||
| f49bfd24db | |||
| d75fb7ca1b | |||
| b0d2150265 | |||
| 0a8babde25 | |||
| d14a387385 | |||
| 36727b6d7a | |||
| 9229962071 | |||
| 6867a7852b | |||
| 89b6d9b496 | |||
| fae6a2b565 | |||
| 728f838322 | |||
| 1743dd8f60 | |||
| 60a9b330a6 | |||
| 1c0ff3ac86 | |||
| 7b638e0268 | |||
| 14027f949e | |||
| 925f15b718 | |||
| e6c58e6e63 | |||
| 44d6f939e4 | |||
| bbcad8ae42 | |||
| 1fd323f635 | |||
| c43f886ce5 | |||
| 184e002eed | |||
| fa1816be27 | |||
| fea71a5332 | |||
| 13382618d8 | |||
| 96e6416885 | |||
| ab8f68092c | |||
| 269056a6fb | |||
| 0ab4ec1169 | |||
| a6d4c2adeb | |||
| 2dbd2381fa | |||
| 6c01e2e5e6 | |||
| 530e3ff9c7 | |||
| d4a5f3fe69 | |||
| 918b931cc6 | |||
| a0dc7b473a | |||
| 8a6cdeff1d | |||
| 90129235e1 | |||
| 542e2a27d7 | |||
| 39c44b9d2e | |||
| ed3bd0977b | |||
| 8d4c25fc09 | |||
| 45d76c9a6d | |||
| 02d7e6ee32 | |||
| 8224ac55f2 | |||
| 573fbc2ab3 | |||
| fe2181f4a8 | |||
| 9b8668520d | |||
| 9d72f73066 | |||
| a361f09cb0 | |||
| b4c22a1236 | |||
| 9699c0883a | |||
| 9a98a373d3 | |||
| 4c6aad6457 | |||
| 549f5dc809 | |||
| 510f1ca461 | |||
| d63ef94bc8 | |||
| 50c0a79bb6 | |||
| b9976ef9a7 | |||
| 1e38c78f55 | |||
| 0addf7a4a4 |
@@ -904,7 +904,6 @@ gtk_text_set_attributes
|
||||
gtk_text_get_attributes
|
||||
gtk_text_set_tabs
|
||||
gtk_text_get_tabs
|
||||
gtk_text_grab_focus_without_selecting
|
||||
<SUBSECTION Private>
|
||||
gtk_text_get_type
|
||||
</SECTION>
|
||||
|
||||
@@ -165,6 +165,7 @@
|
||||
#include <gtk/gtkpicture.h>
|
||||
#include <gtk/gtkpopover.h>
|
||||
#include <gtk/gtkpopovermenu.h>
|
||||
#include <gtk/gtkpopup.h>
|
||||
#include <gtk/gtkprintcontext.h>
|
||||
#include <gtk/gtkprintoperation.h>
|
||||
#include <gtk/gtkprintoperationpreview.h>
|
||||
|
||||
+22
-10
@@ -129,6 +129,22 @@ swatch_activate (GtkColorSwatch *swatch,
|
||||
_gtk_color_chooser_color_activated (GTK_COLOR_CHOOSER (cc), &color);
|
||||
}
|
||||
|
||||
static void
|
||||
show_editor (GtkColorChooserWidget *cc,
|
||||
gboolean show)
|
||||
{
|
||||
gtk_widget_set_visible (cc->priv->palette, !show);
|
||||
gtk_widget_set_visible (cc->priv->editor, show);
|
||||
gtk_widget_set_child_focusable (cc->priv->palette, !show);
|
||||
gtk_widget_set_child_focusable (cc->priv->editor, show);
|
||||
if (show)
|
||||
gtk_widget_child_focus (cc->priv->editor, GTK_DIR_TAB_FORWARD);
|
||||
else
|
||||
gtk_widget_child_focus (cc->priv->palette, GTK_DIR_TAB_FORWARD);
|
||||
|
||||
g_object_notify (G_OBJECT (cc), "show-editor");
|
||||
}
|
||||
|
||||
static void
|
||||
swatch_customize (GtkColorSwatch *swatch,
|
||||
GtkColorChooserWidget *cc)
|
||||
@@ -138,9 +154,7 @@ swatch_customize (GtkColorSwatch *swatch,
|
||||
gtk_color_swatch_get_rgba (swatch, &color);
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (cc->priv->editor), &color);
|
||||
|
||||
gtk_widget_hide (cc->priv->palette);
|
||||
gtk_widget_show (cc->priv->editor);
|
||||
g_object_notify (G_OBJECT (cc), "show-editor");
|
||||
show_editor (cc, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -174,9 +188,7 @@ button_activate (GtkColorSwatch *swatch,
|
||||
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (cc->priv->editor), &color);
|
||||
|
||||
gtk_widget_hide (cc->priv->palette);
|
||||
gtk_widget_show (cc->priv->editor);
|
||||
g_object_notify (G_OBJECT (cc), "show-editor");
|
||||
show_editor (cc, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -260,9 +272,9 @@ gtk_color_chooser_widget_set_use_alpha (GtkColorChooserWidget *cc,
|
||||
|
||||
static void
|
||||
gtk_color_chooser_widget_set_show_editor (GtkColorChooserWidget *cc,
|
||||
gboolean show_editor)
|
||||
gboolean show)
|
||||
{
|
||||
if (show_editor)
|
||||
if (show)
|
||||
{
|
||||
GdkRGBA color = { 0.75, 0.25, 0.25, 1.0 };
|
||||
|
||||
@@ -271,8 +283,7 @@ gtk_color_chooser_widget_set_show_editor (GtkColorChooserWidget *cc,
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (cc->priv->editor), &color);
|
||||
}
|
||||
|
||||
gtk_widget_set_visible (cc->priv->editor, show_editor);
|
||||
gtk_widget_set_visible (cc->priv->palette, !show_editor);
|
||||
show_editor (cc, show);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -592,6 +603,7 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (cc), &color);
|
||||
|
||||
gtk_widget_hide (GTK_WIDGET (cc->priv->editor));
|
||||
gtk_widget_set_child_focusable (GTK_WIDGET (cc->priv->editor), FALSE);
|
||||
|
||||
cc->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
gtk_size_group_add_widget (cc->priv->size_group, cc->priv->palette);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "gtkspinbutton.h"
|
||||
#include "gtkstylecontext.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkroot.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -224,7 +225,7 @@ popup_edit (GtkWidget *widget,
|
||||
{
|
||||
dismiss_current_popup (editor);
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor));
|
||||
g_set_object (&editor->priv->popdown_focus, gtk_window_get_focus (GTK_WINDOW (toplevel)));
|
||||
g_set_object (&editor->priv->popdown_focus, gtk_root_get_focus (GTK_ROOT (toplevel)));
|
||||
editor->priv->current_popup = popup;
|
||||
editor->priv->popup_position = position;
|
||||
gtk_widget_show (popup);
|
||||
|
||||
+1
-122
@@ -39,6 +39,7 @@
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtkpopup.h"
|
||||
|
||||
#include "a11y/gtkcontaineraccessibleprivate.h"
|
||||
|
||||
@@ -117,14 +118,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
struct _GtkContainerPrivate
|
||||
{
|
||||
guint resize_handler;
|
||||
|
||||
guint restyle_pending : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
ADD,
|
||||
REMOVE,
|
||||
@@ -226,9 +219,6 @@ gtk_container_get_type (void)
|
||||
g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer"),
|
||||
&container_info, G_TYPE_FLAG_ABSTRACT);
|
||||
|
||||
GtkContainer_private_offset =
|
||||
g_type_add_instance_private (container_type, sizeof (GtkContainerPrivate));
|
||||
|
||||
g_type_add_interface_static (container_type,
|
||||
GTK_TYPE_BUILDABLE,
|
||||
&buildable_info);
|
||||
@@ -1246,10 +1236,6 @@ static void
|
||||
gtk_container_destroy (GtkWidget *widget)
|
||||
{
|
||||
GtkContainer *container = GTK_CONTAINER (widget);
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
|
||||
if (priv->restyle_pending)
|
||||
priv->restyle_pending = FALSE;
|
||||
|
||||
gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL);
|
||||
|
||||
@@ -1334,113 +1320,6 @@ gtk_container_remove (GtkContainer *container,
|
||||
g_object_unref (container);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_container_needs_idle_sizer (GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
|
||||
if (priv->restyle_pending)
|
||||
return TRUE;
|
||||
|
||||
return gtk_widget_needs_allocate (GTK_WIDGET (container));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_container_idle_sizer (GdkFrameClock *clock,
|
||||
GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
|
||||
/* We validate the style contexts in a single loop before even trying
|
||||
* to handle resizes instead of doing validations inline.
|
||||
* This is mostly necessary for compatibility reasons with old code,
|
||||
* because both style_updated and size_allocate functions often change
|
||||
* styles and so could cause infinite loops in this function.
|
||||
*
|
||||
* It's important to note that even an invalid style context returns
|
||||
* sane values. So the result of an invalid style context will never be
|
||||
* a program crash, but only a wrong layout or rendering.
|
||||
*/
|
||||
if (priv->restyle_pending)
|
||||
{
|
||||
priv->restyle_pending = FALSE;
|
||||
gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (container)));
|
||||
}
|
||||
|
||||
/* we may be invoked with a container_resize_queue of NULL, because
|
||||
* queue_resize could have been adding an extra idle function while
|
||||
* the queue still got processed. we better just ignore such case
|
||||
* than trying to explicitly work around them with some extra flags,
|
||||
* since it doesn't cause any actual harm.
|
||||
*/
|
||||
if (gtk_widget_needs_allocate (GTK_WIDGET (container)))
|
||||
{
|
||||
if (GTK_IS_WINDOW (container))
|
||||
gtk_window_check_resize (GTK_WINDOW (container));
|
||||
else
|
||||
g_warning ("gtk_container_idle_sizer() called on a non-window");
|
||||
}
|
||||
|
||||
if (!gtk_container_needs_idle_sizer (container))
|
||||
{
|
||||
gtk_container_stop_idle_sizer (container);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_frame_clock_request_phase (clock,
|
||||
GDK_FRAME_CLOCK_PHASE_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_container_start_idle_sizer (GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
GdkFrameClock *clock;
|
||||
|
||||
if (priv->resize_handler != 0)
|
||||
return;
|
||||
|
||||
if (!gtk_container_needs_idle_sizer (container))
|
||||
return;
|
||||
|
||||
clock = gtk_widget_get_frame_clock (GTK_WIDGET (container));
|
||||
if (clock == NULL)
|
||||
return;
|
||||
|
||||
priv->resize_handler = g_signal_connect (clock, "layout",
|
||||
G_CALLBACK (gtk_container_idle_sizer), container);
|
||||
gdk_frame_clock_request_phase (clock,
|
||||
GDK_FRAME_CLOCK_PHASE_LAYOUT);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_container_stop_idle_sizer (GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
|
||||
if (priv->resize_handler == 0)
|
||||
return;
|
||||
|
||||
g_signal_handler_disconnect (gtk_widget_get_frame_clock (GTK_WIDGET (container)),
|
||||
priv->resize_handler);
|
||||
priv->resize_handler = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_container_queue_restyle (GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
|
||||
g_return_if_fail (GTK_CONTAINER (container));
|
||||
|
||||
if (priv->restyle_pending)
|
||||
return;
|
||||
|
||||
priv->restyle_pending = TRUE;
|
||||
gtk_container_start_idle_sizer (container);
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
gtk_container_get_request_mode (GtkWidget *widget)
|
||||
{
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
void _gtk_container_queue_restyle (GtkContainer *container);
|
||||
void gtk_container_stop_idle_sizer (GtkContainer *container);
|
||||
void gtk_container_start_idle_sizer (GtkContainer *container);
|
||||
void gtk_container_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
|
||||
|
||||
@@ -1420,3 +1420,9 @@ gtk_css_node_print (GtkCssNode *cssnode,
|
||||
gtk_css_node_print (node, flags, string, indent + 2);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_node_is_invalid (GtkCssNode *cssnode)
|
||||
{
|
||||
return cssnode->invalid;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ void gtk_css_node_invalidate_frame_clock
|
||||
void gtk_css_node_invalidate (GtkCssNode *cssnode,
|
||||
GtkCssChange change);
|
||||
void gtk_css_node_validate (GtkCssNode *cssnode);
|
||||
gboolean gtk_css_node_is_invalid (GtkCssNode *cssnode);
|
||||
|
||||
gboolean gtk_css_node_init_matcher (GtkCssNode *cssnode,
|
||||
GtkCssMatcher *matcher);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "gtkcsswidgetnodeprivate.h"
|
||||
|
||||
#include "gtkcontainerprivate.h"
|
||||
#include "gtkrootprivate.h"
|
||||
#include "gtkcssanimatedstyleprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksettingsprivate.h"
|
||||
@@ -60,7 +60,7 @@ gtk_css_widget_node_queue_callback (GtkWidget *widget,
|
||||
GtkCssNode *node = user_data;
|
||||
|
||||
gtk_css_node_invalidate_frame_clock (node, TRUE);
|
||||
_gtk_container_queue_restyle (GTK_CONTAINER (widget));
|
||||
gtk_root_queue_restyle (GTK_ROOT (widget));
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
@@ -70,8 +70,7 @@ gtk_css_widget_node_queue_validate (GtkCssNode *node)
|
||||
{
|
||||
GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
|
||||
|
||||
if (widget_node->widget && _gtk_widget_is_toplevel (widget_node->widget) &&
|
||||
GTK_IS_CONTAINER (widget_node->widget))
|
||||
if (widget_node->widget && GTK_IS_ROOT (widget_node->widget))
|
||||
widget_node->validate_cb_id = gtk_widget_add_tick_callback (widget_node->widget,
|
||||
gtk_css_widget_node_queue_callback,
|
||||
node,
|
||||
@@ -83,10 +82,12 @@ gtk_css_widget_node_dequeue_validate (GtkCssNode *node)
|
||||
{
|
||||
GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
|
||||
|
||||
if (widget_node->widget && _gtk_widget_is_toplevel (widget_node->widget) &&
|
||||
GTK_IS_CONTAINER (widget_node->widget))
|
||||
gtk_widget_remove_tick_callback (widget_node->widget,
|
||||
widget_node->validate_cb_id);
|
||||
if (widget_node->validate_cb_id)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (widget_node->widget,
|
||||
widget_node->validate_cb_id);
|
||||
widget_node->validate_cb_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+15
-2
@@ -1670,10 +1670,23 @@ gtk_entry_snapshot (GtkWidget *widget,
|
||||
void
|
||||
gtk_entry_grab_focus_without_selecting (GtkEntry *entry)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_ENTRY (entry));
|
||||
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
|
||||
gboolean select, set;
|
||||
|
||||
gtk_text_grab_focus_without_selecting (GTK_TEXT (priv->text));
|
||||
g_return_if_fail (GTK_IS_ENTRY (entry));
|
||||
|
||||
g_object_get (priv->text,
|
||||
"select-on-focus", &select,
|
||||
"select-on-focus-set", &set,
|
||||
NULL);
|
||||
g_object_set (priv->text, "select-on-focus", FALSE, NULL);
|
||||
|
||||
gtk_widget_grab_focus (priv->text);
|
||||
|
||||
g_object_set (priv->text,
|
||||
"select-on-focus", select,
|
||||
"select-on-focus-set", set,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -177,8 +177,6 @@ static void gtk_expander_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline);
|
||||
static gboolean gtk_expander_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static gboolean gtk_expander_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
@@ -253,7 +251,6 @@ gtk_expander_class_init (GtkExpanderClass *klass)
|
||||
|
||||
widget_class->destroy = gtk_expander_destroy;
|
||||
widget_class->size_allocate = gtk_expander_size_allocate;
|
||||
widget_class->focus = gtk_expander_focus;
|
||||
widget_class->drag_motion = gtk_expander_drag_motion;
|
||||
widget_class->drag_leave = gtk_expander_drag_leave;
|
||||
widget_class->measure = gtk_expander_measure;
|
||||
@@ -562,142 +559,6 @@ gtk_expander_drag_leave (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FOCUS_NONE,
|
||||
FOCUS_WIDGET,
|
||||
FOCUS_LABEL,
|
||||
FOCUS_CHILD
|
||||
} FocusSite;
|
||||
|
||||
static gboolean
|
||||
focus_current_site (GtkExpander *expander,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkWidget *current_focus;
|
||||
|
||||
current_focus = gtk_widget_get_focus_child (GTK_WIDGET (expander));
|
||||
|
||||
if (!current_focus)
|
||||
return FALSE;
|
||||
|
||||
return gtk_widget_child_focus (current_focus, direction);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
focus_in_site (GtkExpander *expander,
|
||||
FocusSite site,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
|
||||
|
||||
switch (site)
|
||||
{
|
||||
case FOCUS_WIDGET:
|
||||
gtk_widget_grab_focus (GTK_WIDGET (expander));
|
||||
return TRUE;
|
||||
case FOCUS_LABEL:
|
||||
if (priv->label_widget)
|
||||
return gtk_widget_child_focus (priv->label_widget, direction);
|
||||
else
|
||||
return FALSE;
|
||||
case FOCUS_CHILD:
|
||||
{
|
||||
GtkWidget *child = priv->child;
|
||||
|
||||
if (child && gtk_widget_get_child_visible (child))
|
||||
return gtk_widget_child_focus (child, direction);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
case FOCUS_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static FocusSite
|
||||
get_next_site (GtkExpander *expander,
|
||||
FocusSite site,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gboolean ltr;
|
||||
|
||||
ltr = gtk_widget_get_direction (GTK_WIDGET (expander)) != GTK_TEXT_DIR_RTL;
|
||||
|
||||
switch (site)
|
||||
{
|
||||
case FOCUS_NONE:
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_UP:
|
||||
return FOCUS_CHILD;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_DOWN:
|
||||
case GTK_DIR_RIGHT:
|
||||
default:
|
||||
return FOCUS_WIDGET;
|
||||
}
|
||||
break;
|
||||
case FOCUS_WIDGET:
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_UP:
|
||||
return FOCUS_NONE;
|
||||
case GTK_DIR_LEFT:
|
||||
return ltr ? FOCUS_NONE : FOCUS_LABEL;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_DOWN:
|
||||
default:
|
||||
return FOCUS_LABEL;
|
||||
case GTK_DIR_RIGHT:
|
||||
return ltr ? FOCUS_LABEL : FOCUS_NONE;
|
||||
}
|
||||
break;
|
||||
case FOCUS_LABEL:
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_UP:
|
||||
return FOCUS_WIDGET;
|
||||
case GTK_DIR_LEFT:
|
||||
return ltr ? FOCUS_WIDGET : FOCUS_CHILD;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_DOWN:
|
||||
default:
|
||||
return FOCUS_CHILD;
|
||||
case GTK_DIR_RIGHT:
|
||||
return ltr ? FOCUS_CHILD : FOCUS_WIDGET;
|
||||
}
|
||||
break;
|
||||
case FOCUS_CHILD:
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_UP:
|
||||
return FOCUS_LABEL;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_DOWN:
|
||||
case GTK_DIR_RIGHT:
|
||||
default:
|
||||
return FOCUS_NONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
return FOCUS_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_resize_toplevel (GtkExpander *expander)
|
||||
{
|
||||
@@ -731,41 +592,6 @@ gtk_expander_resize_toplevel (GtkExpander *expander)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_expander_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkExpander *expander = GTK_EXPANDER (widget);
|
||||
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
|
||||
|
||||
if (!focus_current_site (expander, direction))
|
||||
{
|
||||
GtkWidget *old_focus_child;
|
||||
gboolean widget_is_focus;
|
||||
FocusSite site = FOCUS_NONE;
|
||||
|
||||
widget_is_focus = gtk_widget_is_focus (widget);
|
||||
old_focus_child = gtk_widget_get_focus_child (GTK_WIDGET (widget));
|
||||
|
||||
if (old_focus_child && old_focus_child == priv->label_widget)
|
||||
site = FOCUS_LABEL;
|
||||
else if (old_focus_child)
|
||||
site = FOCUS_CHILD;
|
||||
else if (widget_is_focus)
|
||||
site = FOCUS_WIDGET;
|
||||
|
||||
while ((site = get_next_site (expander, site, direction)) != FOCUS_NONE)
|
||||
{
|
||||
if (focus_in_site (expander, site, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_add (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkfilechoosererrorstackprivate.h"
|
||||
#include "gtkentryprivate.h"
|
||||
#include "gtkroot.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
@@ -340,6 +341,7 @@ struct _GtkFileChooserWidgetPrivate {
|
||||
GSource *focus_entry_idle;
|
||||
|
||||
gulong toplevel_set_focus_id;
|
||||
GtkWidget *toplevel_current_focus_widget;
|
||||
GtkWidget *toplevel_last_focus_widget;
|
||||
|
||||
gint sort_column;
|
||||
@@ -1361,7 +1363,7 @@ key_press_cb (GtkEventController *controller,
|
||||
GtkWidget *default_widget, *focus_widget;
|
||||
|
||||
default_widget = gtk_window_get_default_widget (window);
|
||||
focus_widget = gtk_window_get_focus (window);
|
||||
focus_widget = gtk_root_get_focus (GTK_ROOT (window));
|
||||
|
||||
if (widget != default_widget &&
|
||||
!(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget))))
|
||||
@@ -2709,7 +2711,7 @@ location_mode_set (GtkFileChooserWidget *impl,
|
||||
switch_to_file_list = FALSE;
|
||||
if (toplevel)
|
||||
{
|
||||
current_focus = gtk_window_get_focus (toplevel);
|
||||
current_focus = gtk_root_get_focus (GTK_ROOT (toplevel));
|
||||
if (!current_focus || current_focus == priv->location_entry)
|
||||
switch_to_file_list = TRUE;
|
||||
}
|
||||
@@ -3560,13 +3562,14 @@ gtk_file_chooser_widget_dispose (GObject *object)
|
||||
* widget on our toplevel. See gtk_file_chooser_widget_hierarchy_changed()
|
||||
*/
|
||||
static void
|
||||
toplevel_set_focus_cb (GtkWindow *window,
|
||||
GtkWidget *focus,
|
||||
toplevel_set_focus_cb (GtkWindow *window,
|
||||
GParamSpec *pspec,
|
||||
GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkFileChooserWidgetPrivate *priv = impl->priv;
|
||||
|
||||
priv->toplevel_last_focus_widget = gtk_window_get_focus (window);
|
||||
priv->toplevel_last_focus_widget = priv->toplevel_current_focus_widget;
|
||||
priv->toplevel_current_focus_widget = gtk_root_get_focus (GTK_ROOT (window));
|
||||
}
|
||||
|
||||
/* We monitor the focus widget on our toplevel to be able to know which widget
|
||||
@@ -3584,9 +3587,10 @@ gtk_file_chooser_widget_root (GtkWidget *widget)
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
|
||||
g_assert (priv->toplevel_set_focus_id == 0);
|
||||
priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus",
|
||||
priv->toplevel_set_focus_id = g_signal_connect (toplevel, "notify::focus-widget",
|
||||
G_CALLBACK (toplevel_set_focus_cb), impl);
|
||||
priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
priv->toplevel_last_focus_widget = NULL;
|
||||
priv->toplevel_current_focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3602,6 +3606,7 @@ gtk_file_chooser_widget_unroot (GtkWidget *widget)
|
||||
g_signal_handler_disconnect (toplevel, priv->toplevel_set_focus_id);
|
||||
priv->toplevel_set_focus_id = 0;
|
||||
priv->toplevel_last_focus_widget = NULL;
|
||||
priv->toplevel_current_focus_widget = NULL;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->unroot (widget);
|
||||
@@ -5806,7 +5811,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
|
||||
|
||||
toplevel = get_toplevel (GTK_WIDGET (impl));
|
||||
if (toplevel)
|
||||
current_focus = gtk_window_get_focus (toplevel);
|
||||
current_focus = gtk_root_get_focus (GTK_ROOT (toplevel));
|
||||
else
|
||||
current_focus = NULL;
|
||||
|
||||
@@ -6655,7 +6660,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed)
|
||||
|
||||
retval = FALSE;
|
||||
|
||||
current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
current_focus = gtk_root_get_focus (GTK_ROOT (toplevel));
|
||||
|
||||
if (current_focus == priv->browse_files_tree_view)
|
||||
{
|
||||
|
||||
@@ -303,92 +303,8 @@ gtk_flow_box_child_get_box (GtkFlowBoxChild *child)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_flow_box_child_set_focus (GtkFlowBoxChild *child)
|
||||
{
|
||||
GtkFlowBox *box = gtk_flow_box_child_get_box (child);
|
||||
gboolean modify;
|
||||
gboolean extend;
|
||||
|
||||
get_current_selection_modifiers (GTK_WIDGET (box), &modify, &extend);
|
||||
|
||||
if (modify)
|
||||
gtk_flow_box_update_cursor (box, child);
|
||||
else
|
||||
gtk_flow_box_update_selection (box, child, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/* GtkWidget implementation {{{2 */
|
||||
|
||||
static gboolean
|
||||
gtk_flow_box_child_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gboolean had_focus = FALSE;
|
||||
GtkWidget *child;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
|
||||
/* Without "can-focus" flag try to pass the focus to the child immediately */
|
||||
if (!gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
if (child)
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
{
|
||||
GtkFlowBox *box;
|
||||
box = gtk_flow_box_child_get_box (GTK_FLOW_BOX_CHILD (widget));
|
||||
if (box)
|
||||
gtk_flow_box_update_cursor (box, GTK_FLOW_BOX_CHILD (widget));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_get (widget, "has-focus", &had_focus, NULL);
|
||||
if (had_focus)
|
||||
{
|
||||
/* If on row, going right, enter into possible container */
|
||||
if (child &&
|
||||
(direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD))
|
||||
{
|
||||
if (gtk_widget_child_focus (GTK_WIDGET (child), direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (gtk_widget_get_focus_child (widget) != NULL)
|
||||
{
|
||||
/* Child has focus, always navigate inside it first */
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
|
||||
/* If exiting child container to the left, select child */
|
||||
if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
|
||||
{
|
||||
gtk_flow_box_child_set_focus (GTK_FLOW_BOX_CHILD (widget));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If coming from the left, enter into possible container */
|
||||
if (child &&
|
||||
(direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD))
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_flow_box_child_set_focus (GTK_FLOW_BOX_CHILD (widget));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_flow_box_child_activate (GtkFlowBoxChild *child)
|
||||
{
|
||||
@@ -422,7 +338,6 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
widget_class->get_request_mode = gtk_flow_box_child_get_request_mode;
|
||||
widget_class->focus = gtk_flow_box_child_focus;
|
||||
|
||||
class->activate = gtk_flow_box_child_activate;
|
||||
|
||||
@@ -2893,77 +2808,6 @@ gtk_flow_box_child_type (GtkContainer *container)
|
||||
|
||||
/* Keynav {{{2 */
|
||||
|
||||
static gboolean
|
||||
gtk_flow_box_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkFlowBox *box = GTK_FLOW_BOX (widget);
|
||||
GtkWidget *focus_child;
|
||||
GSequenceIter *iter;
|
||||
GtkFlowBoxChild *next_focus_child;
|
||||
|
||||
/* Without "can-focus" flag fall back to the default behavior immediately */
|
||||
if (!gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
return GTK_WIDGET_CLASS (gtk_flow_box_parent_class)->focus (widget, direction);
|
||||
}
|
||||
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
next_focus_child = NULL;
|
||||
|
||||
if (focus_child != NULL)
|
||||
{
|
||||
if (gtk_widget_child_focus (focus_child, direction))
|
||||
return TRUE;
|
||||
|
||||
iter = CHILD_PRIV (focus_child)->iter;
|
||||
|
||||
if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
|
||||
iter = gtk_flow_box_get_previous_focusable (box, iter);
|
||||
else if (direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD)
|
||||
iter = gtk_flow_box_get_next_focusable (box, iter);
|
||||
else if (direction == GTK_DIR_UP)
|
||||
iter = gtk_flow_box_get_above_focusable (box, iter);
|
||||
else if (direction == GTK_DIR_DOWN)
|
||||
iter = gtk_flow_box_get_below_focusable (box, iter);
|
||||
|
||||
if (iter != NULL)
|
||||
next_focus_child = g_sequence_get (iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BOX_PRIV (box)->selected_child)
|
||||
next_focus_child = BOX_PRIV (box)->selected_child;
|
||||
else
|
||||
{
|
||||
if (direction == GTK_DIR_UP || direction == GTK_DIR_TAB_BACKWARD)
|
||||
iter = gtk_flow_box_get_last_focusable (box);
|
||||
else
|
||||
iter = gtk_flow_box_get_first_focusable (box);
|
||||
|
||||
if (iter != NULL)
|
||||
next_focus_child = g_sequence_get (iter);
|
||||
}
|
||||
}
|
||||
|
||||
if (next_focus_child == NULL)
|
||||
{
|
||||
if (direction == GTK_DIR_UP || direction == GTK_DIR_DOWN ||
|
||||
direction == GTK_DIR_LEFT || direction == GTK_DIR_RIGHT)
|
||||
{
|
||||
if (gtk_widget_keynav_failed (GTK_WIDGET (box), direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gtk_widget_child_focus (GTK_WIDGET (next_focus_child), direction))
|
||||
return TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_flow_box_add_move_binding (GtkBindingSet *binding_set,
|
||||
guint keyval,
|
||||
@@ -3373,7 +3217,6 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
|
||||
|
||||
widget_class->size_allocate = gtk_flow_box_size_allocate;
|
||||
widget_class->unmap = gtk_flow_box_unmap;
|
||||
widget_class->focus = gtk_flow_box_focus;
|
||||
widget_class->snapshot = gtk_flow_box_snapshot;
|
||||
widget_class->get_request_mode = gtk_flow_box_get_request_mode;
|
||||
widget_class->measure = gtk_flow_box_measure;
|
||||
|
||||
+194
-217
@@ -33,6 +33,7 @@
|
||||
#include "gtkcssshadowsvalueprivate.h"
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkdnd.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkeventcontrollermotion.h"
|
||||
#include "gtkgesturedrag.h"
|
||||
#include "gtkgesturemultipress.h"
|
||||
@@ -254,7 +255,7 @@ struct _GtkLabelPrivate
|
||||
{
|
||||
GtkLabelSelectionInfo *select_info;
|
||||
GtkWidget *mnemonic_widget;
|
||||
GtkWindow *mnemonic_window;
|
||||
GtkRoot *mnemonic_root;
|
||||
|
||||
PangoAttrList *attrs;
|
||||
PangoAttrList *markup_attrs;
|
||||
@@ -413,8 +414,6 @@ static void gtk_label_state_flags_changed (GtkWidget *widget,
|
||||
static void gtk_label_style_updated (GtkWidget *widget);
|
||||
static void gtk_label_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot);
|
||||
static gboolean gtk_label_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
|
||||
static void gtk_label_realize (GtkWidget *widget);
|
||||
static void gtk_label_unrealize (GtkWidget *widget);
|
||||
@@ -475,7 +474,7 @@ static void gtk_label_update_active_link (GtkWidget *widget,
|
||||
static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
|
||||
gboolean group_cycling);
|
||||
static void gtk_label_setup_mnemonic (GtkLabel *label,
|
||||
GtkWidget *toplevel,
|
||||
GtkRoot *root,
|
||||
guint last_key);
|
||||
static void gtk_label_drag_data_get (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
@@ -525,6 +524,10 @@ static void gtk_label_activate_current_link (GtkLabel *label);
|
||||
static GtkLabelLink *gtk_label_get_current_link (GtkLabel *label);
|
||||
static void emit_activate_link (GtkLabel *label,
|
||||
GtkLabelLink *link);
|
||||
static gboolean range_is_in_ellipsis (GtkLabel *label,
|
||||
gint range_start,
|
||||
gint range_end);
|
||||
static GtkLabelLink *gtk_label_get_focus_link (GtkLabel *label);
|
||||
|
||||
/* Event controller callbacks */
|
||||
static void gtk_label_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
|
||||
@@ -612,7 +615,6 @@ gtk_label_class_init (GtkLabelClass *class)
|
||||
widget_class->drag_data_get = gtk_label_drag_data_get;
|
||||
widget_class->grab_focus = gtk_label_grab_focus;
|
||||
widget_class->popup_menu = gtk_label_popup_menu;
|
||||
widget_class->focus = gtk_label_focus;
|
||||
widget_class->get_request_mode = gtk_label_get_request_mode;
|
||||
widget_class->measure = gtk_label_measure;
|
||||
|
||||
@@ -1122,6 +1124,175 @@ gtk_label_class_init (GtkLabelClass *class)
|
||||
quark_link = g_quark_from_static_string ("link");
|
||||
}
|
||||
|
||||
static void
|
||||
focus_in_cb (GtkEventControllerKey *controller,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkLabel *label = GTK_LABEL (widget);
|
||||
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
|
||||
GtkLabelSelectionInfo *info = priv->select_info;
|
||||
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (info->selectable)
|
||||
{
|
||||
gboolean select_on_focus;
|
||||
|
||||
g_object_get (gtk_widget_get_settings (widget),
|
||||
"gtk-label-select-on-focus",
|
||||
&select_on_focus,
|
||||
NULL);
|
||||
|
||||
if (select_on_focus && !priv->in_click)
|
||||
gtk_label_select_region (label, 0, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info->links && !priv->in_click)
|
||||
{
|
||||
GList *l;
|
||||
int i;
|
||||
|
||||
for (l = info->links, i = 0; l; l = l->next, i++)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
{
|
||||
info->selection_anchor = link->start;
|
||||
info->selection_end = link->start;
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
gtk_widget_queue_draw (widget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_press_cb (GtkEventControllerKey *controller,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
GdkModifierType modifiers,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkLabel *label = GTK_LABEL (widget);
|
||||
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
|
||||
GtkLabelSelectionInfo *info = priv->select_info;
|
||||
GtkDirectionType direction;
|
||||
GtkLabelLink *focus_link;
|
||||
GList *l;
|
||||
|
||||
if (keyval != GDK_KEY_Tab && keyval != GDK_KEY_KP_Tab)
|
||||
return FALSE;
|
||||
|
||||
if ((modifiers & GDK_SHIFT_MASK) != 0)
|
||||
direction = GTK_DIR_TAB_BACKWARD;
|
||||
else
|
||||
direction = GTK_DIR_TAB_FORWARD;
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
if (info->selectable)
|
||||
{
|
||||
int index;
|
||||
int i;
|
||||
|
||||
if (info->selection_anchor != info->selection_end)
|
||||
return FALSE;
|
||||
|
||||
index = info->selection_anchor;
|
||||
|
||||
if (direction == GTK_DIR_TAB_FORWARD)
|
||||
{
|
||||
for (l = info->links, i = 0; l; l = l->next, i++)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
|
||||
if (link->start > index)
|
||||
{
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
{
|
||||
gtk_label_select_region_index (label, link->start, link->start);
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
gtk_widget_queue_draw (widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (l = g_list_last (info->links), i = g_list_length (info->links) - 1; l; l = l->prev, i--)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
|
||||
if (link->end < index)
|
||||
{
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
{
|
||||
gtk_label_select_region_index (label, link->start, link->start);
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
gtk_widget_queue_draw (widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
focus_link = gtk_label_get_focus_link (label);
|
||||
if (direction == GTK_DIR_TAB_FORWARD)
|
||||
{
|
||||
if (focus_link)
|
||||
{
|
||||
l = g_list_find (info->links, focus_link);
|
||||
l = l->next;
|
||||
}
|
||||
else
|
||||
l = info->links;
|
||||
for (; l; l = l->next)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (focus_link)
|
||||
{
|
||||
l = g_list_find (info->links, focus_link);
|
||||
l = l->prev;
|
||||
}
|
||||
else
|
||||
l = g_list_last (info->links);
|
||||
for (; l; l = l->prev)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (l)
|
||||
{
|
||||
focus_link = l->data;
|
||||
info->selection_anchor = focus_link->start;
|
||||
info->selection_end = focus_link->start;
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_label_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -1273,6 +1444,7 @@ static void
|
||||
gtk_label_init (GtkLabel *label)
|
||||
{
|
||||
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
|
||||
GtkEventController *controller;
|
||||
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (label), FALSE);
|
||||
|
||||
@@ -1300,9 +1472,14 @@ gtk_label_init (GtkLabel *label)
|
||||
priv->attrs = NULL;
|
||||
|
||||
priv->mnemonic_widget = NULL;
|
||||
priv->mnemonic_window = NULL;
|
||||
priv->mnemonic_root = NULL;
|
||||
|
||||
priv->mnemonics_visible = TRUE;
|
||||
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_signal_connect (controller, "focus-in", G_CALLBACK (focus_in_cb), label);
|
||||
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_press_cb), label);
|
||||
gtk_widget_add_controller (GTK_WIDGET (label), controller);
|
||||
}
|
||||
|
||||
|
||||
@@ -1741,7 +1918,7 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
gtk_label_setup_mnemonic (GtkLabel *label,
|
||||
GtkWidget *toplevel,
|
||||
GtkRoot *root,
|
||||
guint last_key)
|
||||
{
|
||||
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
|
||||
@@ -1752,12 +1929,10 @@ gtk_label_setup_mnemonic (GtkLabel *label,
|
||||
|
||||
if (last_key != GDK_KEY_VoidSymbol)
|
||||
{
|
||||
if (priv->mnemonic_window)
|
||||
if (priv->mnemonic_root)
|
||||
{
|
||||
gtk_window_remove_mnemonic (priv->mnemonic_window,
|
||||
last_key,
|
||||
widget);
|
||||
priv->mnemonic_window = NULL;
|
||||
gtk_root_remove_mnemonic (priv->mnemonic_root, last_key, widget);
|
||||
priv->mnemonic_root = NULL;
|
||||
}
|
||||
if (mnemonic_menu)
|
||||
{
|
||||
@@ -1773,7 +1948,7 @@ gtk_label_setup_mnemonic (GtkLabel *label,
|
||||
|
||||
connect_mnemonics_visible_notify (GTK_LABEL (widget));
|
||||
|
||||
if (toplevel && gtk_widget_is_toplevel (toplevel))
|
||||
if (root)
|
||||
{
|
||||
GtkWidget *menu_shell;
|
||||
|
||||
@@ -1790,10 +1965,8 @@ gtk_label_setup_mnemonic (GtkLabel *label,
|
||||
|
||||
if (!GTK_IS_MENU (menu_shell))
|
||||
{
|
||||
gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
|
||||
priv->mnemonic_keyval,
|
||||
widget);
|
||||
priv->mnemonic_window = GTK_WINDOW (toplevel);
|
||||
gtk_root_add_mnemonic (root, priv->mnemonic_keyval, widget);
|
||||
priv->mnemonic_root = root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1809,7 +1982,7 @@ gtk_label_root (GtkWidget *widget)
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_label_parent_class)->root (widget);
|
||||
|
||||
gtk_label_setup_mnemonic (label, gtk_widget_get_toplevel (widget), priv->mnemonic_keyval);
|
||||
gtk_label_setup_mnemonic (label, gtk_widget_get_root (widget), priv->mnemonic_keyval);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2144,7 +2317,7 @@ gtk_label_recalculate (GtkLabel *label)
|
||||
|
||||
if (keyval != priv->mnemonic_keyval)
|
||||
{
|
||||
gtk_label_setup_mnemonic (label, gtk_widget_get_toplevel (GTK_WIDGET (label)), keyval);
|
||||
gtk_label_setup_mnemonic (label, gtk_widget_get_root (GTK_WIDGET (label)), keyval);
|
||||
g_object_notify_by_pspec (G_OBJECT (label), label_props[PROP_MNEMONIC_KEYVAL]);
|
||||
}
|
||||
|
||||
@@ -4260,185 +4433,11 @@ gtk_label_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkLabel *label = GTK_LABEL (widget);
|
||||
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
|
||||
gboolean select_on_focus;
|
||||
GtkLabelLink *link;
|
||||
GList *l;
|
||||
|
||||
if (priv->select_info == NULL)
|
||||
return;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_label_parent_class)->grab_focus (widget);
|
||||
|
||||
if (priv->select_info->selectable)
|
||||
{
|
||||
g_object_get (gtk_widget_get_settings (widget),
|
||||
"gtk-label-select-on-focus",
|
||||
&select_on_focus,
|
||||
NULL);
|
||||
|
||||
if (select_on_focus && !priv->in_click)
|
||||
gtk_label_select_region (label, 0, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->select_info->links && !priv->in_click)
|
||||
{
|
||||
for (l = priv->select_info->links; l; l = l->next)
|
||||
{
|
||||
link = l->data;
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
{
|
||||
priv->select_info->selection_anchor = link->start;
|
||||
priv->select_info->selection_end = link->start;
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_label_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkLabel *label = GTK_LABEL (widget);
|
||||
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
|
||||
GtkLabelSelectionInfo *info = priv->select_info;
|
||||
GtkLabelLink *focus_link;
|
||||
GList *l;
|
||||
|
||||
if (!gtk_widget_is_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
if (info)
|
||||
{
|
||||
focus_link = gtk_label_get_focus_link (label);
|
||||
if (focus_link && direction == GTK_DIR_TAB_BACKWARD)
|
||||
{
|
||||
for (l = g_list_last (info->links); l; l = l->prev)
|
||||
{
|
||||
focus_link = l->data;
|
||||
if (!range_is_in_ellipsis (label, focus_link->start, focus_link->end))
|
||||
{
|
||||
info->selection_anchor = focus_link->start;
|
||||
info->selection_end = focus_link->start;
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
if (info->selectable)
|
||||
{
|
||||
gint index;
|
||||
|
||||
if (info->selection_anchor != info->selection_end)
|
||||
goto out;
|
||||
|
||||
index = info->selection_anchor;
|
||||
|
||||
if (direction == GTK_DIR_TAB_FORWARD)
|
||||
for (l = info->links; l; l = l->next)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
|
||||
if (link->start > index)
|
||||
{
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
{
|
||||
gtk_label_select_region_index (label, link->start, link->start);
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (direction == GTK_DIR_TAB_BACKWARD)
|
||||
for (l = g_list_last (info->links); l; l = l->prev)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
|
||||
if (link->end < index)
|
||||
{
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
{
|
||||
gtk_label_select_region_index (label, link->start, link->start);
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
focus_link = gtk_label_get_focus_link (label);
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
if (focus_link)
|
||||
{
|
||||
l = g_list_find (info->links, focus_link);
|
||||
l = l->next;
|
||||
}
|
||||
else
|
||||
l = info->links;
|
||||
for (; l; l = l->next)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
if (focus_link)
|
||||
{
|
||||
l = g_list_find (info->links, focus_link);
|
||||
l = l->prev;
|
||||
}
|
||||
else
|
||||
l = g_list_last (info->links);
|
||||
for (; l; l = l->prev)
|
||||
{
|
||||
GtkLabelLink *link = l->data;
|
||||
if (!range_is_in_ellipsis (label, link->start, link->end))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case GTK_DIR_UP:
|
||||
case GTK_DIR_DOWN:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (l)
|
||||
{
|
||||
focus_link = l->data;
|
||||
info->selection_anchor = focus_link->start;
|
||||
info->selection_end = focus_link->start;
|
||||
_gtk_label_accessible_focus_link_changed (label);
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6205,31 +6204,9 @@ gtk_label_activate_current_link (GtkLabel *label)
|
||||
link = gtk_label_get_focus_link (label);
|
||||
|
||||
if (link)
|
||||
{
|
||||
emit_activate_link (label, link);
|
||||
}
|
||||
emit_activate_link (label, link);
|
||||
else
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkWindow *window;
|
||||
GtkWidget *default_widget, *focus_widget;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
window = GTK_WINDOW (toplevel);
|
||||
|
||||
if (window)
|
||||
{
|
||||
default_widget = gtk_window_get_default_widget (window);
|
||||
focus_widget = gtk_window_get_focus (window);
|
||||
|
||||
if (default_widget != widget &&
|
||||
!(widget == focus_widget && (!default_widget || !gtk_widget_is_sensitive (default_widget))))
|
||||
gtk_window_activate_default (window);
|
||||
}
|
||||
}
|
||||
}
|
||||
gtk_root_activate_default (gtk_widget_get_root (widget));
|
||||
}
|
||||
|
||||
static GtkLabelLink *
|
||||
|
||||
@@ -208,8 +208,6 @@ static void gtk_list_box_update_cursor (GtkListBo
|
||||
GtkListBoxRow *row,
|
||||
gboolean grab_focus);
|
||||
static void gtk_list_box_show (GtkWidget *widget);
|
||||
static gboolean gtk_list_box_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static GSequenceIter* gtk_list_box_get_previous_visible (GtkListBox *box,
|
||||
GSequenceIter *iter);
|
||||
static GtkListBoxRow *gtk_list_box_get_first_focusable (GtkListBox *box);
|
||||
@@ -407,7 +405,6 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
|
||||
object_class->set_property = gtk_list_box_set_property;
|
||||
object_class->finalize = gtk_list_box_finalize;
|
||||
widget_class->show = gtk_list_box_show;
|
||||
widget_class->focus = gtk_list_box_focus;
|
||||
widget_class->compute_expand = gtk_list_box_compute_expand;
|
||||
widget_class->get_request_mode = gtk_list_box_get_request_mode;
|
||||
widget_class->measure = gtk_list_box_measure;
|
||||
@@ -1870,129 +1867,6 @@ gtk_list_box_show (GtkWidget *widget)
|
||||
GTK_WIDGET_CLASS (gtk_list_box_parent_class)->show (widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_list_box_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkListBox *box = GTK_LIST_BOX (widget);
|
||||
GtkListBoxPrivate *priv = BOX_PRIV (box);
|
||||
GtkWidget *focus_child;
|
||||
GtkListBoxRow *next_focus_row;
|
||||
GtkWidget *row;
|
||||
GtkWidget *header;
|
||||
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
next_focus_row = NULL;
|
||||
if (focus_child != NULL)
|
||||
{
|
||||
GSequenceIter *i;
|
||||
|
||||
if (gtk_widget_child_focus (focus_child, direction))
|
||||
return TRUE;
|
||||
|
||||
if (direction == GTK_DIR_UP || direction == GTK_DIR_TAB_BACKWARD)
|
||||
{
|
||||
if (GTK_IS_LIST_BOX_ROW (focus_child))
|
||||
{
|
||||
header = ROW_PRIV (GTK_LIST_BOX_ROW (focus_child))->header;
|
||||
if (header && gtk_widget_child_focus (header, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (GTK_IS_LIST_BOX_ROW (focus_child))
|
||||
row = focus_child;
|
||||
else
|
||||
row = g_hash_table_lookup (priv->header_hash, focus_child);
|
||||
|
||||
if (GTK_IS_LIST_BOX_ROW (row))
|
||||
i = gtk_list_box_get_previous_visible (box, ROW_PRIV (GTK_LIST_BOX_ROW (row))->iter);
|
||||
else
|
||||
i = NULL;
|
||||
|
||||
while (i != NULL)
|
||||
{
|
||||
if (gtk_widget_get_sensitive (g_sequence_get (i)))
|
||||
{
|
||||
next_focus_row = g_sequence_get (i);
|
||||
break;
|
||||
}
|
||||
|
||||
i = gtk_list_box_get_previous_visible (box, i);
|
||||
}
|
||||
}
|
||||
else if (direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD)
|
||||
{
|
||||
if (GTK_IS_LIST_BOX_ROW (focus_child))
|
||||
i = gtk_list_box_get_next_visible (box, ROW_PRIV (GTK_LIST_BOX_ROW (focus_child))->iter);
|
||||
else
|
||||
{
|
||||
row = g_hash_table_lookup (priv->header_hash, focus_child);
|
||||
if (GTK_IS_LIST_BOX_ROW (row))
|
||||
i = ROW_PRIV (GTK_LIST_BOX_ROW (row))->iter;
|
||||
else
|
||||
i = NULL;
|
||||
}
|
||||
|
||||
while (!g_sequence_iter_is_end (i))
|
||||
{
|
||||
if (gtk_widget_get_sensitive (g_sequence_get (i)))
|
||||
{
|
||||
next_focus_row = g_sequence_get (i);
|
||||
break;
|
||||
}
|
||||
|
||||
i = gtk_list_box_get_next_visible (box, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No current focus row */
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_UP:
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
next_focus_row = priv->selected_row;
|
||||
if (next_focus_row == NULL)
|
||||
next_focus_row = gtk_list_box_get_last_focusable (box);
|
||||
break;
|
||||
case GTK_DIR_DOWN:
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
default:
|
||||
next_focus_row = priv->selected_row;
|
||||
if (next_focus_row == NULL)
|
||||
next_focus_row = gtk_list_box_get_first_focusable (box);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (next_focus_row == NULL)
|
||||
{
|
||||
if (direction == GTK_DIR_UP || direction == GTK_DIR_DOWN)
|
||||
{
|
||||
if (gtk_widget_keynav_failed (GTK_WIDGET (box), direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD)
|
||||
{
|
||||
header = ROW_PRIV (next_focus_row)->header;
|
||||
if (header && gtk_widget_child_focus (header, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (gtk_widget_child_focus (GTK_WIDGET (next_focus_row), direction))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
list_box_add_visible_rows (GtkListBox *box,
|
||||
gint n)
|
||||
@@ -2882,77 +2756,6 @@ gtk_list_box_row_new (void)
|
||||
return g_object_new (GTK_TYPE_LIST_BOX_ROW, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_box_row_set_focus (GtkListBoxRow *row)
|
||||
{
|
||||
GtkListBox *box = gtk_list_box_row_get_box (row);
|
||||
gboolean modify;
|
||||
gboolean extend;
|
||||
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
get_current_selection_modifiers (GTK_WIDGET (row), &modify, &extend);
|
||||
|
||||
if (modify)
|
||||
gtk_list_box_update_cursor (box, row, TRUE);
|
||||
else
|
||||
gtk_list_box_update_selection (box, row, FALSE, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_list_box_row_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkListBoxRow *row = GTK_LIST_BOX_ROW (widget);
|
||||
gboolean had_focus = FALSE;
|
||||
GtkWidget *child;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
|
||||
g_object_get (widget, "has-focus", &had_focus, NULL);
|
||||
if (had_focus)
|
||||
{
|
||||
/* If on row, going right, enter into possible container */
|
||||
if (child &&
|
||||
(direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD))
|
||||
{
|
||||
if (gtk_widget_child_focus (GTK_WIDGET (child), direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (gtk_widget_get_focus_child (widget) != NULL)
|
||||
{
|
||||
/* Child has focus, always navigate inside it first */
|
||||
if (gtk_widget_child_focus (gtk_widget_get_focus_child (widget), direction))
|
||||
return TRUE;
|
||||
|
||||
/* If exiting child container to the left, select row */
|
||||
if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
|
||||
{
|
||||
gtk_list_box_row_set_focus (row);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If coming from the left, enter into possible container */
|
||||
if (child &&
|
||||
(direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD))
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_list_box_row_set_focus (row);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_box_row_activate (GtkListBoxRow *row)
|
||||
{
|
||||
@@ -3384,7 +3187,6 @@ gtk_list_box_row_class_init (GtkListBoxRowClass *klass)
|
||||
|
||||
widget_class->show = gtk_list_box_row_show;
|
||||
widget_class->hide = gtk_list_box_row_hide;
|
||||
widget_class->focus = gtk_list_box_row_focus;
|
||||
widget_class->grab_focus = gtk_list_box_row_grab_focus;
|
||||
|
||||
klass->activate = gtk_list_box_row_activate;
|
||||
|
||||
+4
-5
@@ -1456,8 +1456,7 @@ update_pointer_focus_state (GtkWindow *toplevel,
|
||||
return old_target;
|
||||
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
gtk_window_update_pointer_focus (toplevel, device, sequence,
|
||||
new_target, x, y);
|
||||
gtk_window_update_pointer_focus (toplevel, device, sequence, new_target, x, y);
|
||||
|
||||
return old_target;
|
||||
}
|
||||
@@ -1761,17 +1760,17 @@ gtk_main_do_event (GdkEvent *event)
|
||||
|
||||
if (is_pointing_event (event))
|
||||
target_widget = handle_pointing_event (event);
|
||||
else if (GTK_IS_WINDOW (target_widget) &&
|
||||
else if (GTK_IS_ROOT (target_widget) &&
|
||||
(event->any.type == GDK_KEY_PRESS ||
|
||||
event->any.type == GDK_KEY_RELEASE))
|
||||
{
|
||||
GtkWidget *focus_widget;
|
||||
|
||||
if (event->any.type == GDK_KEY_PRESS &&
|
||||
gtk_window_activate_key (GTK_WINDOW (target_widget), (GdkEventKey *) event))
|
||||
gtk_root_activate_key (GTK_ROOT (target_widget), (GdkEventKey *) event))
|
||||
goto cleanup;
|
||||
|
||||
focus_widget = gtk_window_get_focus (GTK_WINDOW (target_widget));
|
||||
focus_widget = gtk_root_get_focus (GTK_ROOT (target_widget));
|
||||
if (focus_widget)
|
||||
target_widget = focus_widget;
|
||||
}
|
||||
|
||||
+9
-7
@@ -251,8 +251,9 @@ static void gtk_menu_handle_scrolling (GtkMenu *menu,
|
||||
gint event_y,
|
||||
gboolean enter,
|
||||
gboolean motion);
|
||||
static gboolean gtk_menu_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static GtkWidget *gtk_menu_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction);
|
||||
static gint gtk_menu_get_popup_delay (GtkMenuShell *menu_shell);
|
||||
static void gtk_menu_move_current (GtkMenuShell *menu_shell,
|
||||
GtkMenuDirectionType direction);
|
||||
@@ -492,7 +493,7 @@ gtk_menu_class_init (GtkMenuClass *class)
|
||||
widget_class->size_allocate = gtk_menu_size_allocate;
|
||||
widget_class->show = gtk_menu_show;
|
||||
widget_class->snapshot = gtk_menu_snapshot;
|
||||
widget_class->focus = gtk_menu_focus;
|
||||
widget_class->next_focus_child = gtk_menu_next_focus_child;
|
||||
widget_class->can_activate_accel = gtk_menu_real_can_activate_accel;
|
||||
widget_class->grab_notify = gtk_menu_grab_notify;
|
||||
widget_class->measure = gtk_menu_measure;
|
||||
@@ -2254,12 +2255,13 @@ gtk_menu_realize (GtkWidget *widget)
|
||||
GTK_MENU_SHELL (widget)->priv->active_menu_item);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_menu_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
static GtkWidget *
|
||||
gtk_menu_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
/* A menu or its menu items cannot have focus */
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
|
||||
+33
-323
@@ -211,7 +211,6 @@ struct _GtkNotebookPrivate
|
||||
|
||||
guint32 timer;
|
||||
|
||||
guint child_has_focus : 1;
|
||||
guint click_child : 3;
|
||||
guint remove_in_detach : 1;
|
||||
guint focus_out : 1; /* Flag used by ::move-focus-out implementation */
|
||||
@@ -303,7 +302,6 @@ struct _GtkNotebookPage
|
||||
GtkWidget *child;
|
||||
GtkWidget *tab_label;
|
||||
GtkWidget *menu_label;
|
||||
GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
|
||||
|
||||
GtkWidget *tab_widget; /* widget used for the tab itself */
|
||||
|
||||
@@ -645,8 +643,6 @@ static void gtk_notebook_grab_notify (GtkWidget *widget,
|
||||
gboolean was_grabbed);
|
||||
static void gtk_notebook_state_flags_changed (GtkWidget *widget,
|
||||
GtkStateFlags previous_state);
|
||||
static gboolean gtk_notebook_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
|
||||
/*** Drag and drop Methods ***/
|
||||
static void gtk_notebook_drag_begin (GtkWidget *widget,
|
||||
@@ -678,8 +674,6 @@ static void gtk_notebook_add (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_notebook_remove (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_notebook_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
static GType gtk_notebook_child_type (GtkContainer *container);
|
||||
static void gtk_notebook_forall (GtkContainer *container,
|
||||
GtkCallback callback,
|
||||
@@ -923,7 +917,6 @@ gtk_notebook_class_init (GtkNotebookClass *class)
|
||||
widget_class->popup_menu = gtk_notebook_popup_menu;
|
||||
widget_class->grab_notify = gtk_notebook_grab_notify;
|
||||
widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
|
||||
widget_class->focus = gtk_notebook_focus;
|
||||
widget_class->drag_begin = gtk_notebook_drag_begin;
|
||||
widget_class->drag_end = gtk_notebook_drag_end;
|
||||
widget_class->drag_motion = gtk_notebook_drag_motion;
|
||||
@@ -937,7 +930,6 @@ gtk_notebook_class_init (GtkNotebookClass *class)
|
||||
container_class->add = gtk_notebook_add;
|
||||
container_class->remove = gtk_notebook_remove;
|
||||
container_class->forall = gtk_notebook_forall;
|
||||
container_class->set_focus_child = gtk_notebook_set_focus_child;
|
||||
container_class->child_type = gtk_notebook_child_type;
|
||||
|
||||
class->switch_page = gtk_notebook_real_switch_page;
|
||||
@@ -1258,7 +1250,6 @@ gtk_notebook_init (GtkNotebook *notebook)
|
||||
priv->scrollable = FALSE;
|
||||
priv->click_child = ARROW_NONE;
|
||||
priv->need_timer = 0;
|
||||
priv->child_has_focus = FALSE;
|
||||
priv->focus_out = FALSE;
|
||||
|
||||
priv->group = 0;
|
||||
@@ -3215,13 +3206,7 @@ gtk_notebook_switch_tab_timeout (gpointer data)
|
||||
priv->switch_tab = NULL;
|
||||
|
||||
if (switch_tab)
|
||||
{
|
||||
/* FIXME: hack, we don't want the
|
||||
* focus to move fom the source widget
|
||||
*/
|
||||
priv->child_has_focus = FALSE;
|
||||
gtk_notebook_switch_focus_tab (notebook, switch_tab);
|
||||
}
|
||||
gtk_notebook_switch_focus_tab (notebook, switch_tab);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -3480,8 +3465,6 @@ gtk_notebook_drag_data_received (GtkWidget *widget,
|
||||
*
|
||||
* gtk_notebook_add
|
||||
* gtk_notebook_remove
|
||||
* gtk_notebook_focus
|
||||
* gtk_notebook_set_focus_child
|
||||
* gtk_notebook_child_type
|
||||
* gtk_notebook_forall
|
||||
*/
|
||||
@@ -3546,7 +3529,6 @@ focus_tabs_in (GtkNotebook *notebook)
|
||||
if (priv->show_tabs && gtk_notebook_has_current_page (notebook))
|
||||
{
|
||||
gtk_widget_grab_focus (GTK_WIDGET (notebook));
|
||||
gtk_notebook_set_focus_child (GTK_CONTAINER (notebook), NULL);
|
||||
gtk_notebook_switch_focus_tab (notebook,
|
||||
g_list_find (priv->children,
|
||||
priv->cur_page));
|
||||
@@ -3557,30 +3539,6 @@ focus_tabs_in (GtkNotebook *notebook)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
focus_tabs_move (GtkNotebook *notebook,
|
||||
GtkDirectionType direction,
|
||||
gint search_direction)
|
||||
{
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
GList *new_page;
|
||||
|
||||
new_page = gtk_notebook_search_page (notebook, priv->focus_tab,
|
||||
search_direction, TRUE);
|
||||
if (!new_page)
|
||||
{
|
||||
new_page = gtk_notebook_search_page (notebook, NULL,
|
||||
search_direction, TRUE);
|
||||
}
|
||||
|
||||
if (new_page)
|
||||
gtk_notebook_switch_focus_tab (notebook, new_page);
|
||||
else
|
||||
gtk_widget_error_bell (GTK_WIDGET (notebook));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
focus_child_in (GtkNotebook *notebook,
|
||||
GtkDirectionType direction)
|
||||
@@ -3593,269 +3551,6 @@ focus_child_in (GtkNotebook *notebook,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
focus_action_in (GtkNotebook *notebook,
|
||||
gint action,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
|
||||
if (priv->action_widget[action] &&
|
||||
gtk_widget_get_visible (priv->action_widget[action]))
|
||||
return gtk_widget_child_focus (priv->action_widget[action], direction);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Focus in the notebook can either be on the pages, or on
|
||||
* the tabs or on the action_widgets.
|
||||
*/
|
||||
static gboolean
|
||||
gtk_notebook_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
GtkWidget *old_focus_child;
|
||||
GtkDirectionType effective_direction;
|
||||
gint first_action;
|
||||
gint last_action;
|
||||
|
||||
gboolean widget_is_focus;
|
||||
|
||||
if (priv->tab_pos == GTK_POS_TOP ||
|
||||
priv->tab_pos == GTK_POS_LEFT)
|
||||
{
|
||||
first_action = ACTION_WIDGET_START;
|
||||
last_action = ACTION_WIDGET_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_action = ACTION_WIDGET_END;
|
||||
last_action = ACTION_WIDGET_START;
|
||||
}
|
||||
|
||||
if (priv->focus_out)
|
||||
{
|
||||
priv->focus_out = FALSE; /* Clear this to catch the wrap-around case */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
widget_is_focus = gtk_widget_is_focus (widget);
|
||||
old_focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
effective_direction = get_effective_direction (notebook, direction);
|
||||
|
||||
if (old_focus_child) /* Focus on page child or action widget */
|
||||
{
|
||||
if (gtk_widget_child_focus (old_focus_child, direction))
|
||||
return TRUE;
|
||||
|
||||
if (old_focus_child == priv->action_widget[ACTION_WIDGET_START])
|
||||
{
|
||||
switch ((guint) effective_direction)
|
||||
{
|
||||
case GTK_DIR_DOWN:
|
||||
return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
|
||||
case GTK_DIR_RIGHT:
|
||||
return focus_tabs_in (notebook);
|
||||
case GTK_DIR_LEFT:
|
||||
return FALSE;
|
||||
case GTK_DIR_UP:
|
||||
return FALSE;
|
||||
default:
|
||||
switch ((guint) direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
if ((priv->tab_pos == GTK_POS_RIGHT || priv->tab_pos == GTK_POS_BOTTOM) &&
|
||||
focus_child_in (notebook, direction))
|
||||
return TRUE;
|
||||
return focus_tabs_in (notebook);
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
return FALSE;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (old_focus_child == priv->action_widget[ACTION_WIDGET_END])
|
||||
{
|
||||
switch ((guint) effective_direction)
|
||||
{
|
||||
case GTK_DIR_DOWN:
|
||||
return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
|
||||
case GTK_DIR_RIGHT:
|
||||
return FALSE;
|
||||
case GTK_DIR_LEFT:
|
||||
return focus_tabs_in (notebook);
|
||||
case GTK_DIR_UP:
|
||||
return FALSE;
|
||||
default:
|
||||
switch ((guint) direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
return FALSE;
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
if ((priv->tab_pos == GTK_POS_TOP || priv->tab_pos == GTK_POS_LEFT) &&
|
||||
focus_child_in (notebook, direction))
|
||||
return TRUE;
|
||||
return focus_tabs_in (notebook);
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((guint) effective_direction)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_UP:
|
||||
/* Focus onto the tabs */
|
||||
return focus_tabs_in (notebook);
|
||||
case GTK_DIR_DOWN:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
return FALSE;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
return focus_action_in (notebook, last_action, direction);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (widget_is_focus) /* Focus was on tabs */
|
||||
{
|
||||
switch ((guint) effective_direction)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
return focus_action_in (notebook, first_action, direction);
|
||||
case GTK_DIR_UP:
|
||||
return FALSE;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
|
||||
return TRUE;
|
||||
return focus_action_in (notebook, last_action, direction);
|
||||
case GTK_DIR_DOWN:
|
||||
/* We use TAB_FORWARD rather than direction so that we focus a more
|
||||
* predictable widget for the user; users may be using arrow focusing
|
||||
* in this situation even if they don't usually use arrow focusing.
|
||||
*/
|
||||
return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
|
||||
case GTK_DIR_LEFT:
|
||||
return focus_tabs_move (notebook, direction, STEP_PREV);
|
||||
case GTK_DIR_RIGHT:
|
||||
return focus_tabs_move (notebook, direction, STEP_NEXT);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* Focus was not on widget */
|
||||
{
|
||||
switch ((guint) effective_direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_DOWN:
|
||||
if (focus_action_in (notebook, first_action, direction))
|
||||
return TRUE;
|
||||
if (focus_tabs_in (notebook))
|
||||
return TRUE;
|
||||
if (focus_action_in (notebook, last_action, direction))
|
||||
return TRUE;
|
||||
if (focus_child_in (notebook, direction))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
if (focus_action_in (notebook, last_action, direction))
|
||||
return TRUE;
|
||||
if (focus_child_in (notebook, direction))
|
||||
return TRUE;
|
||||
if (focus_tabs_in (notebook))
|
||||
return TRUE;
|
||||
if (focus_action_in (notebook, first_action, direction))
|
||||
return TRUE;
|
||||
case GTK_DIR_UP:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
return focus_child_in (notebook, direction);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_notebook_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child)
|
||||
{
|
||||
GtkNotebook *notebook = GTK_NOTEBOOK (container);
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
GtkWidget *page_child;
|
||||
GtkWidget *toplevel;
|
||||
|
||||
/* If the old focus widget was within a page of the notebook,
|
||||
* (child may either be NULL or not in this case), record it
|
||||
* for future use if we switch to the page with a mnemonic.
|
||||
*/
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
|
||||
if (toplevel && gtk_widget_is_toplevel (toplevel))
|
||||
{
|
||||
page_child = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
while (page_child)
|
||||
{
|
||||
if (gtk_widget_get_parent (page_child) == GTK_WIDGET (container))
|
||||
{
|
||||
GList *list = gtk_notebook_find_child (notebook, page_child);
|
||||
if (list != NULL)
|
||||
{
|
||||
GtkNotebookPage *page = list->data;
|
||||
|
||||
if (page->last_focus_child)
|
||||
g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
|
||||
|
||||
page->last_focus_child = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
page_child = gtk_widget_get_parent (page_child);
|
||||
}
|
||||
}
|
||||
|
||||
if (child)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (child));
|
||||
|
||||
priv->child_has_focus = TRUE;
|
||||
if (!priv->focus_tab)
|
||||
{
|
||||
GList *children;
|
||||
GtkNotebookPage *page;
|
||||
|
||||
children = priv->children;
|
||||
while (children)
|
||||
{
|
||||
page = children->data;
|
||||
if (page->child == child || page->tab_label == child)
|
||||
gtk_notebook_switch_focus_tab (notebook, children);
|
||||
children = children->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
priv->child_has_focus = FALSE;
|
||||
|
||||
GTK_CONTAINER_CLASS (gtk_notebook_parent_class)->set_focus_child (container, child);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_notebook_forall (GtkContainer *container,
|
||||
GtkCallback callback,
|
||||
@@ -4305,12 +4000,6 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
if (page->last_focus_child)
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
|
||||
page->last_focus_child = NULL;
|
||||
}
|
||||
|
||||
gtk_widget_unparent (page->tab_widget);
|
||||
|
||||
g_object_unref (page);
|
||||
@@ -5405,6 +5094,25 @@ gtk_notebook_calc_tabs (GtkNotebook *notebook,
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
find_last_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *f = widget;
|
||||
|
||||
while (f)
|
||||
{
|
||||
GtkWidget *focus_child = gtk_widget_get_focus_child (f);
|
||||
if (focus_child == NULL)
|
||||
break;
|
||||
f = focus_child;
|
||||
}
|
||||
|
||||
if (f != widget)
|
||||
return f;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Private GtkNotebook Page Switch Methods:
|
||||
*
|
||||
* gtk_notebook_real_switch_page
|
||||
@@ -5417,16 +5125,19 @@ gtk_notebook_real_switch_page (GtkNotebook *notebook,
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
GList *list = gtk_notebook_find_child (notebook, GTK_WIDGET (child));
|
||||
GtkNotebookPage *page = GTK_NOTEBOOK_PAGE_FROM_LIST (list);
|
||||
gboolean child_has_focus;
|
||||
gboolean child_has_focus = FALSE;
|
||||
|
||||
if (priv->cur_page == page || !gtk_widget_get_visible (GTK_WIDGET (child)))
|
||||
return;
|
||||
|
||||
/* save the value here, changing visibility changes focus */
|
||||
child_has_focus = priv->child_has_focus;
|
||||
|
||||
if (priv->cur_page)
|
||||
gtk_widget_unset_state_flags (priv->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED);
|
||||
{
|
||||
GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (notebook));
|
||||
GtkWidget *focus = gtk_root_get_focus (root);
|
||||
if (focus)
|
||||
child_has_focus = gtk_widget_is_ancestor (focus, priv->cur_page->child);
|
||||
gtk_widget_unset_state_flags (priv->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED);
|
||||
}
|
||||
|
||||
priv->cur_page = page;
|
||||
gtk_widget_set_state_flags (page->tab_widget, GTK_STATE_FLAG_CHECKED, FALSE);
|
||||
@@ -5446,12 +5157,11 @@ gtk_notebook_real_switch_page (GtkNotebook *notebook,
|
||||
*/
|
||||
if (child_has_focus)
|
||||
{
|
||||
if (priv->cur_page->last_focus_child &&
|
||||
gtk_widget_is_ancestor (priv->cur_page->last_focus_child, priv->cur_page->child))
|
||||
gtk_widget_grab_focus (priv->cur_page->last_focus_child);
|
||||
else
|
||||
if (!gtk_widget_child_focus (priv->cur_page->child, GTK_DIR_TAB_FORWARD))
|
||||
gtk_widget_grab_focus (GTK_WIDGET (notebook));
|
||||
GtkWidget *last_focus = find_last_focus (priv->cur_page->child);
|
||||
if (last_focus)
|
||||
gtk_widget_grab_focus (last_focus);
|
||||
else if (!gtk_widget_child_focus (priv->cur_page->child, GTK_DIR_TAB_FORWARD))
|
||||
gtk_widget_grab_focus (GTK_WIDGET (notebook));
|
||||
}
|
||||
|
||||
update_arrow_state (notebook);
|
||||
|
||||
+26
-137
@@ -132,8 +132,6 @@ typedef struct
|
||||
GtkPaned *first_paned;
|
||||
GtkWidget *child1;
|
||||
GtkWidget *child2;
|
||||
GtkWidget *last_child1_focus;
|
||||
GtkWidget *last_child2_focus;
|
||||
GtkWidget *saved_focus;
|
||||
GtkOrientation orientation;
|
||||
|
||||
@@ -218,8 +216,6 @@ static void gtk_paned_size_allocate (GtkWidget *widget,
|
||||
int height,
|
||||
int baseline);
|
||||
static void gtk_paned_unrealize (GtkWidget *widget);
|
||||
static gboolean gtk_paned_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_paned_add (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_paned_remove (GtkContainer *container,
|
||||
@@ -231,16 +227,10 @@ static void gtk_paned_calc_position (GtkPaned *paned,
|
||||
gint allocation,
|
||||
gint child1_req,
|
||||
gint child2_req);
|
||||
static void gtk_paned_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
static void gtk_paned_set_saved_focus (GtkPaned *paned,
|
||||
GtkWidget *widget);
|
||||
static void gtk_paned_set_first_paned (GtkPaned *paned,
|
||||
GtkPaned *first_paned);
|
||||
static void gtk_paned_set_last_child1_focus (GtkPaned *paned,
|
||||
GtkWidget *widget);
|
||||
static void gtk_paned_set_last_child2_focus (GtkPaned *paned,
|
||||
GtkWidget *widget);
|
||||
static gboolean gtk_paned_cycle_child_focus (GtkPaned *paned,
|
||||
gboolean reverse);
|
||||
static gboolean gtk_paned_cycle_handle_focus (GtkPaned *paned,
|
||||
@@ -365,14 +355,12 @@ gtk_paned_class_init (GtkPanedClass *class)
|
||||
widget_class->measure = gtk_paned_measure;
|
||||
widget_class->size_allocate = gtk_paned_size_allocate;
|
||||
widget_class->unrealize = gtk_paned_unrealize;
|
||||
widget_class->focus = gtk_paned_focus;
|
||||
widget_class->pick = gtk_paned_pick;
|
||||
|
||||
container_class->add = gtk_paned_add;
|
||||
container_class->remove = gtk_paned_remove;
|
||||
container_class->forall = gtk_paned_forall;
|
||||
container_class->child_type = gtk_paned_child_type;
|
||||
container_class->set_focus_child = gtk_paned_set_focus_child;
|
||||
container_class->set_child_property = gtk_paned_set_child_property;
|
||||
container_class->get_child_property = gtk_paned_get_child_property;
|
||||
|
||||
@@ -1353,8 +1341,6 @@ gtk_paned_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GtkPaned *paned = GTK_PANED (widget);
|
||||
|
||||
gtk_paned_set_last_child1_focus (paned, NULL);
|
||||
gtk_paned_set_last_child2_focus (paned, NULL);
|
||||
gtk_paned_set_saved_focus (paned, NULL);
|
||||
gtk_paned_set_first_paned (paned, NULL);
|
||||
|
||||
@@ -1410,8 +1396,6 @@ gtk_paned_init (GtkPaned *paned)
|
||||
priv->position_set = FALSE;
|
||||
priv->last_allocation = -1;
|
||||
|
||||
priv->last_child1_focus = NULL;
|
||||
priv->last_child2_focus = NULL;
|
||||
priv->in_recursion = FALSE;
|
||||
priv->original_position = -1;
|
||||
priv->max_position = G_MAXINT;
|
||||
@@ -1498,24 +1482,6 @@ update_drag (GtkPaned *paned,
|
||||
gtk_paned_set_position (paned, size);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_paned_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
|
||||
{
|
||||
gboolean retval;
|
||||
|
||||
/* This is a hack, but how can this be done without
|
||||
* excessive cut-and-paste from gtkcontainer.c?
|
||||
*/
|
||||
|
||||
gtk_widget_set_can_focus (widget, FALSE);
|
||||
retval = GTK_WIDGET_CLASS (gtk_paned_parent_class)->focus (widget, direction);
|
||||
gtk_widget_set_can_focus (widget, TRUE);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_paned_new:
|
||||
* @orientation: the paned’s orientation.
|
||||
@@ -1860,86 +1826,23 @@ gtk_paned_set_first_paned (GtkPaned *paned, GtkPaned *first_paned)
|
||||
(gpointer *)&(priv->first_paned));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_paned_set_last_child1_focus (GtkPaned *paned, GtkWidget *widget)
|
||||
{
|
||||
GtkPanedPrivate *priv = gtk_paned_get_instance_private (paned);
|
||||
|
||||
if (priv->last_child1_focus)
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->last_child1_focus),
|
||||
(gpointer *)&(priv->last_child1_focus));
|
||||
|
||||
priv->last_child1_focus = widget;
|
||||
|
||||
if (priv->last_child1_focus)
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->last_child1_focus),
|
||||
(gpointer *)&(priv->last_child1_focus));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_paned_set_last_child2_focus (GtkPaned *paned, GtkWidget *widget)
|
||||
{
|
||||
GtkPanedPrivate *priv = gtk_paned_get_instance_private (paned);
|
||||
|
||||
if (priv->last_child2_focus)
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->last_child2_focus),
|
||||
(gpointer *)&(priv->last_child2_focus));
|
||||
|
||||
priv->last_child2_focus = widget;
|
||||
|
||||
if (priv->last_child2_focus)
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->last_child2_focus),
|
||||
(gpointer *)&(priv->last_child2_focus));
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
paned_get_focus_widget (GtkPaned *paned)
|
||||
find_last_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *f = widget;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned));
|
||||
if (gtk_widget_is_toplevel (toplevel))
|
||||
return gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_paned_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *focus_child)
|
||||
{
|
||||
GtkPaned *paned = GTK_PANED (container);
|
||||
GtkPanedPrivate *priv = gtk_paned_get_instance_private (paned);
|
||||
GtkWidget *container_focus_child;
|
||||
|
||||
g_return_if_fail (GTK_IS_PANED (container));
|
||||
|
||||
if (focus_child == NULL)
|
||||
while (f)
|
||||
{
|
||||
GtkWidget *last_focus;
|
||||
GtkWidget *w;
|
||||
|
||||
last_focus = paned_get_focus_widget (paned);
|
||||
|
||||
if (last_focus)
|
||||
{
|
||||
/* If there is one or more paned widgets between us and the
|
||||
* focus widget, we want the topmost of those as last_focus
|
||||
*/
|
||||
for (w = last_focus; w != GTK_WIDGET (paned); w = gtk_widget_get_parent (w))
|
||||
if (GTK_IS_PANED (w))
|
||||
last_focus = w;
|
||||
|
||||
container_focus_child = gtk_widget_get_focus_child (GTK_WIDGET (container));
|
||||
if (container_focus_child == priv->child1)
|
||||
gtk_paned_set_last_child1_focus (paned, last_focus);
|
||||
else if (container_focus_child == priv->child2)
|
||||
gtk_paned_set_last_child2_focus (paned, last_focus);
|
||||
}
|
||||
GtkWidget *focus_child = gtk_widget_get_focus_child (f);
|
||||
if (focus_child == NULL)
|
||||
break;
|
||||
f = focus_child;
|
||||
}
|
||||
|
||||
if (GTK_CONTAINER_CLASS (gtk_paned_parent_class)->set_focus_child)
|
||||
GTK_CONTAINER_CLASS (gtk_paned_parent_class)->set_focus_child (container, focus_child);
|
||||
if (f != widget)
|
||||
return f;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1954,24 +1857,14 @@ gtk_paned_get_cycle_chain (GtkPaned *paned,
|
||||
GtkWidget *widget = GTK_WIDGET (paned);
|
||||
GList *temp_list = NULL;
|
||||
GList *list;
|
||||
GtkWidget *last_child1_focus;
|
||||
GtkWidget *last_child2_focus;
|
||||
|
||||
if (priv->in_recursion)
|
||||
return;
|
||||
|
||||
g_assert (widgets != NULL);
|
||||
|
||||
if (priv->last_child1_focus &&
|
||||
!gtk_widget_is_ancestor (priv->last_child1_focus, widget))
|
||||
{
|
||||
gtk_paned_set_last_child1_focus (paned, NULL);
|
||||
}
|
||||
|
||||
if (priv->last_child2_focus &&
|
||||
!gtk_widget_is_ancestor (priv->last_child2_focus, widget))
|
||||
{
|
||||
gtk_paned_set_last_child2_focus (paned, NULL);
|
||||
}
|
||||
|
||||
parent = gtk_widget_get_parent (widget);
|
||||
if (parent)
|
||||
ancestor = gtk_widget_get_ancestor (parent, GTK_TYPE_PANED);
|
||||
@@ -1984,26 +1877,28 @@ gtk_paned_get_cycle_chain (GtkPaned *paned,
|
||||
* priv->last_child?_focus before priv->child?, both when we
|
||||
* are going forward and backward.
|
||||
*/
|
||||
last_child1_focus = find_last_focus (priv->child1);
|
||||
last_child2_focus = find_last_focus (priv->child2);
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (paned));
|
||||
if (direction == GTK_DIR_TAB_FORWARD)
|
||||
{
|
||||
if (focus_child == priv->child1)
|
||||
{
|
||||
temp_list = g_list_append (temp_list, priv->last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child2);
|
||||
temp_list = g_list_append (temp_list, ancestor);
|
||||
}
|
||||
else if (focus_child == priv->child2)
|
||||
{
|
||||
temp_list = g_list_append (temp_list, ancestor);
|
||||
temp_list = g_list_append (temp_list, priv->last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child1);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_list = g_list_append (temp_list, priv->last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child1);
|
||||
temp_list = g_list_append (temp_list, priv->last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child2);
|
||||
temp_list = g_list_append (temp_list, ancestor);
|
||||
}
|
||||
@@ -2013,20 +1908,20 @@ gtk_paned_get_cycle_chain (GtkPaned *paned,
|
||||
if (focus_child == priv->child1)
|
||||
{
|
||||
temp_list = g_list_append (temp_list, ancestor);
|
||||
temp_list = g_list_append (temp_list, priv->last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child2);
|
||||
}
|
||||
else if (focus_child == priv->child2)
|
||||
{
|
||||
temp_list = g_list_append (temp_list, priv->last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child1);
|
||||
temp_list = g_list_append (temp_list, ancestor);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_list = g_list_append (temp_list, priv->last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, last_child2_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child2);
|
||||
temp_list = g_list_append (temp_list, priv->last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, last_child1_focus);
|
||||
temp_list = g_list_append (temp_list, priv->child1);
|
||||
temp_list = g_list_append (temp_list, ancestor);
|
||||
}
|
||||
@@ -2256,10 +2151,8 @@ gtk_paned_restore_focus (GtkPaned *paned)
|
||||
|
||||
if (!gtk_widget_child_focus (GTK_WIDGET (paned), GTK_DIR_TAB_FORWARD))
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned));
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
|
||||
GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (paned));
|
||||
gtk_root_set_focus (root, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2364,7 +2257,6 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned,
|
||||
{
|
||||
GtkPaned *focus;
|
||||
GtkPaned *first;
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *focus_child;
|
||||
|
||||
gtk_paned_find_neighbours (paned, &next, &prev);
|
||||
@@ -2410,10 +2302,7 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned,
|
||||
first = next;
|
||||
}
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned));
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
gtk_paned_set_saved_focus (focus, gtk_window_get_focus (GTK_WINDOW (toplevel)));
|
||||
gtk_paned_set_saved_focus (focus, gtk_root_get_focus (gtk_widget_get_root (GTK_WIDGET (paned))));
|
||||
gtk_paned_set_first_paned (focus, first);
|
||||
priv->original_position = gtk_paned_get_position (focus);
|
||||
|
||||
|
||||
+1
-1
@@ -1766,7 +1766,7 @@ on_key_press_event (GtkEventController *controller,
|
||||
if (!toplevel)
|
||||
return FALSE;
|
||||
|
||||
focus_widget = gtk_window_get_focus (toplevel);
|
||||
focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel));
|
||||
|
||||
if (!GTK_IS_PLACES_VIEW_ROW (focus_widget))
|
||||
return FALSE;
|
||||
|
||||
+3
-36
@@ -614,10 +614,11 @@ window_active_changed (GtkWindow *window,
|
||||
|
||||
static void
|
||||
window_set_focus (GtkWindow *window,
|
||||
GtkWidget *widget,
|
||||
GParamSpec *pspec,
|
||||
GtkPopover *popover)
|
||||
{
|
||||
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
|
||||
GtkWidget *widget = gtk_root_get_focus (GTK_ROOT (window));
|
||||
|
||||
if (!priv->modal || !widget || !gtk_widget_is_drawable (GTK_WIDGET (popover)))
|
||||
return;
|
||||
@@ -673,7 +674,7 @@ gtk_popover_apply_modality (GtkPopover *popover,
|
||||
|
||||
g_signal_connect (priv->window, "notify::is-active",
|
||||
G_CALLBACK (window_active_changed), popover);
|
||||
g_signal_connect (priv->window, "set-focus",
|
||||
g_signal_connect (priv->window, "notify::focus-widget",
|
||||
G_CALLBACK (window_set_focus), popover);
|
||||
}
|
||||
else
|
||||
@@ -1455,39 +1456,6 @@ gtk_popover_grab_focus (GtkWidget *widget)
|
||||
gtk_widget_child_focus (child, GTK_DIR_TAB_FORWARD);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_popover_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkPopover *popover = GTK_POPOVER (widget);
|
||||
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
|
||||
|
||||
if (!priv->visible)
|
||||
return FALSE;
|
||||
|
||||
if (!GTK_WIDGET_CLASS (gtk_popover_parent_class)->focus (widget, direction))
|
||||
{
|
||||
GtkWidget *focus;
|
||||
|
||||
focus = gtk_window_get_focus (priv->window);
|
||||
focus = gtk_widget_get_parent (focus);
|
||||
|
||||
/* Unset focus child through children, so it is next stepped from
|
||||
* scratch.
|
||||
*/
|
||||
while (focus && focus != widget)
|
||||
{
|
||||
gtk_widget_set_focus_child (focus, NULL);
|
||||
focus = gtk_widget_get_parent (focus);
|
||||
}
|
||||
|
||||
return gtk_widget_child_focus (gtk_bin_get_child (GTK_BIN (widget)),
|
||||
direction);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popover_show (GtkWidget *widget)
|
||||
{
|
||||
@@ -1582,7 +1550,6 @@ gtk_popover_class_init (GtkPopoverClass *klass)
|
||||
widget_class->size_allocate = gtk_popover_size_allocate;
|
||||
widget_class->snapshot = gtk_popover_snapshot;
|
||||
widget_class->grab_focus = gtk_popover_grab_focus;
|
||||
widget_class->focus = gtk_popover_focus;
|
||||
widget_class->show = gtk_popover_show;
|
||||
widget_class->hide = gtk_popover_hide;
|
||||
widget_class->state_flags_changed = gtk_popover_state_flags_changed;
|
||||
|
||||
+733
@@ -0,0 +1,733 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Matthias Clasen <mclasen@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkpopup.h"
|
||||
#include "gtkroot.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkenums.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkmnemonichash.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gdk/gdkeventsprivate.h"
|
||||
|
||||
static GListStore *popup_list = NULL;
|
||||
|
||||
typedef struct {
|
||||
GdkDisplay *display;
|
||||
GskRenderer *renderer;
|
||||
GdkSurface *surface;
|
||||
GtkWidget *relative_to;
|
||||
GtkWidget *focus_widget;
|
||||
gboolean active;
|
||||
GtkWidget *default_widget;
|
||||
GtkMnemonicHash *mnemonic_hash;
|
||||
} GtkPopupPrivate;
|
||||
|
||||
enum {
|
||||
ACTIVATE_FOCUS,
|
||||
ACTIVATE_DEFAULT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void gtk_popup_root_interface_init (GtkRootInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkPopup, gtk_popup, GTK_TYPE_BIN,
|
||||
G_ADD_PRIVATE (GtkPopup)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
|
||||
gtk_popup_root_interface_init))
|
||||
|
||||
|
||||
static GdkDisplay *
|
||||
gtk_popup_root_get_display (GtkRoot *root)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (root);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
static GskRenderer *
|
||||
gtk_popup_root_get_renderer (GtkRoot *root)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (root);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
return priv->renderer;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_root_get_surface_transform (GtkRoot *root,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GtkBorder margin, border, padding;
|
||||
|
||||
context = gtk_widget_get_style_context (GTK_WIDGET (root));
|
||||
gtk_style_context_get_margin (context, &margin);
|
||||
gtk_style_context_get_border (context, &border);
|
||||
gtk_style_context_get_padding (context, &padding);
|
||||
|
||||
*x = margin.left + border.left + padding.left;
|
||||
*y = margin.top + border.top + padding.top;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_move_resize (GtkPopup *popup)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GdkRectangle rect;
|
||||
GtkRequisition req;
|
||||
|
||||
gtk_widget_get_preferred_size (GTK_WIDGET (popup), NULL, &req);
|
||||
gdk_surface_resize (priv->surface, req.width, req.height);
|
||||
gtk_widget_get_surface_allocation (priv->relative_to, &rect);
|
||||
|
||||
gdk_surface_move_to_rect (priv->surface,
|
||||
&rect,
|
||||
GDK_GRAVITY_SOUTH,
|
||||
GDK_GRAVITY_NORTH,
|
||||
GDK_ANCHOR_FLIP_Y,
|
||||
0, 10);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_root_check_resize (GtkRoot *root)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (root);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GtkWidget *widget = GTK_WIDGET (popup);
|
||||
|
||||
if (!_gtk_widget_get_alloc_needed (widget))
|
||||
gtk_widget_ensure_allocate (widget);
|
||||
else if (gtk_widget_get_visible (widget))
|
||||
{
|
||||
gtk_popup_move_resize (popup);
|
||||
gtk_widget_allocate (GTK_WIDGET (popup),
|
||||
gdk_surface_get_width (priv->surface),
|
||||
gdk_surface_get_height (priv->surface),
|
||||
-1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void gtk_popup_root_add_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
static void gtk_popup_root_remove_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
static gboolean gtk_popup_root_activate_key (GtkRoot *root,
|
||||
GdkEventKey *event);
|
||||
|
||||
static void
|
||||
gtk_popup_root_interface_init (GtkRootInterface *iface)
|
||||
{
|
||||
iface->get_display = gtk_popup_root_get_display;
|
||||
iface->get_renderer = gtk_popup_root_get_renderer;
|
||||
iface->get_surface_transform = gtk_popup_root_get_surface_transform;
|
||||
iface->check_resize = gtk_popup_root_check_resize;
|
||||
iface->add_mnemonic = gtk_popup_root_add_mnemonic;
|
||||
iface->remove_mnemonic = gtk_popup_root_remove_mnemonic;
|
||||
iface->activate_key = gtk_popup_root_activate_key;
|
||||
}
|
||||
|
||||
static void gtk_popup_set_is_active (GtkPopup *popup, gboolean active);
|
||||
|
||||
static void
|
||||
gtk_popup_focus_in (GtkWidget *widget)
|
||||
{
|
||||
gtk_popup_set_is_active (GTK_POPUP (widget), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_focus_out (GtkWidget *widget)
|
||||
{
|
||||
gtk_popup_set_is_active (GTK_POPUP (widget), FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_popup_init (GtkPopup *popup)
|
||||
{
|
||||
GtkEventController *controller;
|
||||
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (popup), TRUE);
|
||||
gtk_widget_set_can_focus (GTK_WIDGET (popup), TRUE);
|
||||
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_signal_connect_swapped (controller, "focus-in", G_CALLBACK (gtk_popup_focus_in), popup);
|
||||
g_signal_connect_swapped (controller, "focus-out", G_CALLBACK (gtk_popup_focus_out), popup);
|
||||
gtk_widget_add_controller (GTK_WIDGET (popup), controller);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_realize (GtkWidget *widget)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (widget);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GdkRectangle parent_rect;
|
||||
|
||||
if (_gtk_widget_get_alloc_needed (widget))
|
||||
{
|
||||
GdkRectangle allocation;
|
||||
allocation.x = 0;
|
||||
allocation.y = 0;
|
||||
allocation.width = 20; // FIXME
|
||||
allocation.height = 20;
|
||||
gtk_widget_size_allocate (widget, &allocation, -1);
|
||||
gtk_widget_queue_resize (widget);
|
||||
}
|
||||
|
||||
gtk_widget_get_surface_allocation (priv->relative_to, &parent_rect);
|
||||
priv->surface = gdk_surface_new_popup (priv->display, &parent_rect);
|
||||
// TODO xdg-popop window type
|
||||
gdk_surface_set_transient_for (priv->surface, gtk_widget_get_surface (priv->relative_to));
|
||||
gdk_surface_set_type_hint (priv->surface, GDK_SURFACE_TYPE_HINT_POPUP_MENU);
|
||||
|
||||
gdk_surface_move_to_rect (priv->surface,
|
||||
&parent_rect,
|
||||
GDK_GRAVITY_SOUTH,
|
||||
GDK_GRAVITY_NORTH,
|
||||
GDK_ANCHOR_FLIP_Y,
|
||||
0, 10);
|
||||
|
||||
gtk_widget_set_surface (widget, priv->surface);
|
||||
gtk_widget_register_surface (widget, priv->surface);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_popup_parent_class)->realize (widget);
|
||||
|
||||
priv->renderer = gsk_renderer_new_for_surface (priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (widget);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_popup_parent_class)->unrealize (widget);
|
||||
|
||||
gsk_renderer_unrealize (priv->renderer);
|
||||
g_clear_object (&priv->renderer);
|
||||
|
||||
g_clear_object (&priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_show (GtkWidget *widget)
|
||||
{
|
||||
_gtk_widget_set_visible_flag (widget, TRUE);
|
||||
gtk_css_node_validate (gtk_widget_get_css_node (widget));
|
||||
gtk_widget_realize (widget);
|
||||
gtk_widget_map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_hide (GtkWidget *widget)
|
||||
{
|
||||
_gtk_widget_set_visible_flag (widget, FALSE);
|
||||
gtk_widget_unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_map (GtkWidget *widget)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (widget);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GtkWidget *child;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_popup_parent_class)->map (widget);
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
if (child != NULL && gtk_widget_get_visible (child))
|
||||
gtk_widget_map (child);
|
||||
|
||||
gdk_surface_show (priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_unmap (GtkWidget *widget)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (widget);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GtkWidget *child;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_popup_parent_class)->unmap (widget);
|
||||
|
||||
gdk_surface_hide (priv->surface);
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
if (child != NULL)
|
||||
gtk_widget_unmap (child);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_dispose (GObject *object)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (popup_list)); i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (G_LIST_MODEL (popup_list), i);
|
||||
if (item == object)
|
||||
{
|
||||
g_list_store_remove (popup_list, i);
|
||||
break;
|
||||
}
|
||||
else
|
||||
g_object_unref (item);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gtk_popup_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (gtk_popup_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_constructed (GObject *object)
|
||||
{
|
||||
g_list_store_append (popup_list, object);
|
||||
g_object_unref (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
gtk_widget_measure (child, orientation, for_size,
|
||||
minimum, natural,
|
||||
minimum_baseline, natural_baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkWidget *child;
|
||||
GtkPopup *popup = GTK_POPUP (widget);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
if (priv->surface)
|
||||
{
|
||||
// FIXME why is this needed ?
|
||||
gdk_surface_move_resize (priv->surface, 0, 0, width, height);
|
||||
gtk_popup_move_resize (popup);
|
||||
}
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
gtk_widget_size_allocate (child, &(GtkAllocation) { 0, 0, width, height }, baseline);
|
||||
}
|
||||
|
||||
static void gtk_popup_set_focus (GtkPopup *popup,
|
||||
GtkWidget *widget);
|
||||
|
||||
static void gtk_popup_set_default (GtkPopup *popup,
|
||||
GtkWidget *widget);
|
||||
|
||||
static void
|
||||
gtk_popup_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case 1 + GTK_ROOT_PROP_FOCUS_WIDGET:
|
||||
gtk_popup_set_focus (popup, g_value_get_object (value));
|
||||
break;
|
||||
case 1 + GTK_ROOT_PROP_DEFAULT_WIDGET:
|
||||
gtk_popup_set_default (popup, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkPopup *popup = GTK_POPUP (object);
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case 1 + GTK_ROOT_PROP_FOCUS_WIDGET:
|
||||
g_value_set_object (value, priv->focus_widget);
|
||||
break;
|
||||
case 1 + GTK_ROOT_PROP_DEFAULT_WIDGET:
|
||||
g_value_set_object (value, priv->default_widget);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_activate_default (GtkPopup *popup)
|
||||
{
|
||||
gtk_root_activate_default (GTK_ROOT (popup));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_activate_focus (GtkPopup *popup)
|
||||
{
|
||||
gtk_root_activate_focus (GTK_ROOT (popup));
|
||||
}
|
||||
|
||||
static void
|
||||
add_tab_bindings (GtkBindingSet *binding_set,
|
||||
GdkModifierType modifiers,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
|
||||
"move-focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
|
||||
"move-focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_class_init (GtkPopupClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GtkBindingSet *binding_set;
|
||||
|
||||
if (popup_list == NULL)
|
||||
popup_list = g_list_store_new (GTK_TYPE_WIDGET);
|
||||
|
||||
object_class->constructed = gtk_popup_constructed;
|
||||
object_class->dispose = gtk_popup_dispose;
|
||||
object_class->finalize = gtk_popup_finalize;
|
||||
object_class->set_property = gtk_popup_set_property;
|
||||
object_class->get_property = gtk_popup_get_property;
|
||||
|
||||
widget_class->realize = gtk_popup_realize;
|
||||
widget_class->unrealize = gtk_popup_unrealize;
|
||||
widget_class->map = gtk_popup_map;
|
||||
widget_class->unmap = gtk_popup_unmap;
|
||||
widget_class->show = gtk_popup_show;
|
||||
widget_class->hide = gtk_popup_hide;
|
||||
widget_class->measure = gtk_popup_measure;
|
||||
widget_class->size_allocate = gtk_popup_size_allocate;
|
||||
|
||||
klass->activate_default = gtk_popup_activate_default;
|
||||
klass->activate_focus = gtk_popup_activate_focus;
|
||||
|
||||
gtk_root_install_properties (object_class, 1);
|
||||
|
||||
signals[ACTIVATE_FOCUS] =
|
||||
g_signal_new (I_("activate-focus"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GtkPopupClass, activate_focus),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
signals[ACTIVATE_DEFAULT] =
|
||||
g_signal_new (I_("activate-default"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GtkPopupClass, activate_default),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
|
||||
add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
|
||||
add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
|
||||
add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, "activate-focus", 0);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "activate-focus", 0);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "activate-default", 0);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, "activate-default", 0);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "activate-default", 0);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_popup_new (void)
|
||||
{
|
||||
return GTK_WIDGET (g_object_new (GTK_TYPE_POPUP, NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
size_changed (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline,
|
||||
GtkPopup *popup)
|
||||
{
|
||||
gtk_popup_move_resize (popup);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_popup_set_relative_to (GtkPopup *popup,
|
||||
GtkWidget *relative_to)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
priv->relative_to = relative_to;
|
||||
g_signal_connect (priv->relative_to, "size-allocate", G_CALLBACK (size_changed), popup);
|
||||
priv->display = gtk_widget_get_display (relative_to);
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_popup_get_popups (void)
|
||||
{
|
||||
if (popup_list == NULL)
|
||||
popup_list = g_list_store_new (GTK_TYPE_WIDGET);
|
||||
|
||||
return G_LIST_MODEL (popup_list);
|
||||
}
|
||||
|
||||
static void
|
||||
do_focus_change (GtkWidget *widget,
|
||||
gboolean in)
|
||||
{
|
||||
GdkSeat *seat;
|
||||
GList *devices, *d;
|
||||
|
||||
g_object_ref (widget);
|
||||
|
||||
seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
|
||||
devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_KEYBOARD);
|
||||
devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
|
||||
|
||||
for (d = devices; d; d = d->next)
|
||||
{
|
||||
GdkDevice *dev = d->data;
|
||||
GdkEvent *fevent;
|
||||
GdkSurface *surface;
|
||||
|
||||
surface = _gtk_widget_get_surface (widget);
|
||||
|
||||
fevent = gdk_event_new (GDK_FOCUS_CHANGE);
|
||||
gdk_event_set_display (fevent, gtk_widget_get_display (widget));
|
||||
|
||||
fevent->any.type = GDK_FOCUS_CHANGE;
|
||||
fevent->any.surface = surface;
|
||||
if (surface)
|
||||
g_object_ref (surface);
|
||||
fevent->focus_change.in = in;
|
||||
gdk_event_set_device (fevent, dev);
|
||||
|
||||
gtk_widget_send_focus_change (widget, fevent);
|
||||
|
||||
g_object_unref (fevent);
|
||||
}
|
||||
|
||||
g_list_free (devices);
|
||||
g_object_unref (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unset_focus_widget (GtkPopup *popup)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GtkWidget *f;
|
||||
|
||||
for (f = priv->focus_widget; f; f = gtk_widget_get_parent (f))
|
||||
{
|
||||
gtk_widget_unset_state_flags (f, GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE);
|
||||
if (GTK_IS_ROOT (f))
|
||||
break;
|
||||
}
|
||||
|
||||
if (priv->focus_widget)
|
||||
do_focus_change (priv->focus_widget, FALSE);
|
||||
g_set_object (&priv->focus_widget, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
set_focus_widget (GtkPopup *popup,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
GtkWidget *f;
|
||||
GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED;
|
||||
|
||||
flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
|
||||
|
||||
for (f = focus; f; f = gtk_widget_get_parent (f))
|
||||
{
|
||||
GtkWidget *parent = gtk_widget_get_parent (f);
|
||||
gtk_widget_set_state_flags (f, flags, FALSE);
|
||||
if (GTK_IS_ROOT (f))
|
||||
break;
|
||||
if (parent)
|
||||
gtk_widget_set_focus_child (parent, f);
|
||||
}
|
||||
|
||||
g_set_object (&priv->focus_widget, focus);
|
||||
if (priv->focus_widget)
|
||||
do_focus_change (priv->focus_widget, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_set_focus (GtkPopup *popup,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_POPUP (popup));
|
||||
|
||||
if (focus && !gtk_widget_can_take_focus (focus))
|
||||
return;
|
||||
|
||||
unset_focus_widget (popup);
|
||||
set_focus_widget (popup, focus);
|
||||
|
||||
g_object_notify (G_OBJECT (popup), "focus-widget");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_set_is_active (GtkPopup *popup,
|
||||
gboolean active)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
if (priv->active == active)
|
||||
return;
|
||||
|
||||
priv->active = active;
|
||||
|
||||
if (priv->focus_widget &&
|
||||
priv->focus_widget != GTK_WIDGET (popup) &&
|
||||
gtk_widget_has_focus (priv->focus_widget) != active)
|
||||
do_focus_change (priv->focus_widget, active);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_set_default (GtkPopup *popup,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
g_return_if_fail (GTK_IS_POPUP (popup));
|
||||
|
||||
if (widget && !gtk_widget_get_can_default (widget))
|
||||
return;
|
||||
|
||||
if (priv->default_widget == widget)
|
||||
return;
|
||||
|
||||
if (priv->default_widget)
|
||||
{
|
||||
if (priv->focus_widget != priv->default_widget ||
|
||||
!gtk_widget_get_receives_default (priv->default_widget))
|
||||
_gtk_widget_set_has_default (priv->default_widget, FALSE);
|
||||
|
||||
gtk_widget_queue_draw (priv->default_widget);
|
||||
g_object_notify (G_OBJECT (priv->default_widget), "has-default");
|
||||
}
|
||||
|
||||
g_set_object (&priv->default_widget, widget);
|
||||
|
||||
if (priv->default_widget)
|
||||
{
|
||||
if (priv->focus_widget == NULL ||
|
||||
!gtk_widget_get_receives_default (priv->focus_widget))
|
||||
_gtk_widget_set_has_default (priv->default_widget, TRUE);
|
||||
|
||||
gtk_widget_queue_draw (priv->default_widget);
|
||||
g_object_notify (G_OBJECT (priv->default_widget), "has-default");
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (popup), "default-widget");
|
||||
}
|
||||
|
||||
static GtkMnemonicHash *
|
||||
gtk_popup_get_mnemonic_hash (GtkPopup *popup,
|
||||
gboolean create)
|
||||
{
|
||||
GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
|
||||
|
||||
if (!priv->mnemonic_hash && create)
|
||||
priv->mnemonic_hash = _gtk_mnemonic_hash_new ();
|
||||
|
||||
return priv->mnemonic_hash;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_root_add_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
_gtk_mnemonic_hash_add (gtk_popup_get_mnemonic_hash (GTK_POPUP (root), TRUE), keyval, target);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_popup_root_remove_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
_gtk_mnemonic_hash_remove (gtk_popup_get_mnemonic_hash (GTK_POPUP (root), TRUE), keyval, target);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_popup_root_activate_key (GtkRoot *root,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
GdkModifierType modifier = event->state;
|
||||
guint keyval = event->keyval;
|
||||
|
||||
if ((modifier & gtk_accelerator_get_default_mod_mask ()) == GDK_MOD1_MASK)
|
||||
{
|
||||
GtkMnemonicHash *hash = gtk_popup_get_mnemonic_hash (GTK_POPUP (root), FALSE);
|
||||
if (hash)
|
||||
return _gtk_mnemonic_hash_activate (hash, keyval);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Matthias Clasen <mclasen@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_POPUP_H__
|
||||
#define __GTK_POPUP_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkbin.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_POPUP (gtk_popup_get_type ())
|
||||
#define GTK_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPUP, GtkPopup))
|
||||
#define GTK_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_POPUP, GtkPopupClass))
|
||||
#define GTK_IS_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPUP))
|
||||
#define GTK_IS_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_POPUP))
|
||||
#define GTK_POPUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_POPUP, GtkPopupClass))
|
||||
|
||||
typedef struct _GtkPopup GtkPopup;
|
||||
typedef struct _GtkPopupClass GtkPopupClass;
|
||||
|
||||
struct _GtkPopup
|
||||
{
|
||||
GtkBin parent;
|
||||
};
|
||||
|
||||
struct _GtkPopupClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
/* keybinding signals */
|
||||
|
||||
void (* activate_focus) (GtkPopup *popup);
|
||||
void (* activate_default) (GtkPopup *popup);
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_popup_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_popup_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_popup_set_relative_to (GtkPopup *popup,
|
||||
GtkWidget *relative_to);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_popup_get_popups (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_POPUP_H__ */
|
||||
@@ -149,8 +149,6 @@ static GParamSpec *radio_button_props[LAST_PROP] = { NULL, };
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
static void gtk_radio_button_destroy (GtkWidget *widget);
|
||||
static gboolean gtk_radio_button_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_radio_button_clicked (GtkButton *button);
|
||||
static void gtk_radio_button_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -192,7 +190,6 @@ gtk_radio_button_class_init (GtkRadioButtonClass *class)
|
||||
g_object_class_install_properties (gobject_class, LAST_PROP, radio_button_props);
|
||||
|
||||
widget_class->destroy = gtk_radio_button_destroy;
|
||||
widget_class->focus = gtk_radio_button_focus;
|
||||
|
||||
button_class->clicked = gtk_radio_button_clicked;
|
||||
|
||||
@@ -615,99 +612,6 @@ gtk_radio_button_destroy (GtkWidget *widget)
|
||||
GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_radio_button_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget);
|
||||
GtkRadioButtonPrivate *priv = gtk_radio_button_get_instance_private (radio_button);
|
||||
GSList *tmp_slist;
|
||||
|
||||
/* Radio buttons with draw_indicator unset focus "normally", since
|
||||
* they look like buttons to the user.
|
||||
*/
|
||||
if (!gtk_check_button_get_draw_indicator (GTK_CHECK_BUTTON (widget)))
|
||||
return GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->focus (widget, direction);
|
||||
|
||||
if (gtk_widget_is_focus (widget))
|
||||
{
|
||||
GPtrArray *child_array;
|
||||
GtkWidget *new_focus = NULL;
|
||||
GSList *l;
|
||||
guint index;
|
||||
gboolean found;
|
||||
guint i;
|
||||
|
||||
if (direction == GTK_DIR_TAB_FORWARD ||
|
||||
direction == GTK_DIR_TAB_BACKWARD)
|
||||
return FALSE;
|
||||
|
||||
child_array = g_ptr_array_sized_new (g_slist_length (priv->group));
|
||||
for (l = priv->group; l; l = l->next)
|
||||
g_ptr_array_add (child_array, l->data);
|
||||
|
||||
gtk_widget_focus_sort (widget, direction, child_array);
|
||||
found = g_ptr_array_find (child_array, widget, &index);
|
||||
|
||||
if (found)
|
||||
{
|
||||
/* Start at the *next* widget in the list */
|
||||
if (index < child_array->len - 1)
|
||||
index ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Search from the start of the list */
|
||||
index = 0;
|
||||
}
|
||||
|
||||
for (i = index; i < child_array->len; i ++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (child_array, i);
|
||||
|
||||
if (gtk_widget_get_mapped (child) && gtk_widget_is_sensitive (child))
|
||||
{
|
||||
new_focus = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (new_focus)
|
||||
{
|
||||
gtk_widget_grab_focus (new_focus);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (new_focus), TRUE);
|
||||
}
|
||||
|
||||
g_ptr_array_free (child_array, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkRadioButton *selected_button = NULL;
|
||||
|
||||
/* We accept the focus if, we don't have the focus and
|
||||
* - we are the currently active button in the group
|
||||
* - there is no currently active radio button.
|
||||
*/
|
||||
tmp_slist = priv->group;
|
||||
while (tmp_slist)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tmp_slist->data)) &&
|
||||
gtk_widget_get_visible (tmp_slist->data))
|
||||
selected_button = tmp_slist->data;
|
||||
tmp_slist = tmp_slist->next;
|
||||
}
|
||||
|
||||
if (selected_button && selected_button != radio_button)
|
||||
return FALSE;
|
||||
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_radio_button_clicked (GtkButton *button)
|
||||
{
|
||||
|
||||
+342
@@ -20,7 +20,11 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkrootprivate.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gdk/gdk-private.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkintl.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkroot
|
||||
@@ -59,12 +63,56 @@ gtk_root_default_get_surface_transform (GtkRoot *self,
|
||||
*y = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_default_check_resize (GtkRoot *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_default_add_mnemonic (GtkRoot *self,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_default_remove_mnemonic (GtkRoot *self,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_root_default_activate_key (GtkRoot *self,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_default_init (GtkRootInterface *iface)
|
||||
{
|
||||
iface->get_display = gtk_root_default_get_display;
|
||||
iface->get_renderer = gtk_root_default_get_renderer;
|
||||
iface->get_surface_transform = gtk_root_default_get_surface_transform;
|
||||
iface->check_resize = gtk_root_default_check_resize;
|
||||
iface->add_mnemonic = gtk_root_default_add_mnemonic;
|
||||
iface->remove_mnemonic = gtk_root_default_remove_mnemonic;
|
||||
iface->activate_key = gtk_root_default_activate_key;
|
||||
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_object ("focus-widget",
|
||||
P_("Focus widget"),
|
||||
P_("The focus widget"),
|
||||
GTK_TYPE_WIDGET,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
||||
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_object ("default-widget",
|
||||
P_("Default widget"),
|
||||
P_("The default widget"),
|
||||
GTK_TYPE_WIDGET,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
||||
}
|
||||
|
||||
GdkDisplay *
|
||||
@@ -124,3 +172,297 @@ gtk_root_get_for_surface (GdkSurface *surface)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_set_focus:
|
||||
* @self: a #GtkRoot
|
||||
* @focus: (allow-none): widget to be the new focus widget, or %NULL
|
||||
* to unset the focus widget
|
||||
*
|
||||
* If @focus is not the current focus widget, and is focusable, sets
|
||||
* it as the focus widget for the root. If @focus is %NULL, unsets
|
||||
* the focus widget for the root.
|
||||
*
|
||||
* To set the focus to a particular widget in the root, it is usually
|
||||
* more convenient to use gtk_widget_grab_focus() instead of this function.
|
||||
*/
|
||||
void
|
||||
gtk_root_set_focus (GtkRoot *self,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_ROOT (self));
|
||||
g_return_if_fail (focus == NULL || GTK_IS_WIDGET (focus));
|
||||
|
||||
g_object_set (self, "focus-widget", focus, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_get_focus:
|
||||
* @self: a #GtkRoot
|
||||
*
|
||||
* Retrieves the current focused widget within the root.
|
||||
*
|
||||
* Note that this is the widget that would have the focus
|
||||
* if the root is active; if the root is not focused then
|
||||
* `gtk_widget_has_focus (widget)` will be %FALSE for the
|
||||
* widget.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the currently focused widget,
|
||||
* or %NULL if there is none.
|
||||
*/
|
||||
GtkWidget *
|
||||
gtk_root_get_focus (GtkRoot *self)
|
||||
{
|
||||
GtkWidget *focus;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ROOT (self), NULL);
|
||||
|
||||
g_object_get (self, "focus-widget", &focus, NULL);
|
||||
|
||||
if (focus)
|
||||
g_object_unref (focus);
|
||||
|
||||
return focus;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_activate_focus:
|
||||
* @self: a #GtkRoot
|
||||
*
|
||||
* Activates the current focused widget within the root.
|
||||
*
|
||||
* Returns: %TRUE if a widget got activated.
|
||||
**/
|
||||
gboolean
|
||||
gtk_root_activate_focus (GtkRoot *self)
|
||||
{
|
||||
GtkWidget *focus_widget;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ROOT (self), FALSE);
|
||||
|
||||
focus_widget = gtk_root_get_focus (self);
|
||||
|
||||
if (focus_widget && gtk_widget_is_sensitive (focus_widget))
|
||||
return gtk_widget_activate (focus_widget);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_set_default:
|
||||
* @self: a #GtkRoot
|
||||
* @widget: (allow-none): widget to be the default, or %NULL
|
||||
* to unset the default widget
|
||||
*
|
||||
* The default widget is the widget that’s activated when the user
|
||||
* presses Enter in a dialog (for example). This function sets or
|
||||
* unsets the default widget for a #GtkRoot.
|
||||
*
|
||||
* When setting (rather than unsetting) the default widget it is
|
||||
* generally easier to call gtk_widget_grab_default() on the widget.
|
||||
* Before making a widget the default widget, you must call
|
||||
* gtk_widget_set_can_default() on the widget you’d like to make
|
||||
* the default.
|
||||
*/
|
||||
void
|
||||
gtk_root_set_default (GtkRoot *self,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_ROOT (self));
|
||||
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
|
||||
|
||||
g_object_set (self, "default-widget", widget, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_get_default:
|
||||
* @self: a #GtkRoot
|
||||
*
|
||||
* Returns the default widget for @root. See
|
||||
* gtk_root_set_default() for more details.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the default widget, or %NULL
|
||||
* if there is none
|
||||
*/
|
||||
GtkWidget *
|
||||
gtk_root_get_default (GtkRoot *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ROOT (self), NULL);
|
||||
|
||||
g_object_get (self, "default-widget", &widget, NULL);
|
||||
|
||||
if (widget)
|
||||
g_object_unref (widget);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_activate_default:
|
||||
* @self: a #GtkRoot
|
||||
*
|
||||
* Activates the default widget for the window, unless the current
|
||||
* focused widget has been configured to receive the default action
|
||||
* (see gtk_widget_set_receives_default()), in which case the
|
||||
* focused widget is activated.
|
||||
*
|
||||
* Returns: %TRUE if a widget got activated
|
||||
*/
|
||||
gboolean
|
||||
gtk_root_activate_default (GtkRoot *self)
|
||||
{
|
||||
GtkWidget *default_widget;
|
||||
GtkWidget *focus_widget;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ROOT (self), FALSE);
|
||||
|
||||
default_widget = gtk_root_get_default (self);
|
||||
focus_widget = gtk_root_get_focus (self);
|
||||
|
||||
if (default_widget && gtk_widget_is_sensitive (default_widget) &&
|
||||
(!focus_widget || !gtk_widget_get_receives_default (focus_widget)))
|
||||
return gtk_widget_activate (default_widget);
|
||||
else if (focus_widget && gtk_widget_is_sensitive (focus_widget))
|
||||
return gtk_widget_activate (focus_widget);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_root_install_properties (GObjectClass *object_class,
|
||||
guint first_prop)
|
||||
{
|
||||
g_object_class_override_property (object_class, first_prop + GTK_ROOT_PROP_FOCUS_WIDGET, "focus-widget");
|
||||
g_object_class_override_property (object_class, first_prop + GTK_ROOT_PROP_DEFAULT_WIDGET, "default-widget");
|
||||
return GTK_ROOT_NUM_PROPERTIES;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_check_resize (GtkRoot *self)
|
||||
{
|
||||
GtkRootInterface *iface;
|
||||
|
||||
g_return_if_fail (GTK_IS_ROOT (self));
|
||||
|
||||
iface = GTK_ROOT_GET_IFACE (self);
|
||||
iface->check_resize (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_root_needs_layout_phase (GtkRoot *root)
|
||||
{
|
||||
if (gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (root))))
|
||||
return TRUE;
|
||||
|
||||
return gtk_widget_needs_allocate (GTK_WIDGET (root));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_do_layout_phase (GdkFrameClock *clock,
|
||||
GtkRoot *root)
|
||||
{
|
||||
/* We validate the style contexts in a single loop before even trying
|
||||
* to handle resizes instead of doing validations inline.
|
||||
* This is mostly necessary for compatibility reasons with old code,
|
||||
* because both style_updated and size_allocate functions often change
|
||||
* styles and so could cause infinite loops in this function.
|
||||
*
|
||||
* It's important to note that even an invalid style context returns
|
||||
* sane values. So the result of an invalid style context will never be
|
||||
* a program crash, but only a wrong layout or rendering.
|
||||
*/
|
||||
|
||||
if (gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (root))))
|
||||
gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (root)));
|
||||
|
||||
/* we may be invoked with a container_resize_queue of NULL, because
|
||||
* queue_resize could have been adding an extra idle function while
|
||||
* the queue still got processed. we better just ignore such case
|
||||
* than trying to explicitly work around them with some extra flags,
|
||||
* since it doesn't cause any actual harm.
|
||||
*/
|
||||
if (gtk_widget_needs_allocate (GTK_WIDGET (root)))
|
||||
gtk_root_check_resize (root);
|
||||
|
||||
if (!gtk_root_needs_layout_phase (root))
|
||||
gtk_root_stop_layout_phase (root);
|
||||
else
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_root_start_layout_phase (GtkRoot *root)
|
||||
{
|
||||
GdkFrameClock *clock;
|
||||
guint resize_handler;
|
||||
|
||||
resize_handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (root), "resize-handler"));
|
||||
if (resize_handler != 0)
|
||||
return;
|
||||
|
||||
if (!gtk_root_needs_layout_phase (root))
|
||||
return;
|
||||
|
||||
clock = gtk_widget_get_frame_clock (GTK_WIDGET (root));
|
||||
if (clock == NULL)
|
||||
return;
|
||||
|
||||
resize_handler = g_signal_connect (clock, "layout", G_CALLBACK (gtk_root_do_layout_phase), root);
|
||||
g_object_set_data (G_OBJECT (root), "resize-handler", GUINT_TO_POINTER (resize_handler));
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_root_stop_layout_phase (GtkRoot *root)
|
||||
{
|
||||
guint resize_handler;
|
||||
|
||||
resize_handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (root), "resize-handler"));
|
||||
if (resize_handler == 0)
|
||||
return;
|
||||
|
||||
g_signal_handler_disconnect (gtk_widget_get_frame_clock (GTK_WIDGET (root)), resize_handler);
|
||||
g_object_set_data (G_OBJECT (root), "resize-handler", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_root_queue_restyle (GtkRoot *root)
|
||||
{
|
||||
g_return_if_fail (GTK_ROOT (root));
|
||||
|
||||
if (!gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (root))))
|
||||
return;
|
||||
|
||||
gtk_root_start_layout_phase (root);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_root_add_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
g_return_if_fail (GTK_ROOT (root));
|
||||
|
||||
GTK_ROOT_GET_IFACE (root)->add_mnemonic (root, keyval, target);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_root_remove_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
g_return_if_fail (GTK_ROOT (root));
|
||||
|
||||
GTK_ROOT_GET_IFACE (root)->remove_mnemonic (root, keyval, target);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_root_activate_key (GtkRoot *root,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
g_return_val_if_fail (GTK_ROOT (root), FALSE);
|
||||
|
||||
return GTK_ROOT_GET_IFACE (root)->activate_key (root, event);
|
||||
}
|
||||
|
||||
@@ -51,11 +51,46 @@ struct _GtkRootInterface
|
||||
void (* get_surface_transform) (GtkRoot *root,
|
||||
int *x,
|
||||
int *y);
|
||||
void (* check_resize) (GtkRoot *root);
|
||||
|
||||
void (* add_mnemonic) (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
void (* remove_mnemonic) (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
gboolean (* activate_key) (GtkRoot *root,
|
||||
GdkEventKey *event);
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_root_get_for_surface (GdkSurface *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_root_set_focus (GtkRoot *self,
|
||||
GtkWidget *focus);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_root_get_focus (GtkRoot *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_root_activate_focus (GtkRoot *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_root_set_default (GtkRoot *self,
|
||||
GtkWidget *widget);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_root_get_default (GtkRoot *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_root_activate_default (GtkRoot *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_root_add_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_root_remove_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ROOT_H__ */
|
||||
|
||||
+18
-1
@@ -5,12 +5,29 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GdkDisplay * gtk_root_get_display (GtkRoot *root);
|
||||
GdkDisplay * gtk_root_get_display (GtkRoot *self);
|
||||
GskRenderer * gtk_root_get_renderer (GtkRoot *self);
|
||||
|
||||
void gtk_root_get_surface_transform (GtkRoot *self,
|
||||
int *x,
|
||||
int *y);
|
||||
|
||||
void gtk_root_queue_restyle (GtkRoot *self);
|
||||
void gtk_root_start_layout_phase (GtkRoot *self);
|
||||
void gtk_root_stop_layout_phase (GtkRoot *self);
|
||||
|
||||
gboolean gtk_root_activate_key (GtkRoot *self,
|
||||
GdkEventKey *event);
|
||||
|
||||
enum {
|
||||
GTK_ROOT_PROP_FOCUS_WIDGET,
|
||||
GTK_ROOT_PROP_DEFAULT_WIDGET,
|
||||
GTK_ROOT_NUM_PROPERTIES
|
||||
} GtkRootProperties;
|
||||
|
||||
guint gtk_root_install_properties (GObjectClass *object_class,
|
||||
guint first_prop);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ROOT_PRIVATE_H__ */
|
||||
|
||||
@@ -322,8 +322,6 @@ static void gtk_scrolled_window_size_allocate (GtkWidget *widge
|
||||
int width,
|
||||
int height,
|
||||
int baseline);
|
||||
static gboolean gtk_scrolled_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_scrolled_window_add (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_scrolled_window_remove (GtkContainer *container,
|
||||
@@ -507,7 +505,6 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
|
||||
widget_class->destroy = gtk_scrolled_window_destroy;
|
||||
widget_class->snapshot = gtk_scrolled_window_snapshot;
|
||||
widget_class->size_allocate = gtk_scrolled_window_size_allocate;
|
||||
widget_class->focus = gtk_scrolled_window_focus;
|
||||
widget_class->measure = gtk_scrolled_window_measure;
|
||||
widget_class->map = gtk_scrolled_window_map;
|
||||
widget_class->unmap = gtk_scrolled_window_unmap;
|
||||
@@ -3330,45 +3327,6 @@ gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
|
||||
(GDestroyNotify) kinetic_scroll_data_free);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_scrolled_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
|
||||
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
|
||||
GtkWidget *child;
|
||||
gboolean had_focus_child;
|
||||
|
||||
had_focus_child = gtk_widget_get_focus_child (widget) != NULL;
|
||||
|
||||
if (priv->focus_out)
|
||||
{
|
||||
priv->focus_out = FALSE; /* Clear this to catch the wrap-around case */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gtk_widget_is_focus (widget))
|
||||
return FALSE;
|
||||
|
||||
/* We only put the scrolled window itself in the focus chain if it
|
||||
* isn't possible to focus any children.
|
||||
*/
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
if (child)
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!had_focus_child && gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
|
||||
@@ -255,10 +255,10 @@ gtk_search_entry_grab_focus (GtkWidget *widget)
|
||||
GtkSearchEntry *entry = GTK_SEARCH_ENTRY (widget);
|
||||
GtkSearchEntryPrivate *priv = gtk_search_entry_get_instance_private (entry);
|
||||
|
||||
gtk_text_grab_focus_without_selecting (GTK_TEXT (priv->entry));
|
||||
gtk_widget_grab_focus (priv->entry);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
gtk_search_entry_mnemonic_activate (GtkWidget *widget,
|
||||
gboolean group_cycling)
|
||||
{
|
||||
@@ -523,6 +523,7 @@ gtk_search_entry_init (GtkSearchEntry *entry)
|
||||
gtk_widget_set_vexpand (priv->box, FALSE);
|
||||
|
||||
priv->entry = gtk_text_new ();
|
||||
g_object_set (priv->entry, "select-on-focus", FALSE, NULL);
|
||||
gtk_widget_set_hexpand (priv->entry, TRUE);
|
||||
gtk_widget_set_vexpand (priv->entry, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (priv->box), GTK_WIDGET (priv->entry));
|
||||
|
||||
+32
-17
@@ -533,6 +533,9 @@ static void gtk_stack_forall (GtkContainer *contain
|
||||
static void gtk_stack_compute_expand (GtkWidget *widget,
|
||||
gboolean *hexpand,
|
||||
gboolean *vexpand);
|
||||
static GtkWidget *gtk_stack_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_stack_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
@@ -724,6 +727,7 @@ gtk_stack_class_init (GtkStackClass *klass)
|
||||
widget_class->snapshot = gtk_stack_snapshot;
|
||||
widget_class->measure = gtk_stack_measure;
|
||||
widget_class->compute_expand = gtk_stack_compute_expand;
|
||||
widget_class->next_focus_child = gtk_stack_next_focus_child;
|
||||
|
||||
container_class->add = gtk_stack_add;
|
||||
container_class->remove = gtk_stack_remove;
|
||||
@@ -1123,7 +1127,6 @@ set_visible_child (GtkStack *stack,
|
||||
GtkStackPage *info;
|
||||
GtkWidget *widget = GTK_WIDGET (stack);
|
||||
GList *l;
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *focus;
|
||||
gboolean contains_focus = FALSE;
|
||||
guint old_pos = GTK_INVALID_LIST_POSITION;
|
||||
@@ -1165,24 +1168,23 @@ set_visible_child (GtkStack *stack,
|
||||
}
|
||||
}
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
if (gtk_widget_get_root (widget))
|
||||
focus = gtk_root_get_focus (gtk_widget_get_root (widget));
|
||||
else
|
||||
focus = NULL;
|
||||
if (focus &&
|
||||
priv->visible_child &&
|
||||
priv->visible_child->widget &&
|
||||
gtk_widget_is_ancestor (focus, priv->visible_child->widget))
|
||||
{
|
||||
focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
if (focus &&
|
||||
priv->visible_child &&
|
||||
priv->visible_child->widget &&
|
||||
gtk_widget_is_ancestor (focus, priv->visible_child->widget))
|
||||
{
|
||||
contains_focus = TRUE;
|
||||
contains_focus = TRUE;
|
||||
|
||||
if (priv->visible_child->last_focus)
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus),
|
||||
(gpointer *)&priv->visible_child->last_focus);
|
||||
priv->visible_child->last_focus = focus;
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus),
|
||||
(gpointer *)&priv->visible_child->last_focus);
|
||||
}
|
||||
if (priv->visible_child->last_focus)
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus),
|
||||
(gpointer *)&priv->visible_child->last_focus);
|
||||
priv->visible_child->last_focus = focus;
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus),
|
||||
(gpointer *)&priv->visible_child->last_focus);
|
||||
}
|
||||
|
||||
if (priv->last_visible_child)
|
||||
@@ -2436,6 +2438,19 @@ gtk_stack_measure (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
gtk_stack_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (GTK_STACK (widget));
|
||||
|
||||
if (child == NULL)
|
||||
return priv->visible_child->widget;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_stack_init (GtkStack *stack)
|
||||
{
|
||||
|
||||
+70
-65
@@ -225,6 +225,8 @@ struct _GtkTextPrivate
|
||||
guint cursor_handle_dragged : 1;
|
||||
guint selection_handle_dragged : 1;
|
||||
guint populate_all : 1;
|
||||
guint select_on_focus : 1;
|
||||
guint select_on_focus_set : 1;
|
||||
};
|
||||
|
||||
struct _GtkTextPasswordHint
|
||||
@@ -268,6 +270,8 @@ enum {
|
||||
PROP_POPULATE_ALL,
|
||||
PROP_TABS,
|
||||
PROP_ENABLE_EMOJI_COMPLETION,
|
||||
PROP_SELECT_ON_FOCUS,
|
||||
PROP_SELECT_ON_FOCUS_SET,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
@@ -321,7 +325,6 @@ static void gtk_text_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot);
|
||||
static void gtk_text_focus_in (GtkWidget *widget);
|
||||
static void gtk_text_focus_out (GtkWidget *widget);
|
||||
static void gtk_text_grab_focus (GtkWidget *widget);
|
||||
static void gtk_text_style_updated (GtkWidget *widget);
|
||||
static void gtk_text_direction_changed (GtkWidget *widget,
|
||||
GtkTextDirection previous_dir);
|
||||
@@ -675,7 +678,6 @@ gtk_text_class_init (GtkTextClass *class)
|
||||
widget_class->measure = gtk_text_measure;
|
||||
widget_class->size_allocate = gtk_text_size_allocate;
|
||||
widget_class->snapshot = gtk_text_snapshot;
|
||||
widget_class->grab_focus = gtk_text_grab_focus;
|
||||
widget_class->style_updated = gtk_text_style_updated;
|
||||
widget_class->drag_begin = gtk_text_drag_begin;
|
||||
widget_class->drag_end = gtk_text_drag_end;
|
||||
@@ -898,6 +900,26 @@ gtk_text_class_init (GtkTextClass *class)
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkEntry::select-on-focus:
|
||||
*
|
||||
* Whether to select the contents of the text when focus enters it.
|
||||
* When set, this property overrides the system-widget setting for
|
||||
* this feature. See #GtkEntry::select-on-enter-set
|
||||
*/
|
||||
text_props[PROP_SELECT_ON_FOCUS] =
|
||||
g_param_spec_boolean ("select-on-focus",
|
||||
P_("Selet on focus"),
|
||||
P_("Whether to select the text on focus"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||
text_props[PROP_SELECT_ON_FOCUS_SET] =
|
||||
g_param_spec_boolean ("select-on-focus-set",
|
||||
P_("Select on focus set"),
|
||||
P_("Whether the select-on-focus property has been set"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, text_props);
|
||||
|
||||
gtk_editable_install_properties (gobject_class, NUM_PROPERTIES);
|
||||
@@ -1515,6 +1537,27 @@ gtk_text_set_property (GObject *object,
|
||||
set_enable_emoji_completion (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_SELECT_ON_FOCUS:
|
||||
if (priv->select_on_focus != g_value_get_boolean (value))
|
||||
{
|
||||
priv->select_on_focus = g_value_get_boolean (value);
|
||||
g_object_notify_by_pspec (object, pspec);
|
||||
}
|
||||
if (!priv->select_on_focus_set)
|
||||
{
|
||||
priv->select_on_focus_set = TRUE;
|
||||
g_object_notify_by_pspec (object, text_props[PROP_SELECT_ON_FOCUS_SET]);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SELECT_ON_FOCUS_SET:
|
||||
if (priv->select_on_focus_set != g_value_get_boolean (value))
|
||||
{
|
||||
priv->select_on_focus_set = g_value_get_boolean (value);
|
||||
g_object_notify_by_pspec (object, pspec);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -1630,6 +1673,14 @@ gtk_text_get_property (GObject *object,
|
||||
g_value_set_boolean (value, priv->enable_emoji_completion);
|
||||
break;
|
||||
|
||||
case PROP_SELECT_ON_FOCUS:
|
||||
g_value_set_boolean (value, priv->select_on_focus);
|
||||
break;
|
||||
|
||||
case PROP_SELECT_ON_FOCUS_SET:
|
||||
g_value_set_boolean (value, priv->select_on_focus_set);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -2896,6 +2947,22 @@ gtk_text_focus_in (GtkWidget *widget)
|
||||
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
|
||||
GdkKeymap *keymap;
|
||||
|
||||
if (priv->editable && !priv->in_click)
|
||||
{
|
||||
gboolean select_on_focus;
|
||||
|
||||
if (priv->select_on_focus_set)
|
||||
select_on_focus = priv->select_on_focus;
|
||||
else
|
||||
g_object_get (gtk_widget_get_settings (widget),
|
||||
"gtk-entry-select-on-focus",
|
||||
&select_on_focus,
|
||||
NULL);
|
||||
|
||||
if (select_on_focus)
|
||||
gtk_text_set_selection_bounds (self, 0, -1);
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
keymap = gdk_display_get_keymap (gtk_widget_get_display (widget));
|
||||
@@ -2941,47 +3008,6 @@ gtk_text_focus_out (GtkWidget *widget)
|
||||
g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkText *self = GTK_TEXT (widget);
|
||||
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
|
||||
gboolean select_on_focus;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_text_parent_class)->grab_focus (GTK_WIDGET (self));
|
||||
|
||||
if (priv->editable && !priv->in_click)
|
||||
{
|
||||
g_object_get (gtk_widget_get_settings (widget),
|
||||
"gtk-entry-select-on-focus",
|
||||
&select_on_focus,
|
||||
NULL);
|
||||
|
||||
if (select_on_focus)
|
||||
gtk_text_set_selection_bounds (self, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_text_grab_focus_without_selecting:
|
||||
* @self: a #GtkText
|
||||
*
|
||||
* Causes @self to have keyboard focus.
|
||||
*
|
||||
* It behaves like gtk_widget_grab_focus(),
|
||||
* except that it doesn't select the contents of the self.
|
||||
* You only want to call this on some special entries
|
||||
* which the user usually doesn't want to replace all text in,
|
||||
* such as search-as-you-type entries.
|
||||
*/
|
||||
void
|
||||
gtk_text_grab_focus_without_selecting (GtkText *self)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_TEXT (self));
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_text_parent_class)->grab_focus (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_direction_changed (GtkWidget *widget,
|
||||
GtkTextDirection previous_dir)
|
||||
@@ -3810,30 +3836,9 @@ static void
|
||||
gtk_text_real_activate (GtkText *self)
|
||||
{
|
||||
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
|
||||
GtkWindow *window;
|
||||
GtkWidget *default_widget, *focus_widget;
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = GTK_WIDGET (self);
|
||||
|
||||
if (priv->activates_default)
|
||||
{
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
window = GTK_WINDOW (toplevel);
|
||||
|
||||
if (window)
|
||||
{
|
||||
default_widget = gtk_window_get_default_widget (window);
|
||||
focus_widget = gtk_window_get_focus (window);
|
||||
if (widget != default_widget &&
|
||||
!(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget))))
|
||||
gtk_window_activate_default (window);
|
||||
}
|
||||
}
|
||||
}
|
||||
gtk_root_activate_default (gtk_widget_get_root (GTK_WIDGET (self)));
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -131,9 +131,6 @@ void gtk_text_set_tabs (GtkText *self,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
PangoTabArray * gtk_text_get_tabs (GtkText *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_text_grab_focus_without_selecting (GtkText *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_TEXT_H__ */
|
||||
|
||||
@@ -407,8 +407,6 @@ static void gtk_text_view_motion (GtkEventController *controller,
|
||||
gpointer user_data);
|
||||
static void gtk_text_view_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot);
|
||||
static gboolean gtk_text_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_text_view_select_all (GtkWidget *widget,
|
||||
gboolean select);
|
||||
static gboolean get_middle_click_paste (GtkTextView *text_view);
|
||||
@@ -694,7 +692,6 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
|
||||
widget_class->measure = gtk_text_view_measure;
|
||||
widget_class->size_allocate = gtk_text_view_size_allocate;
|
||||
widget_class->snapshot = gtk_text_view_snapshot;
|
||||
widget_class->focus = gtk_text_view_focus;
|
||||
widget_class->drag_begin = gtk_text_view_drag_begin;
|
||||
widget_class->drag_end = gtk_text_view_drag_end;
|
||||
widget_class->drag_data_get = gtk_text_view_drag_data_get;
|
||||
@@ -5447,39 +5444,6 @@ gtk_text_view_snapshot (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_text_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
if (!gtk_widget_is_focus (widget) &&
|
||||
gtk_widget_get_focus_child (widget) == NULL)
|
||||
{
|
||||
if (gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean can_focus;
|
||||
/*
|
||||
* Unset CAN_FOCUS flag so that gtk_container_focus() allows
|
||||
* children to get the focus
|
||||
*/
|
||||
can_focus = gtk_widget_get_can_focus (widget);
|
||||
gtk_widget_set_can_focus (widget, FALSE);
|
||||
result = GTK_WIDGET_CLASS (gtk_text_view_parent_class)->focus (widget, direction);
|
||||
gtk_widget_set_can_focus (widget, can_focus);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Container
|
||||
*/
|
||||
|
||||
@@ -189,8 +189,6 @@ static void gtk_toolbar_size_allocate (GtkWidget *widget,
|
||||
int height,
|
||||
int baseline);
|
||||
static void gtk_toolbar_style_updated (GtkWidget *widget);
|
||||
static gboolean gtk_toolbar_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir);
|
||||
static void gtk_toolbar_move_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir);
|
||||
static void gtk_toolbar_display_changed (GtkWidget *widget,
|
||||
@@ -368,7 +366,6 @@ gtk_toolbar_class_init (GtkToolbarClass *klass)
|
||||
widget_class->measure = gtk_toolbar_measure;
|
||||
widget_class->size_allocate = gtk_toolbar_size_allocate;
|
||||
widget_class->style_updated = gtk_toolbar_style_updated;
|
||||
widget_class->focus = gtk_toolbar_focus;
|
||||
|
||||
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_BAR);
|
||||
|
||||
@@ -1611,43 +1608,6 @@ gtk_toolbar_move_focus (GtkWidget *widget,
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
/* The focus handler for the toolbar. It called when the user presses
|
||||
* TAB or otherwise tries to focus the toolbar.
|
||||
*/
|
||||
static gboolean
|
||||
gtk_toolbar_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir)
|
||||
{
|
||||
GtkToolbar *toolbar = GTK_TOOLBAR (widget);
|
||||
GList *children, *list;
|
||||
gboolean result = FALSE;
|
||||
|
||||
/* if focus is already somewhere inside the toolbar then return FALSE.
|
||||
* The only way focus can stay inside the toolbar is when the user presses
|
||||
* arrow keys or Ctrl TAB (both of which are handled by the
|
||||
* gtk_toolbar_move_focus() keybinding function.
|
||||
*/
|
||||
if (gtk_widget_get_focus_child (widget))
|
||||
return FALSE;
|
||||
|
||||
children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
|
||||
|
||||
for (list = children; list != NULL; list = list->next)
|
||||
{
|
||||
GtkWidget *child = list->data;
|
||||
|
||||
if (gtk_widget_get_mapped (child) && gtk_widget_child_focus (child, dir))
|
||||
{
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkSettings *
|
||||
toolbar_get_settings (GtkToolbar *toolbar)
|
||||
{
|
||||
|
||||
@@ -616,8 +616,6 @@ static void gtk_tree_view_key_controller_key_released (GtkEventControllerKey
|
||||
static void gtk_tree_view_key_controller_focus_out (GtkEventControllerKey *key,
|
||||
GtkTreeView *tree_view);
|
||||
|
||||
static gint gtk_tree_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_tree_view_grab_focus (GtkWidget *widget);
|
||||
static void gtk_tree_view_style_updated (GtkWidget *widget);
|
||||
|
||||
@@ -985,7 +983,6 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
|
||||
widget_class->drag_motion = gtk_tree_view_drag_motion;
|
||||
widget_class->drag_drop = gtk_tree_view_drag_drop;
|
||||
widget_class->drag_data_received = gtk_tree_view_drag_data_received;
|
||||
widget_class->focus = gtk_tree_view_focus;
|
||||
widget_class->grab_focus = gtk_tree_view_grab_focus;
|
||||
widget_class->style_updated = gtk_tree_view_style_updated;
|
||||
|
||||
@@ -7707,170 +7704,6 @@ gtk_tree_view_get_fixed_height_mode (GtkTreeView *tree_view)
|
||||
return tree_view->priv->fixed_height_mode;
|
||||
}
|
||||
|
||||
/* Returns TRUE if the focus is within the headers, after the focus operation is
|
||||
* done
|
||||
*/
|
||||
static gboolean
|
||||
gtk_tree_view_header_focus (GtkTreeView *tree_view,
|
||||
GtkDirectionType dir,
|
||||
gboolean clamp_column_visible)
|
||||
{
|
||||
GtkTreeViewColumn *column;
|
||||
GtkWidget *button;
|
||||
GtkWidget *focus_child;
|
||||
GList *last_column, *first_column;
|
||||
GList *tmp_list;
|
||||
gboolean rtl;
|
||||
|
||||
if (! tree_view->priv->headers_visible)
|
||||
return FALSE;
|
||||
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (tree_view));
|
||||
|
||||
first_column = tree_view->priv->columns;
|
||||
while (first_column)
|
||||
{
|
||||
column = GTK_TREE_VIEW_COLUMN (first_column->data);
|
||||
button = gtk_tree_view_column_get_button (column);
|
||||
|
||||
if (gtk_widget_get_can_focus (button) &&
|
||||
gtk_tree_view_column_get_visible (column) &&
|
||||
(gtk_tree_view_column_get_clickable (column) ||
|
||||
gtk_tree_view_column_get_reorderable (column)))
|
||||
break;
|
||||
first_column = first_column->next;
|
||||
}
|
||||
|
||||
/* No headers are visible, or are focusable. We can't focus in or out.
|
||||
*/
|
||||
if (first_column == NULL)
|
||||
return FALSE;
|
||||
|
||||
last_column = g_list_last (tree_view->priv->columns);
|
||||
while (last_column)
|
||||
{
|
||||
column = GTK_TREE_VIEW_COLUMN (last_column->data);
|
||||
button = gtk_tree_view_column_get_button (column);
|
||||
|
||||
if (gtk_widget_get_can_focus (button) &&
|
||||
gtk_tree_view_column_get_visible (column) &&
|
||||
(gtk_tree_view_column_get_clickable (column) ||
|
||||
gtk_tree_view_column_get_reorderable (column)))
|
||||
break;
|
||||
last_column = last_column->prev;
|
||||
}
|
||||
|
||||
|
||||
rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_UP:
|
||||
case GTK_DIR_DOWN:
|
||||
if (focus_child == NULL)
|
||||
{
|
||||
if (tree_view->priv->focus_column != NULL)
|
||||
button = gtk_tree_view_column_get_button (tree_view->priv->focus_column);
|
||||
else
|
||||
button = NULL;
|
||||
|
||||
if (button && gtk_widget_get_can_focus (button))
|
||||
focus_child = button;
|
||||
else
|
||||
focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (first_column->data));
|
||||
|
||||
gtk_widget_grab_focus (focus_child);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
if (focus_child == NULL)
|
||||
{
|
||||
if (tree_view->priv->focus_column != NULL)
|
||||
focus_child = gtk_tree_view_column_get_button (tree_view->priv->focus_column);
|
||||
else if (dir == GTK_DIR_LEFT)
|
||||
focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (last_column->data));
|
||||
else
|
||||
focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (first_column->data));
|
||||
|
||||
gtk_widget_grab_focus (focus_child);
|
||||
break;
|
||||
}
|
||||
|
||||
if (gtk_widget_child_focus (focus_child, dir))
|
||||
{
|
||||
/* The focus moves inside the button. */
|
||||
/* This is probably a great example of bad UI */
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need to move the focus among the row of buttons. */
|
||||
for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
|
||||
if (gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (tmp_list->data)) == focus_child)
|
||||
break;
|
||||
|
||||
if ((tmp_list == first_column && dir == (rtl ? GTK_DIR_RIGHT : GTK_DIR_LEFT))
|
||||
|| (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)))
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (tree_view));
|
||||
break;
|
||||
}
|
||||
|
||||
while (tmp_list)
|
||||
{
|
||||
if (dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))
|
||||
tmp_list = tmp_list->next;
|
||||
else
|
||||
tmp_list = tmp_list->prev;
|
||||
|
||||
if (tmp_list == NULL)
|
||||
{
|
||||
g_warning ("Internal button not found");
|
||||
break;
|
||||
}
|
||||
column = tmp_list->data;
|
||||
button = gtk_tree_view_column_get_button (column);
|
||||
if (button &&
|
||||
gtk_tree_view_column_get_visible (column) &&
|
||||
gtk_widget_get_can_focus (button))
|
||||
{
|
||||
focus_child = button;
|
||||
gtk_widget_grab_focus (button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* if focus child is non-null, we assume it's been set to the current focus child
|
||||
*/
|
||||
if (focus_child)
|
||||
{
|
||||
for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
|
||||
if (gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (tmp_list->data)) == focus_child)
|
||||
{
|
||||
_gtk_tree_view_set_focus_column (tree_view, GTK_TREE_VIEW_COLUMN (tmp_list->data));
|
||||
break;
|
||||
}
|
||||
|
||||
if (clamp_column_visible)
|
||||
{
|
||||
gtk_tree_view_clamp_column_visible (tree_view,
|
||||
tree_view->priv->focus_column,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (focus_child != NULL);
|
||||
}
|
||||
|
||||
/* This function returns in 'path' the first focusable path, if the given path
|
||||
* is already focusable, it’s the returned one.
|
||||
*/
|
||||
@@ -7917,59 +7750,6 @@ search_first_focusable_path (GtkTreeView *tree_view,
|
||||
return (*path != NULL);
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
|
||||
GtkWidget *focus_child;
|
||||
|
||||
if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_can_focus (widget))
|
||||
return FALSE;
|
||||
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
gtk_tree_view_stop_editing (GTK_TREE_VIEW (widget), FALSE);
|
||||
/* Case 1. Headers currently have focus. */
|
||||
if (focus_child)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
gtk_tree_view_header_focus (tree_view, direction, TRUE);
|
||||
return TRUE;
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_UP:
|
||||
return FALSE;
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_DOWN:
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Case 2. We don't have focus at all. */
|
||||
if (!gtk_widget_has_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Case 3. We have focus already. */
|
||||
if (direction == GTK_DIR_TAB_BACKWARD)
|
||||
return (gtk_tree_view_header_focus (tree_view, direction, FALSE));
|
||||
else if (direction == GTK_DIR_TAB_FORWARD)
|
||||
return FALSE;
|
||||
|
||||
/* Other directions caught by the keybindings */
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_view_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
|
||||
@@ -1016,11 +1016,8 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
|
||||
gtk_widget_set_can_focus (priv->button, FALSE);
|
||||
if (gtk_widget_has_focus (priv->button))
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (priv->tree_view);
|
||||
if (gtk_widget_is_toplevel (toplevel))
|
||||
{
|
||||
gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
|
||||
}
|
||||
GtkRoot *root = gtk_widget_get_root (priv->tree_view);
|
||||
gtk_root_set_focus (root, NULL);
|
||||
}
|
||||
}
|
||||
/* Queue a resize on the assumption that we always want to catch all changes
|
||||
|
||||
+116
-216
@@ -52,9 +52,11 @@
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkmenu.h"
|
||||
#include "gtkpopover.h"
|
||||
#include "gtkpopup.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkrenderbackgroundprivate.h"
|
||||
#include "gtkrenderborderprivate.h"
|
||||
#include "gtkrootprivate.h"
|
||||
#include "gtkscrollable.h"
|
||||
#include "gtkselection.h"
|
||||
#include "gtksettingsprivate.h"
|
||||
@@ -484,7 +486,6 @@ enum {
|
||||
GRAB_NOTIFY,
|
||||
CHILD_NOTIFY,
|
||||
MNEMONIC_ACTIVATE,
|
||||
FOCUS,
|
||||
MOVE_FOCUS,
|
||||
KEYNAV_FAILED,
|
||||
DRAG_BEGIN,
|
||||
@@ -600,8 +601,6 @@ static void gtk_widget_real_style_updated (GtkWidget *widget);
|
||||
static void gtk_widget_dispatch_child_properties_changed (GtkWidget *object,
|
||||
guint n_pspecs,
|
||||
GParamSpec **pspecs);
|
||||
static gboolean gtk_widget_real_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_widget_real_move_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
|
||||
@@ -938,7 +937,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
klass->snapshot = gtk_widget_real_snapshot;
|
||||
klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
|
||||
klass->grab_focus = gtk_widget_real_grab_focus;
|
||||
klass->focus = gtk_widget_real_focus;
|
||||
klass->next_focus_child = gtk_widget_next_focus_child;
|
||||
klass->move_focus = gtk_widget_real_move_focus;
|
||||
klass->keynav_failed = gtk_widget_real_keynav_failed;
|
||||
klass->drag_begin = NULL;
|
||||
@@ -1659,23 +1658,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
/**
|
||||
* GtkWidget::focus:
|
||||
* @widget: the object which received the signal.
|
||||
* @direction:
|
||||
*
|
||||
* Returns: %TRUE to stop other handlers from being invoked for the event. %FALSE to propagate the event further.
|
||||
*/
|
||||
widget_signals[FOCUS] =
|
||||
g_signal_new (I_("focus"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkWidgetClass, focus),
|
||||
_gtk_boolean_handled_accumulator, NULL,
|
||||
_gtk_marshal_BOOLEAN__ENUM,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
GTK_TYPE_DIRECTION_TYPE);
|
||||
|
||||
/**
|
||||
* GtkWidget::move-focus:
|
||||
* @widget: the object which received the signal.
|
||||
@@ -2832,6 +2814,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
|
||||
|
||||
priv->visible = gtk_widget_class_get_visible_by_default (g_class);
|
||||
priv->child_visible = TRUE;
|
||||
priv->child_focusable = TRUE;
|
||||
priv->name = NULL;
|
||||
priv->user_alpha = 255;
|
||||
priv->alpha = 255;
|
||||
@@ -3121,10 +3104,11 @@ gtk_widget_unparent (GtkWidget *widget)
|
||||
toplevel = NULL;
|
||||
|
||||
/* Removing a widget from a container restores the child visible
|
||||
* flag to the default state, so it doesn't affect the child
|
||||
* in the next parent.
|
||||
* and focusable flags to the default state, so they don't affect
|
||||
* the child in the next parent.
|
||||
*/
|
||||
priv->child_visible = TRUE;
|
||||
priv->child_focusable = TRUE;
|
||||
|
||||
old_parent = priv->parent;
|
||||
if (old_parent)
|
||||
@@ -3682,8 +3666,8 @@ gtk_widget_connect_frame_clock (GtkWidget *widget)
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
if (GTK_IS_CONTAINER (widget) && _gtk_widget_is_toplevel (widget))
|
||||
gtk_container_start_idle_sizer (GTK_CONTAINER (widget));
|
||||
if (GTK_IS_ROOT (widget))
|
||||
gtk_root_start_layout_phase (GTK_ROOT (widget));
|
||||
|
||||
frame_clock = gtk_widget_get_frame_clock (widget);
|
||||
|
||||
@@ -3703,8 +3687,8 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
if (GTK_IS_CONTAINER (widget) && _gtk_widget_is_toplevel (widget))
|
||||
gtk_container_stop_idle_sizer (GTK_CONTAINER (widget));
|
||||
if (GTK_IS_ROOT (widget))
|
||||
gtk_root_stop_layout_phase (GTK_ROOT (widget));
|
||||
|
||||
gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
|
||||
|
||||
@@ -4342,7 +4326,8 @@ gtk_widget_allocate (GtkWidget *widget,
|
||||
{
|
||||
/* Still have to move the window... */
|
||||
if (_gtk_widget_get_realized (widget) &&
|
||||
_gtk_widget_get_has_surface (widget))
|
||||
_gtk_widget_get_has_surface (widget) &&
|
||||
GTK_IS_POPOVER (widget))
|
||||
{
|
||||
GtkAllocation window_alloc;
|
||||
|
||||
@@ -4544,7 +4529,8 @@ gtk_widget_real_size_allocate (GtkWidget *widget,
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
if (_gtk_widget_get_realized (widget) &&
|
||||
_gtk_widget_get_has_surface (widget))
|
||||
_gtk_widget_get_has_surface (widget) &&
|
||||
GTK_IS_POPOVER (widget))
|
||||
{
|
||||
GtkAllocation window_alloc;
|
||||
|
||||
@@ -5332,91 +5318,14 @@ gtk_widget_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
if (!gtk_widget_is_sensitive (widget))
|
||||
return;
|
||||
|
||||
g_object_ref (widget);
|
||||
GTK_WIDGET_GET_CLASS (widget)->grab_focus (widget);
|
||||
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]);
|
||||
g_object_unref (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_focus_recurse (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
|
||||
gtk_widget_forall (widget,
|
||||
reset_focus_recurse,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_real_grab_focus (GtkWidget *focus_widget)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *widget;
|
||||
|
||||
/* clear the current focus setting, break if the current widget
|
||||
* is the focus widget's parent, since containers above that will
|
||||
* be set by the next loop.
|
||||
*/
|
||||
toplevel = _gtk_widget_get_toplevel (focus_widget);
|
||||
if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
|
||||
if (widget == focus_widget)
|
||||
{
|
||||
/* We call _gtk_window_internal_set_focus() here so that the
|
||||
* toplevel window can request the focus if necessary.
|
||||
* This is needed when the toplevel is a GtkPlug
|
||||
*/
|
||||
if (!gtk_widget_has_focus (widget))
|
||||
_gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget)
|
||||
{
|
||||
GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget);
|
||||
|
||||
if (widget != common_ancestor)
|
||||
{
|
||||
while (widget->priv->parent)
|
||||
{
|
||||
widget = widget->priv->parent;
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
if (widget == common_ancestor)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (toplevel != focus_widget)
|
||||
{
|
||||
/* gtk_widget_grab_focus() operates on a tree without window...
|
||||
* actually, this is very questionable behavior.
|
||||
*/
|
||||
|
||||
gtk_widget_forall (toplevel,
|
||||
reset_focus_recurse,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* now propagate the new focus up the widget tree and finally
|
||||
* set it on the window
|
||||
*/
|
||||
widget = focus_widget;
|
||||
while (widget->priv->parent)
|
||||
{
|
||||
gtk_widget_set_focus_child (widget->priv->parent, widget);
|
||||
widget = widget->priv->parent;
|
||||
}
|
||||
if (GTK_IS_WINDOW (widget))
|
||||
_gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget);
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (focus_widget);
|
||||
gtk_root_set_focus (priv->root, focus_widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -5512,53 +5421,22 @@ gtk_widget_real_style_updated (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_widget_real_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
if (gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
if (!gtk_widget_is_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (_gtk_widget_get_first_child (widget) == NULL)
|
||||
{
|
||||
/* No children, no possibility to focus anything */
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPtrArray *focus_order = g_ptr_array_new ();
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* Try focusing any of the child widgets, depending on the given @direction */
|
||||
|
||||
gtk_widget_focus_sort (widget, direction, focus_order);
|
||||
ret = gtk_widget_focus_move (widget, direction, focus_order);
|
||||
|
||||
g_ptr_array_unref (focus_order);
|
||||
|
||||
if (ret)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_real_move_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GtkWidget *focus_child;
|
||||
GtkWidget *next_focus;
|
||||
|
||||
if (widget != toplevel && GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0,
|
||||
direction);
|
||||
}
|
||||
focus_child = gtk_root_get_focus (gtk_widget_get_root (widget));
|
||||
if (focus_child)
|
||||
next_focus = gtk_widget_get_next_focus (focus_child, direction);
|
||||
else
|
||||
next_focus = gtk_widget_get_next_focus (widget, direction);
|
||||
|
||||
if (next_focus)
|
||||
gtk_root_set_focus (priv->root, next_focus);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -5704,16 +5582,14 @@ gtk_widget_has_visible_focus (GtkWidget *widget)
|
||||
gboolean
|
||||
gtk_widget_is_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
toplevel = _gtk_widget_get_toplevel (widget);
|
||||
if (priv->root)
|
||||
return widget == gtk_root_get_focus (priv->root);
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
return widget == gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
else
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5864,17 +5740,10 @@ _gtk_widget_set_has_default (GtkWidget *widget,
|
||||
void
|
||||
gtk_widget_grab_default (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *window;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (gtk_widget_get_can_default (widget));
|
||||
|
||||
window = _gtk_widget_get_toplevel (widget);
|
||||
|
||||
if (window && _gtk_widget_is_toplevel (window))
|
||||
gtk_window_set_default (GTK_WINDOW (window), widget);
|
||||
else
|
||||
g_warning (G_STRLOC ": widget not within a GtkWindow");
|
||||
gtk_root_set_default (gtk_widget_get_root (widget), widget);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7575,25 +7444,24 @@ gboolean
|
||||
gtk_widget_child_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gboolean return_val;
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GtkWidget *focus_child;
|
||||
GtkWidget *next_focus;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
if (!_gtk_widget_get_visible (widget) ||
|
||||
!gtk_widget_is_sensitive (widget))
|
||||
return FALSE;
|
||||
focus_child = gtk_root_get_focus (gtk_widget_get_root (widget));
|
||||
if (focus_child)
|
||||
next_focus = gtk_widget_get_next_focus (focus_child, direction);
|
||||
else
|
||||
next_focus = gtk_widget_get_next_focus (widget, direction);
|
||||
if (next_focus && gtk_widget_is_ancestor (next_focus, widget))
|
||||
{
|
||||
gtk_root_set_focus (priv->root, next_focus);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Emit ::focus in any case, even if can-focus is FALSE,
|
||||
* since any widget might have child widgets that will take
|
||||
* focus
|
||||
*/
|
||||
|
||||
g_signal_emit (widget,
|
||||
widget_signals[FOCUS],
|
||||
0,
|
||||
direction, &return_val);
|
||||
|
||||
return return_val;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8919,14 +8787,7 @@ gtk_widget_propagate_state (GtkWidget *widget,
|
||||
priv->state_flags |= GTK_STATE_FLAG_INSENSITIVE;
|
||||
|
||||
if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget))
|
||||
{
|
||||
GtkWidget *window;
|
||||
|
||||
window = _gtk_widget_get_toplevel (widget);
|
||||
|
||||
if (window && _gtk_widget_is_toplevel (window))
|
||||
gtk_window_set_focus (GTK_WINDOW (window), NULL);
|
||||
}
|
||||
gtk_root_set_focus (priv->root, NULL);
|
||||
|
||||
new_flags = priv->state_flags;
|
||||
|
||||
@@ -11722,22 +11583,17 @@ gtk_widget_send_focus_change (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL && event->any.type == GDK_FOCUS_CHANGE, FALSE);
|
||||
|
||||
g_object_ref (widget);
|
||||
|
||||
priv->has_focus = event->focus_change.in;
|
||||
|
||||
res = gtk_widget_event (widget, event);
|
||||
gtk_propagate_event (widget, event);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]);
|
||||
|
||||
g_object_unref (widget);
|
||||
|
||||
return res;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -11800,9 +11656,9 @@ gtk_widget_set_alloc_needed (GtkWidget *widget)
|
||||
if (!priv->visible)
|
||||
break;
|
||||
|
||||
if (_gtk_widget_is_toplevel (widget))
|
||||
if (GTK_IS_ROOT (widget))
|
||||
{
|
||||
gtk_container_start_idle_sizer (GTK_CONTAINER (widget));
|
||||
gtk_root_start_layout_phase (GTK_ROOT (widget));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12076,7 +11932,7 @@ gtk_widget_class_set_css_name (GtkWidgetClass *widget_class,
|
||||
static gboolean
|
||||
gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_class)
|
||||
{
|
||||
return !(GTK_IS_WINDOW_CLASS (widget_class) ||
|
||||
return !(g_type_is_a (G_TYPE_FROM_CLASS (widget_class), GTK_TYPE_ROOT) ||
|
||||
GTK_IS_POPOVER_CLASS (widget_class));
|
||||
}
|
||||
|
||||
@@ -13459,26 +13315,7 @@ gtk_widget_set_focus_child (GtkWidget *widget,
|
||||
g_return_if_fail (gtk_widget_get_parent (child) == widget);
|
||||
}
|
||||
|
||||
if (priv->focus_child)
|
||||
gtk_widget_unset_state_flags (priv->focus_child,
|
||||
GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE);
|
||||
|
||||
if (child)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED;
|
||||
|
||||
toplevel = _gtk_widget_get_toplevel (widget);
|
||||
if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel)))
|
||||
flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
|
||||
|
||||
gtk_widget_set_state_flags (child, flags, FALSE);
|
||||
}
|
||||
|
||||
g_set_object (&priv->focus_child, child);
|
||||
|
||||
if (GTK_IS_CONTAINER (widget))
|
||||
gtk_container_set_focus_child (GTK_CONTAINER (widget), child);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -13665,3 +13502,66 @@ gtk_widget_get_height (GtkWidget *widget)
|
||||
|
||||
return priv->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_get_child_focusable:
|
||||
* @widget: a #GtkWidget
|
||||
*
|
||||
* Gets the value set with gtk_widget_set_child_focusable().
|
||||
* If you feel a need to use this function, your code probably
|
||||
* needs reorganization.
|
||||
*
|
||||
* This function is only useful for widget implementations and
|
||||
* never should be called by an application.
|
||||
*
|
||||
* Returns: %TRUE if the widget is focusable
|
||||
**/
|
||||
gboolean
|
||||
gtk_widget_get_child_focusable (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
return priv->child_focusable;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_set_child_focusable:
|
||||
* @widget: a #GtkWidget
|
||||
* @focusable: if %TRUE, @widget should be focusable
|
||||
*
|
||||
* Sets whether @widget should be able to receive focus
|
||||
*
|
||||
* Child focusability will be reset to its default state of %TRUE
|
||||
* when the widget is removed from its parent.
|
||||
*
|
||||
* This function is only useful for widget implementations and
|
||||
* never should be called by an application.
|
||||
**/
|
||||
void
|
||||
gtk_widget_set_child_focusable (GtkWidget *widget,
|
||||
gboolean focusable)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
focusable = !!focusable;
|
||||
|
||||
if (priv->child_focusable == focusable)
|
||||
return;
|
||||
|
||||
if (focusable)
|
||||
priv->child_focusable = TRUE;
|
||||
else
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
|
||||
priv->child_focusable = FALSE;
|
||||
|
||||
toplevel = _gtk_widget_get_toplevel (widget);
|
||||
if (toplevel != widget && _gtk_widget_is_toplevel (toplevel))
|
||||
_gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -185,7 +185,7 @@ struct _GtkWidget
|
||||
* %FALSE, and just grabs the focus if @group_cycling is %TRUE.
|
||||
* @grab_focus: Causes @widget to have the keyboard focus for the
|
||||
* #GtkWindow it’s inside.
|
||||
* @focus:
|
||||
* @next_focus_child: Returns the next child that is a candidate for receiving focus
|
||||
* @move_focus: Signal emitted when a change of focus is requested
|
||||
* @keynav_failed: Signal emitted if keyboard navigation fails.
|
||||
* @drag_begin: Signal emitted on the drag source when a drag is
|
||||
@@ -278,7 +278,8 @@ struct _GtkWidgetClass
|
||||
|
||||
/* explicit focus */
|
||||
void (* grab_focus) (GtkWidget *widget);
|
||||
gboolean (* focus) (GtkWidget *widget,
|
||||
GtkWidget * (* next_focus_child) (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction);
|
||||
|
||||
/* keyboard navigation */
|
||||
@@ -451,9 +452,6 @@ gboolean gtk_widget_mnemonic_activate (GtkWidget *widget,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_widget_event (GtkWidget *widget,
|
||||
const GdkEvent *event);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_widget_send_focus_change (GtkWidget *widget,
|
||||
GdkEvent *event);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_widget_activate (GtkWidget *widget);
|
||||
@@ -480,6 +478,9 @@ gboolean gtk_widget_has_visible_focus (GtkWidget *widget);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_widget_grab_focus (GtkWidget *widget);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget *gtk_widget_get_next_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_widget_set_focus_on_click (GtkWidget *widget,
|
||||
gboolean focus_on_click);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -1062,6 +1063,12 @@ void gtk_widget_insert_before (GtkWidget *widget,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_widget_set_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_widget_set_child_focusable (GtkWidget *widget,
|
||||
gboolean focusable);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_widget_get_child_focusable (GtkWidget *widget);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_widget_snapshot_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
|
||||
+92
-26
@@ -155,15 +155,11 @@ static gboolean
|
||||
old_focus_coords (GtkWidget *widget,
|
||||
graphene_rect_t *old_focus_bounds)
|
||||
{
|
||||
GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
|
||||
GtkWidget *old_focus;
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
old_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
if (old_focus)
|
||||
return gtk_widget_compute_bounds (old_focus, widget, old_focus_bounds);
|
||||
}
|
||||
old_focus = gtk_root_get_focus (gtk_widget_get_root (widget));
|
||||
if (old_focus)
|
||||
return gtk_widget_compute_bounds (old_focus, widget, old_focus_bounds);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -426,7 +422,9 @@ gtk_widget_focus_sort (GtkWidget *widget,
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_realized (child))
|
||||
if (_gtk_widget_get_realized (child) &&
|
||||
gtk_widget_get_child_focusable (child) &&
|
||||
gtk_widget_get_sensitive (child))
|
||||
g_ptr_array_add (focus_order, child);
|
||||
}
|
||||
}
|
||||
@@ -451,36 +449,104 @@ gtk_widget_focus_sort (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
gtk_widget_focus_move (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order)
|
||||
gtk_widget_can_take_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *focus_child = gtk_widget_get_focus_child (widget);
|
||||
int i;
|
||||
GtkWidget *w;
|
||||
|
||||
for (i = 0; i < focus_order->len; i ++)
|
||||
if (!gtk_widget_is_sensitive (widget) ||
|
||||
!gtk_widget_get_can_focus (widget))
|
||||
return FALSE;
|
||||
|
||||
w = widget;
|
||||
do {
|
||||
if (!gtk_widget_get_child_focusable (w))
|
||||
return FALSE;
|
||||
w = gtk_widget_get_parent (w);
|
||||
} while (w != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_get_next_focus:
|
||||
* @widget: a #GtkWidget
|
||||
* @direction: diretion to move in
|
||||
*
|
||||
* Finds the widget that would get focused if @widget was
|
||||
* the focus widget, and focus was moved in @direcion.
|
||||
*
|
||||
* Returns: (transfer none): the next focus widget
|
||||
*/
|
||||
GtkWidget *
|
||||
gtk_widget_get_next_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir)
|
||||
{
|
||||
GtkWidget *prev;
|
||||
GtkWidget *next;
|
||||
GHashTable *seen;
|
||||
|
||||
seen = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
prev = NULL;
|
||||
do {
|
||||
next = GTK_WIDGET_GET_CLASS (widget)->next_focus_child (widget, prev, dir);
|
||||
if (next == NULL)
|
||||
{
|
||||
prev = widget;
|
||||
widget = gtk_widget_get_parent (widget);
|
||||
}
|
||||
else if (gtk_widget_can_take_focus (next))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (g_hash_table_contains (seen, next))
|
||||
{
|
||||
next = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hash_table_add (seen, next);
|
||||
widget = next;
|
||||
prev = NULL;
|
||||
}
|
||||
} while (widget);
|
||||
|
||||
g_hash_table_unref (seen);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_widget_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *focus_child,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GPtrArray *focus_order;
|
||||
int i;
|
||||
GtkWidget *next_child = NULL;
|
||||
|
||||
focus_order = g_ptr_array_new ();
|
||||
gtk_widget_focus_sort (widget, direction, focus_order);
|
||||
|
||||
for (i = 0; i < focus_order->len; i++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (focus_order, i);
|
||||
|
||||
if (focus_child)
|
||||
{
|
||||
if (focus_child == child)
|
||||
{
|
||||
focus_child = NULL;
|
||||
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
focus_child = NULL;
|
||||
}
|
||||
else if (_gtk_widget_is_drawable (child) &&
|
||||
gtk_widget_is_ancestor (child, widget))
|
||||
else
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
next_child = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
g_ptr_array_unref (focus_order);
|
||||
|
||||
return next_child;
|
||||
}
|
||||
|
||||
+10
-3
@@ -72,6 +72,7 @@ struct _GtkWidgetPrivate
|
||||
guint has_grab : 1;
|
||||
guint shadowed : 1;
|
||||
guint child_visible : 1;
|
||||
guint child_focusable : 1;
|
||||
guint multidevice : 1;
|
||||
guint can_pick : 1;
|
||||
|
||||
@@ -317,9 +318,9 @@ GtkWidget *gtk_widget_get_focus_child (GtkWidget
|
||||
void gtk_widget_focus_sort (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order);
|
||||
gboolean gtk_widget_focus_move (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order);
|
||||
GtkWidget * gtk_widget_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction);
|
||||
void gtk_widget_get_surface_allocation (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
|
||||
@@ -336,6 +337,12 @@ gboolean gtk_widget_run_controllers (GtkWidget
|
||||
const GdkEvent *event,
|
||||
GtkPropagationPhase phase);
|
||||
|
||||
gboolean gtk_widget_send_focus_change (GtkWidget *widget,
|
||||
GdkEvent *event);
|
||||
|
||||
gboolean gtk_widget_can_take_focus (GtkWidget *widget);
|
||||
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline GtkWidget *
|
||||
|
||||
+113
-326
@@ -122,16 +122,12 @@
|
||||
* elements representing the #GtkAccelGroup objects you want to add to
|
||||
* your window (synonymous with gtk_window_add_accel_group().
|
||||
*
|
||||
* It also supports the <initial-focus> element, whose name property names
|
||||
* the widget to receive the focus when the window is mapped.
|
||||
*
|
||||
* An example of a UI definition fragment with accel groups:
|
||||
* |[
|
||||
* <object class="GtkWindow">
|
||||
* <accel-groups>
|
||||
* <group name="accelgroup1"/>
|
||||
* </accel-groups>
|
||||
* <initial-focus name="thunderclap"/>
|
||||
* </object>
|
||||
*
|
||||
* ...
|
||||
@@ -299,7 +295,6 @@ static const char *dnd_dest_targets [] = {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SET_FOCUS,
|
||||
ACTIVATE_FOCUS,
|
||||
ACTIVATE_DEFAULT,
|
||||
KEYS_CHANGED,
|
||||
@@ -436,12 +431,6 @@ static void gtk_window_remove (GtkContainer *container,
|
||||
static void gtk_window_forall (GtkContainer *container,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data);
|
||||
static gint gtk_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_window_move_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir);
|
||||
static void gtk_window_real_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus);
|
||||
|
||||
static void gtk_window_real_activate_default (GtkWindow *window);
|
||||
static void gtk_window_real_activate_focus (GtkWindow *window);
|
||||
@@ -771,6 +760,27 @@ gtk_window_pick (GtkWidget *widget,
|
||||
return GTK_WIDGET_CLASS (gtk_window_parent_class)->pick (widget, x, y);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
gtk_window_next_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkWidget *next;
|
||||
|
||||
next = GTK_WIDGET_CLASS (gtk_window_parent_class)->next_focus_child (widget, child, direction);
|
||||
if (next)
|
||||
return next;
|
||||
|
||||
switch ((int)direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
return GTK_WIDGET_CLASS (gtk_window_parent_class)->next_focus_child (widget, NULL, direction);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_class_init (GtkWindowClass *klass)
|
||||
{
|
||||
@@ -804,20 +814,17 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
widget_class->realize = gtk_window_realize;
|
||||
widget_class->unrealize = gtk_window_unrealize;
|
||||
widget_class->size_allocate = gtk_window_size_allocate;
|
||||
widget_class->focus = gtk_window_focus;
|
||||
widget_class->move_focus = gtk_window_move_focus;
|
||||
widget_class->measure = gtk_window_measure;
|
||||
widget_class->state_flags_changed = gtk_window_state_flags_changed;
|
||||
widget_class->style_updated = gtk_window_style_updated;
|
||||
widget_class->snapshot = gtk_window_snapshot;
|
||||
widget_class->pick = gtk_window_pick;
|
||||
widget_class->next_focus_child = gtk_window_next_focus_child;
|
||||
|
||||
container_class->add = gtk_window_add;
|
||||
container_class->remove = gtk_window_remove;
|
||||
container_class->forall = gtk_window_forall;
|
||||
|
||||
klass->set_focus = gtk_window_real_set_focus;
|
||||
|
||||
klass->activate_default = gtk_window_real_activate_default;
|
||||
klass->activate_focus = gtk_window_real_activate_focus;
|
||||
klass->keys_changed = gtk_window_keys_changed;
|
||||
@@ -1118,24 +1125,7 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, LAST_ARG, window_props);
|
||||
|
||||
/**
|
||||
* GtkWindow:set-focus:
|
||||
* @window: the window which received the signal
|
||||
* @widget: (nullable): the newly focused widget (or %NULL for no focus)
|
||||
*
|
||||
* This signal is emitted whenever the currently focused widget in
|
||||
* this window changes.
|
||||
*/
|
||||
window_signals[SET_FOCUS] =
|
||||
g_signal_new (I_("set-focus"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkWindowClass, set_focus),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
GTK_TYPE_WIDGET);
|
||||
gtk_root_install_properties (gobject_class, LAST_ARG);
|
||||
|
||||
/**
|
||||
* GtkWindow::activate-focus:
|
||||
@@ -2095,6 +2085,12 @@ gtk_window_set_property (GObject *object,
|
||||
case PROP_FOCUS_VISIBLE:
|
||||
gtk_window_set_focus_visible (window, g_value_get_boolean (value));
|
||||
break;
|
||||
case LAST_ARG + GTK_ROOT_PROP_FOCUS_WIDGET:
|
||||
gtk_window_set_focus (window, g_value_get_object (value));
|
||||
break;
|
||||
case LAST_ARG + GTK_ROOT_PROP_DEFAULT_WIDGET:
|
||||
gtk_window_set_default (window, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -2210,6 +2206,12 @@ gtk_window_get_property (GObject *object,
|
||||
case PROP_IS_MAXIMIZED:
|
||||
g_value_set_boolean (value, gtk_window_is_maximized (window));
|
||||
break;
|
||||
case LAST_ARG + GTK_ROOT_PROP_FOCUS_WIDGET:
|
||||
g_value_set_object (value, gtk_window_get_focus (window));
|
||||
break;
|
||||
case LAST_ARG + GTK_ROOT_PROP_DEFAULT_WIDGET:
|
||||
g_value_set_object (value, gtk_window_get_default_widget (window));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -2365,55 +2367,6 @@ static const GMarkupParser window_parser =
|
||||
window_start_element
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GObject *object;
|
||||
GtkBuilder *builder;
|
||||
gchar *name;
|
||||
gint line;
|
||||
gint col;
|
||||
} NameSubParserData;
|
||||
|
||||
static void
|
||||
focus_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
NameSubParserData *data = (NameSubParserData*)user_data;
|
||||
|
||||
if (strcmp (element_name, "initial-focus") == 0)
|
||||
{
|
||||
const gchar *name;
|
||||
|
||||
if (!_gtk_builder_check_parent (data->builder, context, "object", error))
|
||||
return;
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING, "name", &name,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, context, error);
|
||||
return;
|
||||
}
|
||||
|
||||
data->name = g_strdup (name);
|
||||
g_markup_parse_context_get_position (context, &data->line, &data->col);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_builder_error_unhandled_tag (data->builder, context,
|
||||
"GtkWindow", element_name,
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
static const GMarkupParser focus_parser =
|
||||
{
|
||||
focus_start_element
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
@@ -2441,21 +2394,6 @@ gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (strcmp (tagname, "initial-focus") == 0)
|
||||
{
|
||||
NameSubParserData *data;
|
||||
|
||||
data = g_slice_new0 (NameSubParserData);
|
||||
data->name = NULL;
|
||||
data->object = G_OBJECT (buildable);
|
||||
data->builder = builder;
|
||||
|
||||
*parser = focus_parser;
|
||||
*parser_data = data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2478,23 +2416,6 @@ gtk_window_buildable_custom_finished (GtkBuildable *buildable,
|
||||
|
||||
g_slice_free (GSListSubParserData, data);
|
||||
}
|
||||
|
||||
if (strcmp (tagname, "initial-focus") == 0)
|
||||
{
|
||||
NameSubParserData *data = (NameSubParserData*)user_data;
|
||||
|
||||
if (data->name)
|
||||
{
|
||||
GObject *object;
|
||||
|
||||
object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col);
|
||||
if (object)
|
||||
gtk_window_set_focus (GTK_WINDOW (buildable), GTK_WIDGET (object));
|
||||
g_free (data->name);
|
||||
}
|
||||
|
||||
g_slice_free (NameSubParserData, data);
|
||||
}
|
||||
}
|
||||
|
||||
static GdkDisplay *
|
||||
@@ -2533,12 +2454,45 @@ gtk_window_root_get_surface_transform (GtkRoot *root,
|
||||
*y = margin.top + border.top + padding.top;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_root_check_resize (GtkRoot *root)
|
||||
{
|
||||
gtk_window_check_resize (GTK_WINDOW (root));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_root_add_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
gtk_window_add_mnemonic (GTK_WINDOW (root), keyval, target);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_root_remove_mnemonic (GtkRoot *root,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
gtk_window_remove_mnemonic (GTK_WINDOW (root), keyval, target);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_window_root_activate_key (GtkRoot *root,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
return gtk_window_activate_key (GTK_WINDOW (root), event);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_root_interface_init (GtkRootInterface *iface)
|
||||
{
|
||||
iface->get_display = gtk_window_root_get_display;
|
||||
iface->get_renderer = gtk_window_root_get_renderer;
|
||||
iface->get_surface_transform = gtk_window_root_get_surface_transform;
|
||||
iface->check_resize = gtk_window_root_check_resize;
|
||||
iface->add_mnemonic = gtk_window_root_add_mnemonic;
|
||||
iface->remove_mnemonic = gtk_window_root_remove_mnemonic;
|
||||
iface->activate_key = gtk_window_root_activate_key;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2771,70 +2725,6 @@ gtk_window_get_role (GtkWindow *window)
|
||||
return priv->wm_role;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_set_focus:
|
||||
* @window: a #GtkWindow
|
||||
* @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
|
||||
* any focus widget for the toplevel window.
|
||||
*
|
||||
* If @focus is not the current focus widget, and is focusable, sets
|
||||
* it as the focus widget for the window. If @focus is %NULL, unsets
|
||||
* the focus widget for this window. To set the focus to a particular
|
||||
* widget in the toplevel, it is usually more convenient to use
|
||||
* gtk_widget_grab_focus() instead of this function.
|
||||
**/
|
||||
void
|
||||
gtk_window_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
GtkWidget *parent;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
|
||||
if (focus)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (focus));
|
||||
g_return_if_fail (gtk_widget_get_can_focus (focus));
|
||||
|
||||
if (!gtk_widget_get_visible (GTK_WIDGET (window)))
|
||||
priv->initial_focus = focus;
|
||||
else
|
||||
gtk_widget_grab_focus (focus);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the existing focus chain, so that when we focus into
|
||||
* the window again, we start at the beginnning.
|
||||
*/
|
||||
GtkWidget *widget = priv->focus_widget;
|
||||
if (widget)
|
||||
{
|
||||
while ((parent = _gtk_widget_get_parent (widget)))
|
||||
{
|
||||
widget = parent;
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
_gtk_window_internal_set_focus (window, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_window_internal_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
|
||||
priv->initial_focus = NULL;
|
||||
if ((priv->focus_widget != focus) ||
|
||||
(focus && !gtk_widget_has_focus (focus)))
|
||||
g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_set_default:
|
||||
* @window: a #GtkWindow
|
||||
@@ -5774,7 +5664,7 @@ gtk_window_show (GtkWidget *widget)
|
||||
if (priv->initial_focus)
|
||||
gtk_window_set_focus (window, priv->initial_focus);
|
||||
else
|
||||
gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
|
||||
gtk_widget_child_focus (widget, GTK_DIR_TAB_FORWARD);
|
||||
}
|
||||
|
||||
if (priv->modal)
|
||||
@@ -7233,172 +7123,69 @@ gtk_window_forall (GtkContainer *container,
|
||||
(* callback) (priv->title_box, callback_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
static void
|
||||
unset_focus_widget (GtkWindow *window)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
GtkBin *bin;
|
||||
GtkContainer *container;
|
||||
GtkWidget *child;
|
||||
GtkWidget *old_focus_child;
|
||||
GtkWidget *parent;
|
||||
GtkWidget *f;
|
||||
|
||||
if (!_gtk_widget_is_toplevel (widget))
|
||||
return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
|
||||
|
||||
container = GTK_CONTAINER (widget);
|
||||
bin = GTK_BIN (widget);
|
||||
|
||||
old_focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
/* We need a special implementation here to deal properly with wrapping
|
||||
* around in the tab chain without the danger of going into an
|
||||
* infinite loop.
|
||||
*/
|
||||
if (old_focus_child)
|
||||
{
|
||||
if (gtk_widget_child_focus (old_focus_child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
for (f = priv->focus_widget; f; f = gtk_widget_get_parent (f))
|
||||
gtk_widget_unset_state_flags (f, GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE);
|
||||
|
||||
if (priv->focus_widget)
|
||||
{
|
||||
if (direction == GTK_DIR_LEFT ||
|
||||
direction == GTK_DIR_RIGHT ||
|
||||
direction == GTK_DIR_UP ||
|
||||
direction == GTK_DIR_DOWN)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Wrapped off the end, clear the focus setting for the toplpevel */
|
||||
parent = _gtk_widget_get_parent (priv->focus_widget);
|
||||
while (parent)
|
||||
{
|
||||
gtk_widget_set_focus_child (parent, NULL);
|
||||
parent = _gtk_widget_get_parent (parent);
|
||||
}
|
||||
|
||||
gtk_window_set_focus (GTK_WINDOW (container), NULL);
|
||||
}
|
||||
|
||||
/* Now try to focus the first widget in the window,
|
||||
* taking care to hook titlebar widgets into the
|
||||
* focus chain.
|
||||
*/
|
||||
if (priv->title_box != NULL &&
|
||||
old_focus_child != NULL &&
|
||||
priv->title_box != old_focus_child)
|
||||
child = priv->title_box;
|
||||
else
|
||||
child = gtk_bin_get_child (bin);
|
||||
|
||||
if (child)
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
else if (priv->title_box != NULL &&
|
||||
priv->title_box != child &&
|
||||
gtk_widget_child_focus (priv->title_box, direction))
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
do_focus_change (priv->focus_widget, FALSE);
|
||||
g_set_object (&priv->focus_widget, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_move_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir)
|
||||
{
|
||||
if (!_gtk_widget_is_toplevel (widget))
|
||||
{
|
||||
GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_child_focus (widget, dir);
|
||||
|
||||
if (!gtk_widget_get_focus_child (widget))
|
||||
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_real_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus)
|
||||
set_focus_widget (GtkWindow *window,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
GtkWidget *old_focus = priv->focus_widget;
|
||||
GtkWidget *f;
|
||||
GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED;
|
||||
|
||||
if (old_focus)
|
||||
if (gtk_window_get_focus_visible (window))
|
||||
flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
|
||||
|
||||
for (f = focus; f; f = gtk_widget_get_parent (f))
|
||||
{
|
||||
g_object_ref (old_focus);
|
||||
g_object_freeze_notify (G_OBJECT (old_focus));
|
||||
}
|
||||
if (focus)
|
||||
{
|
||||
g_object_ref (focus);
|
||||
g_object_freeze_notify (G_OBJECT (focus));
|
||||
GtkWidget *parent = gtk_widget_get_parent (f);
|
||||
gtk_widget_set_state_flags (f, flags, FALSE);
|
||||
if (parent)
|
||||
gtk_widget_set_focus_child (parent, f);
|
||||
}
|
||||
|
||||
g_set_object (&priv->focus_widget, focus);
|
||||
if (priv->focus_widget)
|
||||
{
|
||||
if (gtk_widget_get_receives_default (priv->focus_widget) &&
|
||||
(priv->focus_widget != priv->default_widget))
|
||||
{
|
||||
_gtk_widget_set_has_default (priv->focus_widget, FALSE);
|
||||
do_focus_change (priv->focus_widget, TRUE);
|
||||
}
|
||||
|
||||
if (priv->default_widget)
|
||||
_gtk_widget_set_has_default (priv->default_widget, TRUE);
|
||||
}
|
||||
/**
|
||||
* gtk_window_set_focus:
|
||||
* @window: a #GtkWindow
|
||||
* @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
|
||||
* any focus widget for the toplevel window.
|
||||
*
|
||||
* If @focus is not the current focus widget, and is focusable, sets
|
||||
* it as the focus widget for the window. If @focus is %NULL, unsets
|
||||
* the focus widget for this window. To set the focus to a particular
|
||||
* widget in the toplevel, it is usually more convenient to use
|
||||
* gtk_widget_grab_focus() instead of this function.
|
||||
**/
|
||||
void
|
||||
gtk_window_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
|
||||
priv->focus_widget = NULL;
|
||||
if (focus && !gtk_widget_can_take_focus (focus))
|
||||
return;
|
||||
|
||||
if (priv->is_active)
|
||||
do_focus_change (old_focus, FALSE);
|
||||
unset_focus_widget (window);
|
||||
set_focus_widget (window, focus);
|
||||
|
||||
g_object_notify (G_OBJECT (old_focus), "is-focus");
|
||||
}
|
||||
|
||||
/* The above notifications may have set a new focus widget,
|
||||
* if so, we don't want to override it.
|
||||
*/
|
||||
if (focus && !priv->focus_widget)
|
||||
{
|
||||
priv->focus_widget = focus;
|
||||
|
||||
if (gtk_widget_get_receives_default (priv->focus_widget) &&
|
||||
(priv->focus_widget != priv->default_widget))
|
||||
{
|
||||
if (gtk_widget_get_can_default (priv->focus_widget))
|
||||
_gtk_widget_set_has_default (priv->focus_widget, TRUE);
|
||||
|
||||
if (priv->default_widget)
|
||||
_gtk_widget_set_has_default (priv->default_widget, FALSE);
|
||||
}
|
||||
|
||||
if (priv->is_active)
|
||||
do_focus_change (priv->focus_widget, TRUE);
|
||||
|
||||
/* It's possible for do_focus_change() above to have callbacks
|
||||
* that clear priv->focus_widget here.
|
||||
*/
|
||||
if (priv->focus_widget)
|
||||
g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
|
||||
}
|
||||
|
||||
if (old_focus)
|
||||
{
|
||||
g_object_thaw_notify (G_OBJECT (old_focus));
|
||||
g_object_unref (old_focus);
|
||||
}
|
||||
if (focus)
|
||||
{
|
||||
g_object_thaw_notify (G_OBJECT (focus));
|
||||
g_object_unref (focus);
|
||||
}
|
||||
g_object_notify (G_OBJECT (window), "focus-widget");
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -70,11 +70,6 @@ struct _GtkWindowClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
|
||||
void (* set_focus) (GtkWindow *window,
|
||||
GtkWidget *focus);
|
||||
|
||||
/* G_SIGNAL_ACTION signals for keybindings */
|
||||
|
||||
void (* activate_focus) (GtkWindow *window);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
#include "config.h"
|
||||
#include "focusoverlay.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
struct _GtkFocusOverlay
|
||||
{
|
||||
GtkInspectorOverlay parent_instance;
|
||||
};
|
||||
|
||||
struct _GtkFocusOverlayClass
|
||||
{
|
||||
GtkInspectorOverlayClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkFocusOverlay, gtk_focus_overlay, GTK_TYPE_INSPECTOR_OVERLAY)
|
||||
|
||||
static void
|
||||
draw_focus_location (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GtkSnapshot *snapshot,
|
||||
const char *color,
|
||||
const char *text)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
graphene_rect_t bounds;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle rect;
|
||||
GskRoundedRect rrect;
|
||||
int x, y;
|
||||
GdkRGBA rgba;
|
||||
|
||||
if (child == NULL)
|
||||
return;
|
||||
|
||||
gdk_rgba_parse (&rgba, color);
|
||||
|
||||
gtk_widget_get_allocation (child, &allocation);
|
||||
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
gtk_widget_translate_coordinates (child, widget, 0, 0, &x, &y);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
|
||||
gtk_snapshot_push_debug (snapshot, "Widget focus debugging");
|
||||
|
||||
layout = gtk_widget_create_pango_layout (widget, NULL);
|
||||
pango_layout_set_markup (layout, text, -1);
|
||||
pango_layout_get_extents (layout, NULL, &rect);
|
||||
graphene_rect_init (&bounds,
|
||||
0, 0,
|
||||
rect.width / PANGO_SCALE + 20,
|
||||
rect.height / PANGO_SCALE + 20);
|
||||
gsk_rounded_rect_init_from_rect (&rrect, &bounds, 10.0f);
|
||||
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &rrect);
|
||||
|
||||
gtk_snapshot_append_color (snapshot, &rgba, &bounds);
|
||||
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (10, 10));
|
||||
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA) { 1, 1, 1, 1 });
|
||||
g_object_unref (layout);
|
||||
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_focus_locations (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkWidget *focus;
|
||||
GtkWidget *next;
|
||||
int i;
|
||||
char text[20];
|
||||
|
||||
if (!gtk_widget_get_mapped (widget))
|
||||
return;
|
||||
|
||||
focus = gtk_root_get_focus (GTK_ROOT (widget));
|
||||
if (focus == NULL)
|
||||
return;
|
||||
|
||||
draw_focus_location (widget, focus, snapshot, "rgba(0,0,255,0.4)", "Focus");
|
||||
|
||||
next = focus;
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
g_snprintf (text, 20, "<big>⇥</big> %d", i);
|
||||
next = gtk_widget_get_next_focus (next, GTK_DIR_TAB_FORWARD);
|
||||
if (!next)
|
||||
break;
|
||||
draw_focus_location (widget, next, snapshot, "rgba(255,0,255,0.4)", text);
|
||||
}
|
||||
|
||||
next = focus;
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
g_snprintf (text, 20, "<big>⇤</big> %d", i);
|
||||
next = gtk_widget_get_next_focus (next, GTK_DIR_TAB_BACKWARD);
|
||||
if (!next)
|
||||
break;
|
||||
draw_focus_location (widget, next, snapshot, "rgba(255,0,255,0.4)", text);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_overlay_snapshot (GtkInspectorOverlay *overlay,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
draw_focus_locations (widget, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_overlay_init (GtkFocusOverlay *self)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_overlay_class_init (GtkFocusOverlayClass *klass)
|
||||
{
|
||||
GtkInspectorOverlayClass *overlay_class = (GtkInspectorOverlayClass *)klass;
|
||||
|
||||
overlay_class->snapshot = gtk_focus_overlay_snapshot;
|
||||
}
|
||||
|
||||
GtkInspectorOverlay *
|
||||
gtk_focus_overlay_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FOCUS_OVERLAY, NULL);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
#ifndef __GTK_FOCUS_OVERLAY_H__
|
||||
#define __GTK_FOCUS_OVERLAY_H__
|
||||
|
||||
#include "inspectoroverlay.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FOCUS_OVERLAY (gtk_focus_overlay_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkFocusOverlay, gtk_focus_overlay, GTK, FOCUS_OVERLAY, GtkInspectorOverlay)
|
||||
|
||||
GtkInspectorOverlay * gtk_focus_overlay_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,7 @@ inspector_sources = files(
|
||||
'css-editor.c',
|
||||
'css-node-tree.c',
|
||||
'data-list.c',
|
||||
'focusoverlay.c',
|
||||
'fpsoverlay.c',
|
||||
'general.c',
|
||||
'graphdata.c',
|
||||
|
||||
@@ -46,9 +46,6 @@ struct _GtkInspectorMiscInfoPrivate {
|
||||
GtkWidget *default_widget_row;
|
||||
GtkWidget *default_widget;
|
||||
GtkWidget *default_widget_button;
|
||||
GtkWidget *focus_widget_row;
|
||||
GtkWidget *focus_widget;
|
||||
GtkWidget *focus_widget_button;
|
||||
GtkWidget *mnemonic_label_row;
|
||||
GtkWidget *mnemonic_label;
|
||||
GtkWidget *request_mode_row;
|
||||
@@ -217,43 +214,6 @@ show_default_widget (GtkWidget *button, GtkInspectorMiscInfo *sl)
|
||||
show_object (sl, G_OBJECT (widget), "properties");
|
||||
}
|
||||
|
||||
static void
|
||||
update_focus_widget (GtkInspectorMiscInfo *sl)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->object));
|
||||
if (widget)
|
||||
{
|
||||
gchar *tmp;
|
||||
tmp = g_strdup_printf ("%p", widget);
|
||||
gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), tmp);
|
||||
g_free (tmp);
|
||||
gtk_widget_set_sensitive (sl->priv->focus_widget_button, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), "NULL");
|
||||
gtk_widget_set_sensitive (sl->priv->focus_widget_button, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_focus_cb (GtkWindow *window, GtkWidget *focus, GtkInspectorMiscInfo *sl)
|
||||
{
|
||||
update_focus_widget (sl);
|
||||
}
|
||||
|
||||
static void
|
||||
show_focus_widget (GtkWidget *button, GtkInspectorMiscInfo *sl)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->object));
|
||||
if (widget)
|
||||
show_object (sl, G_OBJECT (widget), "properties");
|
||||
}
|
||||
|
||||
static void
|
||||
show_mnemonic_label (GtkWidget *button, GtkInspectorMiscInfo *sl)
|
||||
{
|
||||
@@ -358,7 +318,6 @@ update_info (gpointer data)
|
||||
if (GTK_IS_WINDOW (sl->priv->object))
|
||||
{
|
||||
update_default_widget (sl);
|
||||
update_focus_widget (sl);
|
||||
}
|
||||
|
||||
if (GDK_IS_FRAME_CLOCK (sl->priv->object))
|
||||
@@ -408,7 +367,6 @@ gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl,
|
||||
if (sl->priv->object)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (sl->priv->object, state_flags_changed, sl);
|
||||
g_signal_handlers_disconnect_by_func (sl->priv->object, set_focus_cb, sl);
|
||||
g_signal_handlers_disconnect_by_func (sl->priv->object, allocation_changed, sl);
|
||||
disconnect_each_other (sl->priv->object, G_OBJECT (sl));
|
||||
disconnect_each_other (sl, sl->priv->object);
|
||||
@@ -475,14 +433,10 @@ gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl,
|
||||
if (GTK_IS_WINDOW (object))
|
||||
{
|
||||
gtk_widget_show (sl->priv->default_widget_row);
|
||||
gtk_widget_show (sl->priv->focus_widget_row);
|
||||
|
||||
g_signal_connect_object (object, "set-focus", G_CALLBACK (set_focus_cb), sl, G_CONNECT_AFTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (sl->priv->default_widget_row);
|
||||
gtk_widget_hide (sl->priv->focus_widget_row);
|
||||
}
|
||||
|
||||
if (GDK_IS_FRAME_CLOCK (object))
|
||||
@@ -595,9 +549,6 @@ gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass)
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_row);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_button);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_row);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_button);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, mnemonic_label_row);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, mnemonic_label);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, request_mode_row);
|
||||
@@ -631,7 +582,6 @@ gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass)
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, child_visible);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, show_default_widget);
|
||||
gtk_widget_class_bind_template_callback (widget_class, show_focus_widget);
|
||||
gtk_widget_class_bind_template_callback (widget_class, show_frame_clock);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,42 +157,6 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow" id="focus_widget_row">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">40</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="focus_widget_label">
|
||||
<property name="label" translatable="yes">Focus Widget</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="xalign">0.0</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="focus_widget">
|
||||
<property name="selectable">1</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="focus_widget_button">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label" translatable="yes">Properties</property>
|
||||
<signal name="clicked" handler="show_focus_widget"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow" id="mnemonic_label_row">
|
||||
<property name="activatable">0</property>
|
||||
@@ -616,7 +580,6 @@
|
||||
<widget name="state_label"/>
|
||||
<widget name="buildable_id_label"/>
|
||||
<widget name="default_widget_label"/>
|
||||
<widget name="focus_widget_label"/>
|
||||
<widget name="frame_clock_label"/>
|
||||
</widgets>
|
||||
</object>
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "gtksearchbar.h"
|
||||
#include "gtksearchentry.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkpopup.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -1144,6 +1145,7 @@ create_root_model (void)
|
||||
g_object_unref);
|
||||
gtk_filter_list_model_set_model (filter, gtk_window_get_toplevels ());
|
||||
g_list_store_append (list, filter);
|
||||
g_list_store_append (list, gtk_popup_get_popups ());
|
||||
g_object_unref (filter);
|
||||
|
||||
flatten = gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list));
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "visual.h"
|
||||
|
||||
#include "focusoverlay.h"
|
||||
#include "fpsoverlay.h"
|
||||
#include "updatesoverlay.h"
|
||||
#include "layoutoverlay.h"
|
||||
@@ -83,6 +84,7 @@ struct _GtkInspectorVisualPrivate
|
||||
GtkInspectorOverlay *fps_overlay;
|
||||
GtkInspectorOverlay *updates_overlay;
|
||||
GtkInspectorOverlay *layout_overlay;
|
||||
GtkInspectorOverlay *focus_overlay;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorVisual, gtk_inspector_visual, GTK_TYPE_SCROLLED_WINDOW)
|
||||
@@ -298,6 +300,41 @@ updates_activate (GtkSwitch *sw,
|
||||
redraw_everything ();
|
||||
}
|
||||
|
||||
static void
|
||||
focus_activate (GtkSwitch *sw,
|
||||
GParamSpec *pspec,
|
||||
GtkInspectorVisual *vis)
|
||||
{
|
||||
GtkInspectorVisualPrivate *priv = vis->priv;
|
||||
GtkInspectorWindow *iw;
|
||||
gboolean focus;
|
||||
|
||||
focus = gtk_switch_get_active (sw);
|
||||
iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (vis)));
|
||||
if (iw == NULL)
|
||||
return;
|
||||
|
||||
if (focus)
|
||||
{
|
||||
if (priv->focus_overlay == NULL)
|
||||
{
|
||||
priv->focus_overlay = gtk_focus_overlay_new ();
|
||||
gtk_inspector_window_add_overlay (iw, priv->focus_overlay);
|
||||
g_object_unref (priv->focus_overlay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->focus_overlay != NULL)
|
||||
{
|
||||
gtk_inspector_window_remove_overlay (iw, priv->focus_overlay);
|
||||
priv->focus_overlay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
redraw_everything ();
|
||||
}
|
||||
|
||||
static void
|
||||
baselines_activate (GtkSwitch *sw)
|
||||
{
|
||||
@@ -952,6 +989,7 @@ gtk_inspector_visual_class_init (GtkInspectorVisualClass *klass)
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, font_scale_entry);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, font_scale_adjustment);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, focus_activate);
|
||||
gtk_widget_class_bind_template_callback (widget_class, fps_activate);
|
||||
gtk_widget_class_bind_template_callback (widget_class, updates_activate);
|
||||
gtk_widget_class_bind_template_callback (widget_class, direction_changed);
|
||||
|
||||
@@ -371,6 +371,33 @@
|
||||
<child>
|
||||
<object class="GtkListBox" id="debug_box">
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">40</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="focus_label">
|
||||
<property name="label" translatable="yes">Show focus overlay</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="focus_switch">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="hexpand">1</property>
|
||||
<signal name="notify::active" handler="focus_activate"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
|
||||
@@ -296,6 +296,7 @@ gtk_public_sources = files([
|
||||
'gtkpicture.c',
|
||||
'gtkpopover.c',
|
||||
'gtkpopovermenu.c',
|
||||
'gtkpopup.c',
|
||||
'gtkprintcontext.c',
|
||||
'gtkprintoperation.c',
|
||||
'gtkprintoperationpreview.c',
|
||||
|
||||
@@ -239,6 +239,5 @@
|
||||
<action-widget response="-6">cancel_button</action-widget>
|
||||
<action-widget response="apply">confirm_button</action-widget>
|
||||
</action-widgets>
|
||||
<initial-focus name="name_entry"/>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
+38
-35
@@ -1,51 +1,50 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static void
|
||||
draw_popup (GtkDrawingArea *da,
|
||||
cairo_t *cr,
|
||||
int width,
|
||||
int height,
|
||||
gpointer data)
|
||||
clicked (GtkButton *button)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
cairo_paint (cr);
|
||||
g_print ("Yes!\n");
|
||||
}
|
||||
|
||||
static void
|
||||
place_popup (GtkEventControllerMotion *motion,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
GtkWidget *popup)
|
||||
static GtkWidget *
|
||||
add_content (GtkWidget *parent)
|
||||
{
|
||||
gint width, height, win_x, win_y;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *box, *label, *entry, *button;
|
||||
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (motion));
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
|
||||
|
||||
gtk_window_get_size (GTK_WINDOW (popup), &width, &height);
|
||||
gtk_window_get_position (GTK_WINDOW (widget), &win_x, &win_y);
|
||||
gtk_window_move (GTK_WINDOW (popup),
|
||||
(int) win_x + x - width / 2,
|
||||
(int) win_y + y - height / 2);
|
||||
label = gtk_label_new_with_mnemonic ("_Test");
|
||||
entry = gtk_entry_new ();
|
||||
button = gtk_button_new_with_mnemonic ("_Yes!");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (clicked), NULL);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
|
||||
gtk_widget_set_can_default (button, TRUE);
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (box), label);
|
||||
gtk_container_add (GTK_CONTAINER (box), entry);
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_container_add (GTK_CONTAINER (parent), box);
|
||||
|
||||
gtk_widget_grab_default (button);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_map (GtkWidget *parent)
|
||||
create_popup (GtkWidget *parent)
|
||||
{
|
||||
GtkWidget *popup, *da;
|
||||
GtkEventController *motion;
|
||||
GtkWidget *popup;
|
||||
|
||||
popup = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
da = gtk_drawing_area_new ();
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_popup, NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (popup), da);
|
||||
popup = gtk_popup_new ();
|
||||
gtk_popup_set_relative_to (GTK_POPUP (popup), parent);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (popup), "background");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (popup), "frame");
|
||||
|
||||
gtk_widget_set_size_request (GTK_WIDGET (popup), 20, 20);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (popup), GTK_WINDOW (parent));
|
||||
|
||||
motion = gtk_event_controller_motion_new ();
|
||||
gtk_widget_add_controller (parent, motion);
|
||||
g_signal_connect (motion, "motion", G_CALLBACK (place_popup), popup);
|
||||
add_content (popup);
|
||||
|
||||
gtk_widget_show (popup);
|
||||
|
||||
@@ -56,13 +55,17 @@ int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *label;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
|
||||
|
||||
g_signal_connect (window, "destroy", gtk_main_quit, NULL);
|
||||
g_signal_connect (window, "map", G_CALLBACK (on_map), NULL);
|
||||
label = add_content (window);
|
||||
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
|
||||
g_signal_connect_swapped (window, "map", G_CALLBACK (create_popup), label);
|
||||
|
||||
gtk_widget_show (window);
|
||||
|
||||
|
||||
+1
-1
@@ -344,7 +344,7 @@ popup_context_menu (GtkToolbar *toolbar, gint x, gint y, gint button_number)
|
||||
GtkWidget *widget;
|
||||
|
||||
window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (toolbar)));
|
||||
widget = gtk_window_get_focus (window);
|
||||
widget = gtk_root_get_focus (GTK_ROOT (window));
|
||||
if (!widget)
|
||||
widget = GTK_WIDGET (toolbar);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user