listbase: Move focus moving keybindings here

The focus tracker is not yet moved because that depends on scroll_to()
support and we don't have that yet.
Whoops.
So we use a hack.
This commit is contained in:
Benjamin Otte 2019-10-24 06:49:38 +02:00 committed by Matthias Clasen
parent dd5e6d47db
commit 12331e3376
4 changed files with 359 additions and 350 deletions

View File

@ -399,64 +399,46 @@ gtk_grid_view_set_anchor (GtkGridView *self,
}
}
static gboolean
gtk_grid_view_focus (GtkWidget *widget,
GtkDirectionType direction)
static guint
gtk_grid_view_move_focus_along (GtkListBase *base,
guint pos,
int steps)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
GtkWidget *old_focus_child, *new_focus_child;
GtkGridView *self = GTK_GRID_VIEW (base);
old_focus_child = gtk_widget_get_focus_child (widget);
steps *= self->n_columns;
if (old_focus_child == NULL &&
(direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD))
if (steps < 0)
{
Cell *cell;
guint pos;
/* When tabbing into the listview, don't focus the first/last item,
* but keep the previously focused item
*/
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
cell = gtk_list_item_manager_get_nth (self->item_manager, pos, NULL);
if (cell && gtk_widget_grab_focus (cell->parent.widget))
goto moved_focus;
if (pos >= self->n_columns)
pos -= MIN (pos, -steps);
}
else
{
guint n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
if (n_items / self->n_columns > pos / self->n_columns)
pos += MIN (n_items - pos - 1, steps);
}
if (!GTK_WIDGET_CLASS (gtk_grid_view_parent_class)->focus (widget, direction))
return FALSE;
return pos;
}
moved_focus:
new_focus_child = gtk_widget_get_focus_child (widget);
static guint
gtk_grid_view_move_focus_across (GtkListBase *base,
guint pos,
int steps)
{
GtkGridView *self = GTK_GRID_VIEW (base);
if (old_focus_child != new_focus_child &&
GTK_IS_LIST_ITEM (new_focus_child))
if (steps < 0)
return pos - MIN (pos, -steps);
else
{
gboolean extend = FALSE, modify = FALSE;
if (old_focus_child)
{
GdkSeat *seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
if (seat)
{
GdkDevice *keyboard = gdk_seat_get_keyboard (seat);
if (keyboard)
{
GdkModifierType state = gdk_device_get_modifier_state (keyboard);
extend = (state & GDK_SHIFT_MASK) != 0;
modify = (state & GDK_CONTROL_MASK) != 0;
}
}
}
gtk_list_base_select_item (GTK_LIST_BASE (self),
gtk_list_item_get_position (GTK_LIST_ITEM (new_focus_child)),
modify,
extend);
guint n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
pos += MIN (n_items - pos - 1, steps);
}
return TRUE;
return pos;
}
static void
@ -1279,87 +1261,6 @@ gtk_grid_view_activate_item (GtkWidget *widget,
g_signal_emit (widget, signals[ACTIVATE], 0, pos);
}
static gboolean
gtk_grid_view_move_cursor (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
int amount;
guint orientation;
guint pos, n_items;
gboolean select, modify, extend;
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
if (gtk_list_base_get_orientation (GTK_LIST_BASE (self)) == orientation)
amount *= self->n_columns;
if (orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
amount = -amount;
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
if (pos >= n_items || /* no focused item */
(amount < 0 && pos < -amount))
return TRUE;
if (amount > 0 && amount > n_items - pos)
{
/* pressing down with no item below the current item is more complicated
* because we want to move to the last row if we're not there yet */
if (pos / self->n_columns < (n_items - 1) / self->n_columns)
amount = n_items - pos - 1;
else
return TRUE;
}
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos + amount, select, modify, extend);
return TRUE;
}
static gboolean
gtk_grid_view_move_cursor_to_start (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
gboolean select, modify, extend;
if (self->model == NULL || g_list_model_get_n_items (self->model) == 0)
return TRUE;
g_variant_get (args, "(bbb)", &select, &modify, &extend);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), 0, select, modify, extend);
return TRUE;
}
static gboolean
gtk_grid_view_move_cursor_to_end (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
gboolean select, modify, extend;
guint n_items;
if (self->model == NULL)
return TRUE;
n_items = g_list_model_get_n_items (self->model);
if (n_items == 0)
return TRUE;
g_variant_get (args, "(bbb)", &select, &modify, &extend);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), n_items - 1, select, modify, extend);
return TRUE;
}
static gboolean
gtk_grid_view_move_cursor_page_up (GtkWidget *widget,
GVariant *args,
@ -1478,29 +1379,6 @@ gtk_grid_view_add_custom_move_binding (GtkWidgetClass *widget_class,
"(bbb)", TRUE, TRUE, TRUE);
}
static void
gtk_grid_view_add_move_binding (GtkWidgetClass *widget_class,
guint keyval,
GtkOrientation orientation,
int amount)
{
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK,
gtk_grid_view_move_cursor,
"(ubbbi)", orientation, FALSE, FALSE, FALSE, amount);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_SHIFT_MASK,
gtk_grid_view_move_cursor,
"(ubbbi)", orientation, TRUE, FALSE, TRUE, amount);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
gtk_grid_view_move_cursor,
"(ubbbi)", orientation, TRUE, TRUE, TRUE, amount);
}
static void
gtk_grid_view_class_init (GtkGridViewClass *klass)
{
@ -1513,8 +1391,9 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
list_base_class->list_item_augment_size = sizeof (CellAugment);
list_base_class->list_item_augment_func = cell_augment;
list_base_class->adjustment_value_changed = gtk_grid_view_adjustment_value_changed;
list_base_class->move_focus_along = gtk_grid_view_move_focus_along;
list_base_class->move_focus_across = gtk_grid_view_move_focus_across;
widget_class->focus = gtk_grid_view_focus;
widget_class->measure = gtk_grid_view_measure;
widget_class->size_allocate = gtk_grid_view_size_allocate;
@ -1624,31 +1503,12 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
"u",
gtk_grid_view_scroll_to_item);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_Up, GTK_ORIENTATION_VERTICAL, -1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_KP_Up, GTK_ORIENTATION_VERTICAL, -1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_Down, GTK_ORIENTATION_VERTICAL, 1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_KP_Down, GTK_ORIENTATION_VERTICAL, 1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_Left, GTK_ORIENTATION_HORIZONTAL, -1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_KP_Left, GTK_ORIENTATION_HORIZONTAL, -1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_Right, GTK_ORIENTATION_HORIZONTAL, 1);
gtk_grid_view_add_move_binding (widget_class, GDK_KEY_KP_Right, GTK_ORIENTATION_HORIZONTAL, 1);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_Home, gtk_grid_view_move_cursor_to_start);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_KP_Home, gtk_grid_view_move_cursor_to_start);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_End, gtk_grid_view_move_cursor_to_end);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_KP_End, gtk_grid_view_move_cursor_to_end);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_Page_Up, gtk_grid_view_move_cursor_page_up);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_KP_Page_Up, gtk_grid_view_move_cursor_page_up);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_Page_Down, gtk_grid_view_move_cursor_page_down);
gtk_grid_view_add_custom_move_binding (widget_class, GDK_KEY_KP_Page_Down, gtk_grid_view_move_cursor_page_down);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_a, GDK_CONTROL_MASK, "list.select-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_slash, GDK_CONTROL_MASK, "list.select-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "list.unselect-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_backslash, GDK_CONTROL_MASK, "list.unselect-all", NULL);
gtk_widget_class_set_css_name (widget_class, I_("flowbox"));
}
static void

