diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-05-05 14:57:21 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-05-10 23:24:48 -0400 |
commit | edc31a264c6778274376e892dc38ab186c952c4a (patch) | |
tree | 90f976c6f00ba5803249f5db904e65b97ee0cde5 | |
parent | f6a4e68973fcf78504e320453c576abb789d9e03 (diff) | |
download | gtk+-edc31a264c6778274376e892dc38ab186c952c4a.tar.gz |
widget: Add a :focusable property
Add back a property that determines whether an individual
widget will accept focus or not. :can-focus prevents the
focus from ever entering the entire widget hierarchy
below a widget, and :focusable just determines if grabbing
the focus to the widget itself will succeed.
See #2686
-rw-r--r-- | docs/reference/gtk/gtk4-sections.txt | 2 | ||||
-rw-r--r-- | gtk/gtkbutton.c | 1 | ||||
-rw-r--r-- | gtk/gtkcalendar.c | 2 | ||||
-rw-r--r-- | gtk/gtkcellrendereraccel.c | 2 | ||||
-rw-r--r-- | gtk/gtkcolorplane.c | 2 | ||||
-rw-r--r-- | gtk/gtkcolorswatch.c | 2 | ||||
-rw-r--r-- | gtk/gtkdrawingarea.c | 5 | ||||
-rw-r--r-- | gtk/gtkexpander.c | 2 | ||||
-rw-r--r-- | gtk/gtkiconview.c | 1 | ||||
-rw-r--r-- | gtk/gtklabel.c | 4 | ||||
-rw-r--r-- | gtk/gtklistbox.c | 3 | ||||
-rw-r--r-- | gtk/gtkmodelbutton.c | 2 | ||||
-rw-r--r-- | gtk/gtknotebook.c | 2 | ||||
-rw-r--r-- | gtk/gtkpaned.c | 2 | ||||
-rw-r--r-- | gtk/gtkpopovermenubar.c | 2 | ||||
-rw-r--r-- | gtk/gtkscale.c | 7 | ||||
-rw-r--r-- | gtk/gtkscrolledwindow.c | 2 | ||||
-rw-r--r-- | gtk/gtkswitch.c | 2 | ||||
-rw-r--r-- | gtk/gtktext.c | 2 | ||||
-rw-r--r-- | gtk/gtktextview.c | 2 | ||||
-rw-r--r-- | gtk/gtktreeview.c | 11 | ||||
-rw-r--r-- | gtk/gtktreeviewcolumn.c | 4 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 103 | ||||
-rw-r--r-- | gtk/gtkwidget.h | 5 | ||||
-rw-r--r-- | gtk/gtkwidgetprivate.h | 1 |
25 files changed, 132 insertions, 41 deletions
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index a3ee19ba46..807d92b3a9 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -4050,6 +4050,8 @@ GtkPickFlags gtk_widget_pick gtk_widget_get_can_focus gtk_widget_set_can_focus +gtk_widget_get_focusable +gtk_widget_set_focusable gtk_widget_get_focus_on_click gtk_widget_set_focus_on_click gtk_widget_set_focus_child diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c index 7c10d21b16..1859a088c1 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -421,6 +421,7 @@ gtk_button_init (GtkButton *button) GtkButtonPrivate *priv = gtk_button_get_instance_private (button); GtkEventController *key_controller; + gtk_widget_set_focusable (GTK_WIDGET (button), TRUE); gtk_widget_set_receives_default (GTK_WIDGET (button), TRUE); priv->in_button = FALSE; diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c index ff6b0569ae..3afe2d8e55 100644 --- a/gtk/gtkcalendar.c +++ b/gtk/gtkcalendar.c @@ -574,7 +574,7 @@ gtk_calendar_init (GtkCalendar *calendar) int min_year_width; GDateTime *now; - gtk_widget_set_can_focus (widget, TRUE); + gtk_widget_set_focusable (widget, TRUE); gtk_widget_add_css_class (GTK_WIDGET (calendar), GTK_STYLE_CLASS_VIEW); diff --git a/gtk/gtkcellrendereraccel.c b/gtk/gtkcellrendereraccel.c index 7c3fc2c526..3c806270c6 100644 --- a/gtk/gtkcellrendereraccel.c +++ b/gtk/gtkcellrendereraccel.c @@ -697,7 +697,7 @@ gtk_cell_editable_widget_init (GtkCellEditableWidget *box) GtkWidget *widget = GTK_WIDGET (box); GtkEventController *controller; - gtk_widget_set_can_focus (widget, TRUE); + gtk_widget_set_focusable (widget, TRUE); controller = gtk_event_controller_key_new (); g_signal_connect (controller, "key-pressed", diff --git a/gtk/gtkcolorplane.c b/gtk/gtkcolorplane.c index 5b88ea3ba9..8d18aed3f9 100644 --- a/gtk/gtkcolorplane.c +++ b/gtk/gtkcolorplane.c @@ -407,6 +407,8 @@ gtk_color_plane_init (GtkColorPlane *plane) plane->priv = gtk_color_plane_get_instance_private (plane); + gtk_widget_set_focusable (GTK_WIDGET (plane), TRUE); + atk_obj = gtk_widget_get_accessible (GTK_WIDGET (plane)); if (GTK_IS_ACCESSIBLE (atk_obj)) { diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c index 9d19aeb500..bfdcd9d336 100644 --- a/gtk/gtkcolorswatch.c +++ b/gtk/gtkcolorswatch.c @@ -528,7 +528,7 @@ gtk_color_swatch_init (GtkColorSwatch *swatch) swatch->color.blue = 0.25; swatch->color.alpha = 1.0; - gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (swatch), TRUE); gtk_widget_set_overflow (GTK_WIDGET (swatch), GTK_OVERFLOW_HIDDEN); gesture = gtk_gesture_long_press_new (); diff --git a/gtk/gtkdrawingarea.c b/gtk/gtkdrawingarea.c index 201768e179..b501f3b07c 100644 --- a/gtk/gtkdrawingarea.c +++ b/gtk/gtkdrawingarea.c @@ -278,10 +278,8 @@ gtk_drawing_area_class_init (GtkDrawingAreaClass *class) gobject_class->dispose = gtk_drawing_area_dispose; widget_class->measure = gtk_drawing_area_measure; - widget_class->snapshot = gtk_drawing_area_snapshot; - widget_class->focus = gtk_widget_focus_none; - widget_class->grab_focus = gtk_widget_grab_focus_none; widget_class->size_allocate = gtk_drawing_area_size_allocate; + widget_class->snapshot = gtk_drawing_area_snapshot; /** * GtkDrawingArea:content-width @@ -338,6 +336,7 @@ gtk_drawing_area_class_init (GtkDrawingAreaClass *class) static void gtk_drawing_area_init (GtkDrawingArea *darea) { + gtk_widget_set_focusable (GTK_WIDGET (darea), FALSE); } /** diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c index c4d9cb139c..3e5f58a0a0 100644 --- a/gtk/gtkexpander.c +++ b/gtk/gtkexpander.c @@ -383,6 +383,8 @@ gtk_expander_init (GtkExpander *expander) expander->expand_timer = 0; expander->resize_toplevel = 0; + gtk_widget_set_focusable (GTK_WIDGET (expander), TRUE); + expander->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_widget_set_parent (expander->box, GTK_WIDGET (expander)); diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 848961f8d8..8b3be342a7 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -950,6 +950,7 @@ gtk_icon_view_init (GtkIconView *icon_view) icon_view->priv->mouse_y = -1; gtk_widget_set_overflow (GTK_WIDGET (icon_view), GTK_OVERFLOW_HIDDEN); + gtk_widget_set_focusable (GTK_WIDGET (icon_view), TRUE); icon_view->priv->item_orientation = GTK_ORIENTATION_VERTICAL; diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index cad4982e6d..2aac9270d0 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -4417,7 +4417,7 @@ gtk_label_ensure_select_info (GtkLabel *self) { self->select_info = g_new0 (GtkLabelSelectionInfo, 1); - gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (self), TRUE); self->select_info->drag_gesture = gtk_gesture_drag_new (); g_signal_connect (self->select_info->drag_gesture, "drag-begin", @@ -4469,7 +4469,7 @@ gtk_label_clear_select_info (GtkLabel *self) gtk_widget_set_cursor (GTK_WIDGET (self), NULL); - gtk_widget_set_can_focus (GTK_WIDGET (self), FALSE); + gtk_widget_set_focusable (GTK_WIDGET (self), FALSE); } } diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c index fd9376ae35..f240f92e9d 100644 --- a/gtk/gtklistbox.c +++ b/gtk/gtklistbox.c @@ -689,6 +689,8 @@ gtk_list_box_init (GtkListBox *box) GtkWidget *widget = GTK_WIDGET (box); GtkGesture *gesture; + gtk_widget_set_focusable (GTK_WIDGET (box), TRUE); + box->selection_mode = GTK_SELECTION_SINGLE; box->activate_single_click = TRUE; @@ -3482,6 +3484,7 @@ gtk_list_box_row_init (GtkListBoxRow *row) ROW_PRIV (row)->activatable = TRUE; ROW_PRIV (row)->selectable = TRUE; + gtk_widget_set_focusable (GTK_WIDGET (row), TRUE); gtk_widget_add_css_class (GTK_WIDGET (row), "activatable"); } diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c index e8fe1bebaf..1737137878 100644 --- a/gtk/gtkmodelbutton.c +++ b/gtk/gtkmodelbutton.c @@ -1380,7 +1380,7 @@ gtk_model_button_init (GtkModelButton *self) GtkEventController *controller; GtkGesture *gesture; - gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (self), TRUE); self->role = GTK_BUTTON_ROLE_NORMAL; self->label = gtk_label_new (""); diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c index c0b128408a..0b9ba6e6f2 100644 --- a/gtk/gtknotebook.c +++ b/gtk/gtknotebook.c @@ -1414,6 +1414,8 @@ gtk_notebook_init (GtkNotebook *notebook) notebook->detached_tab = NULL; notebook->has_scrolled = FALSE; + gtk_widget_set_focusable (GTK_WIDGET (notebook), TRUE); + notebook->header_widget = g_object_new (GTK_TYPE_BOX, "css-name", "header", NULL); diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c index b39d5bd56a..82e1d700d2 100644 --- a/gtk/gtkpaned.c +++ b/gtk/gtkpaned.c @@ -1347,7 +1347,7 @@ gtk_paned_init (GtkPaned *paned) GtkPanedPrivate *priv = gtk_paned_get_instance_private (paned); GtkGesture *gesture; - gtk_widget_set_can_focus (GTK_WIDGET (paned), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (paned), TRUE); gtk_widget_set_overflow (GTK_WIDGET (paned), GTK_OVERFLOW_HIDDEN); priv->orientation = GTK_ORIENTATION_HORIZONTAL; diff --git a/gtk/gtkpopovermenubar.c b/gtk/gtkpopovermenubar.c index 5adec80cba..e563bfa1d4 100644 --- a/gtk/gtkpopovermenubar.c +++ b/gtk/gtkpopovermenubar.c @@ -244,7 +244,7 @@ gtk_popover_menu_bar_item_init (GtkPopoverMenuBarItem *item) { GtkEventController *controller; - gtk_widget_set_can_focus (GTK_WIDGET (item), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (item), TRUE); item->label = g_object_new (GTK_TYPE_LABEL, "use-underline", TRUE, diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c index 3f043c6305..455a004ac9 100644 --- a/gtk/gtkscale.c +++ b/gtk/gtkscale.c @@ -806,8 +806,7 @@ gtk_scale_class_init (GtkScaleClass *class) add_slider_binding (binding_set, GDK_KEY_KP_Subtract, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD); - - + add_slider_binding (binding_set, GDK_KEY_Home, 0, GTK_SCROLL_START); @@ -830,11 +829,11 @@ gtk_scale_init (GtkScale *scale) GtkScalePrivate *priv = gtk_scale_get_instance_private (scale); GtkRange *range = GTK_RANGE (scale); + gtk_widget_set_focusable (GTK_WIDGET (scale), TRUE); + priv->value_pos = GTK_POS_TOP; priv->digits = 1; - gtk_widget_set_can_focus (GTK_WIDGET (scale), TRUE); - gtk_range_set_slider_size_fixed (range, TRUE); _gtk_range_set_has_origin (range, TRUE); diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c index 24bdd5a063..90ef269140 100644 --- a/gtk/gtkscrolledwindow.c +++ b/gtk/gtkscrolledwindow.c @@ -1963,7 +1963,7 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) }; gint i; - gtk_widget_set_can_focus (widget, TRUE); + gtk_widget_set_focusable (widget, TRUE); /* Instantiated by gtk_scrolled_window_set_[hv]adjustment * which are both construct properties diff --git a/gtk/gtkswitch.c b/gtk/gtkswitch.c index ffc7371c73..454bbce04a 100644 --- a/gtk/gtkswitch.c +++ b/gtk/gtkswitch.c @@ -622,7 +622,7 @@ gtk_switch_init (GtkSwitch *self) GtkLayoutManager *layout; GtkGesture *gesture; - gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (self), TRUE); gesture = gtk_gesture_click_new (); gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), FALSE); diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 7ff5855f89..fb50485772 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -1822,7 +1822,7 @@ gtk_text_init (GtkText *self) int i; GtkDropTarget *target; - gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); + gtk_widget_set_focusable (GTK_WIDGET (self), TRUE); gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN); priv->editable = TRUE; diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index b6ec008b14..9bc7954a4d 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -1858,7 +1858,7 @@ gtk_text_view_init (GtkTextView *text_view) text_view->priv = gtk_text_view_get_instance_private (text_view); priv = text_view->priv; - gtk_widget_set_can_focus (widget, TRUE); + gtk_widget_set_focusable (widget, TRUE); gtk_widget_set_overflow (widget, GTK_OVERFLOW_HIDDEN); gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_VIEW); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 2b3b46441c..cc6599e9fe 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -1683,6 +1683,7 @@ gtk_tree_view_init (GtkTreeView *tree_view) guint n_controllers, i; gtk_widget_set_overflow (GTK_WIDGET (tree_view), GTK_OVERFLOW_HIDDEN); + gtk_widget_set_focusable (GTK_WIDGET (tree_view), TRUE); tree_view->show_expanders = TRUE; tree_view->draw_keyfocus = TRUE; @@ -2688,7 +2689,7 @@ grab_focus_and_unset_draw_keyfocus (GtkTreeView *tree_view) { GtkWidget *widget = GTK_WIDGET (tree_view); - if (gtk_widget_get_can_focus (widget) && + if (gtk_widget_get_focusable (widget) && !gtk_widget_has_focus (widget) && !_gtk_widget_get_shadowed (widget)) gtk_widget_grab_focus (widget); @@ -7628,7 +7629,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, column = GTK_TREE_VIEW_COLUMN (first_column->data); button = gtk_tree_view_column_get_button (column); - if (gtk_widget_get_can_focus (button) && + if (gtk_widget_get_focusable (button) && gtk_tree_view_column_get_visible (column) && (gtk_tree_view_column_get_clickable (column) || gtk_tree_view_column_get_reorderable (column))) @@ -7647,7 +7648,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, column = GTK_TREE_VIEW_COLUMN (last_column->data); button = gtk_tree_view_column_get_button (column); - if (gtk_widget_get_can_focus (button) && + if (gtk_widget_get_focusable (button) && gtk_tree_view_column_get_visible (column) && (gtk_tree_view_column_get_clickable (column) || gtk_tree_view_column_get_reorderable (column))) @@ -7671,7 +7672,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, else button = NULL; - if (button && gtk_widget_get_can_focus (button)) + if (button && gtk_widget_get_focusable (button)) focus_child = button; else focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (first_column->data)); @@ -7731,7 +7732,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, button = gtk_tree_view_column_get_button (column); if (button && gtk_tree_view_column_get_visible (column) && - gtk_widget_get_can_focus (button)) + gtk_widget_get_focusable (button)) { focus_child = button; gtk_widget_grab_focus (button); diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 923712126b..50a0e62d03 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -1019,11 +1019,11 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) if (priv->reorderable || priv->clickable) { - gtk_widget_set_can_focus (priv->button, TRUE); + gtk_widget_set_focusable (priv->button, TRUE); } else { - gtk_widget_set_can_focus (priv->button, FALSE); + gtk_widget_set_focusable (priv->button, FALSE); if (gtk_widget_has_focus (priv->button)) { GtkRoot *root = gtk_widget_get_root (priv->tree_view); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index e6c6308ef8..17e21b8b36 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -518,6 +518,7 @@ enum { PROP_HAS_FOCUS, PROP_CAN_TARGET, PROP_FOCUS_ON_CLICK, + PROP_FOCUSABLE, PROP_HAS_DEFAULT, PROP_RECEIVES_DEFAULT, PROP_CURSOR, @@ -1018,6 +1019,18 @@ gtk_widget_class_init (GtkWidgetClass *klass) TRUE, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkWidget:focusable: + * + * Whether this widget itself will accept the input focus. + */ + widget_props[PROP_FOCUSABLE] = + g_param_spec_boolean ("focusable", + P_("Focusable"), + P_("Whether the widget can accept the input focus"), + FALSE, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + widget_props[PROP_HAS_FOCUS] = g_param_spec_boolean ("has-focus", P_("Has focus"), @@ -1696,6 +1709,9 @@ gtk_widget_set_property (GObject *object, case PROP_CAN_FOCUS: gtk_widget_set_can_focus (widget, g_value_get_boolean (value)); break; + case PROP_FOCUSABLE: + gtk_widget_set_focusable (widget, g_value_get_boolean (value)); + break; case PROP_CAN_TARGET: gtk_widget_set_can_target (widget, g_value_get_boolean (value)); break; @@ -1846,6 +1862,9 @@ gtk_widget_get_property (GObject *object, case PROP_CAN_FOCUS: g_value_set_boolean (value, gtk_widget_get_can_focus (widget)); break; + case PROP_FOCUSABLE: + g_value_set_boolean (value, gtk_widget_get_focusable (widget)); + break; case PROP_HAS_FOCUS: g_value_set_boolean (value, gtk_widget_has_focus (widget)); break; @@ -2316,6 +2335,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class) priv->highlight_resize = FALSE; #endif priv->can_focus = TRUE; + priv->focusable = FALSE; priv->can_target = TRUE; switch (_gtk_widget_get_direction (widget)) @@ -4768,7 +4788,11 @@ gtk_widget_grab_focus_self (GtkWidget *widget) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); + if (!priv->focusable) + return FALSE; + gtk_root_set_focus (priv->root, widget); + return TRUE; } @@ -4951,10 +4975,7 @@ gtk_widget_focus_all (GtkWidget *widget, if (direction_is_forward (direction)) return FALSE; else - { - gtk_widget_grab_focus (widget); - return TRUE; - } + return gtk_widget_grab_focus (widget); } if (!direction_is_forward (direction)) @@ -4963,8 +4984,7 @@ gtk_widget_focus_all (GtkWidget *widget, return TRUE; } - gtk_widget_grab_focus (widget); - return TRUE; + return gtk_widget_grab_focus (widget); } gboolean @@ -5030,14 +5050,16 @@ gtk_widget_real_keynav_failed (GtkWidget *widget, /** * gtk_widget_set_can_focus: * @widget: a #GtkWidget - * @can_focus: whether or not @widget can own the input focus. + * @can_focus: whether or not the input focus can enter + * the widget tree below @widget * - * Specifies whether @widget can own the input focus. + * Specifies whether the input focus can enter the widget + * tree below @widget. * * Note that having @can_focus be %TRUE is only one of the * necessary conditions for being focusable. A widget must * also be sensitive and not have an ancestor that is marked - * as not child-focusable in order to receive input focus. + * as not can-focus in order to receive input focus. * * See gtk_widget_grab_focus() for actually setting the input * focus on a widget. @@ -5063,22 +5085,73 @@ gtk_widget_set_can_focus (GtkWidget *widget, * gtk_widget_get_can_focus: * @widget: a #GtkWidget * - * Determines whether @widget can own the input focus. See - * gtk_widget_set_can_focus(). + * Determines whether the input focus can enter @widget. + * See gtk_widget_set_focusable(). * - * Returns: %TRUE if @widget can own the input focus, %FALSE otherwise + * Returns: %TRUE if the input focus can enter @widget, %FALSE otherwise **/ gboolean gtk_widget_get_can_focus (GtkWidget *widget) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); - g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE); return priv->can_focus; } /** + * gtk_widget_set_focusable: + * @widget: a #GtkWidget + * @focusable: whether or not @widget can own the input focus. + * + * Specifies whether @widget can own the input focus. + * + * Note that having @focusable be %TRUE is only one of the + * necessary conditions for being focusable. A widget must + * also be sensitive and not have an ancestor that is marked + * as not child-focusable in order to receive input focus. + * + * See gtk_widget_grab_focus() for actually setting the input + * focus on a widget. + **/ +void +gtk_widget_set_focusable (GtkWidget *widget, + gboolean focusable) +{ + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); + + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (priv->focusable == focusable) + return; + + priv->focusable = focusable; + + gtk_widget_queue_resize (widget); + g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_FOCUSABLE]); +} + +/** + * gtk_widget_get_focusable: + * @widget: a #GtkWidget + * + * Determines whether @widget can own the input focus. + * See gtk_widget_set_focusable(). + * + * Returns: %TRUE if @widget can own the input focus, %FALSE otherwise + **/ +gboolean +gtk_widget_get_focusable (GtkWidget *widget) +{ + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); + + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + + return priv->focusable; +} + +/** * gtk_widget_has_focus: * @widget: a #GtkWidget * @@ -6662,7 +6735,7 @@ gtk_widget_get_display (GtkWidget *widget) * writing an app, you’d use gtk_widget_grab_focus() to move the focus * to a particular widget. * - * gtk_widget_child_focus() is called by containers as the user moves + * gtk_widget_child_focus() is called by widgets as the user moves * around the window using keyboard shortcuts. @direction indicates * what kind of motion is taking place (up, down, left, right, tab * forward, tab backward). gtk_widget_child_focus() emits the @@ -6689,7 +6762,7 @@ gtk_widget_child_focus (GtkWidget *widget, !gtk_widget_get_can_focus (widget)) return FALSE; - /* Emit ::focus in any case, even if can-focus is FALSE, + /* Emit ::focus in any case, even if focusable is FALSE, * since any widget might have child widgets that will take * focus */ diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 7352eded9a..f18ae9899e 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -406,6 +406,11 @@ void gtk_widget_set_can_focus (GtkWidget *widget, GDK_AVAILABLE_IN_ALL gboolean gtk_widget_get_can_focus (GtkWidget *widget); GDK_AVAILABLE_IN_ALL +void gtk_widget_set_focusable (GtkWidget *widget, + gboolean focusable); +GDK_AVAILABLE_IN_ALL +gboolean gtk_widget_get_focusable (GtkWidget *widget); +GDK_AVAILABLE_IN_ALL gboolean gtk_widget_has_focus (GtkWidget *widget); GDK_AVAILABLE_IN_ALL gboolean gtk_widget_is_focus (GtkWidget *widget); diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 6d3fadb929..e42969c830 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -77,6 +77,7 @@ struct _GtkWidgetPrivate guint visible : 1; guint sensitive : 1; guint can_focus : 1; + guint focusable : 1; guint has_focus : 1; guint focus_on_click : 1; guint has_default : 1; |