From 7f61c15040187bb391e4559569440b9f2c6e9c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 6 Mar 2026 11:30:59 -0800 Subject: [PATCH 1/8] GridView: use carousel as source of truth for page pos --- src/SlingshotView.vala | 10 ++-- src/Views/GridView.vala | 108 +++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 68 deletions(-) diff --git a/src/SlingshotView.vala b/src/SlingshotView.vala index 0c3d4ce5..094351cd 100644 --- a/src/SlingshotView.vala +++ b/src/SlingshotView.vala @@ -264,9 +264,9 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { var key = Gdk.keyval_name (keyval).replace ("KP_", ""); int page = int.parse (key); if (page < 0 || page == 9) { - grid_view.go_to_last (); + grid_view.last_page (); } else { - grid_view.go_to_number (page); + grid_view.set_page (page - 1); } } @@ -277,7 +277,7 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { switch (keyval) { case Gdk.Key.Page_Up: if (modality == Modality.NORMAL_VIEW) { - grid_view.go_to_previous (); + grid_view.previous_page (); } else if (modality == Modality.CATEGORY_VIEW) { category_view.page_up (); } @@ -285,7 +285,7 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { case Gdk.Key.Page_Down: if (modality == Modality.NORMAL_VIEW) { - grid_view.go_to_next (); + grid_view.next_page (); } else if (modality == Modality.CATEGORY_VIEW) { category_view.page_down (); } @@ -293,7 +293,7 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { case Gdk.Key.End: if (modality == Modality.NORMAL_VIEW) { - grid_view.go_to_last (); + grid_view.last_page (); } break; diff --git a/src/Views/GridView.vala b/src/Views/GridView.vala index 5391f36d..7776f85a 100644 --- a/src/Views/GridView.vala +++ b/src/Views/GridView.vala @@ -24,8 +24,6 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { public uint columns; } - private Gtk.Grid current_grid; - private Gee.HashMap grids; private Hdy.Carousel paginator; private Page page; @@ -63,26 +61,6 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { } } - private uint _current_grid_key = 0; - public uint current_grid_key { - get { - return _current_grid_key; - } - - set { - // Clamp to valid values for keyboard navigation - _current_grid_key = value.clamp (1, paginator.n_pages); - var grid = grids.@get (_current_grid_key); - if (grid == null) { - return; - } - - paginator.scroll_to (grid); - current_grid = grid; - refocus (); - } - } - construct { page.rows = 3; page.columns = 5; @@ -101,8 +79,6 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { add (paginator); add (page_switcher); - grids = new Gee.HashMap (null, null); - can_focus = true; focus_in_event.connect_after (() => { refocus (); @@ -111,17 +87,18 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { key_controller = new Gtk.EventControllerKey (this); key_controller.key_pressed.connect (on_key_press); + + paginator.page_changed.connect ((index) => { + refocus (); + }); } public void populate (Backend.AppSystem app_system) { - foreach (Gtk.Grid grid in grids.values) { - grid.destroy (); + foreach (Gtk.Widget child in paginator.get_children ()) { + child.destroy (); } - grids.clear (); - _current_grid_key = 0; // Avoids clamp - add_new_grid (); // Increments current_grid_key to 1 - + var grid = add_new_grid (); // Where to insert new app button var next_row_index = 0; var next_col_index = 0; @@ -136,22 +113,22 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { } if (next_row_index == page.rows) { - add_new_grid (); + grid = add_new_grid (); next_row_index = 0; next_col_index = 0; } - current_grid.attach (app_button, (int)next_col_index, (int)next_row_index); + grid.attach (app_button, (int)next_col_index, (int)next_row_index); next_col_index++; } show_all (); // Show first page after populating the carousel - current_grid_key = 1; + set_page (0); } - private void add_new_grid () { - current_grid = new Gtk.Grid () { + private Gtk.Grid add_new_grid () { + var grid = new Gtk.Grid () { expand = true, row_homogeneous = true, column_homogeneous = true, @@ -164,13 +141,12 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { // Fake grids in case there are not enough apps to fill the grid for (var row = 0; row < page.rows; row++) { for (var column = 0; column < page.columns; column++) { - current_grid.attach (new Gtk.Grid (), column, row, 1, 1); + grid.attach (new Gtk.Grid (), column, row, 1, 1); } } - paginator.add (current_grid); - current_grid_key = current_grid_key + 1; - grids.set (current_grid_key, current_grid); + paginator.add (grid); + return grid; } @@ -178,7 +154,8 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { if (col < 1 || col > page.columns || row < 1 || row > page.rows) { return null; } else { - return current_grid.get_child_at ((int)col - 1, (int)row - 1); + var grid = (Gtk.Grid) paginator.get_children ().nth_data ((int) paginator.get_position ()); + return grid.get_child_at ((int) col - 1, (int) row - 1); } } @@ -188,27 +165,11 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { focused_column = focused_column; } - public void go_to_next () { - current_grid_key++; - } - - public void go_to_previous () { - current_grid_key--; - } - - public void go_to_last () { - current_grid_key = paginator.n_pages; - } - - public void go_to_number (int number) { - current_grid_key = number; - } - private bool on_key_press (uint keyval, uint keycode, Gdk.ModifierType state) { switch (keyval) { case Gdk.Key.Home: case Gdk.Key.KP_Home: - current_grid_key = 1; + set_page (0); return Gdk.EVENT_STOP; case Gdk.Key.Left: @@ -251,9 +212,9 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { private void move_left (Gdk.ModifierType state) { if ((state & Gdk.ModifierType.SHIFT_MASK) > 0) { - current_grid_key--; - } else if (focused_column == 1 && current_grid_key > 1) { - current_grid_key--; + previous_page (); + } else if (focused_column == 1 && paginator.get_position () > 0) { + previous_page (); focused_column = page.columns; } else { focused_column--; @@ -262,12 +223,33 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { private void move_right (Gdk.ModifierType state) { if ((state & Gdk.ModifierType.SHIFT_MASK) > 0) { - current_grid_key++; - } else if (focused_column == page.columns && current_grid_key < paginator.n_pages) { - current_grid_key++; + next_page (); + } else if (focused_column == page.columns && paginator.get_position () < paginator.n_pages - 1) { + next_page (); focused_column = 1; } else { focused_column++; } } + + public void next_page () { + set_page ((int) paginator.get_position () + 1); + } + + public void previous_page () { + set_page ((int) paginator.get_position () - 1); + } + + public void last_page () { + set_page (paginator.n_pages); + } + + public void set_page (uint pos) { + var grid = paginator.get_children ().nth_data (pos); + if (grid == null) { + return; + } + + paginator.scroll_to (grid); + } } From cff626e6c8f13e2893e1657ccf51418eb19cbc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Sat, 7 Mar 2026 07:15:38 -0800 Subject: [PATCH 2/8] Update GridView.vala Co-authored-by: Leonhard --- src/Views/GridView.vala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Views/GridView.vala b/src/Views/GridView.vala index 7776f85a..1973cb5a 100644 --- a/src/Views/GridView.vala +++ b/src/Views/GridView.vala @@ -88,9 +88,7 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { key_controller = new Gtk.EventControllerKey (this); key_controller.key_pressed.connect (on_key_press); - paginator.page_changed.connect ((index) => { - refocus (); - }); + paginator.page_changed.connect (refocus); } public void populate (Backend.AppSystem app_system) { From d066b28752e307ef56b9a8a4cd99dbcb08b92f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Sat, 7 Mar 2026 07:15:48 -0800 Subject: [PATCH 3/8] Update GridView.vala Co-authored-by: Leonhard --- src/Views/GridView.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/GridView.vala b/src/Views/GridView.vala index 1973cb5a..8e09dc18 100644 --- a/src/Views/GridView.vala +++ b/src/Views/GridView.vala @@ -92,7 +92,7 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { } public void populate (Backend.AppSystem app_system) { - foreach (Gtk.Widget child in paginator.get_children ()) { + foreach (var child in paginator.get_children ()) { child.destroy (); } From 320104523cb7ec8a5b8fc4ca0f49fd390ed2de2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Sat, 7 Mar 2026 07:16:07 -0800 Subject: [PATCH 4/8] Update GridView.vala Co-authored-by: Leonhard --- src/Views/GridView.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/GridView.vala b/src/Views/GridView.vala index 8e09dc18..1f530828 100644 --- a/src/Views/GridView.vala +++ b/src/Views/GridView.vala @@ -93,7 +93,7 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { public void populate (Backend.AppSystem app_system) { foreach (var child in paginator.get_children ()) { - child.destroy (); + paginator.remove (child); } var grid = add_new_grid (); From f99a3bc2682998c7992ac39e18c06a43e67b7446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Sun, 8 Mar 2026 09:04:35 -0700 Subject: [PATCH 5/8] revert one more --- src/Views/GridView.vala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Views/GridView.vala b/src/Views/GridView.vala index aac12ced..59e463d6 100644 --- a/src/Views/GridView.vala +++ b/src/Views/GridView.vala @@ -77,8 +77,6 @@ public class Slingshot.Widgets.Grid : Gtk.Box { key_controller = new Gtk.EventControllerKey (this); key_controller.key_pressed.connect (on_key_press); - - paginator.page_changed.connect (refocus); } public void populate (Backend.AppSystem app_system) { @@ -240,5 +238,6 @@ public class Slingshot.Widgets.Grid : Gtk.Box { } paginator.scroll_to (grid); + refocus (); } } From 4cd701b9c866aee1c8eefbeeb5d1a89e7aaa88a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Mon, 9 Mar 2026 10:29:10 -0700 Subject: [PATCH 6/8] Explicitly define first and last shortcuts --- src/SlingshotView.vala | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/SlingshotView.vala b/src/SlingshotView.vala index 094351cd..7a049642 100644 --- a/src/SlingshotView.vala +++ b/src/SlingshotView.vala @@ -251,6 +251,21 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { return Gdk.EVENT_STOP; case Gdk.Key.@0: + if (modality == Modality.NORMAL_VIEW) { + grid_view.set_page (0); + return Gdk.EVENT_STOP; + } + + return Gdk.EVENT_PROPAGATE; + + case Gdk.Key.@9: + if (modality == Modality.NORMAL_VIEW) { + grid_view.last_page (); + return Gdk.EVENT_STOP; + } + + return Gdk.EVENT_PROPAGATE; + case Gdk.Key.@1: case Gdk.Key.@2: case Gdk.Key.@3: @@ -259,15 +274,9 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { case Gdk.Key.@6: case Gdk.Key.@7: case Gdk.Key.@8: - case Gdk.Key.@9: if (modality == Modality.NORMAL_VIEW) { var key = Gdk.keyval_name (keyval).replace ("KP_", ""); - int page = int.parse (key); - if (page < 0 || page == 9) { - grid_view.last_page (); - } else { - grid_view.set_page (page - 1); - } + grid_view.set_page (int.parse (key) - 1); } return Gdk.EVENT_STOP; From 0ba687b3bc9a1427c362fce874405da4efda2061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Mon, 9 Mar 2026 10:31:52 -0700 Subject: [PATCH 7/8] Better conditional --- src/SlingshotView.vala | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/SlingshotView.vala b/src/SlingshotView.vala index 7a049642..b30c3b02 100644 --- a/src/SlingshotView.vala +++ b/src/SlingshotView.vala @@ -243,43 +243,42 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { return Gdk.EVENT_STOP; } } + // Alt accelerators if ((state & Gdk.ModifierType.MOD1_MASK) != 0) { switch (keyval) { case Gdk.Key.F4: close_indicator (); return Gdk.EVENT_STOP; + } - case Gdk.Key.@0: - if (modality == Modality.NORMAL_VIEW) { - grid_view.set_page (0); + if (modality == NORMAL_VIEW) { + switch (keyval) { + case Gdk.Key.F4: + close_indicator (); return Gdk.EVENT_STOP; - } - return Gdk.EVENT_PROPAGATE; + case Gdk.Key.@0: + grid_view.set_page (0); + return Gdk.EVENT_STOP; - case Gdk.Key.@9: - if (modality == Modality.NORMAL_VIEW) { + case Gdk.Key.@9: grid_view.last_page (); return Gdk.EVENT_STOP; - } - - return Gdk.EVENT_PROPAGATE; - case Gdk.Key.@1: - case Gdk.Key.@2: - case Gdk.Key.@3: - case Gdk.Key.@4: - case Gdk.Key.@5: - case Gdk.Key.@6: - case Gdk.Key.@7: - case Gdk.Key.@8: - if (modality == Modality.NORMAL_VIEW) { + case Gdk.Key.@1: + case Gdk.Key.@2: + case Gdk.Key.@3: + case Gdk.Key.@4: + case Gdk.Key.@5: + case Gdk.Key.@6: + case Gdk.Key.@7: + case Gdk.Key.@8: var key = Gdk.keyval_name (keyval).replace ("KP_", ""); grid_view.set_page (int.parse (key) - 1); - } - return Gdk.EVENT_STOP; + return Gdk.EVENT_STOP; + } } } From 4b85b80c24aaab279232614ccb0c9daff4e464b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Mon, 9 Mar 2026 10:36:28 -0700 Subject: [PATCH 8/8] Remove duplicate --- src/SlingshotView.vala | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/SlingshotView.vala b/src/SlingshotView.vala index b30c3b02..af478343 100644 --- a/src/SlingshotView.vala +++ b/src/SlingshotView.vala @@ -254,10 +254,6 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { if (modality == NORMAL_VIEW) { switch (keyval) { - case Gdk.Key.F4: - close_indicator (); - return Gdk.EVENT_STOP; - case Gdk.Key.@0: grid_view.set_page (0); return Gdk.EVENT_STOP;