View File

@ -93,6 +93,68 @@ gtk_list_base_clear_adjustment (GtkListBase *self,
g_clear_object (&priv->adjustment[orientation]);
}
/*
* gtk_list_base_move_focus_along:
* @self: a #GtkListBase
* @pos: position from which to move focus
* @steps: steps to move focus - negative numbers
* move focus backwards
*
* Moves focus @steps in the direction of the list.
* If focus cannot be moved, @pos is returned.
* If focus should be moved out of the widget, %GTK_INVALID_LIST_POSITION
* is returned.
*
* Returns: new focus position
**/
static guint
gtk_list_base_move_focus_along (GtkListBase *self,
guint pos,
int steps)
{
return GTK_LIST_BASE_GET_CLASS (self)->move_focus_along (self, pos, steps);
}
/*
* gtk_list_base_move_focus_across:
* @self: a #GtkListBase
* @pos: position from which to move focus
* @steps: steps to move focus - negative numbers
* move focus backwards
*
* Moves focus @steps in the direction across the list.
* If focus cannot be moved, @pos is returned.
* If focus should be moved out of the widget, %GTK_INVALID_LIST_POSITION
* is returned.
*
* Returns: new focus position
**/
static guint
gtk_list_base_move_focus_across (GtkListBase *self,
guint pos,
int steps)
{
return GTK_LIST_BASE_GET_CLASS (self)->move_focus_across (self, pos, steps);
}
static guint
gtk_list_base_move_focus (GtkListBase *self,
guint pos,
GtkOrientation orientation,
int steps)
{
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
if (orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
steps = -steps;
if (orientation == priv->orientation)
return gtk_list_base_move_focus_along (self, pos, steps);
else
return gtk_list_base_move_focus_across (self, pos, steps);
}
/*
* gtk_list_base_select_item:
* @self: a %GtkListBase
@ -185,6 +247,108 @@ gtk_list_base_select_item (GtkListBase *self,
0, 0);
}
static guint
gtk_list_base_get_n_items (GtkListBase *self)
{
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
GtkSelectionModel *model;
model = gtk_list_item_manager_get_model (priv->item_manager);
if (model == NULL)
return 0;
return g_list_model_get_n_items (G_LIST_MODEL (model));
}
guint
gtk_list_base_get_focus_position (GtkListBase *self)
{
#if 0
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
return gtk_list_item_tracker_get_position (priv->item_manager, priv->focus);
#else
GtkWidget *focus_child = gtk_widget_get_focus_child (GTK_WIDGET (self));
if (focus_child)
return gtk_list_item_get_position (GTK_LIST_ITEM (focus_child));
else
return GTK_INVALID_LIST_POSITION;
#endif
}
static gboolean
gtk_list_base_focus (GtkWidget *widget,
GtkDirectionType direction)
{
GtkListBase *self = GTK_LIST_BASE (widget);
guint old, pos, n_items;
pos = gtk_list_base_get_focus_position (self);
n_items = gtk_list_base_get_n_items (self);
old = pos;
if (pos >= n_items)
{
if (n_items == 0)
return FALSE;
pos = 0;
}
else if (gtk_widget_get_focus_child (widget) == NULL)
{
/* Focus was outside the list, just grab the old focus item
* while keeping the selection intact.
*/
return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, FALSE, FALSE, FALSE);
}
else
{
switch (direction)
{
case GTK_DIR_TAB_FORWARD:
pos++;
if (pos >= n_items)
return FALSE;
break;
case GTK_DIR_TAB_BACKWARD:
if (pos == 0)
return FALSE;
pos--;
break;
case GTK_DIR_UP:
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_VERTICAL, -1);
break;
case GTK_DIR_DOWN:
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_VERTICAL, 1);
break;
case GTK_DIR_LEFT:
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_HORIZONTAL, -1);
break;
case GTK_DIR_RIGHT:
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_HORIZONTAL, 1);
break;
default:
g_assert_not_reached ();
return TRUE;
}
}
if (old != pos)
{
return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, TRUE, FALSE, FALSE);
}
else
{
return TRUE;
}
}
static void
gtk_list_base_dispose (GObject *object)
{
@ -378,6 +542,115 @@ gtk_list_base_unselect_all (GtkWidget *widget,
gtk_selection_model_unselect_all (selection_model);
}
static gboolean
gtk_list_base_move_cursor_to_start (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkListBase *self = GTK_LIST_BASE (widget);
gboolean select, modify, extend;
if (gtk_list_base_get_n_items (self) == 0)
return TRUE;
g_variant_get (args, "(bbb)", &select, &modify, &extend);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), 0, select, modify, extend);
return TRUE;
}
static gboolean
gtk_list_base_move_cursor_to_end (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkListBase *self = GTK_LIST_BASE (widget);
gboolean select, modify, extend;
guint n_items;
n_items = gtk_list_base_get_n_items (self);
if (n_items == 0)
return TRUE;
g_variant_get (args, "(bbb)", &select, &modify, &extend);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), n_items - 1, select, modify, extend);
return TRUE;
}
static gboolean
gtk_list_base_move_cursor (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkListBase *self = GTK_LIST_BASE (widget);
int amount;
guint orientation;
guint pos;
gboolean select, modify, extend;
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
pos = gtk_list_base_get_focus_position (self);
pos = gtk_list_base_move_focus (self, pos, orientation, amount);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, select, modify, extend);
return TRUE;
}
static void
gtk_list_base_add_move_binding (GtkWidgetClass *widget_class,
guint keyval,
GtkOrientation orientation,
int amount)
{
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK,
gtk_list_base_move_cursor,
"(ubbbi)", orientation, FALSE, FALSE, FALSE, amount);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_SHIFT_MASK,
gtk_list_base_move_cursor,
"(ubbbi)", orientation, TRUE, FALSE, TRUE, amount);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
gtk_list_base_move_cursor,
"(ubbbi)", orientation, TRUE, TRUE, TRUE, amount);
}
static void
gtk_list_base_add_custom_move_binding (GtkWidgetClass *widget_class,
guint keyval,
GtkShortcutFunc callback)
{
gtk_widget_class_add_binding (widget_class,
keyval,
0,
callback,
"(bbb)", TRUE, FALSE, FALSE);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK,
callback,
"(bbb)", FALSE, FALSE, FALSE);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_SHIFT_MASK,
callback,
"(bbb)", TRUE, FALSE, TRUE);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
callback,
"(bbb)", TRUE, TRUE, TRUE);
}
static void
gtk_list_base_class_init (GtkListBaseClass *klass)
{
@ -385,6 +658,8 @@ gtk_list_base_class_init (GtkListBaseClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gpointer iface;
widget_class->focus = gtk_list_base_focus;
gobject_class->dispose = gtk_list_base_dispose;
gobject_class->get_property = gtk_list_base_get_property;
gobject_class->set_property = gtk_list_base_set_property;
@ -465,6 +740,24 @@ gtk_list_base_class_init (GtkListBaseClass *klass)
NULL,
gtk_list_base_unselect_all);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_Up, GTK_ORIENTATION_VERTICAL, -1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_KP_Up, GTK_ORIENTATION_VERTICAL, -1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_Down, GTK_ORIENTATION_VERTICAL, 1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_KP_Down, GTK_ORIENTATION_VERTICAL, 1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_Left, GTK_ORIENTATION_HORIZONTAL, -1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_KP_Left, GTK_ORIENTATION_HORIZONTAL, -1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_Right, GTK_ORIENTATION_HORIZONTAL, 1);
gtk_list_base_add_move_binding (widget_class, GDK_KEY_KP_Right, GTK_ORIENTATION_HORIZONTAL, 1);
gtk_list_base_add_custom_move_binding (widget_class, GDK_KEY_Home, gtk_list_base_move_cursor_to_start);
gtk_list_base_add_custom_move_binding (widget_class, GDK_KEY_KP_Home, gtk_list_base_move_cursor_to_start);
gtk_list_base_add_custom_move_binding (widget_class, GDK_KEY_End, gtk_list_base_move_cursor_to_end);
gtk_list_base_add_custom_move_binding (widget_class, GDK_KEY_KP_End, gtk_list_base_move_cursor_to_end);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_a, GDK_CONTROL_MASK, "list.select-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_slash, GDK_CONTROL_MASK, "list.select-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "list.unselect-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_backslash, GDK_CONTROL_MASK, "list.unselect-all", NULL);
}
static void

