summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/apps/default.nix15
-rw-r--r--lib/apps/fuzzy.vala6
-rw-r--r--lib/astal/gtk3/default.nix21
-rw-r--r--lib/astal/gtk3/src/config.vala.in1
-rw-r--r--lib/astal/gtk3/src/meson.build1
-rw-r--r--lib/astal/gtk3/src/widget/circularprogress.vala2
-rw-r--r--lib/astal/gtk3/src/widget/icon.vala19
-rw-r--r--lib/astal/gtk3/src/widget/slider.vala12
-rw-r--r--lib/astal/gtk3/src/widget/window.vala9
-rw-r--r--lib/astal/gtk4/default.nix21
-rw-r--r--lib/astal/gtk4/src/application.vala20
-rw-r--r--lib/astal/gtk4/src/config.vala.in1
-rw-r--r--lib/astal/gtk4/src/meson.build3
-rw-r--r--lib/astal/gtk4/src/widget/box.vala50
-rw-r--r--lib/astal/gtk4/src/widget/slider.vala77
-rw-r--r--lib/astal/gtk4/src/widget/window.vala7
-rw-r--r--lib/astal/io/config.vala.in1
-rw-r--r--lib/astal/io/daemon.vala88
-rw-r--r--lib/astal/io/default.nix12
-rw-r--r--lib/astal/io/file.vala10
-rw-r--r--lib/astal/io/meson.build2
-rw-r--r--lib/astal/io/process.vala89
-rw-r--r--lib/astal/io/variable.vala2
-rw-r--r--lib/auth/default.nix15
-rw-r--r--lib/battery/config.vala.in1
-rw-r--r--lib/battery/default.nix15
-rw-r--r--lib/battery/meson.build1
-rw-r--r--lib/bluetooth/config.vala.in1
-rw-r--r--lib/bluetooth/default.nix10
-rw-r--r--lib/bluetooth/meson.build1
-rw-r--r--lib/cava/cava.c4
-rw-r--r--lib/cava/default.nix56
-rw-r--r--lib/greet/config.vala.in1
-rw-r--r--lib/greet/default.nix15
-rw-r--r--lib/greet/meson.build1
-rw-r--r--lib/hyprland/config.vala.in1
-rw-r--r--lib/hyprland/default.nix15
-rw-r--r--lib/hyprland/hyprland.vala43
-rw-r--r--lib/hyprland/meson.build1
-rw-r--r--lib/hyprland/structs.vala6
-rw-r--r--lib/mpris/config.vala.in1
-rw-r--r--lib/mpris/default.nix15
-rw-r--r--lib/mpris/meson.build1
-rw-r--r--lib/mpris/player.vala10
-rw-r--r--lib/network/config.vala.in1
-rw-r--r--lib/network/default.nix16
-rw-r--r--lib/network/meson.build1
-rw-r--r--lib/network/network.vala16
-rw-r--r--lib/notifd/config.vala.in1
-rw-r--r--lib/notifd/default.nix15
-rw-r--r--lib/notifd/meson.build1
-rw-r--r--lib/powerprofiles/cli.vala2
-rw-r--r--lib/powerprofiles/config.vala.in1
-rw-r--r--lib/powerprofiles/default.nix15
-rw-r--r--lib/powerprofiles/meson.build1
-rw-r--r--lib/powerprofiles/power-profiles.vala13
-rw-r--r--lib/river/default.nix21
-rw-r--r--lib/river/include/wayland-source.h16
-rw-r--r--lib/river/meson.build3
-rw-r--r--lib/river/src/meson.build4
-rw-r--r--lib/river/src/river.c12
-rw-r--r--lib/river/src/wayland-source.c104
l---------lib/river/subprojects/wayland-glib1
-rw-r--r--lib/tray/config.vala.in1
-rw-r--r--lib/tray/default.nix41
-rw-r--r--lib/tray/meson.build49
-rw-r--r--lib/tray/trayItem.vala244
-rw-r--r--lib/wayland-glib/meson.build40
-rw-r--r--lib/wayland-glib/version1
-rw-r--r--lib/wayland-glib/wl-source.vala44
-rw-r--r--lib/wireplumber/default.nix16
71 files changed, 1017 insertions, 346 deletions
diff --git a/lib/apps/default.nix b/lib/apps/default.nix
new file mode 100644
index 0000000..64466a2
--- /dev/null
+++ b/lib/apps/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-apps";
+ src = ./.;
+ packages = [pkgs.json-glib];
+
+ libname = "apps";
+ gir-suffix = "Apps";
+ authors = "Aylur";
+ description = "Application query library";
+}
diff --git a/lib/apps/fuzzy.vala b/lib/apps/fuzzy.vala
index 7745320..590112e 100644
--- a/lib/apps/fuzzy.vala
+++ b/lib/apps/fuzzy.vala
@@ -2,15 +2,15 @@ namespace AstalApps {
private int fuzzy_match_string(string pattern, string str) {
const int unmatched_letter_penalty = -1;
int score = 100;
+ int not_found_score = -10;
if (pattern.length == 0) return score;
- if (str.length < pattern.length) return int.MIN;
+ if (str.length < pattern.length) return not_found_score;
bool found = fuzzy_match_recurse(pattern, str, score, true, out score);
score += unmatched_letter_penalty * (str.length - pattern.length);
- if(!found) score = -10;
-
+ if(!found) score = not_found_score;
return score;
}
diff --git a/lib/astal/gtk3/default.nix b/lib/astal/gtk3/default.nix
new file mode 100644
index 0000000..c86f3de
--- /dev/null
+++ b/lib/astal/gtk3/default.nix
@@ -0,0 +1,21 @@
+{
+ mkAstalPkg,
+ pkgs,
+ self,
+}:
+mkAstalPkg {
+ pname = "astal3";
+ src = ./.;
+ packages = [
+ self.packages.${pkgs.system}.io
+ pkgs.gtk3
+ pkgs.gtk-layer-shell
+ ];
+
+ libname = "astal3";
+ gir-suffix = "";
+ authors = "Aylur";
+ description = "Astal GTK3 widget library";
+ dependencies = ["AstalIO-0.1" "Gtk-3.0"];
+ repo-path = "astal/gtk3";
+}
diff --git a/lib/astal/gtk3/src/config.vala.in b/lib/astal/gtk3/src/config.vala.in
index 88bfe9c..a141571 100644
--- a/lib/astal/gtk3/src/config.vala.in
+++ b/lib/astal/gtk3/src/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "Astal", gir_version = "@API_VERSION@")]
namespace Astal {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/astal/gtk3/src/meson.build b/lib/astal/gtk3/src/meson.build
index bf8f72a..2587b10 100644
--- a/lib/astal/gtk3/src/meson.build
+++ b/lib/astal/gtk3/src/meson.build
@@ -10,6 +10,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/astal/gtk3/src/widget/circularprogress.vala b/lib/astal/gtk3/src/widget/circularprogress.vala
index df1635d..de7a5c7 100644
--- a/lib/astal/gtk3/src/widget/circularprogress.vala
+++ b/lib/astal/gtk3/src/widget/circularprogress.vala
@@ -41,7 +41,7 @@ public class Astal.CircularProgress : Gtk.Bin {
}
static construct {
- set_css_name("circular-progress");
+ set_css_name("circularprogress");
}
public override Gtk.SizeRequestMode get_request_mode() {
diff --git a/lib/astal/gtk3/src/widget/icon.vala b/lib/astal/gtk3/src/widget/icon.vala
index 9a20359..ee6808c 100644
--- a/lib/astal/gtk3/src/widget/icon.vala
+++ b/lib/astal/gtk3/src/widget/icon.vala
@@ -9,7 +9,21 @@ public class Astal.Icon : Gtk.Image {
private double size { get; set; default = 14; }
public new Gdk.Pixbuf pixbuf { get; set; }
- public GLib.Icon g_icon { get; set; }
+
+ private static bool gicon_warned = false;
+ [Version (deprecated = true, deprecated_since = "0.1.0", replacement = "gicon")]
+ public GLib.Icon g_icon {
+ owned get {
+ return this.gicon;
+ }
+ set {
+ if( !gicon_warned ) {
+ GLib.warning("g-icon is deprecated. Use gicon instead.");
+ gicon_warned = true;
+ }
+ this.gicon = value;
+ }
+ }
/**
* Either a named icon or a path to a file.
@@ -57,7 +71,6 @@ public class Astal.Icon : Gtk.Image {
break;
case IconType.GICON:
pixel_size = (int)size;
- gicon = g_icon;
break;
}
@@ -86,7 +99,7 @@ public class Astal.Icon : Gtk.Image {
display_icon.begin();
});
- notify["g-icon"].connect(() => {
+ notify["gicon"].connect(() => {
type = IconType.GICON;
display_icon.begin();
});
diff --git a/lib/astal/gtk3/src/widget/slider.vala b/lib/astal/gtk3/src/widget/slider.vala
index 97cfb69..b927e32 100644
--- a/lib/astal/gtk3/src/widget/slider.vala
+++ b/lib/astal/gtk3/src/widget/slider.vala
@@ -30,6 +30,10 @@ public class Astal.Slider : Gtk.Scale {
step = 0.05;
}
+ if (page == 0) {
+ page = 0.01;
+ }
+
notify["orientation"].connect(() => {
notify_property("vertical");
});
@@ -90,5 +94,13 @@ public class Astal.Slider : Gtk.Scale {
set { adjustment.step_increment = value; }
}
+ /**
+ * Size of page increments. Defaults to `0.01`.
+ */
+ public double page {
+ get { return adjustment.page_increment; }
+ set { adjustment.page_increment = value; }
+ }
+
// TODO: marks
}
diff --git a/lib/astal/gtk3/src/widget/window.vala b/lib/astal/gtk3/src/widget/window.vala
index 11d542d..a066806 100644
--- a/lib/astal/gtk3/src/widget/window.vala
+++ b/lib/astal/gtk3/src/widget/window.vala
@@ -50,6 +50,13 @@ public class Astal.Window : Gtk.Window {
private InhibitManager? inhibit_manager;
private Inhibitor? inhibitor;
+ /**
+ * Get the current [[email protected]] this window resides in.
+ */
+ public Gdk.Monitor get_current_monitor() {
+ return Gdk.Display.get_default().get_monitor_at_window(base.get_window());
+ }
+
private bool check(string action) {
if (!is_supported()) {
critical(@"can not $action on window: layer shell not supported");
@@ -63,7 +70,7 @@ public class Astal.Window : Gtk.Window {
}
construct {
- // If the window has no size allocatoted when it gets mapped.
+ // If the window has no size allocatoted when it gets mapped
// It won't show up later either when it size changes by adding children.
height_request = 1;
width_request = 1;
diff --git a/lib/astal/gtk4/default.nix b/lib/astal/gtk4/default.nix
new file mode 100644
index 0000000..0bca3c0
--- /dev/null
+++ b/lib/astal/gtk4/default.nix
@@ -0,0 +1,21 @@
+{
+ mkAstalPkg,
+ pkgs,
+ self,
+}:
+mkAstalPkg {
+ pname = "astal4";
+ src = ./.;
+ packages = [
+ self.packages.${pkgs.system}.io
+ pkgs.gtk4
+ pkgs.gtk4-layer-shell
+ ];
+
+ libname = "astal4";
+ gir-suffix = "";
+ authors = "Aylur";
+ description = "Astal GTK4 widget library";
+ dependencies = ["AstalIO-0.1" "Gtk-4.0"];
+ repo-path = "astal/gtk4";
+}
diff --git a/lib/astal/gtk4/src/application.vala b/lib/astal/gtk4/src/application.vala
index fadf705..99f18f8 100644
--- a/lib/astal/gtk4/src/application.vala
+++ b/lib/astal/gtk4/src/application.vala
@@ -143,16 +143,22 @@ public class Astal.Application : Gtk.Application, AstalIO.Application {
public void apply_css(string style, bool reset = false) {
var provider = new Gtk.CssProvider();
+ provider.parsing_error.connect((section, error) => {
+ critical("CSS Error %s:%zu:%zu: %s\n",
+ section.get_file()?.get_basename() ?? "",
+ section.get_start_location().lines + 1,
+ section.get_start_location().line_chars + 1,
+ error.message
+ );
+ });
+
if (reset)
reset_css();
- try {
- if (FileUtils.test(style, FileTest.EXISTS))
- provider.load_from_path(style);
- else
- provider.load_from_string(style);
- } catch (Error err) {
- critical(err.message);
+ if (FileUtils.test(style, FileTest.EXISTS)) {
+ provider.load_from_path(style);
+ } else {
+ provider.load_from_string(style);
}
Gtk.StyleContext.add_provider_for_display(
diff --git a/lib/astal/gtk4/src/config.vala.in b/lib/astal/gtk4/src/config.vala.in
index 88bfe9c..a141571 100644
--- a/lib/astal/gtk4/src/config.vala.in
+++ b/lib/astal/gtk4/src/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "Astal", gir_version = "@API_VERSION@")]
namespace Astal {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/astal/gtk4/src/meson.build b/lib/astal/gtk4/src/meson.build
index 8aac969..58408a6 100644
--- a/lib/astal/gtk4/src/meson.build
+++ b/lib/astal/gtk4/src/meson.build
@@ -10,6 +10,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
@@ -25,6 +26,8 @@ deps = [
]
sources = [config] + files(
+ 'widget/box.vala',
+ 'widget/slider.vala',
'widget/window.vala',
'application.vala',
)
diff --git a/lib/astal/gtk4/src/widget/box.vala b/lib/astal/gtk4/src/widget/box.vala
new file mode 100644
index 0000000..28f2b00
--- /dev/null
+++ b/lib/astal/gtk4/src/widget/box.vala
@@ -0,0 +1,50 @@
+public class Astal.Box : Gtk.Box {
+ /**
+ * Corresponds to [[email protected] :orientation].
+ */
+ [CCode (notify = false)]
+ public bool vertical {
+ get { return orientation == Gtk.Orientation.VERTICAL; }
+ set { orientation = value ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL; }
+ }
+
+ construct {
+ notify["orientation"].connect(() => {
+ notify_property("vertical");
+ });
+ }
+
+ public List<weak Gtk.Widget> children {
+ set {
+ foreach (var child in children) {
+ remove(child);
+ }
+ foreach (var child in value) {
+ append(child);
+ }
+ }
+ owned get {
+ var list = new List<weak Gtk.Widget>();
+ var child = get_first_child();
+ while (child != null) {
+ list.append(child);
+ child = child.get_next_sibling();
+ }
+ return list;
+ }
+ }
+
+ public Gtk.Widget? child {
+ owned get {
+ foreach (var child in children) {
+ return child;
+ }
+ return null;
+ }
+ set {
+ var list = new List<weak Gtk.Widget>();
+ list.append(child);
+ this.children = children;
+ }
+ }
+}
diff --git a/lib/astal/gtk4/src/widget/slider.vala b/lib/astal/gtk4/src/widget/slider.vala
new file mode 100644
index 0000000..371f5be
--- /dev/null
+++ b/lib/astal/gtk4/src/widget/slider.vala
@@ -0,0 +1,77 @@
+public class Astal.Slider : Gtk.Scale {
+ private Gtk.EventControllerLegacy controller;
+ private bool dragging;
+
+ construct {
+ if (adjustment == null)
+ adjustment = new Gtk.Adjustment(0,0,0,0,0,0);
+
+ if (max == 0 && min == 0) {
+ max = 1;
+ }
+
+ if (step == 0) {
+ step = 0.05;
+ }
+
+ if (page == 0) {
+ page = 0.01;
+ }
+
+ controller = new Gtk.EventControllerLegacy();
+ add_controller(controller);
+ controller.event.connect((event) => {
+ var type = event.get_event_type();
+ if (type == Gdk.EventType.BUTTON_PRESS ||
+ type == Gdk.EventType.KEY_PRESS ||
+ type == Gdk.EventType.TOUCH_BEGIN) {
+ dragging = true;
+ }
+ if (type == Gdk.EventType.BUTTON_RELEASE ||
+ type == Gdk.EventType.KEY_RELEASE ||
+ type == Gdk.EventType.TOUCH_END) {
+ dragging = false;
+ }
+ });
+ }
+
+ /**
+ * Value of this slider. Defaults to `0`.
+ */
+ public double value {
+ get { return adjustment.value; }
+ set { if (!dragging) adjustment.value = value; }
+ }
+
+ /**
+ * Minimum possible value of this slider. Defaults to `0`.
+ */
+ public double min {
+ get { return adjustment.lower; }
+ set { adjustment.lower = value; }
+ }
+
+ /**
+ * Maximum possible value of this slider. Defaults to `1`.
+ */
+ public double max {
+ get { return adjustment.upper; }
+ set { adjustment.upper = value; }
+ }
+
+ /**
+ * Size of step increments. Defaults to `0.05`.
+ */
+ public double step {
+ get { return adjustment.step_increment; }
+ set { adjustment.step_increment = value; }
+ }
+
+ /**
+ * Size of page increments. Defaults to `0.01`.
+ */
+ public double page {
+ get { return adjustment.page_increment; }
+ set { adjustment.page_increment = value; }
+ }
+}
diff --git a/lib/astal/gtk4/src/widget/window.vala b/lib/astal/gtk4/src/widget/window.vala
index 0cf3d11..3b0d113 100644
--- a/lib/astal/gtk4/src/widget/window.vala
+++ b/lib/astal/gtk4/src/widget/window.vala
@@ -47,6 +47,13 @@ public enum Astal.Keymode {
* Subclass of [[email protected]] which integrates GtkLayerShell as class fields.
*/
public class Astal.Window : Gtk.Window {
+ /**
+ * Get the current [[email protected]] this window resides in.
+ */
+ public Gdk.Monitor get_current_monitor() {
+ return Gdk.Display.get_default().get_monitor_at_surface(base.get_surface());
+ }
+
private bool check(string action) {
if (!is_supported()) {
critical(@"can not $action on window: layer shell not supported");
diff --git a/lib/astal/io/config.vala.in b/lib/astal/io/config.vala.in
index fe1e450..4aee790 100644
--- a/lib/astal/io/config.vala.in
+++ b/lib/astal/io/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalIO", gir_version = "@API_VERSION@")]
namespace AstalIO {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/astal/io/daemon.vala b/lib/astal/io/daemon.vala
new file mode 100644
index 0000000..7f3173e
--- /dev/null
+++ b/lib/astal/io/daemon.vala
@@ -0,0 +1,88 @@
+[DBus (name="io.Astal.Application")]
+public class AstalIO.Daemon : GLib.Application, AstalIO.Application {
+ private SocketService service;
+ private DBusConnection conn;
+ private string _instance_name = "astal";
+ private string socket_path { get; private set; }
+
+ /**
+ * A unique instance name.
+ *
+ * This is the identifier used by the AstalIO package and the CLI.
+ */
+ [DBus (visible=false)]
+ public string instance_name {
+ owned get { return _instance_name; }
+ construct set {
+ _instance_name = value != null ? value : "astal";
+ application_id = @"io.Astal.$_instance_name";
+ }
+ }
+
+ /**
+ * Handler for an incoming request.
+ *
+ * @param msg Body of the message
+ * @param conn The connection which expects the response.
+ */
+ [DBus (visible=false)]
+ public virtual void request(string msg, SocketConnection conn) {
+ AstalIO.write_sock.begin(conn, @"missing response implementation on $application_id");
+ }
+
+ /**
+ * Attempt to acquire the astal socket for this app identified by its [[email protected]:instance_name].
+ * If the socket is in use by another app with the same name an [[email protected]_OCCUPIED] is thrown.
+ */
+ [DBus (visible=false)]
+ public void acquire_socket() throws Error {
+ string path;
+ service = AstalIO.acquire_socket(this, out path);
+ socket_path = path;
+
+ Bus.own_name(
+ BusType.SESSION,
+ application_id,
+ BusNameOwnerFlags.NONE,
+ (conn) => {
+ try {
+ this.conn = conn;
+ conn.register_object("/io/Astal/Application", this);
+ } catch (Error err) {
+ critical(err.message);
+ }
+ },
+ () => {},
+ () => {}
+ );
+ }
+
+ public void inspector() throws DBusError, IOError {
+ throw new DBusError.FAILED("Daemon does not implement inspector");
+ }
+
+ public void toggle_window(string window) throws DBusError, IOError {
+ throw new DBusError.FAILED("Daemon does not implement toggle_window");
+ }
+
+ /**
+ * Quit and stop the socket if it was acquired.
+ */
+ public new void quit() throws DBusError, IOError {
+ if (service != null) {
+ service.stop();
+ service.close();
+ }
+
+ base.quit();
+ }
+
+ construct {
+ hold();
+
+ shutdown.connect(() => { try { quit(); } catch(Error err) {} });
+ Unix.signal_add(1, () => { try { quit(); } catch(Error err) {} }, Priority.HIGH);
+ Unix.signal_add(2, () => { try { quit(); } catch(Error err) {} }, Priority.HIGH);
+ Unix.signal_add(15, () => { try { quit(); } catch(Error err) {} }, Priority.HIGH);
+ }
+}
diff --git a/lib/astal/io/default.nix b/lib/astal/io/default.nix
new file mode 100644
index 0000000..c33132a
--- /dev/null
+++ b/lib/astal/io/default.nix
@@ -0,0 +1,12 @@
+{mkAstalPkg, ...}:
+mkAstalPkg {
+ pname = "astal";
+ src = ./.;
+
+ libname = "io";
+ gir-suffix = "IO";
+ authors = "Aylur";
+ description = "Astal Core library";
+ repo-path = "astal/io";
+ website-path = "io";
+}
diff --git a/lib/astal/io/file.vala b/lib/astal/io/file.vala
index 57b6dc0..e8e8a8b 100644
--- a/lib/astal/io/file.vala
+++ b/lib/astal/io/file.vala
@@ -26,6 +26,11 @@ public async string read_file_async(string path) throws Error {
*/
public void write_file(string path, string content) {
try {
+ var dir = Path.get_dirname(path);
+ if (!FileUtils.test(dir, FileTest.IS_DIR)) {
+ File.new_for_path(dir).make_directory_with_parents(null);
+ }
+
FileUtils.set_contents(path, content);
} catch (Error error) {
critical(error.message);
@@ -36,6 +41,11 @@ public void write_file(string path, string content) {
* Write content to a file asynchronously.
*/
public async void write_file_async(string path, string content) throws Error {
+ var dir = Path.get_dirname(path);
+ if (!FileUtils.test(dir, FileTest.IS_DIR)) {
+ File.new_for_path(dir).make_directory_with_parents(null);
+ }
+
yield File.new_for_path(path).replace_contents_async(
content.data,
null,
diff --git a/lib/astal/io/meson.build b/lib/astal/io/meson.build
index 023dece..9a00904 100644
--- a/lib/astal/io/meson.build
+++ b/lib/astal/io/meson.build
@@ -22,6 +22,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
@@ -38,6 +39,7 @@ deps = [
sources = [config] + files(
'application.vala',
+ 'daemon.vala',
'file.vala',
'process.vala',
'time.vala',
diff --git a/lib/astal/io/process.vala b/lib/astal/io/process.vala
index cfd05b9..95c67a3 100644
--- a/lib/astal/io/process.vala
+++ b/lib/astal/io/process.vala
@@ -2,20 +2,22 @@
* `Process` provides shortcuts for [[email protected]] with sane defaults.
*/
public class AstalIO.Process : Object {
+ public string[] argv { construct; get; }
+
private void read_stream(DataInputStream stream, bool err) {
stream.read_line_utf8_async.begin(Priority.DEFAULT, null, (_, res) => {
try {
var output = stream.read_line_utf8_async.end(res);
if (output != null) {
- if (err)
+ if (err) {
stdout(output.strip());
- else
+ } else {
stderr(output.strip());
-
+ }
read_stream(stream, err);
}
} catch (Error err) {
- printerr("%s\n", err.message);
+ critical(err.message);
}
});
}
@@ -24,20 +26,27 @@ public class AstalIO.Process : Object {
private DataInputStream err_stream;
private DataOutputStream in_stream;
private Subprocess process;
- public string[] argv { construct; get; }
+ /**
+ * When the underlying subprocess writes to its stdout.
+ *
+ * @param out Line written to stdout
+ */
+ public signal void stdout(string out);
/**
- * When the underlying subprocess writes to its stdout
- * this signal is emitted with that line.
+ * When the underlying subprocess writes to its stderr.
+ *
+ * @param err Line written to stderr
*/
- public signal void stdout (string out);
+ public signal void stderr(string err);
/**
- * When the underlying subprocess writes to its stderr
- * this signal is emitted with that line.
+ * When the underlying subprocess exits or is terminated.
+ *
+ * @param code Exit code or signal number if terminated
*/
- public signal void stderr (string err);
+ public signal void exit(int code, bool terminated);
/**
* Force quit the subprocess.
@@ -48,6 +57,8 @@ public class AstalIO.Process : Object {
/**
* Send a signal to the subprocess.
+ *
+ * @param signal_num Signal number to be sent
*/
public void signal(int signal_num) {
process.send_signal(signal_num);
@@ -55,6 +66,8 @@ public class AstalIO.Process : Object {
/**
* Write a line to the subprocess' stdin synchronously.
+ *
+ * @param in String to be written to stdin
*/
public void write(string in) throws Error {
in_stream.put_string(in);
@@ -62,6 +75,8 @@ public class AstalIO.Process : Object {
/**
* Write a line to the subprocess' stdin asynchronously.
+ *
+ * @param in String to be written to stdin
*/
public async void write_async(string in) {
try {
@@ -71,23 +86,47 @@ public class AstalIO.Process : Object {
}
}
- /**
- * Start a new subprocess with the given command.
- *
- * The first element of the vector is executed with the remaining elements as the argument list.
- */
- public Process.subprocessv(string[] cmd) throws Error {
+ /** See [[email protected]] */
+ public Process(string[] cmd) throws Error {
Object(argv: cmd);
- process = new Subprocess.newv(cmd,
+ process = new Subprocess.newv(
+ cmd,
SubprocessFlags.STDIN_PIPE |
SubprocessFlags.STDERR_PIPE |
SubprocessFlags.STDOUT_PIPE
);
+
out_stream = new DataInputStream(process.get_stdout_pipe());
err_stream = new DataInputStream(process.get_stderr_pipe());
in_stream = new DataOutputStream(process.get_stdin_pipe());
+
read_stream(out_stream, true);
read_stream(err_stream, false);
+
+ process.wait_async.begin(null, (_, res) => {
+ try {
+ process.wait_async.end(res);
+ } catch (Error err) {
+ // ignore
+ }
+
+ if (process.get_if_exited()) {
+ exit(process.get_exit_status(), false);
+ }
+
+ if (process.get_if_signaled()) {
+ exit(process.get_term_sig(), true);
+ }
+ });
+ }
+
+ /**
+ * Start a new subprocess with the given command.
+ *
+ * The first element of the vector is executed with the remaining elements as the argument list.
+ */
+ public static Process subprocessv(string[] cmd) throws Error {
+ return new Process(cmd);
}
/**
@@ -97,7 +136,7 @@ public class AstalIO.Process : Object {
public static Process subprocess(string cmd) throws Error {
string[] argv;
Shell.parse_argv(cmd, out argv);
- return new Process.subprocessv(argv);
+ return Process.subprocessv(argv);
}
/**
@@ -116,11 +155,11 @@ public class AstalIO.Process : Object {
string err_str, out_str;
process.communicate_utf8(null, null, out out_str, out err_str);
var success = process.get_successful();
- process.dispose();
- if (success)
+ if (success) {
return out_str.strip();
- else
+ } else {
throw new IOError.FAILED(err_str.strip());
+ }
}
/**
@@ -151,11 +190,11 @@ public class AstalIO.Process : Object {
string err_str, out_str;
yield process.communicate_utf8_async(null, null, out out_str, out err_str);
var success = process.get_successful();
- process.dispose();
- if (success)
+ if (success) {
return out_str.strip();
- else
+ } else {
throw new IOError.FAILED(err_str.strip());
+ }
}
/**
diff --git a/lib/astal/io/variable.vala b/lib/astal/io/variable.vala
index 312a27a..e4105f8 100644
--- a/lib/astal/io/variable.vala
+++ b/lib/astal/io/variable.vala
@@ -172,7 +172,7 @@ public class AstalIO.Variable : VariableBase {
return_if_fail(watch_proc == null);
return_if_fail(watch_exec != null);
- watch_proc = new Process.subprocessv(watch_exec);
+ watch_proc = Process.subprocessv(watch_exec);
watch_proc.stdout.connect((str) => set_closure(str, watch_transform));
watch_proc.stderr.connect((str) => this.error(str));
}
diff --git a/lib/auth/default.nix b/lib/auth/default.nix
new file mode 100644
index 0000000..3b8b276
--- /dev/null
+++ b/lib/auth/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-auth";
+ src = ./.;
+ packages = [pkgs.pam];
+
+ libname = "auth";
+ gir-suffix = "Auth";
+ authors = "kotontrion";
+ description = "Authentication using pam";
+}
diff --git a/lib/battery/config.vala.in b/lib/battery/config.vala.in
index 6e7f77e..404e60a 100644
--- a/lib/battery/config.vala.in
+++ b/lib/battery/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalBattery", gir_version = "@API_VERSION@")]
namespace AstalBattery {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/battery/default.nix b/lib/battery/default.nix
new file mode 100644
index 0000000..17bf67a
--- /dev/null
+++ b/lib/battery/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-battery";
+ src = ./.;
+ packages = [pkgs.json-glib];
+
+ libname = "battery";
+ authors = "Aylur";
+ gir-suffix = "Battery";
+ description = "DBus proxy for upowerd devices";
+}
diff --git a/lib/battery/meson.build b/lib/battery/meson.build
index 054e9db..ec8e3d0 100644
--- a/lib/battery/meson.build
+++ b/lib/battery/meson.build
@@ -25,6 +25,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/bluetooth/config.vala.in b/lib/bluetooth/config.vala.in
index 9fce720..f43dba3 100644
--- a/lib/bluetooth/config.vala.in
+++ b/lib/bluetooth/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalBluetooth", gir_version = "@API_VERSION@")]
namespace AstalBluetooth {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/bluetooth/default.nix b/lib/bluetooth/default.nix
new file mode 100644
index 0000000..f2d58c8
--- /dev/null
+++ b/lib/bluetooth/default.nix
@@ -0,0 +1,10 @@
+{mkAstalPkg, ...}:
+mkAstalPkg {
+ pname = "astal-bluetooth";
+ src = ./.;
+
+ libname = "bluetooth";
+ authors = "Aylur";
+ gir-suffix = "Bluetooth";
+ description = "DBus proxy for bluez";
+}
diff --git a/lib/bluetooth/meson.build b/lib/bluetooth/meson.build
index 5288a9e..529e85f 100644
--- a/lib/bluetooth/meson.build
+++ b/lib/bluetooth/meson.build
@@ -20,6 +20,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/cava/cava.c b/lib/cava/cava.c
index 1c5ef66..2934335 100644
--- a/lib/cava/cava.c
+++ b/lib/cava/cava.c
@@ -440,7 +440,7 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa
g_value_set_int(value, self->bars);
break;
case ASTAL_CAVA_CAVA_PROP_VALUES:
- g_value_set_pointer(value, self->values);
+ g_value_set_boxed(value, self->values);
break;
case ASTAL_CAVA_CAVA_PROP_AUTOSENS:
g_value_set_boolean(value, self->autosens);
@@ -558,7 +558,7 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) {
* be 0.
*/
astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_VALUES] =
- g_param_spec_pointer("values", "values", "a list of values", G_PARAM_READABLE);
+ g_param_spec_boxed("values", "values", "a list of values", G_TYPE_ARRAY, G_PARAM_READABLE);
/**
* AstalCavaCava:active:
*
diff --git a/lib/cava/default.nix b/lib/cava/default.nix
new file mode 100644
index 0000000..5472e8c
--- /dev/null
+++ b/lib/cava/default.nix
@@ -0,0 +1,56 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}: let
+ libcava = pkgs.stdenv.mkDerivation rec {
+ pname = "cava";
+ version = "0.10.3";
+
+ src = pkgs.fetchFromGitHub {
+ owner = "LukashonakV";
+ repo = "cava";
+ rev = "0.10.3";
+ hash = "sha256-ZDFbI69ECsUTjbhlw2kHRufZbQMu+FQSMmncCJ5pagg=";
+ };
+
+ buildInputs = with pkgs; [
+ alsa-lib
+ libpulseaudio
+ ncurses
+ iniparser
+ sndio
+ SDL2
+ libGL
+ portaudio
+ jack2
+ pipewire
+ ];
+
+ propagatedBuildInputs = with pkgs; [
+ fftw
+ ];
+
+ nativeBuildInputs = with pkgs; [
+ autoreconfHook
+ autoconf-archive
+ pkgconf
+ meson
+ ninja
+ ];
+
+ preAutoreconf = ''
+ echo ${version} > version
+ '';
+ };
+in
+ mkAstalPkg {
+ pname = "astal-cava";
+ src = ./.;
+ packages = [libcava];
+
+ libname = "cava";
+ authors = "kotontrion";
+ gir-suffix = "Cava";
+ description = "Audio visualization library using cava";
+ }
diff --git a/lib/greet/config.vala.in b/lib/greet/config.vala.in
index 333d735..a7990aa 100644
--- a/lib/greet/config.vala.in
+++ b/lib/greet/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalGreet", gir_version = "@API_VERSION@")]
namespace AstalGreet {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/greet/default.nix b/lib/greet/default.nix
new file mode 100644
index 0000000..22b9456
--- /dev/null
+++ b/lib/greet/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-greet";
+ src = ./.;
+ packages = [pkgs.json-glib];
+
+ libname = "greet";
+ authors = "Aylur";
+ gir-suffix = "Greet";
+ description = "IPC client for greetd";
+}
diff --git a/lib/greet/meson.build b/lib/greet/meson.build
index 11321b0..8bd35d7 100644
--- a/lib/greet/meson.build
+++ b/lib/greet/meson.build
@@ -25,6 +25,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/hyprland/config.vala.in b/lib/hyprland/config.vala.in
index 65993b2..0cdba75 100644
--- a/lib/hyprland/config.vala.in
+++ b/lib/hyprland/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalHyprland", gir_version = "@API_VERSION@")]
namespace AstalHyprland {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/hyprland/default.nix b/lib/hyprland/default.nix
new file mode 100644
index 0000000..6b5e15d
--- /dev/null
+++ b/lib/hyprland/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-hyprland";
+ src = ./.;
+ packages = [pkgs.json-glib];
+
+ libname = "hyprland";
+ authors = "Aylur";
+ gir-suffix = "Hyprland";
+ description = "IPC client for Hyprland";
+}
diff --git a/lib/hyprland/hyprland.vala b/lib/hyprland/hyprland.vala
index 9825a91..70b5a25 100644
--- a/lib/hyprland/hyprland.vala
+++ b/lib/hyprland/hyprland.vala
@@ -303,6 +303,20 @@ public class Hyprland : Object {
}
}
+ private async bool try_add_client(string addr) throws Error {
+ if (addr == "" || get_client(addr) != null) {
+ return true;
+ }
+
+ var client = new Client();
+ _clients.insert(addr, client);
+ yield sync_clients();
+ yield sync_workspaces();
+ client_added(client);
+ notify_property("clients");
+ return false;
+ }
+
private async void handle_event(string line) throws Error {
var args = line.split(">>");
@@ -315,25 +329,11 @@ public class Hyprland : Object {
case "focusedmon":
var argv = args[1].split(",", 2);
+ yield sync_monitors();
focused_monitor = get_monitor_by_name(argv[0]);
focused_workspace = get_workspace_by_name(argv[1]);
break;
- // first event that signals a new client
- case "activewindowv2":
- if (args[1] != "" && get_client(args[1]) == null) {
- var client = new Client();
- _clients.insert(args[1], client);
- yield sync_clients();
- yield sync_workspaces();
- client_added(client);
- notify_property("clients");
- focused_client = client;
- } else {
- focused_client = get_client(args[1]);
- }
- break;
-
// TODO: nag vaxry for fullscreenv2 that passes address
case "fullscreen":
yield sync_clients();
@@ -392,9 +392,18 @@ public class Hyprland : Object {
keyboard_layout(argv[0], argv[1]);
break;
+ // first event that signals a new client when it opens as an active window
+ case "activewindowv2":
+ yield try_add_client(args[1]);
+ focused_client = get_client(args[1]);
+ break;
+
case "openwindow":
- yield sync_clients();
- yield sync_workspaces();
+ var addr = args[1].split(",")[0];
+ if (yield try_add_client(addr)) {
+ yield sync_clients();
+ yield sync_workspaces();
+ }
break;
case "closewindow":
diff --git a/lib/hyprland/meson.build b/lib/hyprland/meson.build
index 7112ee1..9598ba9 100644
--- a/lib/hyprland/meson.build
+++ b/lib/hyprland/meson.build
@@ -25,6 +25,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/hyprland/structs.vala b/lib/hyprland/structs.vala
index 25f70c3..d5180b1 100644
--- a/lib/hyprland/structs.vala
+++ b/lib/hyprland/structs.vala
@@ -4,12 +4,15 @@ public class Bind : Object {
public bool mouse { get; construct set; }
public bool release { get; construct set; }
public bool repeat { get; construct set; }
+ public bool long_press { get; construct set; }
public bool non_consuming { get; construct set; }
+ public bool has_description { get; construct set; }
public int64 modmask { get; construct set; }
public string submap { get; construct set; }
public string key { get; construct set; }
public int64 keycode { get; construct set; }
public bool catch_all { get; construct set; }
+ public string description { get; construct set; }
public string dispatcher { get; construct set; }
public string arg { get; construct set; }
@@ -18,12 +21,15 @@ public class Bind : Object {
mouse = obj.get_boolean_member("mouse");
release = obj.get_boolean_member("release");
repeat = obj.get_boolean_member("repeat");
+ long_press = obj.get_member("longPress")?.get_boolean() ?? false;
non_consuming = obj.get_boolean_member("non_consuming");
+ has_description = obj.get_member("has_description")?.get_boolean() ?? false;
modmask = obj.get_int_member("modmask");
submap = obj.get_string_member("submap");
key = obj.get_string_member("key");
keycode = obj.get_int_member("keycode");
catch_all = obj.get_boolean_member("catch_all");
+ description = obj.get_member("description")?.get_string() ?? "";
dispatcher = obj.get_string_member("dispatcher");
arg = obj.get_string_member("arg");
}
diff --git a/lib/mpris/config.vala.in b/lib/mpris/config.vala.in
index 767c4bd..f44c3dc 100644
--- a/lib/mpris/config.vala.in
+++ b/lib/mpris/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalMpris", gir_version = "@API_VERSION@")]
namespace AstalMpris {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/mpris/default.nix b/lib/mpris/default.nix
new file mode 100644
index 0000000..082c647
--- /dev/null
+++ b/lib/mpris/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-mpris";
+ src = ./.;
+ packages = with pkgs; [gvfs json-glib];
+
+ libname = "mpris";
+ authors = "Aylur";
+ gir-suffix = "Mpris";
+ description = "Control mpris players";
+}
diff --git a/lib/mpris/meson.build b/lib/mpris/meson.build
index bf215c9..91185c8 100644
--- a/lib/mpris/meson.build
+++ b/lib/mpris/meson.build
@@ -25,6 +25,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/mpris/player.vala b/lib/mpris/player.vala
index c69eb21..e6d84bf 100644
--- a/lib/mpris/player.vala
+++ b/lib/mpris/player.vala
@@ -440,6 +440,9 @@ public class AstalMpris.Player : Object {
_loop_status = Loop.from_string(proxy.loop_status);
notify_property("loop-status");
}
+ } else {
+ _loop_status = Loop.UNSUPPORTED;
+ notify_property("loop-status");
}
if (rate != proxy.rate) {
@@ -452,6 +455,9 @@ public class AstalMpris.Player : Object {
_shuffle_status = Shuffle.from_bool(proxy.shuffle);
notify_property("shuffle-status");
}
+ } else {
+ _shuffle_status = Shuffle.UNSUPPORTED;
+ notify_property("shuffle-status");
}
if (volume != proxy.volume) {
@@ -498,8 +504,10 @@ public class AstalMpris.Player : Object {
}
private async void cache_cover() {
- if (art_url == null || art_url == "")
+ if (art_url == null || art_url == "") {
+ cover_art = null;
return;
+ }
var file = File.new_for_uri(art_url);
if (file.get_path() != null) {
diff --git a/lib/network/config.vala.in b/lib/network/config.vala.in
index dbec0f3..3e5beb5 100644
--- a/lib/network/config.vala.in
+++ b/lib/network/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalNetwork", gir_version = "@API_VERSION@")]
namespace AstalNetwork {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/network/default.nix b/lib/network/default.nix
new file mode 100644
index 0000000..cfa2378
--- /dev/null
+++ b/lib/network/default.nix
@@ -0,0 +1,16 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-network";
+ src = ./.;
+ packages = [pkgs.networkmanager];
+
+ libname = "network";
+ authors = "Aylur";
+ gir-suffix = "Network";
+ description = "NetworkManager wrapper library";
+ dependencies = ["NM-1.0"];
+}
diff --git a/lib/network/meson.build b/lib/network/meson.build
index 17ea358..a490179 100644
--- a/lib/network/meson.build
+++ b/lib/network/meson.build
@@ -20,6 +20,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/network/network.vala b/lib/network/network.vala
index 96e19c8..b5a6c61 100644
--- a/lib/network/network.vala
+++ b/lib/network/network.vala
@@ -104,14 +104,14 @@ public enum AstalNetwork.Primary {
// alias for NM.State
public enum AstalNetwork.State {
- UNKNOWN,
- ASLEEP,
- DISCONNECTED,
- DISCONNECTING,
- CONNECTING,
- CONNECTED_LOCAL,
- CONNECTED_SITE,
- CONNECTED_GLOBAL;
+ UNKNOWN = 0,
+ ASLEEP = 10,
+ DISCONNECTED = 20,
+ DISCONNECTING = 30,
+ CONNECTING = 40,
+ CONNECTED_LOCAL = 50,
+ CONNECTED_SITE = 60,
+ CONNECTED_GLOBAL = 70;
public string to_string() {
switch (this) {
diff --git a/lib/notifd/config.vala.in b/lib/notifd/config.vala.in
index 752c754..04b2cd2 100644
--- a/lib/notifd/config.vala.in
+++ b/lib/notifd/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalNotifd", gir_version = "@API_VERSION@")]
namespace AstalNotifd {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/notifd/default.nix b/lib/notifd/default.nix
new file mode 100644
index 0000000..e23528c
--- /dev/null
+++ b/lib/notifd/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-notifd";
+ src = ./.;
+ packages = with pkgs; [json-glib gdk-pixbuf];
+
+ libname = "notifd";
+ authors = "Aylur";
+ gir-suffix = "Notifd";
+ description = "Notification daemon library";
+}
diff --git a/lib/notifd/meson.build b/lib/notifd/meson.build
index 3d4de95..a9e7faf 100644
--- a/lib/notifd/meson.build
+++ b/lib/notifd/meson.build
@@ -26,6 +26,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/powerprofiles/cli.vala b/lib/powerprofiles/cli.vala
index 1e5cc70..87ffe82 100644
--- a/lib/powerprofiles/cli.vala
+++ b/lib/powerprofiles/cli.vala
@@ -100,7 +100,7 @@ string to_json_string(AstalPowerProfiles.PowerProfiles profiles) {
foreach (var prof in profiles.profiles) {
profs.add_value(new Json.Builder()
.begin_object()
- .set_member_name("profie").add_string_value(prof.profile)
+ .set_member_name("profile").add_string_value(prof.profile)
.set_member_name("driver").add_string_value(prof.driver)
.set_member_name("cpu_driver").add_string_value(prof.cpu_driver)
.set_member_name("platform_driver").add_string_value(prof.platform_driver)
diff --git a/lib/powerprofiles/config.vala.in b/lib/powerprofiles/config.vala.in
index 79034f1..cc9d309 100644
--- a/lib/powerprofiles/config.vala.in
+++ b/lib/powerprofiles/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalPowerProfiles", gir_version = "@API_VERSION@")]
namespace AstalPowerProfiles {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/powerprofiles/default.nix b/lib/powerprofiles/default.nix
new file mode 100644
index 0000000..f35f9e5
--- /dev/null
+++ b/lib/powerprofiles/default.nix
@@ -0,0 +1,15 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-powerprofiles";
+ src = ./.;
+ packages = [pkgs.json-glib];
+
+ libname = "powerprofiles";
+ authors = "Aylur";
+ gir-suffix = "PowerProfiles";
+ description = "DBus proxy for upowerd profiles";
+}
diff --git a/lib/powerprofiles/meson.build b/lib/powerprofiles/meson.build
index cd8cc2b..4a31afa 100644
--- a/lib/powerprofiles/meson.build
+++ b/lib/powerprofiles/meson.build
@@ -25,6 +25,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
diff --git a/lib/powerprofiles/power-profiles.vala b/lib/powerprofiles/power-profiles.vala
index a104d2e..931fc04 100644
--- a/lib/powerprofiles/power-profiles.vala
+++ b/lib/powerprofiles/power-profiles.vala
@@ -113,6 +113,11 @@ public class PowerProfiles : Object {
owned get { return proxy.performance_degraded; }
}
+ private string? get_hashtable_string(HashTable<string, Variant> table, string key) {
+ var v = table.get(key);
+ return v == null ? null : v.get_string();
+ }
+
/**
* List of each profile.
*/
@@ -122,10 +127,10 @@ public class PowerProfiles : Object {
for (var i = 0; i < proxy.profiles.length; ++i) {
var prof = proxy.profiles[i];
profs[i] = Profile() {
- profile = prof.get("Profile").get_string(),
- cpu_driver = prof.get("CpuDriver").get_string(),
- platform_driver = prof.get("PlatformDriver").get_string(),
- driver = prof.get("Driver").get_string()
+ profile = get_hashtable_string(prof, "Profile"),
+ cpu_driver = get_hashtable_string(prof, "CpuDriver"),
+ platform_driver = get_hashtable_string(prof, "PlatformDriver"),
+ driver = get_hashtable_string(prof, "Driver"),
};
}
return profs;
diff --git a/lib/river/default.nix b/lib/river/default.nix
new file mode 100644
index 0000000..15c6eb4
--- /dev/null
+++ b/lib/river/default.nix
@@ -0,0 +1,21 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-river";
+ src = ./.;
+ packages = [pkgs.json-glib];
+
+ libname = "river";
+ authors = "kotontrion";
+ gir-suffix = "River";
+ description = "IPC client for River";
+
+ postUnpack = ''
+ rm -rf $sourceRoot/subprojects
+ mkdir -p $sourceRoot/subprojects
+ cp -r --remove-destination ${../wayland-glib} $sourceRoot/subprojects/wayland-glib
+ '';
+}
diff --git a/lib/river/include/wayland-source.h b/lib/river/include/wayland-source.h
deleted file mode 100644
index b219589..0000000
--- a/lib/river/include/wayland-source.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __WAYLAND_SOURCE_H__
-#define __WAYLAND_SOURCE_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-typedef struct _WLSource WLSource;
-
-WLSource* wl_source_new();
-void wl_source_free(WLSource* self);
-struct wl_display* wl_source_get_display(WLSource* source);
-
-G_END_DECLS
-
-#endif /* __WAYLAND_SOURCE_H__ */
diff --git a/lib/river/meson.build b/lib/river/meson.build
index aa5e23b..2f98315 100644
--- a/lib/river/meson.build
+++ b/lib/river/meson.build
@@ -13,6 +13,9 @@ lib_so_version = version_split[0] + '.' + version_split[1]
pkg_config = import('pkgconfig')
gnome = import('gnome')
+wayland_glib = subproject('wayland-glib')
+wayland_glib_dep = wayland_glib.get_variable('wayland_glib')
+
subdir('protocols')
subdir('include')
subdir('src')
diff --git a/lib/river/src/meson.build b/lib/river/src/meson.build
index b7ce20d..9c58e41 100644
--- a/lib/river/src/meson.build
+++ b/lib/river/src/meson.build
@@ -1,7 +1,6 @@
srcs = files(
'river-output.c',
- 'river.c',
- 'wayland-source.c',
+ 'river.c'
)
deps = [
@@ -9,6 +8,7 @@ deps = [
dependency('gio-2.0'),
dependency('wayland-client'),
dependency('json-glib-1.0'),
+ wayland_glib_dep
]
astal_river_lib = library(
diff --git a/lib/river/src/river.c b/lib/river/src/river.c
index 124cb20..6f94c9c 100644
--- a/lib/river/src/river.c
+++ b/lib/river/src/river.c
@@ -6,7 +6,8 @@
#include "river-control-unstable-v1-client.h"
#include "river-private.h"
#include "river-status-unstable-v1-client.h"
-#include "wayland-source.h"
+// #include "wayland-source.h"
+#include <wayland-glib.h>
struct _AstalRiverRiver {
GObject parent_instance;
@@ -22,7 +23,7 @@ typedef struct {
struct wl_registry* wl_registry;
struct wl_seat* seat;
struct wl_display* display;
- WLSource* wl_source;
+ WlGlibWlSource* wl_source;
struct zriver_status_manager_v1* river_status_manager;
struct zriver_control_v1* river_control;
struct zriver_seat_status_v1* river_seat_status;
@@ -340,7 +341,7 @@ static gboolean astal_river_river_initable_init(GInitable* initable, GCancellabl
if (priv->init) return TRUE;
- priv->wl_source = wl_source_new(NULL, NULL);
+ priv->wl_source = wl_glib_wl_source_new();
if (priv->wl_source == NULL) {
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -348,7 +349,7 @@ static gboolean astal_river_river_initable_init(GInitable* initable, GCancellabl
return FALSE;
}
- priv->display = wl_source_get_display(priv->wl_source);
+ priv->display = priv->wl_source->display;
priv->wl_registry = wl_display_get_registry(priv->display);
wl_registry_add_listener(priv->wl_registry, &registry_listener, self);
@@ -449,7 +450,8 @@ static void astal_river_river_finalize(GObject* object) {
if (priv->seat != NULL) wl_seat_destroy(priv->seat);
if (priv->display != NULL) wl_display_flush(priv->display);
- if (priv->wl_source != NULL) wl_source_free(priv->wl_source);
+ // if (priv->wl_source != NULL) wl_source_free(priv->wl_source);
+ if (priv->wl_source != NULL) g_source_unref((GSource*)(priv->wl_source));
g_free(self->focused_view);
g_free(self->focused_output);
diff --git a/lib/river/src/wayland-source.c b/lib/river/src/wayland-source.c
deleted file mode 100644
index 875c32c..0000000
--- a/lib/river/src/wayland-source.c
+++ /dev/null
@@ -1,104 +0,0 @@
-
-#include "wayland-source.h"
-
-#include <errno.h>
-#include <glib.h>
-#include <wayland-client.h>
-
-struct _WLSource {
- GSource source;
- struct wl_display *display;
- gpointer fd;
- int error;
-};
-
-static gboolean wl_source_prepare(GSource *source, gint *timeout) {
- WLSource *self = (WLSource *)source;
-
- *timeout = 0;
- if (wl_display_prepare_read(self->display) != 0)
- return TRUE;
- else if (wl_display_flush(self->display) < 0) {
- self->error = errno;
- return TRUE;
- }
- *timeout = -1;
- return FALSE;
-}
-
-static gboolean wl_source_check(GSource *source) {
- WLSource *self = (WLSource *)source;
-
- if (self->error > 0) return TRUE;
-
- GIOCondition revents;
- revents = g_source_query_unix_fd(source, self->fd);
-
- if (revents & G_IO_IN) {
- if (wl_display_read_events(self->display) < 0) self->error = errno;
- } else
- wl_display_cancel_read(self->display);
-
- return revents > 0;
-}
-
-static gboolean wl_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
- WLSource *self = (WLSource *)source;
- GIOCondition revents;
-
- revents = g_source_query_unix_fd(source, self->fd);
- if ((self->error > 0) || (revents & (G_IO_ERR | G_IO_HUP))) {
- errno = self->error;
- self->error = 0;
- if (callback != NULL) return callback(user_data);
- return G_SOURCE_REMOVE;
- }
-
- if (wl_display_dispatch_pending(self->display) < 0) {
- if (callback != NULL) return callback(user_data);
- return G_SOURCE_REMOVE;
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static void wl_source_finalize(GSource *source) {
- WLSource *self = (WLSource *)source;
- wl_display_disconnect(self->display);
-}
-
-static GSourceFuncs wl_source_funcs = {
- .prepare = wl_source_prepare,
- .check = wl_source_check,
- .dispatch = wl_source_dispatch,
- .finalize = wl_source_finalize,
-};
-
-WLSource *wl_source_new() {
- struct wl_display *display;
- WLSource *self;
- GSource *source;
-
- display = wl_display_connect(NULL);
- if (display == NULL) return NULL;
-
- source = g_source_new(&wl_source_funcs, sizeof(WLSource));
- self = (WLSource *)source;
- self->display = display;
-
- self->fd = g_source_add_unix_fd(source, wl_display_get_fd(self->display),
- G_IO_IN | G_IO_ERR | G_IO_HUP);
-
- g_source_attach(source, NULL);
-
- return self;
-}
-
-void wl_source_free(WLSource *self) {
- GSource *source = (GSource *)self;
- g_return_if_fail(source != NULL);
- g_source_destroy(source);
- g_source_unref(source);
-}
-
-struct wl_display *wl_source_get_display(WLSource *self) { return self->display; }
diff --git a/lib/river/subprojects/wayland-glib b/lib/river/subprojects/wayland-glib
new file mode 120000
index 0000000..41372cf
--- /dev/null
+++ b/lib/river/subprojects/wayland-glib
@@ -0,0 +1 @@
+../../wayland-glib \ No newline at end of file
diff --git a/lib/tray/config.vala.in b/lib/tray/config.vala.in
index 8ef8498..6a46bec 100644
--- a/lib/tray/config.vala.in
+++ b/lib/tray/config.vala.in
@@ -1,3 +1,4 @@
+[CCode (gir_namespace = "AstalTray", gir_version = "@API_VERSION@")]
namespace AstalTray {
public const int MAJOR_VERSION = @MAJOR_VERSION@;
public const int MINOR_VERSION = @MINOR_VERSION@;
diff --git a/lib/tray/default.nix b/lib/tray/default.nix
new file mode 100644
index 0000000..6dd0d61
--- /dev/null
+++ b/lib/tray/default.nix
@@ -0,0 +1,41 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}: let
+ vala-panel-appmenu = pkgs.fetchFromGitLab {
+ owner = "vala-panel-project";
+ repo = "vala-panel-appmenu";
+ rev = "24.05";
+ hash = "sha256-8GWauw7r3zKhvGF2TNOI8GDVctUFDhtG/Vy1cNUpsVo=";
+ };
+
+ appmenu-glib-translator = pkgs.stdenv.mkDerivation {
+ pname = "appmenu-glib-translator";
+ version = "24.05";
+
+ src = "${vala-panel-appmenu}/subprojects/appmenu-glib-translator";
+
+ buildInputs = with pkgs; [
+ glib
+ ];
+
+ nativeBuildInputs = with pkgs; [
+ gobject-introspection
+ meson
+ pkg-config
+ ninja
+ vala
+ ];
+ };
+in
+ mkAstalPkg {
+ pname = "astal-tray";
+ src = ./.;
+ packages = [pkgs.json-glib appmenu-glib-translator];
+
+ libname = "tray";
+ authors = "kotontrion";
+ gir-suffix = "Tray";
+ description = "StatusNotifierItem implementation";
+ }
diff --git a/lib/tray/meson.build b/lib/tray/meson.build
index fbf2f98..4fca2e4 100644
--- a/lib/tray/meson.build
+++ b/lib/tray/meson.build
@@ -26,6 +26,7 @@ config = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
+ 'API_VERSION': api_version,
'VERSION': meson.project_version(),
'MAJOR_VERSION': version_split[0],
'MINOR_VERSION': version_split[1],
@@ -39,29 +40,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 +52,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 +99,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..6da51cb 100644
--- a/lib/tray/trayItem.vala
+++ b/lib/tray/trayItem.vala
@@ -1,5 +1,3 @@
-using DbusmenuGtk;
-
namespace AstalTray {
public struct Pixmap {
int width;
@@ -88,21 +86,20 @@ public class TrayItem : Object {
private IItem proxy;
private List<ulong> connection_ids;
-
/** The Title of the TrayItem */
public string title { owned get { return proxy.Title; } }
-
+
/** The category this item belongs to */
public Category category { get { return proxy.Category; } }
-
- /** the current status of this item */
+
+ /** The current status of this item */
public Status status { get { return proxy.Status; } }
-
- /** the tooltip of this item */
+
+ /** The tooltip of this item */
public Tooltip? tooltip { owned get { return proxy.ToolTip; } }
-
- /**
- * a markup representation of the tooltip. This is basically equvivalent
+
+ /**
+ * A markup representation of the tooltip. This is basically equvivalent
* to `tooltip.title \n tooltip.description`
*/
public string tooltip_markup {
@@ -120,26 +117,24 @@ public class TrayItem : Object {
/** the id of the item. This id is specified by the tray app.*/
public string id { owned get { return proxy.Id ;} }
-
- /**
- * If set, this only supports the menu, so showing the menu should be prefered
+
+ /**
+ * If set, this only supports the menu, so showing the menu should be prefered
* over calling [[email protected]].
*/
public bool is_menu { get { return proxy.ItemIsMenu ;} }
-
- /**
- * the icon theme path, where to look for the [[email protected]:icon-name].
- *
- * It is recommended to use the [[email protected]:gicon] property,
+
+ /**
+ * The icon theme path, where to look for the [[email protected]:icon-name].
+ * It is recommended to use the [[email protected]:gicon] property,
* which does the icon lookups for you.
*/
public string icon_theme_path { owned get { return proxy.IconThemePath ;} }
-
- /**
- * the name of the icon. This should be looked up in the [[email protected]:icon-theme-path]
- * if set or in the currently used icon theme otherwise.
- *
- * It is recommended to use the [[email protected]:gicon] property,
+
+ /**
+ * The name of the icon. This should be looked up in the [[email protected]:icon-theme-path]
+ * if set or in the currently used icon theme otherwise.
+ * It is recommended to use the [[email protected]:gicon] property,
* which does the icon lookups for you.
*/
public string icon_name {
@@ -149,26 +144,41 @@ public class TrayItem : Object {
: proxy.IconName;
}
}
-
- /**
- * a pixbuf containing the icon.
- *
- * It is recommended to use the [[email protected]:gicon] property,
+
+ /**
+ * A pixbuf containing the icon.
+ * It is recommended to use the [[email protected]:gicon] property,
* which does the icon lookups for you.
*/
public Gdk.Pixbuf icon_pixbuf { owned get { return _get_icon_pixbuf(); } }
/**
- * contains the items icon. This property is intended to be used with the gicon property
+ * Contains the items icon. This property is intended to be used with the gicon property
* of the Icon widget and the recommended way to display the icon.
- * This property unifies the [[email protected]:icon-name],
+ * This property unifies the [[email protected]:icon-name],
* [[email protected]:icon-theme-path] and [[email protected]:icon-pixbuf] properties.
*/
public GLib.Icon gicon { get; private set; }
-
- /** the id of the item used to uniquely identify the TrayItems by this lib.*/
+
+ /** 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();
@@ -183,7 +193,8 @@ public class TrayItem : Object {
proxy = yield Bus.get_proxy(
BusType.SESSION,
service,
- path);
+ path
+ );
connection_ids.append(proxy.NewStatus.connect(refresh_all_properties));
connection_ids.append(proxy.NewToolTip.connect(refresh_all_properties));
@@ -196,9 +207,16 @@ public class TrayItem : Object {
SignalHandler.disconnect(proxy, id);
}
});
-
- update_gicon();
+ 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();
} catch (Error err) {
critical(err.message);
@@ -206,28 +224,33 @@ public class TrayItem : Object {
}
private void _notify() {
- string[] props = { "category", "id", "title", "status", "is-menu", "tooltip-markup", "icon-name", "icon-pixbuf" };
-
- foreach (string prop in props)
+ string[] props = {
+ "category",
+ "id",
+ "title",
+ "status",
+ "is-menu",
+ "tooltip-markup",
+ "icon-name",
+ "icon-pixbuf"
+ };
+
+ foreach (string prop in props) {
notify_property(prop);
+ }
changed();
}
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_name != null && icon_name != "") {
+ if (GLib.FileUtils.test(icon_name, GLib.FileTest.EXISTS)) {
+ gicon = new GLib.FileIcon(GLib.File.new_for_path(icon_name));
+ }
+ else 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);
}
@@ -274,33 +297,60 @@ public class TrayItem : Object {
}
);
}
-
+
+ /**
+ * tells the tray app that its menu is about to be opened,
+ * so it can update the menu if needed. You should call this method
+ * before openening the menu.
+ */
+ public void about_to_show() {
+ if(proxy.Menu == null) return;
+ try {
+ Bus.get_sync(BusType.SESSION).call_sync(
+ this.proxy.g_name_owner,
+ this.proxy.Menu,
+ "com.canonical.dbusmenu",
+ "AboutToShow",
+ new Variant("(i)", 0),
+ null,
+ DBusCallFlags.NONE,
+ -1,
+ null
+ );
+ }
+ catch (Error r) {
+ //silently ignore
+ }
+ }
+
/**
- * send an activate request to the tray app.
+ * Send an activate request to the tray app.
*/
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)
+ if (e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD) {
warning(e.message);
+ }
}
}
/**
- * send a secondary activate request to the tray app.
+ * Send a secondary activate request to the tray app.
*/
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)
+ if (e.domain != DBusError.quark() || e.code != DBusError.UNKNOWN_METHOD) {
warning(e.message);
+ }
}
}
/**
- * send a scroll request to the tray app.
+ * Send a scroll request to the tray app.
* valid values for the orientation are "horizontal" and "vertical".
*/
public void scroll(int delta, string orientation) {
@@ -312,58 +362,44 @@ public class TrayItem : Object {
}
}
- /**
- * creates a new Gtk Menu for this item.
- */
- public Gtk.Menu? create_menu() {
- if (proxy.Menu == 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;
+ }
- return new DbusmenuGtk.Menu(
- proxy.get_name_owner(),
- proxy.Menu);
- }
-
- private Gdk.Pixbuf? _get_icon_pixbuf() {
- Pixmap[] pixmaps = proxy.Status == Status.NEEDS_ATTENTION
- ? 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);
+ try {
+ Dir dir = Dir.open(theme_path, 0);
+ string? name = null;
- if (pixbuf == null)
- pixbuf = pixmap_to_pixbuf(pixmaps);
+ while ((name = dir.read_name ()) != null) {
+ var path = Path.build_filename(theme_path, name);
- return pixbuf;
- }
+ if (FileUtils.test(path, FileTest.IS_DIR)) {
+ string? icon = find_icon_in_theme(icon_name, path);
+ if (icon != null) return icon;
+ else continue;
+ }
- private Gdk.Pixbuf? load_from_theme(string icon_name, string theme_path) {
- if (theme_path == "" || theme_path == null)
- return null;
+ int dot_index = name.last_index_of(".");
+ if (dot_index != -1) {
+ name = name.substring(0, dot_index);
+ }
- if (icon_name == "" || icon_name == null)
+ if (name == icon_name) return path;
+ }
+ } catch (FileError err) {
return 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();
+ private Gdk.Pixbuf? _get_icon_pixbuf() {
+ Pixmap[] pixmaps = proxy.Status == Status.NEEDS_ATTENTION
+ ? proxy.AttentionIconPixmap
+ : proxy.IconPixmap;
- return null;
+ return pixmap_to_pixbuf(pixmaps);
}
private Gdk.Pixbuf? pixmap_to_pixbuf(Pixmap[] pixmaps) {
@@ -371,6 +407,12 @@ public class TrayItem : Object {
return null;
Pixmap pixmap = pixmaps[0];
+
+ for (int i = 0; i < pixmaps.length; i++){
+ if(pixmap.width < pixmaps[i].width)
+ pixmap = pixmaps[i];
+ };
+
uint8[] image_data = pixmap.bytes.copy();
for (int i = 0; i < pixmap.width * pixmap.height * 4; i += 4) {
diff --git a/lib/wayland-glib/meson.build b/lib/wayland-glib/meson.build
new file mode 100644
index 0000000..3d93ac0
--- /dev/null
+++ b/lib/wayland-glib/meson.build
@@ -0,0 +1,40 @@
+project(
+ 'wayland-glib',
+ 'vala',
+ 'c',
+ version: run_command('cat', join_paths(meson.project_source_root(), 'version')).stdout().strip(),
+ meson_version: '>= 0.62.0',
+ default_options: [
+ 'warning_level=2',
+ 'werror=false',
+ 'c_std=gnu11',
+ ],
+)
+
+version_split = meson.project_version().split('.')
+
+deps = [
+ dependency('glib-2.0'),
+ dependency('gio-2.0'),
+ dependency('gobject-2.0'),
+ dependency('wayland-client'),
+]
+
+sources = [
+ 'wl-source.vala',
+]
+
+lib = static_library(
+ meson.project_name(),
+ sources,
+ dependencies: deps,
+ vala_header: meson.project_name() + '.h',
+ vala_vapi: meson.project_name() + '.vapi',
+)
+
+wayland_glib = declare_dependency(
+ link_with: lib,
+ include_directories: include_directories('.')
+ )
+
+
diff --git a/lib/wayland-glib/version b/lib/wayland-glib/version
new file mode 100644
index 0000000..6e8bf73
--- /dev/null
+++ b/lib/wayland-glib/version
@@ -0,0 +1 @@
+0.1.0
diff --git a/lib/wayland-glib/wl-source.vala b/lib/wayland-glib/wl-source.vala
new file mode 100644
index 0000000..f8472fb
--- /dev/null
+++ b/lib/wayland-glib/wl-source.vala
@@ -0,0 +1,44 @@
+namespace WlGlib {
+public class WlSource : Source {
+
+ public Wl.Display display;
+ public void* fd;
+ public int error;
+
+ public override bool dispatch(SourceFunc callback) {
+ IOCondition revents = this.query_unix_fd(this.fd);
+ if (this.error > 0 || (revents & (IOCondition.ERR | IOCondition.HUP)) != 0) {
+ errno = this.error;
+ if(callback != null) return callback();
+ return Source.REMOVE;
+ }
+ if (((revents & IOCondition.IN) != 0) && this.display.dispatch() < 0) {
+ if(callback != null) return callback();
+ return Source.REMOVE;
+ }
+ return Source.CONTINUE;
+ }
+
+ public override bool check() {
+ IOCondition revents = this.query_unix_fd(this.fd);
+ return revents > 0;
+ }
+
+ public override bool prepare(out int timeout) {
+ if(this.display.flush() < 0)
+ this.error = errno;
+ timeout = -1;
+ return false;
+ }
+
+ public WlSource() {
+ base();
+ this.display = new Wl.Display.connect(null);
+ if(this.display == null) return;
+ this.fd = this.add_unix_fd(this.display.get_fd(),
+ IOCondition.IN | IOCondition.ERR | IOCondition.HUP);
+ this.attach(null);
+ }
+}
+}
+
diff --git a/lib/wireplumber/default.nix b/lib/wireplumber/default.nix
new file mode 100644
index 0000000..f9eb832
--- /dev/null
+++ b/lib/wireplumber/default.nix
@@ -0,0 +1,16 @@
+{
+ mkAstalPkg,
+ pkgs,
+ ...
+}:
+mkAstalPkg {
+ pname = "astal-wireplumber";
+ src = ./.;
+ packages = [pkgs.wireplumber];
+
+ libname = "wireplumber";
+ authors = "kotontrion";
+ gir-suffix = "Wp";
+ description = "Wrapper library over the wireplumber API";
+ dependencies = ["WP-0.5"];
+}