diff options
-rw-r--r-- | examples/js/simple-bar/widget/Bar.tsx | 17 | ||||
-rw-r--r-- | examples/lua/simple-bar/widget/Bar.lua | 26 | ||||
-rw-r--r-- | examples/vala/simple-bar/widget/Bar.vala | 21 | ||||
-rw-r--r-- | lang/gjs/src/gtk3/astalify.ts | 5 | ||||
-rw-r--r-- | lang/gjs/src/gtk3/jsx-runtime.ts | 2 | ||||
-rw-r--r-- | lang/gjs/src/gtk3/widget.ts | 9 | ||||
-rw-r--r-- | lang/lua/astal/gtk3/widget.lua | 7 | ||||
-rw-r--r-- | lib/tray/meson.build | 48 | ||||
-rw-r--r-- | lib/tray/trayItem.vala | 111 |
9 files changed, 105 insertions, 141 deletions
diff --git a/examples/js/simple-bar/widget/Bar.tsx b/examples/js/simple-bar/widget/Bar.tsx index efc065a..029aca1 100644 --- a/examples/js/simple-bar/widget/Bar.tsx +++ b/examples/js/simple-bar/widget/Bar.tsx @@ -13,19 +13,14 @@ function SysTray() { return <box> {bind(tray, "items").as(items => items.map(item => { - if (item.iconThemePath) - App.add_icons(item.iconThemePath) - - const menu = item.create_menu() - - return <button + + return <menubutton tooltipMarkup={bind(item, "tooltipMarkup")} - onDestroy={() => menu?.destroy()} - onClickRelease={self => { - menu?.popup_at_widget(self, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null) - }}> + usePopover={false} + actionGroup={bind(item, "action-group").as(ag => { return { prefix: "dbusmenu", actionGroup: ag}})} + menuModel={bind(item, "menu-model")} > <icon gIcon={bind(item, "gicon")} /> - </button> + </menubutton> }))} </box> } diff --git a/examples/lua/simple-bar/widget/Bar.lua b/examples/lua/simple-bar/widget/Bar.lua index bf230bb..843e292 100644 --- a/examples/lua/simple-bar/widget/Bar.lua +++ b/examples/lua/simple-bar/widget/Bar.lua @@ -19,24 +19,16 @@ local function SysTray() return Widget.Box({ bind(tray, "items"):as(function(items) return map(items, function(item) - if item.icon_theme_path ~= nil then - App:add_icons(item.icon_theme_path) - end - - local menu = item:create_menu() - - return Widget.Button({ + return Widget.MenuButton({ tooltip_markup = bind(item, "tooltip_markup"), - on_destroy = function() - if menu ~= nil then - menu:destroy() - end - end, - on_click_release = function(self) - if menu ~= nil then - menu:popup_at_widget(self, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, nil) - end - end, + use_popover = false, + menu_model = bind(item, "menu-model"), + action_group = bind(item, "action-group"):as(function(ag) + return { + prefix = "dbusmenu", + action_group = ag + } + end), Widget.Icon({ g_icon = bind(item, "gicon"), }), diff --git a/examples/vala/simple-bar/widget/Bar.vala b/examples/vala/simple-bar/widget/Bar.vala index ba4062c..3893ec5 100644 --- a/examples/vala/simple-bar/widget/Bar.vala +++ b/examples/vala/simple-bar/widget/Bar.vala @@ -113,22 +113,19 @@ class SysTray : Gtk.Box { var item = tray.get_item(id); - var menu = item.create_menu(); - var btn = new Astal.Button(); + var btn = new Gtk.MenuButton() { + use_popover = false + }; var icon = new Astal.Icon(); - btn.clicked.connect(() => { - if (menu != null) - menu.popup_at_widget(this, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null); - }); - - btn.destroy.connect(() => { - if (menu != null) - menu.destroy(); - }); - item.bind_property("tooltip-markup", btn, "tooltip-markup", BindingFlags.SYNC_CREATE); item.bind_property("gicon", icon, "g-icon", BindingFlags.SYNC_CREATE); + item.bind_property("menu-model", btn, "menu-model", BindingFlags.SYNC_CREATE); + btn.insert_action_group("dbusmenu", item.action_group); + item.notify["action-group"].connect(() => { + btn.insert_action_group("dbusmenu", item.action_group); + }); + btn.add(icon); add(btn); btn.show_all(); diff --git a/lang/gjs/src/gtk3/astalify.ts b/lang/gjs/src/gtk3/astalify.ts index 6973805..b758976 100644 --- a/lang/gjs/src/gtk3/astalify.ts +++ b/lang/gjs/src/gtk3/astalify.ts @@ -69,6 +69,9 @@ export default function astalify< get noImplicitDestroy(): boolean { return this.__no_implicit_destroy } set noImplicitDestroy(value: boolean) { this.__no_implicit_destroy = value } + set actionGroup(actionGroup: ActionGroup) { this.insert_action_group(actionGroup.prefix, actionGroup.actionGroup) } + set_action_group(actionGroup: ActionGroup) { this.actionGroup = actionGroup } + _setChildren(children: Gtk.Widget[]) { children = children.flat(Infinity).map(ch => ch instanceof Gtk.Widget ? ch @@ -327,3 +330,5 @@ type Cursor = | "nwse-resize" | "zoom-in" | "zoom-out" + +type ActionGroup = { prefix: string, actionGroup: Gtk.ActionGroup } diff --git a/lang/gjs/src/gtk3/jsx-runtime.ts b/lang/gjs/src/gtk3/jsx-runtime.ts index 22dc424..10b3bcf 100644 --- a/lang/gjs/src/gtk3/jsx-runtime.ts +++ b/lang/gjs/src/gtk3/jsx-runtime.ts @@ -54,6 +54,7 @@ const ctors = { label: Widget.Label, levelbar: Widget.LevelBar, // TODO: listbox + menubutton: Widget.MenuButton, overlay: Widget.Overlay, revealer: Widget.Revealer, scrollable: Widget.Scrollable, @@ -82,6 +83,7 @@ declare global { label: Widget.LabelProps levelbar: Widget.LevelBarProps // TODO: listbox + menubutton: Widget.MenuButton, overlay: Widget.OverlayProps revealer: Widget.RevealerProps scrollable: Widget.ScrollableProps diff --git a/lang/gjs/src/gtk3/widget.ts b/lang/gjs/src/gtk3/widget.ts index b4e8497..b3c4a4d 100644 --- a/lang/gjs/src/gtk3/widget.ts +++ b/lang/gjs/src/gtk3/widget.ts @@ -102,6 +102,15 @@ export class LevelBar extends astalify(Astal.LevelBar) { // TODO: ListBox + +// MenuButton +export type MenuButtonProps = ConstructProps<MenuButton, Gtk.MenuButton.ConstructorProps> +export class MenuButton extends astalify(Gtk.MenuButton) { + static { GObject.registerClass({ GTypeName: "MenuButton" }, this) } + constructor(props?: MenuButtonProps, child?: BindableChild) { super({ child, ...props } as any) } +} + + // Overlay Object.defineProperty(Astal.Overlay.prototype, "overlays", { get() { return this.get_overlays() }, diff --git a/lang/lua/astal/gtk3/widget.lua b/lang/lua/astal/gtk3/widget.lua index c8857e7..adcb65f 100644 --- a/lang/lua/astal/gtk3/widget.lua +++ b/lang/lua/astal/gtk3/widget.lua @@ -19,6 +19,7 @@ local Widget = { Label = astalify(Gtk.Label), LevelBar = astalify(Astal.LevelBar), -- TODO: ListBox + MenuButton = astalify(Gtk.MenuButton), Overlay = astalify(Astal.Overlay), Revealer = astalify(Gtk.Revealer), Scrollable = astalify(Astal.Scrollable), @@ -64,6 +65,12 @@ Gtk.Widget._attribute.click_through = { set = Astal.widget_set_click_through, } +Gtk.Widget._attribute.action_group = { + set = function (self, v) + self:insert_action_group(v.prefix, v.action_group) + end +} + local no_implicit_destroy = {} Gtk.Widget._attribute.no_implicit_destroy = { get = function(self) diff --git a/lib/tray/meson.build b/lib/tray/meson.build index fbf2f98..139cfb1 100644 --- a/lib/tray/meson.build +++ b/lib/tray/meson.build @@ -39,29 +39,9 @@ deps = [ dependency('gio-2.0'), dependency('json-glib-1.0'), dependency('gdk-pixbuf-2.0'), - dependency('gtk+-3.0'), + dependency('appmenu-glib-translator') ] -dbusmenu_cflags = run_command( - find_program('pkg-config', required: true), - '--cflags', 'dbusmenu-gtk3-0.4', - 'gobject-introspection-1.0', - 'gobject-2.0', - 'glib-2.0', - capture: true, - check: true, -).stdout().strip() - -dbusmenu_libs = run_command( - find_program('pkg-config', required: true), - '--libs', 'dbusmenu-gtk3-0.4', - 'gobject-introspection-1.0', - 'gobject-2.0', - 'glib-2.0', - capture: true, - check: true, -).stdout().strip() - sources = [config] + files('tray.vala', 'watcher.vala', 'trayItem.vala') if get_option('lib') @@ -71,15 +51,13 @@ if get_option('lib') dependencies: deps, vala_header: meson.project_name() + '.h', vala_vapi: meson.project_name() + '-' + api_version + '.vapi', - vala_args: ['--vapi-comments', '--pkg', 'DbusmenuGtk3-0.4', '--pkg', 'Dbusmenu-0.4'], + vala_args: ['--vapi-comments'], version: meson.project_version(), - c_args: dbusmenu_cflags.split(' '), - link_args: dbusmenu_libs.split(' '), install: true, install_dir: [true, true, true] ) - pkgs = ['--pkg', 'DbusmenuGtk3-0.4', '--pkg', 'Dbusmenu-0.4'] + pkgs = [] foreach dep : deps pkgs += ['--pkg=' + dep.name()] endforeach @@ -120,31 +98,13 @@ if get_option('lib') requires: deps, install_dir: get_option('libdir') / 'pkgconfig', ) - # - # custom_target( - # typelib, - # command: [ - # find_program('g-ir-compiler'), - # '--output', '@OUTPUT@', - # '--shared-library', get_option('prefix') / get_option('libdir') / '@PLAINNAME@', - # meson.current_build_dir() / gir, - # ], - # input: lib, - # output: typelib, - # depends: lib, - # install: true, - # install_dir: get_option('libdir') / 'girepository-1.0', - # ) -endif + endif if get_option('cli') executable( meson.project_name(), ['cli.vala', sources], dependencies: deps, - vala_args: ['--pkg', 'DbusmenuGtk3-0.4', '--pkg', 'Dbusmenu-0.4'], - c_args: dbusmenu_cflags.split(' '), - link_args: dbusmenu_libs.split(' '), install: true, ) endif diff --git a/lib/tray/trayItem.vala b/lib/tray/trayItem.vala index db0e6d4..be221bf 100644 --- a/lib/tray/trayItem.vala +++ b/lib/tray/trayItem.vala @@ -1,4 +1,3 @@ -using DbusmenuGtk; namespace AstalTray { public struct Pixmap { @@ -169,6 +168,22 @@ public class TrayItem : Object { /** the id of the item used to uniquely identify the TrayItems by this lib.*/ public string item_id { get; private set; } + private DBusMenu.Importer menu_importer; + + public MenuModel menu_model { + owned get { + if (menu_importer == null) return null; + return menu_importer.model; + } + } + + public ActionGroup action_group { + owned get { + if (menu_importer == null) return null; + return menu_importer.action_group; + } + } + public signal void changed(); public signal void ready(); @@ -197,6 +212,14 @@ public class TrayItem : Object { } }); + if(proxy.Menu != null) { + this.menu_importer = new DBusMenu.Importer(proxy.get_name_owner(), proxy.Menu); + this.menu_importer.notify["model"].connect(() => { + notify_property("menu-model"); + notify_property("action-group"); + }); + } + update_gicon(); ready(); @@ -216,18 +239,9 @@ public class TrayItem : Object { private void update_gicon() { if(icon_name != null && icon_name != "") { - if(icon_theme_path != null && icon_theme_path != "") { - - Gtk.IconTheme icon_theme = new Gtk.IconTheme(); - string[] paths = {icon_theme_path}; - icon_theme.set_search_path(paths); - - int size = icon_theme.get_icon_sizes(icon_name)[0]; - Gtk.IconInfo icon_info = icon_theme.lookup_icon( - icon_name, size, Gtk.IconLookupFlags.FORCE_SIZE); - - if (icon_info != null) - gicon = new GLib.FileIcon(GLib.File.new_for_path(icon_info.get_filename())); + if(icon_theme_path != null && icon_theme_path != "") { + gicon = new GLib.FileIcon(GLib.File.new_for_path( + find_icon_in_theme(icon_name, icon_theme_path))); } else { gicon = new GLib.ThemedIcon(icon_name); } @@ -312,16 +326,33 @@ public class TrayItem : Object { } } - /** - * creates a new Gtk Menu for this item. - */ - public Gtk.Menu? create_menu() { - if (proxy.Menu == null) - return null; + private string? find_icon_in_theme(string icon_name, string theme_path){ + if(icon_name == null || theme_path == null || icon_name == "" || theme_path == "") return null; + + try { + Dir dir = Dir.open (theme_path, 0); + string? name = null; + + while ((name = dir.read_name ()) != null) { + string path = Path.build_filename (theme_path, name); + + if (FileUtils.test (path, FileTest.IS_DIR)) { + string? icon = find_icon_in_theme(icon_name, path); + if(icon != null) return icon; + else continue; + } + + int dot_index = name.last_index_of("."); + if (dot_index != -1) + name = name.substring(0, dot_index); + if (name == icon_name) return path; + + } + } catch (FileError err) { + return null; + } + return null; - return new DbusmenuGtk.Menu( - proxy.get_name_owner(), - proxy.Menu); } private Gdk.Pixbuf? _get_icon_pixbuf() { @@ -329,41 +360,7 @@ public class TrayItem : Object { ? proxy.AttentionIconPixmap : proxy.IconPixmap; - - string icon_name = proxy.Status == Status.NEEDS_ATTENTION - ? proxy.AttentionIconName - : proxy.IconName; - - Gdk.Pixbuf pixbuf = null; - - if (icon_name != null && proxy.IconThemePath != null) - pixbuf = load_from_theme(icon_name, proxy.IconThemePath); - - if (pixbuf == null) - pixbuf = pixmap_to_pixbuf(pixmaps); - - return pixbuf; - } - - private Gdk.Pixbuf? load_from_theme(string icon_name, string theme_path) { - if (theme_path == "" || theme_path == null) - return null; - - if (icon_name == "" || icon_name == null) - return null; - - Gtk.IconTheme icon_theme = new Gtk.IconTheme(); - string[] paths = {theme_path}; - icon_theme.set_search_path(paths); - - int size = icon_theme.get_icon_sizes(icon_name)[0]; - Gtk.IconInfo icon_info = icon_theme.lookup_icon( - icon_name, size, Gtk.IconLookupFlags.FORCE_SIZE); - - if (icon_info != null) - return icon_info.load_icon(); - - return null; + return pixmap_to_pixbuf(pixmaps); } private Gdk.Pixbuf? pixmap_to_pixbuf(Pixmap[] pixmaps) { |