View File

@ -41,10 +41,17 @@ struct _GtkListBaseClass
void (* adjustment_value_changed) (GtkListBase *self,
GtkOrientation orientation);
guint (* move_focus_along) (GtkListBase *self,
guint pos,
int steps);
guint (* move_focus_across) (GtkListBase *self,
guint pos,
int steps);
};
GtkOrientation gtk_list_base_get_orientation (GtkListBase *self);
#define gtk_list_base_get_opposite_orientation(self) OPPOSITE_ORIENTATION(gtk_list_base_get_orientation(self))
guint gtk_list_base_get_focus_position (GtkListBase *self);
GtkListItemManager * gtk_list_base_get_manager (GtkListBase *self);
GtkScrollablePolicy gtk_list_base_get_scroll_policy (GtkListBase *self,
GtkOrientation orientation);

View File

@ -392,6 +392,32 @@ gtk_list_view_adjustment_value_changed (GtkListBase *base,
gtk_widget_queue_allocate (GTK_WIDGET (self));
}
static guint
gtk_list_view_move_focus_along (GtkListBase *base,
guint pos,
int steps)
{
GtkListView *self = GTK_LIST_VIEW (base);
if (steps < 0)
return pos - MIN (pos, -steps);
else
{
guint n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
pos += MIN (n_items - pos - 1, steps);
}
return pos;
}
static guint
gtk_list_view_move_focus_across (GtkListBase *base,
guint pos,
int steps)
{
return pos;
}
static int
gtk_list_view_update_adjustments (GtkListView *self,
GtkOrientation orientation)
@ -688,66 +714,6 @@ gtk_list_view_size_allocate (GtkWidget *widget,
}
}
static gboolean
gtk_list_view_focus (GtkWidget *widget,
GtkDirectionType direction)
{
GtkListView *self = GTK_LIST_VIEW (widget);
GtkWidget *old_focus_child, *new_focus_child;
old_focus_child = gtk_widget_get_focus_child (widget);
if (old_focus_child == NULL &&
(direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD))
{
ListRow *row;
guint pos;
/* When tabbing into the listview, don't focus the first/last item,
* but keep the previously focused item
*/
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
row = gtk_list_item_manager_get_nth (self->item_manager, pos, NULL);
if (row && gtk_widget_grab_focus (row->parent.widget))
goto moved_focus;
}
if (!GTK_WIDGET_CLASS (gtk_list_view_parent_class)->focus (widget, direction))
return FALSE;
moved_focus:
new_focus_child = gtk_widget_get_focus_child (widget);
if (old_focus_child != new_focus_child &&
GTK_IS_LIST_ITEM (new_focus_child))
{
gboolean extend = FALSE, modify = FALSE;
if (old_focus_child)
{
GdkSeat *seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
if (seat)
{
GdkDevice *keyboard = gdk_seat_get_keyboard (seat);
if (keyboard)
{
GdkModifierType state = gdk_device_get_modifier_state (keyboard);
extend = (state & GDK_SHIFT_MASK) != 0;
modify = (state & GDK_CONTROL_MASK) != 0;
}
}
}
gtk_list_base_select_item (GTK_LIST_BASE (self),
gtk_list_item_get_position (GTK_LIST_ITEM (new_focus_child)),
modify,
extend);
}
return TRUE;
}
static void
gtk_list_view_dispose (GObject *object)
{
@ -965,82 +931,6 @@ gtk_list_view_activate_item (GtkWidget *widget,
g_signal_emit (widget, signals[ACTIVATE], 0, pos);
}
static gboolean
gtk_list_view_move_cursor (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkListView *self = GTK_LIST_VIEW (widget);
int amount;
guint orientation;
guint pos, new_pos, n_items;
gboolean select, modify, extend;
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
if (gtk_list_base_get_orientation (GTK_LIST_BASE (self)) != orientation)
return TRUE;
if (orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
amount = -amount;
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
if (pos >= n_items)
return TRUE;
new_pos = pos + amount;
/* This overflow check only works reliably for amount == 1 */
if (new_pos >= n_items)
return TRUE;
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), new_pos, select, modify, extend);
return TRUE;
}
static gboolean
gtk_list_view_move_cursor_to_start (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkListView *self = GTK_LIST_VIEW (widget);
gboolean select, modify, extend;
if (self->model == NULL || g_list_model_get_n_items (self->model) == 0)
return TRUE;
g_variant_get (args, "(bbb)", &select, &modify, &extend);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), 0, select, modify, extend);
return TRUE;
}
static gboolean
gtk_list_view_move_cursor_to_end (GtkWidget *widget,
GVariant *args,
gpointer unused)
{
GtkListView *self = GTK_LIST_VIEW (widget);
gboolean select, modify, extend;
guint n_items;
if (self->model == NULL)
return TRUE;
n_items = g_list_model_get_n_items (self->model);
if (n_items == 0)
return TRUE;
g_variant_get (args, "(bbb)", &select, &modify, &extend);
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), n_items - 1, select, modify, extend);
return TRUE;
}
static gboolean
gtk_list_view_move_cursor_page_up (GtkWidget *widget,
GVariant *args,
@ -1153,29 +1043,6 @@ gtk_list_view_add_custom_move_binding (GtkWidgetClass *widget_class,
"(bbb)", TRUE, TRUE, TRUE);
}
static void
gtk_list_view_add_move_binding (GtkWidgetClass *widget_class,
guint keyval,
GtkOrientation orientation,
int amount)
{
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK,
gtk_list_view_move_cursor,
"(ubbbi)", orientation, FALSE, FALSE, FALSE, amount);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_SHIFT_MASK,
gtk_list_view_move_cursor,
"(ubbbi)", orientation, TRUE, FALSE, TRUE, amount);
gtk_widget_class_add_binding (widget_class,
keyval,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
gtk_list_view_move_cursor,
"(ubbbi)", orientation, TRUE, TRUE, TRUE, amount);
}
static void
gtk_list_view_class_init (GtkListViewClass *klass)
{
@ -1188,10 +1055,11 @@ gtk_list_view_class_init (GtkListViewClass *klass)
list_base_class->list_item_augment_size = sizeof (ListRowAugment);
list_base_class->list_item_augment_func = list_row_augment;
list_base_class->adjustment_value_changed = gtk_list_view_adjustment_value_changed;
list_base_class->move_focus_along = gtk_list_view_move_focus_along;
list_base_class->move_focus_across = gtk_list_view_move_focus_across;
widget_class->measure = gtk_list_view_measure;
widget_class->size_allocate = gtk_list_view_size_allocate;
widget_class->focus = gtk_list_view_focus;
gobject_class->dispose = gtk_list_view_dispose;
gobject_class->get_property = gtk_list_view_get_property;
@ -1283,30 +1151,11 @@ gtk_list_view_class_init (GtkListViewClass *klass)
"u",
gtk_list_view_scroll_to_item);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_Up, GTK_ORIENTATION_VERTICAL, -1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_KP_Up, GTK_ORIENTATION_VERTICAL, -1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_Down, GTK_ORIENTATION_VERTICAL, 1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_KP_Down, GTK_ORIENTATION_VERTICAL, 1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_Left, GTK_ORIENTATION_HORIZONTAL, -1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_KP_Left, GTK_ORIENTATION_HORIZONTAL, -1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_Right, GTK_ORIENTATION_HORIZONTAL, 1);
gtk_list_view_add_move_binding (widget_class, GDK_KEY_KP_Right, GTK_ORIENTATION_HORIZONTAL, 1);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_Home, gtk_list_view_move_cursor_to_start);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_KP_Home, gtk_list_view_move_cursor_to_start);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_End, gtk_list_view_move_cursor_to_end);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_KP_End, gtk_list_view_move_cursor_to_end);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_Page_Up, gtk_list_view_move_cursor_page_up);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_KP_Page_Up, gtk_list_view_move_cursor_page_up);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_Page_Down, gtk_list_view_move_cursor_page_down);
gtk_list_view_add_custom_move_binding (widget_class, GDK_KEY_KP_Page_Down, gtk_list_view_move_cursor_page_down);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_a, GDK_CONTROL_MASK, "list.select-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_slash, GDK_CONTROL_MASK, "list.select-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "list.unselect-all", NULL);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_backslash, GDK_CONTROL_MASK, "list.unselect-all", NULL);
gtk_widget_class_set_css_name (widget_class, I_("list"));
}