forked from AuroraMiddleware/gtk
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:
parent
dd5e6d47db
commit
12331e3376
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user