summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAylur <[email protected]>2024-06-28 17:07:18 +0200
committerGitHub <[email protected]>2024-06-28 17:07:18 +0200
commit9a484bdee02904034449961612fd5b2cdbe6a337 (patch)
tree7be3b0a66894a980e6e9ddef5ef2e8782a2fe964
parent2c701b970e7b2b208d8d12d3ea34078236d3f62e (diff)
add flake, format, small fixes (#1)
* add flake, format, small fixes * moved the mainloop in cli.vala to the scope of deamonize * made versions public in config.vala * added notify_property("items") calls in tray.vala, this makes it work with the bind API in gjs * added flake.nix NOTE for nix: The dbusmenu workaround in meson seems to break typelib linking on nix which I could not find a solution for. A simple workaround is to simply put the dependencies of dbusmenu-gtk in buildInputs, which is fine, but I'm sure this will cause confusion since no other libs require additional packages in buildInputs * fix(cli): item changed event * move header to includedir/astal
-rw-r--r--flake.lock27
-rw-r--r--flake.nix56
-rw-r--r--meson-install.sh16
-rw-r--r--meson.build5
-rw-r--r--meson_options.txt13
-rw-r--r--src/cli.vala91
-rw-r--r--src/config.vala.in8
-rw-r--r--src/meson.build84
-rw-r--r--src/tray.vala196
-rw-r--r--src/trayItem.vala442
-rw-r--r--src/watcher.vala92
11 files changed, 551 insertions, 479 deletions
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..8d2ab6e
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,27 @@
+{
+ "nodes": {
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1719254875,
+ "narHash": "sha256-ECni+IkwXjusHsm9Sexdtq8weAq/yUyt1TWIemXt3Ko=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "2893f56de08021cffd9b6b6dfc70fd9ccd51eb60",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..c78cbaa
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,56 @@
+{
+ description = "Library and cli for the StatusNotifierItem protocol";
+
+ inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+
+ outputs = {
+ self,
+ nixpkgs,
+ }: let
+ version = builtins.replaceStrings ["\n"] [""] (builtins.readFile ./version);
+ system = "x86_64-linux";
+ pkgs = import nixpkgs {inherit system;};
+
+ nativeBuildInputs = with pkgs; [
+ gobject-introspection
+ meson
+ pkg-config
+ ninja
+ vala
+ ];
+
+ buildInputs = with pkgs; [
+ gtk3
+ glib
+ gdk-pixbuf
+ libdbusmenu-gtk3
+ json-glib
+ ];
+ in {
+ packages.${system} = rec {
+ default = tray;
+ tray = pkgs.stdenv.mkDerivation {
+ inherit nativeBuildInputs buildInputs;
+ pname = "astal-tray";
+ version = version;
+ src = ./.;
+ outputs = ["out" "dev"];
+ };
+ };
+
+ devShells.${system} = {
+ default = pkgs.mkShell {
+ inherit nativeBuildInputs buildInputs;
+ };
+ tray = pkgs.mkShell {
+ inherit nativeBuildInputs;
+ buildInputs =
+ buildInputs
+ ++ [
+ self.packages.${system}.default
+ pkgs.gjs
+ ];
+ };
+ };
+ };
+}
diff --git a/meson-install.sh b/meson-install.sh
deleted file mode 100644
index 0e6b258..0000000
--- a/meson-install.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-meson setup \
- --prefix /usr \
- --libexecdir lib \
- --sbindir bin \
- --buildtype plain \
- --auto-features enabled \
- --wrap-mode nodownload \
- -D b_lto=false \
- -D b_pie=true \
- -D python.bytecompile=1 \
- --wipe \
- build
-
-meson install -C build
diff --git a/meson.build b/meson.build
index 24780ca..4a52d56 100644
--- a/meson.build
+++ b/meson.build
@@ -11,4 +11,9 @@ project(
],
)
+assert(
+ get_option('lib') or get_option('cli'),
+ 'Either lib or cli option must be set to true.',
+)
+
subdir('src')
diff --git a/meson_options.txt b/meson_options.txt
index d157c62..f110242 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,2 +1,11 @@
-option('typelib', type: 'boolean', value: true, description: 'Needed files for runtime bindings.')
-option('cli', type: 'boolean', value: true, description: 'a simple cli tool for interacting with the tray.')
+option(
+ 'lib',
+ type: 'boolean',
+ value: true,
+)
+
+option(
+ 'cli',
+ type: 'boolean',
+ value: true,
+)
diff --git a/src/cli.vala b/src/cli.vala
index c22e096..3147fb5 100644
--- a/src/cli.vala
+++ b/src/cli.vala
@@ -1,55 +1,54 @@
-static bool help;
static bool version;
static bool daemonize;
const OptionEntry[] options = {
- { "version", 'v', OptionFlags.NONE, OptionArg.NONE, ref version, "Print version number", null },
- { "daemon", 'd', OptionFlags.NONE, OptionArg.NONE, ref daemonize, "Monitor the systemtray", null },
- { null },
+ { "version", 'v', OptionFlags.NONE, OptionArg.NONE, ref version, "Print version number", null },
+ { "daemonize", 'd', OptionFlags.NONE, OptionArg.NONE, ref daemonize, "Monitor the systemtray", null },
+ { null },
};
int main(string[] argv) {
- try {
- var opts = new OptionContext();
- opts.add_main_entries(options, null);
- opts.set_help_enabled(true);
- opts.set_ignore_unknown_options(false);
- opts.parse(ref argv);
- } catch (OptionError err) {
- printerr (err.message);
- return 1;
- }
-
- var loop = new MainLoop();
- var tray = new AstalTray.Tray();
-
- if (version) {
- print(AstalTray.VERSION);
+ try {
+ var opts = new OptionContext();
+ opts.add_main_entries(options, null);
+ opts.set_help_enabled(true);
+ opts.set_ignore_unknown_options(false);
+ opts.parse(ref argv);
+ } catch (OptionError err) {
+ printerr (err.message);
+ return 1;
+ }
+
+ if (version) {
+ print(AstalTray.VERSION);
+ return 0;
+ }
+
+ if (daemonize) {
+ var loop = new MainLoop();
+ var tray = new AstalTray.Tray();
+
+ tray.item_added.connect((id) => {
+ AstalTray.TrayItem item = tray.get_item(id);
+
+ stdout.printf("{\"event\":\"item_added\",\"id\":\"%s\",\"item\":%s}\n",
+ id, item.to_json_string());
+ stdout.flush();
+
+ item.changed.connect(() => {
+ stdout.printf("{\"event\":\"item_changed\",\"id\":\"%s\",\"item\":%s}\n",
+ id, item.to_json_string());
+ stdout.flush();
+ });
+ });
+
+ tray.item_removed.connect((id) => {
+ stdout.printf("{\"event\":\"item_removed\",\"id\":\"%s\"}\n", id);
+ stdout.flush();
+ });
+
+ loop.run();
+ }
+
return 0;
- }
-
- if (daemonize) {
- tray.item_added.connect((id) => {
-
- AstalTray.TrayItem item = tray.get_item(id);
-
- string item_json = item.to_json_string();
- stdout.printf("{\"event\":\"item_added\",\"id\":\"%s\",\"item\":%s}\n",
- id, item_json);
- stdout.flush();
-
- item.changed.connect(() => {
- stdout.printf("{\"event\":\"item_changed\",\"id\":\"%s\",\"item\":%s}\n",
- id, item_json);
- stdout.flush();
- });
- });
- tray.item_removed.connect((id) => {
- stdout.printf("{\"event\":\"item_removed\",\"id\":\"%s\"}\n", id);
- stdout.flush();
- });
- }
-
- loop.run();
- return 0;
}
diff --git a/src/config.vala.in b/src/config.vala.in
index 85cca51..8ef8498 100644
--- a/src/config.vala.in
+++ b/src/config.vala.in
@@ -1,6 +1,6 @@
namespace AstalTray {
- const int MAJOR_VERSION = @MAJOR_VERSION@;
- const int MINOR_VERSION = @MINOR_VERSION@;
- const int MICRO_VERSION = @MICRO_VERSION@;
- const string VERSION = "@VERSION@";
+ public const int MAJOR_VERSION = @MAJOR_VERSION@;
+ public const int MINOR_VERSION = @MINOR_VERSION@;
+ public const int MICRO_VERSION = @MICRO_VERSION@;
+ public const string VERSION = "@VERSION@";
}
diff --git a/src/meson.build b/src/meson.build
index 546b9f3..bfbe11c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,8 +1,8 @@
version_split = meson.project_version().split('.')
api_version = version_split[0] + '.' + version_split[1]
-tray_gir = 'AstalTray-' + api_version + '.gir'
-tray_typelib = 'AstalTray-' + api_version + '.typelib'
-tray_so = 'libastal-tray.so.' + meson.project_version()
+gir = 'AstalTray-' + api_version + '.gir'
+typelib = 'AstalTray-' + api_version + '.typelib'
+so = 'lib' + meson.project_name() + '.so.' + meson.project_version()
config = configure_file(
input: 'config.vala.in',
@@ -26,69 +26,63 @@ deps = [
dbusmenu_cflags = run_command(
find_program('pkg-config', required: true),
- '--cflags',
- 'dbusmenu-gtk3-0.4',
+ '--cflags', 'dbusmenu-gtk3-0.4',
'gobject-introspection-1.0',
- 'gobject-2.0', 'glib-2.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',
+ '--libs', 'dbusmenu-gtk3-0.4',
'gobject-introspection-1.0',
- 'gobject-2.0', 'glib-2.0',
+ 'gobject-2.0',
+ 'glib-2.0',
capture: true,
check: true,
).stdout().strip()
-sources = [
- config,
- 'tray.vala',
- 'watcher.vala',
- 'trayItem.vala'
-]
+sources = [config, 'tray.vala', 'watcher.vala', 'trayItem.vala']
-libtray = library(
- meson.project_name(),
- sources,
- dependencies: deps,
- vala_header: meson.project_name() + '.h',
- vala_vapi: meson.project_name() + '-' + api_version + '.vapi',
- vala_gir: tray_gir,
- vala_args: ['--pkg', 'DbusmenuGtk3-0.4', '--pkg', 'Dbusmenu-0.4'],
- version: meson.project_version(),
- c_args: dbusmenu_cflags.split(' '),
- link_args: dbusmenu_libs.split(' '),
- install: true,
- install_dir: [true, true, true, true],
-)
+if get_option('lib')
+ lib = library(
+ meson.project_name(),
+ sources,
+ dependencies: deps,
+ vala_header: meson.project_name().replace('astal-', '') + '.h',
+ vala_vapi: meson.project_name() + '-' + api_version + '.vapi',
+ vala_gir: gir,
+ vala_args: ['--pkg', 'DbusmenuGtk3-0.4', '--pkg', 'Dbusmenu-0.4'],
+ version: meson.project_version(),
+ c_args: dbusmenu_cflags.split(' '),
+ link_args: dbusmenu_libs.split(' '),
+ install: true,
+ install_dir: [true, get_option('includedir') / 'astal', true, true],
+ )
-import('pkgconfig').generate(
- description: 'libastal-tray',
- libraries: libtray,
- name: meson.project_name(),
- filebase: meson.project_name() + '-' + api_version,
- version: meson.project_version(),
- subdirs: meson.project_name(),
- requires: deps + [dependency('dbusmenu-gtk3-0.4')],
- install_dir: get_option('libdir') / 'pkgconfig',
-)
+ import('pkgconfig').generate(
+ lib,
+ name: meson.project_name(),
+ filebase: meson.project_name() + '-' + api_version,
+ version: meson.project_version(),
+ subdirs: meson.project_name(),
+ requires: deps,
+ install_dir: get_option('libdir') / 'pkgconfig',
+ )
-if get_option('typelib')
custom_target(
- tray_typelib,
+ typelib,
command: [
find_program('g-ir-compiler'),
'--output', '@OUTPUT@',
'--shared-library', get_option('prefix') / get_option('libdir') / '@PLAINNAME@',
- meson.current_build_dir() / tray_gir,
+ meson.current_build_dir() / gir,
],
- input: libtray,
- output: tray_typelib,
- depends: libtray,
+ input: lib,
+ output: typelib,
+ depends: lib,
install: true,
install_dir: get_option('libdir') / 'girepository-1.0',
)
diff --git a/src/tray.vala b/src/tray.vala
index 8f67194..09b0643 100644
--- a/src/tray.vala
+++ b/src/tray.vala
@@ -1,131 +1,135 @@
namespace AstalTray {
+[DBus (name="org.kde.StatusNotifierWatcher")]
+internal interface IWatcher : Object {
+ public abstract string[] RegisteredStatusNotifierItems { owned get; }
+ public abstract int ProtocolVersion { owned get; }
+
+ public abstract void RegisterStatusNotifierItem(string service, BusName sender) throws DBusError, IOError;
+ public abstract void RegisterStatusNotifierHost(string service) throws DBusError, IOError;
+
+ public signal void StatusNotifierItemRegistered(string service);
+ public signal void StatusNotifierItemUnregistered(string service);
+ public signal void StatusNotifierHostRegistered();
+ public signal void StatusNotifierHostUnregistered();
+}
- [DBus (name="org.kde.StatusNotifierWatcher")]
- internal interface IWatcher : Object {
-
- public abstract string[] RegisteredStatusNotifierItems { owned get; }
- public abstract int ProtocolVersion { owned get; }
-
- public abstract void RegisterStatusNotifierItem(string service, BusName sender) throws DBusError, IOError;
- public abstract void RegisterStatusNotifierHost(string service) throws DBusError, IOError;
+public Tray get_default() {
+ return Tray.get_default();
+}
- public signal void StatusNotifierItemRegistered(string service);
- public signal void StatusNotifierItemUnregistered(string service);
- public signal void StatusNotifierHostRegistered();
- public signal void StatusNotifierHostUnregistered();
+public class Tray : Object {
+ private static Tray? instance;
+ public static unowned Tray get_default() {
+ if (instance == null)
+ instance = new Tray();
+ return instance;
}
- public class Tray : Object {
-
private StatusNotifierWatcher watcher;
private IWatcher proxy;
- private HashTable<string, TrayItem> _items;
+ private HashTable<string, TrayItem> _items =
+ new HashTable<string, TrayItem>(str_hash, str_equal);
+
public List<weak TrayItem> items { owned get { return _items.get_values(); }}
- public signal void item_added(string service);
- public signal void item_removed(string service);
+ public signal void item_added(string service) {
+ notify_property("items");
+ }
- construct {
- _items = new HashTable<string, TrayItem>(GLib.str_hash, GLib.str_equal);
- try {
-
- Bus.own_name(
- BusType.SESSION,
- "org.kde.StatusNotifierWatcher",
- BusNameOwnerFlags.NONE,
- start_watcher,
- () => {
- if (proxy != null) {
- proxy = null;
- }
- },
- start_host);
+ public signal void item_removed(string service) {
+ notify_property("items");
+ }
- } catch (Error err) {
- critical("%s", err.message);
- }
+ construct {
+ try {
+ Bus.own_name(
+ BusType.SESSION,
+ "org.kde.StatusNotifierWatcher",
+ BusNameOwnerFlags.NONE,
+ start_watcher,
+ () => {
+ if (proxy != null) {
+ proxy = null;
+ }
+ },
+ start_host
+ );
+ } catch (Error err) {
+ critical(err.message);
+ }
}
private void start_watcher(DBusConnection conn) {
- try {
- watcher = new StatusNotifierWatcher();
- conn.register_object("/StatusNotifierWatcher", watcher);
- watcher.StatusNotifierItemRegistered.connect(on_item_register);
- watcher.StatusNotifierItemUnregistered.connect(on_item_unregister);
- } catch (Error err) {
- critical(err.message);
- }
+ try {
+ watcher = new StatusNotifierWatcher();
+ conn.register_object("/StatusNotifierWatcher", watcher);
+ watcher.StatusNotifierItemRegistered.connect(on_item_register);
+ watcher.StatusNotifierItemUnregistered.connect(on_item_unregister);
+ } catch (Error err) {
+ critical(err.message);
+ }
}
private void start_host() {
- if(proxy != null) return;
-
- try {
- proxy = Bus.get_proxy_sync(BusType.SESSION,
- "org.kde.StatusNotifierWatcher",
- "/StatusNotifierWatcher");
-
- proxy.StatusNotifierItemRegistered.connect(on_item_register);
- proxy.StatusNotifierItemUnregistered.connect(on_item_unregister);
+ if (proxy != null)
+ return;
+
+ try {
+ proxy = Bus.get_proxy_sync(BusType.SESSION,
+ "org.kde.StatusNotifierWatcher",
+ "/StatusNotifierWatcher");
+
+ proxy.StatusNotifierItemRegistered.connect(on_item_register);
+ proxy.StatusNotifierItemUnregistered.connect(on_item_unregister);
+
+ proxy.notify["g-name-owner"].connect(() => {
+ _items.foreach((service, _) => {
+ item_removed(service);
+ });
+
+ _items.remove_all();
+
+ if(proxy != null) {
+ foreach (string item in proxy.RegisteredStatusNotifierItems) {
+ on_item_register(item);
+ }
+ } else {
+ foreach (string item in watcher.RegisteredStatusNotifierItems) {
+ on_item_register(item);
+ }
+ }
+ });
- proxy.notify["g-name-owner"].connect(() => {
- _items.foreach((service, _) => {
- item_removed(service);
- });
- _items.remove_all();
-
- if(proxy != null) {
foreach (string item in proxy.RegisteredStatusNotifierItems) {
- on_item_register(item);
- }
- } else {
- foreach (string item in watcher.RegisteredStatusNotifierItems) {
- on_item_register(item);
+ on_item_register(item);
}
- }
- });
-
- foreach (string item in proxy.RegisteredStatusNotifierItems) {
- on_item_register(item);
+ } catch (Error err) {
+ critical("cannot get proxy: %s", err.message);
}
- } catch (Error err) {
- critical("cannot get proxy: %s", err.message);
- }
}
private void on_item_register(string service) {
- if(_items.contains(service)) return;
- string[] parts = service.split("/", 2);
- TrayItem item = new TrayItem(parts[0], "/" + parts[1]);
- item.ready.connect(() => {
- _items.set(service, item);
- item_added(service);
- });
+ if (_items.contains(service))
+ return;
+
+ var parts = service.split("/", 2);
+ TrayItem item = new TrayItem(parts[0], "/" + parts[1]);
+ item.ready.connect(() => {
+ _items.set(service, item);
+ item_added(service);
+ });
}
private void on_item_unregister(string service) {
- _items.remove(service);
- item_removed(service);
+ _items.remove(service);
+ item_removed(service);
}
public TrayItem get_item(string service) {
- return _items.get(service);
+ return _items.get(service);
}
-
- private static Tray? instance;
-
- public static unowned Tray get_default() {
-
- if (instance == null) instance = new Tray();
-
- return instance;
- }
-
-
- }
}
-
-
+}
diff --git a/src/trayItem.vala b/src/trayItem.vala
index 4af3398..d954f8f 100644
--- a/src/trayItem.vala
+++ b/src/trayItem.vala
@@ -1,91 +1,90 @@
using DbusmenuGtk;
namespace AstalTray {
-
- public struct Pixmap {
+public struct Pixmap {
int width;
int height;
uint8[] bytes;
- }
+}
- public struct Tooltip {
+public struct Tooltip {
string icon_name;
Pixmap[] icon;
string title;
string description;
- }
-
- [DBus (use_string_marshalling = true)]
- public enum Category {
- [DBus (value = "ApplicationStatus"), Description (nick = "ApplicationStatus")]
- APPLICATION,
- [DBus (value = "Communications"), Description (nick = "Communications")]
- COMMUNICATIONS,
- [DBus (value = "SystemServices"), Description (nick = "SystemServices")]
- SYSTEM,
- [DBus (value = "Hardware"), Description (nick = "Hardware")]
- HARDWARE;
-
- public string to_nick () {
- EnumClass enumc = (EnumClass) typeof (Category).class_ref ();
- unowned EnumValue eval = enumc.get_value (this);
- return eval.value_nick;
- }
- }
+}
+[DBus (use_string_marshalling = true)]
+public enum Category {
+ [DBus (value = "ApplicationStatus"), Description (nick = "ApplicationStatus")]
+ APPLICATION,
- [DBus (use_string_marshalling = true)]
- public enum Status {
- [DBus (value = "Passive"), Description (nick = "Passive")]
- PASSIVE,
- [DBus (value = "Active"), Description (nick = "Active")]
- ACTIVE,
- [DBus (value = "NeedsAttention"), Description (nick = "NeedsAttention")]
- NEEDS_ATTENTION;
+ [DBus (value = "Communications"), Description (nick = "Communications")]
+ COMMUNICATIONS,
-
- public string to_nick () {
- EnumClass enumc = (EnumClass) typeof (Status).class_ref ();
- unowned EnumValue eval = enumc.get_value (this);
- return eval.value_nick;
- }
+ [DBus (value = "SystemServices"), Description (nick = "SystemServices")]
+ SYSTEM,
+
+ [DBus (value = "Hardware"), Description (nick = "Hardware")]
+ HARDWARE;
+ public string to_nick () {
+ var enumc = (EnumClass)typeof (Category).class_ref();
+ unowned var eval = enumc.get_value(this);
+ return eval.value_nick;
}
+}
- [DBus (name="org.kde.StatusNotifierItem")]
- internal interface IItem : DBusProxy {
-
- public abstract string Title { owned get; }
- public abstract Category Category { owned get; }
- public abstract Status Status { owned get; }
- public abstract Tooltip? ToolTip { owned get; }
- public abstract string Id { owned get; }
- public abstract string? IconThemePath { owned get; }
- public abstract bool ItemIsMenu { owned get; }
- public abstract ObjectPath? Menu { owned get; }
- public abstract string IconName { owned get; }
- public abstract Pixmap[] IconPixmap { owned get; }
- public abstract string AttentionIconName { owned get; }
- public abstract Pixmap[] AttentionIconPixmap { owned get; }
- public abstract string OverlayIconName { owned get; }
- public abstract Pixmap[] OverlayIconPixmap { owned get; }
-
- public abstract void ContexMenu(int x, int y) throws DBusError, IOError;
- public abstract void Activate(int x, int y) throws DBusError, IOError;
- public abstract void SecondaryActivate(int x, int y) throws DBusError, IOError;
- public abstract void Scroll(int delta, string orientation) throws DBusError, IOError;
-
- public signal void NewTitle();
- public signal void NewIcon();
- public signal void NewAttentionIcon();
- public signal void NewOverlayIcon();
- public signal void NewToolTip();
- public signal void NewStatus(string status);
+[DBus (use_string_marshalling = true)]
+public enum Status {
+ [DBus (value = "Passive"), Description (nick = "Passive")]
+ PASSIVE,
+
+ [DBus (value = "Active"), Description (nick = "Active")]
+ ACTIVE,
+
+ [DBus (value = "NeedsAttention"), Description (nick = "NeedsAttention")]
+ NEEDS_ATTENTION;
+
+ public string to_nick () {
+ var enumc = (EnumClass)typeof (Status).class_ref();
+ unowned var eval = enumc.get_value(this);
+ return eval.value_nick;
}
+}
- public class TrayItem : Object {
+[DBus (name="org.kde.StatusNotifierItem")]
+internal interface IItem : DBusProxy {
+ public abstract string Title { owned get; }
+ public abstract Category Category { owned get; }
+ public abstract Status Status { owned get; }
+ public abstract Tooltip? ToolTip { owned get; }
+ public abstract string Id { owned get; }
+ public abstract string? IconThemePath { owned get; }
+ public abstract bool ItemIsMenu { owned get; }
+ public abstract ObjectPath? Menu { owned get; }
+ public abstract string IconName { owned get; }
+ public abstract Pixmap[] IconPixmap { owned get; }
+ public abstract string AttentionIconName { owned get; }
+ public abstract Pixmap[] AttentionIconPixmap { owned get; }
+ public abstract string OverlayIconName { owned get; }
+ public abstract Pixmap[] OverlayIconPixmap { owned get; }
+
+ public abstract void ContexMenu(int x, int y) throws DBusError, IOError;
+ public abstract void Activate(int x, int y) throws DBusError, IOError;
+ public abstract void SecondaryActivate(int x, int y) throws DBusError, IOError;
+ public abstract void Scroll(int delta, string orientation) throws DBusError, IOError;
+
+ public signal void NewTitle();
+ public signal void NewIcon();
+ public signal void NewAttentionIcon();
+ public signal void NewOverlayIcon();
+ public signal void NewToolTip();
+ public signal void NewStatus(string status);
+}
+public class TrayItem : Object {
private IItem proxy;
private List<ulong> connection_ids;
@@ -93,215 +92,220 @@ namespace AstalTray {
public Category category { get { return proxy.Category; } }
public Status status { get { return proxy.Status; } }
public Tooltip? tooltip { owned get { return proxy.ToolTip; } }
- public string tooltip_markup {
- owned get {
- if(proxy.ToolTip == null) return "";
- string tt = proxy.ToolTip.title;
- if (proxy.ToolTip.description != "")
- tt += "\n" + proxy.ToolTip.description;
+ public string tooltip_markup {
+ owned get {
+ if (proxy.ToolTip == null)
+ return "";
+
+ var tt = proxy.ToolTip.title;
+ if (proxy.ToolTip.description != "")
+ tt += "\n" + proxy.ToolTip.description;
- return tt;
- }
+ return tt;
+ }
}
+
public string id { owned get { return proxy.Id ;} }
public string icon_theme_path { owned get { return proxy.IconThemePath ;} }
public bool is_menu { get { return proxy.ItemIsMenu ;} }
public string icon_name {
- owned get {
- if(proxy.Status == Status.NEEDS_ATTENTION)
- return proxy.AttentionIconName;
- else return proxy.IconName;
- }
+ owned get {
+ return proxy.Status == Status.NEEDS_ATTENTION
+ ? proxy.AttentionIconName
+ : proxy.IconName;
+ }
}
public Gdk.Pixbuf icon_pixbuf { owned get { return _get_icon_pixbuf(); } }
-
+
public string item_id { get; private set; }
public signal void changed();
public signal void ready();
public TrayItem(string service, string path) {
-
- connection_ids = new List<ulong>();
- item_id = service + path;
- setup_proxy.begin(service, path, (_, res) => setup_proxy.end(res));
-
+ connection_ids = new List<ulong>();
+ item_id = service + path;
+ setup_proxy.begin(service, path, (_, res) => setup_proxy.end(res));
}
private async void setup_proxy(string service, string path) {
-
- try {
- proxy = yield Bus.get_proxy(
- BusType.SESSION,
- service,
- path);
-
- connection_ids.append(proxy.NewStatus.connect(() => refresh_all_properties()));
- connection_ids.append(proxy.NewToolTip.connect(() => refresh_all_properties()));
- connection_ids.append(proxy.NewTitle.connect(() => refresh_all_properties()));
- connection_ids.append(proxy.NewIcon.connect(() => refresh_all_properties()));
-
- proxy.notify["g-name-owner"].connect(() => {
- if (proxy.g_name_owner == null) {
- foreach (var id in connection_ids)
- SignalHandler.disconnect(proxy, id);
- }
- });
-
- ready();
- } catch (Error err) {
- critical("%s", err.message);
- }
-
+ try {
+ proxy = yield Bus.get_proxy(
+ BusType.SESSION,
+ service,
+ path);
+
+ connection_ids.append(proxy.NewStatus.connect(refresh_all_properties));
+ connection_ids.append(proxy.NewToolTip.connect(refresh_all_properties));
+ connection_ids.append(proxy.NewTitle.connect(refresh_all_properties));
+ connection_ids.append(proxy.NewIcon.connect(refresh_all_properties));
+
+ proxy.notify["g-name-owner"].connect(() => {
+ if (proxy.g_name_owner == null) {
+ foreach (var id in connection_ids)
+ SignalHandler.disconnect(proxy, id);
+ }
+ });
+
+ ready();
+ } catch (Error err) {
+ critical(err.message);
+ }
}
private void _notify() {
- string[] props = {
- "category", "id", "title", "status", "is-menu",
- "tooltip-markup"
- };
+ string[] props = { "category", "id", "title", "status", "is-menu", "tooltip-markup" };
- foreach (string prop in props)
- notify_property(prop);
+ foreach (string prop in props)
+ notify_property(prop);
- changed();
+ changed();
}
private void refresh_all_properties() {
- proxy.g_connection.call.begin(
- proxy.g_name,
- proxy.g_object_path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- new Variant("(s)", proxy.g_interface_name),
- new VariantType("(a{sv})"),
- DBusCallFlags.NONE,
- -1,
- null,
- (_, result) => {
- try {
- Variant parameters = proxy.g_connection.call.end(result);
- VariantIter prop_iter;
- parameters.get("(a{sv})", out prop_iter);
-
- string prop_key;
- Variant prop_value;
-
- while (prop_iter.next ("{sv}", out prop_key, out prop_value)) {
- proxy.set_cached_property(prop_key, prop_value);
+ proxy.g_connection.call.begin(
+ proxy.g_name,
+ proxy.g_object_path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ new Variant("(s)", proxy.g_interface_name),
+ new VariantType("(a{sv})"),
+ DBusCallFlags.NONE,
+ -1,
+ null,
+ (_, result) => {
+ try {
+ Variant parameters = proxy.g_connection.call.end(result);
+ VariantIter prop_iter;
+ parameters.get("(a{sv})", out prop_iter);
+
+ string prop_key;
+ Variant prop_value;
+
+ while (prop_iter.next ("{sv}", out prop_key, out prop_value)) {
+ proxy.set_cached_property(prop_key, prop_value);
+ }
+
+ _notify();
+ } catch(Error e) {
+ //silently ignore
+ }
}
- _notify();
-
- } catch(Error e) {
- //silently ignore
- }
- });
+ );
}
-
+
public void activate(int x, int y) {
- try {
- proxy.Activate(x, y);
- } catch (Error e) {
- if(e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD)
- warning("%s\n", e.message);
- }
+ try {
+ proxy.Activate(x, y);
+ } catch (Error e) {
+ if(e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD)
+ warning(e.message);
+ }
}
-
+
public void secondary_activate(int x, int y) {
- try {
- proxy.SecondaryActivate(x, y);
- } catch (Error e) {
- if(e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD)
- warning("%s\n", e.message);
- }
+ try {
+ proxy.SecondaryActivate(x, y);
+ } catch (Error e) {
+ if(e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD)
+ warning(e.message);
+ }
}
-
+
public void scroll(int delta, string orientation) {
- try {
- proxy.Scroll(delta, orientation);
- } catch (Error e) {
- if(e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD)
- warning("%s\n", e.message);
- }
- }
+ try {
+ proxy.Scroll(delta, orientation);
+ } catch (Error e) {
+ if(e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD)
+ warning("%s\n", e.message);
+ }
+ }
public DbusmenuGtk.Menu? create_menu() {
- if(proxy.Menu == null) return null;
- return new DbusmenuGtk.Menu(
- proxy.get_name_owner(),
- proxy.Menu);
+ if (proxy.Menu == null)
+ return null;
+
+ return new DbusmenuGtk.Menu(
+ proxy.get_name_owner(),
+ proxy.Menu);
}
public Gdk.Pixbuf? _get_icon_pixbuf() {
- Pixmap[] pixmaps = proxy.Status == Status.NEEDS_ATTENTION
- ? proxy.AttentionIconPixmap
- : proxy.IconPixmap;
+ Pixmap[] pixmaps = proxy.Status == Status.NEEDS_ATTENTION
+ ? proxy.AttentionIconPixmap
+ : proxy.IconPixmap;
- string icon_name = proxy.Status == Status.NEEDS_ATTENTION
- ? proxy.AttentionIconName
- : proxy.IconName;
+ string icon_name = proxy.Status == Status.NEEDS_ATTENTION
+ ? proxy.AttentionIconName
+ : proxy.IconName;
- Gdk.Pixbuf pixbuf = null;
+ Gdk.Pixbuf pixbuf = null;
+ if (icon_name != null && proxy.IconThemePath != null)
+ pixbuf = load_from_theme(icon_name, proxy.IconThemePath);
- 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;
+ 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;
+ 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);
+ 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);
+ 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;
+ if (icon_info != null)
+ return icon_info.load_icon();
+
+ return null;
}
private Gdk.Pixbuf? pixmap_to_pixbuf(Pixmap[] pixmaps) {
- if(pixmaps == null || pixmaps.length == 0) return null;
- Pixmap pixmap = pixmaps[0];
- uint8[] image_data = pixmap.bytes.copy();
-
- for (int i = 0; i < pixmap.width * pixmap.height * 4; i += 4) {
- uint8 alpha = image_data[i];
- image_data[i] = image_data[i + 1];
- image_data[i + 1] = image_data[i + 2];
- image_data[i + 2] = image_data[i + 3];
- image_data[i + 3] = alpha;
- }
-
- return new Gdk.Pixbuf.from_bytes(
- new Bytes(image_data),
- Gdk.Colorspace.RGB,
- true,
- 8,
- (int)pixmap.width,
- (int)pixmap.height,
- (int)(pixmap.width * 4)
- );
+ if (pixmaps == null || pixmaps.length == 0)
+ return null;
+
+ Pixmap pixmap = pixmaps[0];
+ uint8[] image_data = pixmap.bytes.copy();
+
+ for (int i = 0; i < pixmap.width * pixmap.height * 4; i += 4) {
+ uint8 alpha = image_data[i];
+ image_data[i] = image_data[i + 1];
+ image_data[i + 1] = image_data[i + 2];
+ image_data[i + 2] = image_data[i + 3];
+ image_data[i + 3] = alpha;
+ }
+
+ return new Gdk.Pixbuf.from_bytes(
+ new Bytes(image_data),
+ Gdk.Colorspace.RGB,
+ true,
+ 8,
+ (int)pixmap.width,
+ (int)pixmap.height,
+ (int)(pixmap.width * 4)
+ );
}
- public string to_json_string() {
+ public string to_json_string() {
var generator = new Json.Generator();
- generator.set_root(to_json());
- return generator.to_data(null);
+ generator.set_root(to_json());
+ return generator.to_data(null);
}
internal Json.Node to_json() {
@@ -322,7 +326,5 @@ namespace AstalTray {
.end_object()
.get_root();
}
- }
}
-
-
+}
diff --git a/src/watcher.vala b/src/watcher.vala
index cf06c7d..974cd02 100644
--- a/src/watcher.vala
+++ b/src/watcher.vala
@@ -1,67 +1,59 @@
namespace AstalTray {
+[DBus (name="org.kde.StatusNotifierWatcher")]
+internal class StatusNotifierWatcher : Object {
+ private HashTable<string, string> _items =
+ new HashTable<string, string>(str_hash, str_equal);
- [DBus (name="org.kde.StatusNotifierWatcher")]
- internal class StatusNotifierWatcher : Object {
+ public string[] RegisteredStatusNotifierItems { owned get { return _items.get_values_as_ptr_array().data; } }
+ public bool IsStatusNotifierHostRegistered { get; default = true; }
+ public int ProtocolVersion { get; default = 0; }
- private HashTable<string, string> _items;
+ public signal void StatusNotifierItemRegistered(string service);
+ public signal void StatusNotifierItemUnregistered(string service);
+ public signal void StatusNotifierHostRegistered();
+ public signal void StatusNotifierHostUnregistered();
- public string[] RegisteredStatusNotifierItems { owned get { return _items.get_values_as_ptr_array().data; } }
- public bool IsStatusNotifierHostRegistered { get; default = true; }
- public int ProtocolVersion { get; default = 0; }
-
- public signal void StatusNotifierItemRegistered(string service);
- public signal void StatusNotifierItemUnregistered(string service);
- public signal void StatusNotifierHostRegistered();
- public signal void StatusNotifierHostUnregistered();
-
- construct {
- _items = new HashTable<string, string>(GLib.str_hash, GLib.str_equal);
- }
-
- public void RegisterStatusNotifierItem(string service, BusName sender) throws DBusError, IOError {
+ public void RegisterStatusNotifierItem(string service, BusName sender) throws DBusError, IOError {
string busName;
string path;
- if(service[0] == '/') {
- path = service;
- busName = sender;
- }
- else {
- busName = service;
- path = "/StatusNotifierItem";
+ if (service[0] == '/') {
+ path = service;
+ busName = sender;
+ } else {
+ busName = service;
+ path = "/StatusNotifierItem";
}
Bus.get_sync(BusType.SESSION).signal_subscribe(
- null,
- "org.freedesktop.DBus",
- "NameOwnerChanged",
- null,
- null,
- DBusSignalFlags.NONE,
- (connection, sender_name, path, interface_name, signal_name, parameters) => {
- string name = null;
- string new_owner = null;
- string old_owner = null;
- parameters.get("(sss)", &name, &old_owner, &new_owner);
- if(new_owner == "" && _items.contains(old_owner)){
- string full_path = _items.take(old_owner);
- StatusNotifierItemUnregistered(full_path);
+ null,
+ "org.freedesktop.DBus",
+ "NameOwnerChanged",
+ null,
+ null,
+ DBusSignalFlags.NONE,
+ (connection, sender_name, path, interface_name, signal_name, parameters) => {
+ string name = null;
+ string new_owner = null;
+ string old_owner = null;
+ parameters.get("(sss)", &name, &old_owner, &new_owner);
+ if (new_owner == "" && _items.contains(old_owner)) {
+ string full_path = _items.take(old_owner);
+ StatusNotifierItemUnregistered(full_path);
+ }
}
- }
);
_items.set(busName, busName+path);
-
StatusNotifierItemRegistered(busName+path);
- }
+ }
- public void RegisterStatusNotifierHost(string service) throws DBusError, IOError {
- /*
- NOTE:
- usually the watcher should keep track of registered host
- but some tray applications do net register their trayitem properly
- when hosts register/deregister. This is fixed by setting isHostRegistered
- always to true, this also make host handling logic unneccessary.
- */
- }
+ public void RegisterStatusNotifierHost(string service) throws DBusError, IOError {
+ /* NOTE:
+ usually the watcher should keep track of registered host
+ but some tray applications do net register their trayitem properly
+ when hosts register/deregister. This is fixed by setting isHostRegistered
+ always to true, this also make host handling logic unneccessary.
+ */
}
}
+}