diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 8147fab7..9e42554e 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -24,7 +24,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y libadwaita-1-dev libgee-0.8-dev libgranite-dev libgtk-3-dev libhandy-1-dev libjson-glib-dev libswitchboard-3-dev libwingpanel-dev libzeitgeist-2.0-dev meson valac bc + apt install -y libadwaita-1-dev libgee-0.8-dev libgranite-7-dev libgtk-4-dev libjson-glib-dev libswitchboard-3-dev libwingpanel-8-dev libzeitgeist-2.0-dev meson valac bc - name: Build env: DESTDIR: out diff --git a/README.md b/README.md index ed23d9b2..9be83ca2 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ Lightweight and stylish app launcher. You'll need the following dependencies: * bc * gettext +* libadwaita-1-dev * libgee-0.8-dev -* libgranite-dev >= 6.1.0 -* libgtk-3-dev -* libhandy-1-dev >= 0.83.0 +* libgranite-7-dev >= 7.6.0 +* libgtk-4-dev * libjson-glib-dev * libswitchboard-3-dev -* libwingpanel-dev +* libwingpanel-8-dev * libzeitgeist-2.0-dev * meson * pkg-config diff --git a/meson.build b/meson.build index 82683106..dd492446 100644 --- a/meson.build +++ b/meson.build @@ -37,14 +37,14 @@ add_project_arguments( glib_dep = dependency('glib-2.0') gee_dep = dependency('gee-0.8') gio_dep = dependency('gio-2.0') -gtk_dep = dependency('gtk+-3.0') -granite_dep = dependency('granite', version: '>=6.1.0') +gtk_dep = dependency('gtk4') +granite_dep = dependency('granite-7', version: '>=6.1.0') gobject_dep = dependency('gobject-2.0') gio_unix_dep = dependency('gio-unix-2.0') json_glib_dep = dependency('json-glib-1.0') switchboard_dep = dependency('switchboard-3') -libhandy_dep = dependency('libhandy-1', version: '>= 0.83.0') -wingpanel_dep = dependency('wingpanel', version: '>=2.1.0') +libhandy_dep = dependency('libadwaita-1', version: '>= 0.83.0') +wingpanel_dep = dependency('wingpanel-8', version: '>=2.1.0') posix_dep = meson.get_compiler('vala').find_library('posix') zeitgeist_dep = [] diff --git a/src/Backend/App.vala b/src/Backend/App.vala index 32dc7888..cfc07040 100644 --- a/src/Backend/App.vala +++ b/src/Backend/App.vala @@ -28,7 +28,7 @@ public class Slingshot.Backend.App : Object { SYNAPSE } - public const string ACTION_GROUP_PREFIX = "app-actions"; + private const string ACTION_GROUP_PREFIX = "app-actions"; private const string ACTION_PREFIX = ACTION_GROUP_PREFIX + "."; private const string APP_ACTION = "action.%s"; private const string PINNED_ACTION = "pinned"; @@ -36,7 +36,6 @@ public class Slingshot.Backend.App : Object { private const string UNINSTALL_ACTION = "uninstall"; private const string VIEW_ACTION = "view-in-appcenter"; - public SimpleActionGroup action_group { get; private set; } public string name { get; construct set; } public string description { get; private set; default = ""; } public string desktop_id { get; construct set; } @@ -142,7 +141,7 @@ public class Slingshot.Backend.App : Object { launched (this); // Emit launched signal var context = Gdk.Display.get_default ().get_app_launch_context (); - context.set_timestamp (Gtk.get_current_event_time ()); + context.set_timestamp (Gdk.CURRENT_TIME); switcheroo_control.apply_gpu_environment (context, prefers_default_gpu); new DesktopAppInfo (desktop_id).launch (null, context); @@ -197,11 +196,11 @@ public class Slingshot.Backend.App : Object { } } - public GLib.Menu get_menu_model () { + public Gtk.PopoverMenu get_context_menu (Gtk.Widget parent) { var actions_section = new GLib.Menu (); var shell_section = new GLib.Menu (); - action_group = new SimpleActionGroup (); + var action_group = new SimpleActionGroup (); var app_info = new DesktopAppInfo (desktop_id); foreach (unowned var action in app_info.list_actions ()) { @@ -300,7 +299,13 @@ public class Slingshot.Backend.App : Object { model.append_section (null, actions_section); model.append_section (null, shell_section); - return model; + var context_menu = new Gtk.PopoverMenu.from_model (model) { + has_arrow = false + }; + context_menu.insert_action_group (ACTION_GROUP_PREFIX, action_group); + context_menu.set_parent (parent); + + return context_menu; } private void action_uninstall () { diff --git a/src/Indicator.vala b/src/Indicator.vala index 4aa2843f..fb918ad7 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -45,7 +45,7 @@ public class Slingshot.Indicator : Wingpanel.Indicator { Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_default (); + weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); default_theme.add_resource_path ("/io/elementary/desktop/wingpanel/applications-menu/icons"); } @@ -75,7 +75,7 @@ public class Slingshot.Indicator : Wingpanel.Indicator { var indicator_label = new Gtk.Label (_("Applications")); indicator_label.vexpand = true; - var indicator_icon = new Gtk.Image.from_icon_name ("system-search-symbolic", Gtk.IconSize.MENU); + var indicator_icon = new Gtk.Image.from_icon_name ("system-search-symbolic"); indicator_grid = new Gtk.Grid (); indicator_grid.attach (indicator_icon, 0, 0, 1, 1); diff --git a/src/SlingshotView.vala b/src/SlingshotView.vala index 0c3d4ce5..01d7fbd3 100644 --- a/src/SlingshotView.vala +++ b/src/SlingshotView.vala @@ -4,7 +4,7 @@ * 2011-2012 Giulio Collura */ -public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { +public class Slingshot.SlingshotView : Granite.Bin, UnityClient { public signal void close_indicator (); public Backend.AppSystem app_system; @@ -25,8 +25,6 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { private Widgets.Grid grid_view; private Widgets.SearchView search_view; private Widgets.CategoryView category_view; - private Gtk.EventControllerKey key_controller; - private Gtk.EventControllerKey search_key_controller; private static GLib.Settings settings { get; private set; default = null; } @@ -41,27 +39,28 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { var grid_view_btn = new Gtk.ToggleButton () { action_name = "view.view-mode", action_target = new Variant.string ("grid"), - image = new Gtk.Image.from_icon_name ("view-grid-symbolic", BUTTON), + icon_name = "view-grid-symbolic", tooltip_markup = Granite.markup_accel_tooltip ({"1"}, _("View as Grid")) }; var category_view_btn = new Gtk.ToggleButton () { action_name = "view.view-mode", action_target = new Variant.string ("category"), - image = new Gtk.Image.from_icon_name ("view-filter-symbolic", BUTTON), + icon_name = "view-filter-symbolic", tooltip_markup = Granite.markup_accel_tooltip ({"2"}, _("View by Category")) }; var view_selector = new Gtk.Box (HORIZONTAL, 0) { margin_end = 12 }; - view_selector.add (grid_view_btn); - view_selector.add (category_view_btn); - view_selector.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); + view_selector.append (grid_view_btn); + view_selector.append (category_view_btn); + view_selector.add_css_class (Granite.STYLE_CLASS_LINKED); view_selector_revealer = new Gtk.Revealer () { child = view_selector, - transition_type = SLIDE_RIGHT + transition_type = SLIDE_RIGHT, + overflow = VISIBLE }; search_entry = new Gtk.SearchEntry () { @@ -73,8 +72,8 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { margin_start = 12, margin_end = 12 }; - top_box.add (view_selector_revealer); - top_box.add (search_entry); + top_box.append (view_selector_revealer); + top_box.append (search_entry); grid_view = new Widgets.Grid (); @@ -93,8 +92,8 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { var container = new Gtk.Box (VERTICAL, 12) { margin_top = 12 }; - container.add (top_box); - container.add (stack); + container.append (top_box); + container.append (stack); // This function must be after creating the page switcher grid_view.populate (app_system); @@ -116,22 +115,18 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { search.begin (search_entry.text, match, target); }); - key_press_event.connect ((event) => { - var search_handles_event = search_entry.handle_event (event); - if (search_handles_event && !search_entry.has_focus) { - search_entry.grab_focus (); - search_entry.move_cursor (BUFFER_ENDS, 0, false); - } - - return search_handles_event; - }); + search_entry.set_key_capture_widget (this); - key_controller = new Gtk.EventControllerKey (this); + var key_controller = new Gtk.EventControllerKey (); key_controller.key_pressed.connect (on_key_press); - search_key_controller = new Gtk.EventControllerKey (search_entry); + add_controller (key_controller); + + var search_key_controller = new Gtk.EventControllerKey (); search_key_controller.key_pressed.connect (on_search_view_key_press); + search_entry.add_controller (search_key_controller); + // Showing a menu reverts the effect of the grab_device function. search_entry.search_changed.connect (() => { if (modality != Modality.SEARCH_VIEW) { @@ -243,8 +238,8 @@ public class Slingshot.SlingshotView : Gtk.Bin, UnityClient { return Gdk.EVENT_STOP; } } - // Alt accelerators - if ((state & Gdk.ModifierType.MOD1_MASK) != 0) { + + if ((state & Gdk.ModifierType.ALT_MASK) != 0) { switch (keyval) { case Gdk.Key.F4: close_indicator (); diff --git a/src/Utils.vala b/src/Utils.vala new file mode 100644 index 00000000..e64e6b77 --- /dev/null +++ b/src/Utils.vala @@ -0,0 +1,19 @@ +namespace Slingshot.Utils { + public void menu_popup_on_keypress (Gtk.Popover popover) { + popover.halign = END; + popover.set_pointing_to (Gdk.Rectangle () { + x = (int) popover.parent.get_width (), + y = (int) popover.parent.get_height () / 2 + }); + popover.popup (); + } + + public void menu_popup_at_pointer (Gtk.Popover popover, double x, double y) { + var rect = Gdk.Rectangle () { + x = (int) x, + y = (int) y + }; + popover.pointing_to = rect; + popover.popup (); + } +} diff --git a/src/Views/CategoryView.vala b/src/Views/CategoryView.vala index 3e8b2a53..b95d051e 100644 --- a/src/Views/CategoryView.vala +++ b/src/Views/CategoryView.vala @@ -4,24 +4,17 @@ * 2011-2012 Giulio Collura */ -public class Slingshot.Widgets.CategoryView : Gtk.EventBox { +public class Slingshot.Widgets.CategoryView : Granite.Bin { public SlingshotView view { get; construct; } - private string? drag_uri = null; private Gtk.ListBox category_switcher; private Gtk.ListBox listbox; - private const Gtk.TargetEntry DND = { "text/uri-list", 0, 0 }; - private Gtk.GestureMultiPress click_controller; - private Gtk.EventControllerKey listbox_key_controller; - private Gtk.EventControllerKey category_switcher_key_controller; - public CategoryView (SlingshotView view) { Object (view: view); } construct { - set_visible_window (false); hexpand = true; category_switcher = new Gtk.ListBox () { @@ -30,11 +23,11 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { }; category_switcher.set_sort_func ((Gtk.ListBoxSortFunc) category_sort_func); - var scrolled_category = new Gtk.ScrolledWindow (null, null) { + var scrolled_category = new Gtk.ScrolledWindow () { child = category_switcher, hscrollbar_policy = NEVER }; - scrolled_category.get_style_context ().add_class (Gtk.STYLE_CLASS_SIDEBAR); + scrolled_category.add_css_class (Granite.STYLE_CLASS_SIDEBAR); var separator = new Gtk.Separator (VERTICAL); @@ -45,7 +38,7 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { }; listbox.set_filter_func ((Gtk.ListBoxFilterFunc) filter_function); - var listbox_scrolled = new Gtk.ScrolledWindow (null, null) { + var listbox_scrolled = new Gtk.ScrolledWindow () { child = listbox, hscrollbar_policy = NEVER }; @@ -53,9 +46,8 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { var container = new Gtk.Box (HORIZONTAL, 0) { hexpand = true }; - container.add (scrolled_category); - container.add (separator); - container.add (listbox_scrolled); + container.append (scrolled_category); + container.append (listbox_scrolled); child = container; @@ -76,7 +68,7 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { }); }); - click_controller = new Gtk.GestureMultiPress (listbox) { + var click_controller = new Gtk.GestureClick () { button = 0, exclusive = true }; @@ -85,14 +77,17 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { var event = click_controller.get_last_event (sequence); if (event.triggers_context_menu ()) { - create_context_menu ().popup_at_pointer (); + var context_menu = ((AppListRow) listbox.get_row_at_y ((int) y)).app.get_context_menu (this); + context_menu.halign = START; + + Utils.menu_popup_at_pointer (context_menu, x, y); click_controller.set_state (CLAIMED); click_controller.reset (); } }); - listbox_key_controller = new Gtk.EventControllerKey (listbox); + var listbox_key_controller = new Gtk.EventControllerKey (); listbox_key_controller.key_pressed.connect (on_key_press); listbox_key_controller.key_released.connect ((keyval, keycode, state) => { var mods = state & Gtk.accelerator_get_default_mod_mask (); @@ -100,50 +95,54 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { case Gdk.Key.F10: if (mods == Gdk.ModifierType.SHIFT_MASK) { var selected_row = (AppListRow) listbox.get_selected_row (); - create_context_menu ().popup_at_widget (selected_row , EAST, CENTER); + Utils.menu_popup_on_keypress (selected_row.app.get_context_menu (selected_row)); } break; case Gdk.Key.Menu: case Gdk.Key.MenuKB: var selected_row = (AppListRow) listbox.get_selected_row (); - create_context_menu ().popup_at_widget (selected_row, EAST, CENTER); + Utils.menu_popup_on_keypress (selected_row.app.get_context_menu (selected_row)); break; default: return; } }); - category_switcher_key_controller = new Gtk.EventControllerKey (category_switcher); - category_switcher_key_controller.key_pressed.connect (on_key_press); - - Gtk.drag_source_set (listbox, Gdk.ModifierType.BUTTON1_MASK, {DND}, Gdk.DragAction.COPY); - - listbox.drag_begin.connect ((ctx) => { - unowned Gtk.ListBoxRow? selected_row = listbox.get_selected_row (); - if (selected_row != null) { - var drag_item = (AppListRow) selected_row; - drag_uri = "file://" + drag_item.desktop_path; - if (drag_uri != null) { - Gtk.drag_set_icon_gicon (ctx, drag_item.app_info.get_icon (), 32, 32); - } - - view.close_indicator (); + var drag_source = new Gtk.DragSource () { + actions = COPY + }; + drag_source.prepare.connect ((x, y) => { + var drag_item = (AppListRow) listbox.get_row_at_y ((int) y); + if (drag_item == null) { + return null; } + + drag_source.set_icon ( + Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).lookup_by_gicon ( + drag_item.app_info.get_icon (), + 32, + scale_factor, + get_direction (), + PRELOAD + ), 0, 0 + ); + + return new Gdk.ContentProvider.union ({ + new Gdk.ContentProvider.for_value ("file://" + drag_item.desktop_path) + }); + }); + drag_source.drag_begin.connect ((drag_source, drag) => { + view.close_indicator (); }); - listbox.drag_end.connect (() => { - if (drag_uri != null) { - view.close_indicator (); - } + listbox.add_controller (click_controller); + listbox.add_controller (drag_source); + listbox.add_controller (listbox_key_controller); - drag_uri = null; - }); + var category_switcher_key_controller = new Gtk.EventControllerKey (); + category_switcher_key_controller.key_pressed.connect (on_key_press); - listbox.drag_data_get.connect ((ctx, sel, info, time) => { - if (drag_uri != null) { - sel.set_uris ({drag_uri}); - } - }); + category_switcher.add_controller (category_switcher_key_controller); setup_sidebar (); } @@ -152,22 +151,13 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { return row1.cat_name.collate (row2.cat_name); } - private Gtk.Menu create_context_menu () { - var selected_row = (AppListRow) listbox.get_selected_row (); - - var context_menu = new Gtk.Menu.from_model (selected_row.app.get_menu_model ()); - context_menu.insert_action_group (Backend.App.ACTION_GROUP_PREFIX, selected_row.app.action_group); - - return context_menu; - } - public void page_down () { - category_switcher.move_cursor (Gtk.MovementStep.DISPLAY_LINES, 1); + category_switcher.move_cursor (DISPLAY_LINES, 1, false, true); focus_select_first_row (); } public void page_up () { - category_switcher.move_cursor (Gtk.MovementStep.DISPLAY_LINES, -1); + category_switcher.move_cursor (DISPLAY_LINES, -1, false, true); focus_select_first_row (); } @@ -181,16 +171,13 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { public void setup_sidebar () { CategoryRow? old_selected = (CategoryRow) category_switcher.get_selected_row (); - foreach (unowned Gtk.Widget child in category_switcher.get_children ()) { - child.destroy (); - } - listbox.foreach ((app_list_row) => listbox.remove (app_list_row)); + category_switcher.remove_all (); + listbox.remove_all (); foreach (unowned Backend.App app in view.app_system.get_apps_by_name ()) { - listbox.add (new AppListRow (app)); + listbox.append (new AppListRow (app)); } - listbox.show_all (); // Fill the sidebar unowned Gtk.ListBoxRow? new_selected = null; @@ -200,13 +187,12 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { } var row = new CategoryRow (cat_name); - category_switcher.add (row); + category_switcher.append (row); if (old_selected != null && old_selected.cat_name == cat_name) { new_selected = row; } } - category_switcher.show_all (); category_switcher.select_row (new_selected ?? category_switcher.get_row_at_index (0)); } @@ -235,11 +221,11 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { page_down (); return Gdk.EVENT_STOP; case Gdk.Key.Home: - category_switcher.move_cursor (Gtk.MovementStep.PAGES, -1); + category_switcher.move_cursor (PAGES, -1, false, true); focus_select_first_row (); return Gdk.EVENT_STOP; case Gdk.Key.End: - category_switcher.move_cursor (Gtk.MovementStep.PAGES, 1); + category_switcher.move_cursor (PAGES, 1, false, true); focus_select_first_row (); return Gdk.EVENT_STOP; case Gdk.Key.KP_Up: @@ -262,7 +248,7 @@ public class Slingshot.Widgets.CategoryView : Gtk.EventBox { return Gdk.EVENT_PROPAGATE; } - private void move_cursor (Gtk.ListBox list_box, Gtk.MovementStep step, int count) { + private void move_cursor (Gtk.ListBox list_box, Gtk.MovementStep step, int count, bool extend, bool modify) { unowned var selected = list_box.get_selected_row (); if (step != DISPLAY_LINES || selected == null) { return; diff --git a/src/Views/GridView.vala b/src/Views/GridView.vala index 5391f36d..ae703d53 100644 --- a/src/Views/GridView.vala +++ b/src/Views/GridView.vala @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -public class Slingshot.Widgets.Grid : Gtk.Grid { +public class Slingshot.Widgets.Grid : Gtk.Box { public signal void app_launched (); private struct Page { @@ -26,11 +26,9 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { private Gtk.Grid current_grid; private Gee.HashMap grids; - private Hdy.Carousel paginator; + private Adw.Carousel paginator; private Page page; - private Gtk.EventControllerKey key_controller; - private uint _focused_column = 1; public uint focused_column { set { @@ -77,7 +75,7 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { return; } - paginator.scroll_to (grid); + paginator.scroll_to (grid, true); current_grid = grid; refocus (); } @@ -87,30 +85,34 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { page.rows = 3; page.columns = 5; - paginator = new Hdy.Carousel (); - paginator.expand = true; + paginator = new Adw.Carousel () { + hexpand = true, + vexpand = true + }; var page_switcher = new Widgets.Switcher () { carousel = paginator, halign = CENTER }; - orientation = Gtk.Orientation.VERTICAL; - row_spacing = 24; + orientation = VERTICAL; + spacing = 24; margin_bottom = 12; - add (paginator); - add (page_switcher); + append (paginator); + append (page_switcher); grids = new Gee.HashMap (null, null); can_focus = true; - focus_in_event.connect_after (() => { - refocus (); - return Gdk.EVENT_STOP; - }); + // focus_in_event.connect_after (() => { + // refocus (); + // return Gdk.EVENT_STOP; + // }); - key_controller = new Gtk.EventControllerKey (this); + var key_controller = new Gtk.EventControllerKey (); key_controller.key_pressed.connect (on_key_press); + + add_controller (key_controller); } public void populate (Backend.AppSystem app_system) { @@ -145,14 +147,14 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { next_col_index++; } - show_all (); // Show first page after populating the carousel current_grid_key = 1; } private void add_new_grid () { current_grid = new Gtk.Grid () { - expand = true, + hexpand = true, + vexpand = true, row_homogeneous = true, column_homogeneous = true, margin_start = 12, @@ -168,7 +170,7 @@ public class Slingshot.Widgets.Grid : Gtk.Grid { } } - paginator.add (current_grid); + paginator.append (current_grid); current_grid_key = current_grid_key + 1; grids.set (current_grid_key, current_grid); } diff --git a/src/Views/SearchView.vala b/src/Views/SearchView.vala index db0ed287..03604a55 100644 --- a/src/Views/SearchView.vala +++ b/src/Views/SearchView.vala @@ -68,31 +68,26 @@ public enum Slingshot.Widgets.ResultType { } } -public class Slingshot.Widgets.SearchView : Gtk.Bin { +public class Slingshot.Widgets.SearchView : Granite.Bin { const int MAX_RESULTS = 10; public signal void start_search (Synapse.SearchMatch search_match, Synapse.Match? target); public signal void app_launched (); - private Granite.Widgets.AlertView alert_view; + private Granite.Placeholder alert_view; private Gtk.ListBox list_box; Gee.HashMap limitator; - private string? drag_uri = null; - - private Gtk.GestureMultiPress click_controller; - private Gtk.EventControllerKey menu_key_controller; construct { - alert_view = new Granite.Widgets.AlertView ("", _("Try changing search terms."), "edit-find-symbolic"); - alert_view.show_all (); + alert_view = new Granite.Placeholder ("") { + icon = new ThemedIcon ("edit-find-symbolic"), + description = _("Try changing search terms.") + }; // list box limitator = new Gee.HashMap (); - const Gtk.TargetEntry DND = {"text/uri-list", 0, 0}; - Gtk.drag_source_set (this, Gdk.ModifierType.BUTTON1_MASK, {DND}, Gdk.DragAction.COPY); - list_box = new Gtk.ListBox () { activate_on_single_click = true, selection_mode = BROWSE @@ -101,38 +96,38 @@ public class Slingshot.Widgets.SearchView : Gtk.Bin { list_box.set_header_func ((Gtk.ListBoxUpdateHeaderFunc) update_header); list_box.set_placeholder (alert_view); - var scrolled_window = new Gtk.ScrolledWindow (null, null) { + var scrolled_window = new Gtk.ScrolledWindow () { child = list_box, hscrollbar_policy = NEVER }; child = scrolled_window; - list_box.drag_begin.connect ((ctx) => { - var selected_row = list_box.get_selected_row (); - if (selected_row != null) { - var drag_item = (Slingshot.Widgets.SearchItem) selected_row; - drag_uri = drag_item.app_uri; - if (drag_uri != null) { - Gtk.drag_set_icon_gicon (ctx, drag_item.image.gicon, 32, 32); - } - - app_launched (); - } - }); - - list_box.drag_end.connect (() => { - if (drag_uri != null) { - app_launched (); + var drag_source = new Gtk.DragSource () { + actions = COPY + }; + drag_source.prepare.connect ((x, y) => { + var drag_item = (Slingshot.Widgets.SearchItem) list_box.get_row_at_y ((int) y); + if (drag_item == null) { + return null; } - drag_uri = null; + drag_source.set_icon ( + Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).lookup_by_gicon ( + drag_item.image.gicon, + 32, + scale_factor, + get_direction (), + PRELOAD + ), 0, 0 + ); + + return new Gdk.ContentProvider.union ({ + new Gdk.ContentProvider.for_value (drag_item.app_uri) + }); }); - - list_box.drag_data_get.connect ((ctx, sel, info, time) => { - if (drag_uri != null) { - sel.set_uris ({drag_uri}); - } + drag_source.drag_begin.connect ((drag_source, drag) => { + app_launched (); }); list_box.move_cursor.connect (move_cursor); @@ -160,7 +155,7 @@ public class Slingshot.Widgets.SearchView : Gtk.Bin { }); }); - click_controller = new Gtk.GestureMultiPress (list_box) { + var click_controller = new Gtk.GestureClick () { button = 0, exclusive = true }; @@ -171,14 +166,17 @@ public class Slingshot.Widgets.SearchView : Gtk.Bin { var event = click_controller.get_last_event (sequence); if (event.triggers_context_menu ()) { - search_item.create_context_menu ()?.popup_at_pointer (); + var context_menu = search_item.create_context_menu (); + if (context_menu != null) { + Utils.menu_popup_at_pointer (context_menu, x, y); + } click_controller.set_state (CLAIMED); click_controller.reset (); } }); - menu_key_controller = new Gtk.EventControllerKey (list_box); + var menu_key_controller = new Gtk.EventControllerKey (); menu_key_controller.key_released.connect ((keyval, keycode, state) => { var search_item = (SearchItem) list_box.get_selected_row (); @@ -186,17 +184,27 @@ public class Slingshot.Widgets.SearchView : Gtk.Bin { switch (keyval) { case Gdk.Key.F10: if (mods == Gdk.ModifierType.SHIFT_MASK) { - search_item.create_context_menu ()?.popup_at_widget (this, EAST, CENTER); + var context_menu = search_item.create_context_menu (); + if (context_menu != null) { + Utils.menu_popup_on_keypress (context_menu); + } } break; case Gdk.Key.Menu: case Gdk.Key.MenuKB: - search_item.create_context_menu ()?.popup_at_widget (this, EAST, CENTER); + var context_menu = search_item.create_context_menu (); + if (context_menu != null) { + Utils.menu_popup_on_keypress (context_menu); + } break; default: return; } }); + + list_box.add_controller (click_controller); + list_box.add_controller (drag_source); + list_box.add_controller (menu_key_controller); } private void move_cursor (Gtk.MovementStep step, int count) { @@ -275,15 +283,12 @@ public class Slingshot.Widgets.SearchView : Gtk.Bin { app.launched.connect (() => app_launched ()); - list_box.add (search_item); - search_item.show_all (); + list_box.append (search_item); } public void clear () { limitator.clear (); - list_box.get_children ().foreach ((child) => { - child.destroy (); - }); + list_box.remove_all (); } public void activate_selection () { diff --git a/src/Widgets/AppButton.vala b/src/Widgets/AppButton.vala index 8c1ee6a6..154d9b2b 100644 --- a/src/Widgets/AppButton.vala +++ b/src/Widgets/AppButton.vala @@ -10,26 +10,16 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { public Backend.App app { get; construct; } private const int ICON_SIZE = 64; - private Gtk.Label badge; - private bool dragging = false; //prevent launching - - private Gtk.GestureMultiPress click_controller; - private Gtk.EventControllerKey menu_key_controller; public AppButton (Backend.App app) { Object (app: app); } construct { - Gtk.TargetEntry dnd = {"text/uri-list", 0, 0}; - Gtk.drag_source_set (this, Gdk.ModifierType.BUTTON1_MASK, {dnd}, - Gdk.DragAction.COPY); - + has_frame = false; tooltip_text = app.description; - get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - var app_label = new Gtk.Label (app.name) { halign = CENTER, ellipsize = END, @@ -41,12 +31,12 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { }; var icon = app.icon; - unowned var theme = Gtk.IconTheme.get_default (); - if (icon == null || theme.lookup_by_gicon (icon, ICON_SIZE, Gtk.IconLookupFlags.USE_BUILTIN) == null) { + unowned var theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); + if (icon == null || theme.lookup_by_gicon (icon, ICON_SIZE, ICON_SIZE, get_direction (), 0) == null) { icon = new ThemedIcon ("application-default-icon"); } - var image = new Gtk.Image.from_gicon (icon, ICON_SIZE) { + var image = new Gtk.Image.from_gicon (icon) { margin_top = 9, margin_end = 6, margin_start = 6, @@ -58,7 +48,7 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { valign = START, visible = false }; - badge.get_style_context ().add_class (Granite.STYLE_CLASS_BADGE); + badge.add_css_class (Granite.STYLE_CLASS_BADGE); var overlay = new Gtk.Overlay () { child = image, @@ -71,8 +61,8 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { hexpand = true, vexpand = true }; - box.add (overlay); - box.add (app_label); + box.append (overlay); + box.append (app_label); child = box; @@ -80,7 +70,7 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { this.clicked.connect (launch_app); - click_controller = new Gtk.GestureMultiPress (this) { + var click_controller = new Gtk.GestureClick () { button = 0, exclusive = true }; @@ -89,50 +79,59 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { var event = click_controller.get_last_event (sequence); if (event.triggers_context_menu ()) { - var context_menu = new Gtk.Menu.from_model (app.get_menu_model ()); - context_menu.insert_action_group (Backend.App.ACTION_GROUP_PREFIX, app.action_group); - context_menu.popup_at_pointer (); + var context_menu = app.get_context_menu (this); + context_menu.halign = START; + + Utils.menu_popup_at_pointer (context_menu, x, y); click_controller.set_state (CLAIMED); click_controller.reset (); } }); - menu_key_controller = new Gtk.EventControllerKey (this); + var menu_key_controller = new Gtk.EventControllerKey (); menu_key_controller.key_released.connect ((keyval, keycode, state) => { var mods = state & Gtk.accelerator_get_default_mod_mask (); switch (keyval) { case Gdk.Key.F10: if (mods == Gdk.ModifierType.SHIFT_MASK) { - var context_menu = new Gtk.Menu.from_model (app.get_menu_model ()); - context_menu.insert_action_group (Backend.App.ACTION_GROUP_PREFIX, app.action_group); - context_menu.popup_at_widget (this, EAST, CENTER); + Utils.menu_popup_on_keypress (app.get_context_menu (this)); } break; case Gdk.Key.Menu: case Gdk.Key.MenuKB: - var context_menu = new Gtk.Menu.from_model (app.get_menu_model ()); - context_menu.insert_action_group (Backend.App.ACTION_GROUP_PREFIX, app.action_group); - context_menu.popup_at_widget (this, EAST, CENTER); + Utils.menu_popup_on_keypress (app.get_context_menu (this)); break; default: return; } }); - this.drag_begin.connect ((ctx) => { - this.dragging = true; - Gtk.drag_set_icon_gicon (ctx, app.icon, 16, 16); - app_launched (); - }); + var drag_source = new Gtk.DragSource () { + actions = COPY, + content = new Gdk.ContentProvider.union ({ + new Gdk.ContentProvider.for_value ( + File.new_for_path (app.desktop_path).get_uri () + ) + }) + }; + drag_source.drag_begin.connect ((drag_source, drag) => { + drag_source.set_icon ( + Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).lookup_by_gicon ( + icon, + 32, + scale_factor, + get_direction (), + PRELOAD + ), 0, 0 + ); - this.drag_end.connect ( () => { - this.dragging = false; + app_launched (); }); - this.drag_data_get.connect ( (ctx, sel, info, time) => { - sel.set_uris ({File.new_for_path (app.desktop_path).get_uri ()}); - }); + add_controller (click_controller); + add_controller (menu_key_controller); + add_controller (drag_source); app.notify["current-count"].connect (update_badge_count); app.notify["count-visible"].connect (update_badge_visibility); @@ -158,11 +157,6 @@ public class Slingshot.Widgets.AppButton : Gtk.Button { private void update_badge_visibility () { var count_visible = app.count_visible && app.current_count > 0; - badge.no_show_all = !count_visible; - if (count_visible) { - badge.show_all (); - } else { - badge.hide (); - } + badge.visible = count_visible; } } diff --git a/src/Widgets/AppListRow.vala b/src/Widgets/AppListRow.vala index c112ce5d..f857c21a 100644 --- a/src/Widgets/AppListRow.vala +++ b/src/Widgets/AppListRow.vala @@ -25,8 +25,8 @@ public class Slingshot.AppListRow : Gtk.ListBoxRow { app_info = new GLib.DesktopAppInfo (app_id); var icon = app_info.get_icon (); - weak Gtk.IconTheme theme = Gtk.IconTheme.get_default (); - if (icon == null || theme.lookup_by_gicon (icon, 32, Gtk.IconLookupFlags.USE_BUILTIN) == null) { + unowned var theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); + if (icon == null || theme.lookup_by_gicon (icon, 32, 32, get_direction (), 0) == null) { icon = new ThemedIcon ("application-default-icon"); } @@ -43,8 +43,8 @@ public class Slingshot.AppListRow : Gtk.ListBoxRow { tooltip_text = app_info.get_description (); var box = new Gtk.Box (HORIZONTAL, 12); - box.add (image); - box.add (name_label); + box.append (image); + box.append (name_label); child = box; } diff --git a/src/Widgets/PageChecker.vala b/src/Widgets/PageChecker.vala index 07177031..ae5cf6c8 100644 --- a/src/Widgets/PageChecker.vala +++ b/src/Widgets/PageChecker.vala @@ -8,10 +8,10 @@ public class Slingshot.Widgets.PageChecker : Gtk.Button { public const double MIN_OPACITY = 0.4; - public unowned Hdy.Carousel carousel { get; construct; } + public unowned Adw.Carousel carousel { get; construct; } public int index { get; construct; } - public PageChecker (Hdy.Carousel carousel, int index) { + public PageChecker (Adw.Carousel carousel, int index) { Object ( carousel: carousel, index: index @@ -22,23 +22,28 @@ public class Slingshot.Widgets.PageChecker : Gtk.Button { var provider = new Gtk.CssProvider (); provider.load_from_resource ("/io/elementary/desktop/wingpanel/applications-menu/PageChecker.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), + Gtk.StyleContext.add_provider_for_display ( + Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); } construct { - get_style_context ().add_class ("switcher"); + add_css_class ("switcher"); - child = new Gtk.Image.from_icon_name ("pager-checked-symbolic", MENU); + icon_name = "pager-checked-symbolic"; update_opacity (); carousel.notify["position"].connect (() => { update_opacity (); }); + + clicked.connect (() => { + unowned var page = carousel.get_nth_page (index); + carousel.scroll_to (page, true); + }); } private void update_opacity () { diff --git a/src/Widgets/SearchItem.vala b/src/Widgets/SearchItem.vala index fee44e78..033706fd 100644 --- a/src/Widgets/SearchItem.vala +++ b/src/Widgets/SearchItem.vala @@ -47,8 +47,8 @@ public class Slingshot.Widgets.SearchItem : Gtk.ListBoxRow { }; var icon = app.icon; - unowned var theme = Gtk.IconTheme.get_default (); - if (icon == null || theme.lookup_by_gicon (icon, ICON_SIZE, Gtk.IconLookupFlags.USE_BUILTIN) == null) { + unowned var theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); + if (icon == null || theme.lookup_by_gicon (icon, ICON_SIZE, ICON_SIZE, get_direction (), 0) == null) { icon = new ThemedIcon ("application-default-icon"); } @@ -69,8 +69,8 @@ public class Slingshot.Widgets.SearchItem : Gtk.ListBoxRow { var box = new Gtk.Box (HORIZONTAL, 12) { margin_start = 6 }; - box.add (image); - box.add (name_label); + box.append (image); + box.append (name_label); child = box; @@ -134,14 +134,11 @@ public class Slingshot.Widgets.SearchItem : Gtk.ListBoxRow { } } - public Gtk.Menu? create_context_menu () { + public Gtk.Popover? create_context_menu () { if (result_type != APPLICATION) { return null; } - var context_menu = new Gtk.Menu.from_model (app.get_menu_model ()); - context_menu.insert_action_group (Backend.App.ACTION_GROUP_PREFIX, app.action_group); - - return context_menu; + return app.get_context_menu (this); } } diff --git a/src/Widgets/Switcher.vala b/src/Widgets/Switcher.vala index 3c128d6a..fcfb9c86 100644 --- a/src/Widgets/Switcher.vala +++ b/src/Widgets/Switcher.vala @@ -6,8 +6,8 @@ */ public class Slingshot.Widgets.Switcher : Gtk.Box { - private Hdy.Carousel _carousel; - public Hdy.Carousel carousel { + private Adw.Carousel _carousel; + public Adw.Carousel carousel { set { if (_carousel != null) { _carousel.notify["n-pages"].disconnect (update_pages); @@ -26,27 +26,20 @@ public class Slingshot.Widgets.Switcher : Gtk.Box { } private void update_pages () { - get_children ().foreach ((child) => { - child.destroy (); - }); + while (get_first_child () != null) { + remove (get_first_child ()); + } if (_carousel.n_pages == 1) { hide (); return; + } else { + show (); } for (int i = 0; i < _carousel.get_n_pages (); i++) { - // In Adwaita, Carousel has a get_nth_page function - unowned var page = _carousel.get_children ().nth_data (i); - var button = new PageChecker (_carousel, i); - button.show (); - - add (button); - - button.clicked.connect (() => { - _carousel.scroll_to (page); - }); + append (button); } } } diff --git a/src/meson.build b/src/meson.build index e913d34e..194605fa 100644 --- a/src/meson.build +++ b/src/meson.build @@ -8,6 +8,7 @@ endif sources = [ 'Indicator.vala', 'SlingshotView.vala', + 'Utils.vala', 'Backend/AppCenter.vala', 'Backend/AppSystem.vala', diff --git a/src/synapse-plugins/desktop-file-plugin.vala b/src/synapse-plugins/desktop-file-plugin.vala index 266ffa24..c2cd9cc2 100644 --- a/src/synapse-plugins/desktop-file-plugin.vala +++ b/src/synapse-plugins/desktop-file-plugin.vala @@ -62,7 +62,7 @@ namespace Synapse { public override void execute (Match? match) { var context = Gdk.Display.get_default ().get_app_launch_context (); - context.set_timestamp (Gtk.get_current_event_time ()); + context.set_timestamp (Gdk.CURRENT_TIME); ((DesktopAppInfo) app_info).launch_action (action_name, context); } }