Skip to content

Commit

Permalink
Daemon: Port to GTK4 (#1964)
Browse files Browse the repository at this point in the history
  • Loading branch information
leolost2605 authored Jul 5, 2024
1 parent fdd5e44 commit 3a81898
Show file tree
Hide file tree
Showing 16 changed files with 740 additions and 147 deletions.
File renamed without changes.
133 changes: 133 additions & 0 deletions daemon-gtk3/DBus.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright 2024 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*/

[DBus (name = "org.pantheon.gala")]
public interface Gala.WMDBus : GLib.Object {
public abstract void perform_action (Gala.ActionType type) throws DBusError, IOError;
}

public struct Gala.Daemon.MonitorLabelInfo {
public int monitor;
public string label;
public string background_color;
public string text_color;
public int x;
public int y;
}

[DBus (name = "org.pantheon.gala.daemon")]
public class Gala.Daemon.DBus : GLib.Object {
private const string DBUS_NAME = "org.pantheon.gala";
private const string DBUS_OBJECT_PATH = "/org/pantheon/gala";

private const string DAEMON_DBUS_NAME = "org.pantheon.gala.daemon";
private const string DAEMON_DBUS_OBJECT_PATH = "/org/pantheon/gala/daemon";

private WMDBus? wm_proxy = null;

private WindowMenu? window_menu;
private BackgroundMenu? background_menu;

private List<MonitorLabel> monitor_labels = new List<MonitorLabel> ();

construct {
Bus.watch_name (BusType.SESSION, DBUS_NAME, BusNameWatcherFlags.NONE, gala_appeared, lost_gala);
}

private void on_gala_get (GLib.Object? obj, GLib.AsyncResult? res) {
try {
wm_proxy = Bus.get_proxy.end (res);
} catch (Error e) {
warning ("Failed to get Gala proxy: %s", e.message);
}
}

private void lost_gala () {
wm_proxy = null;
}

private void gala_appeared () {
if (wm_proxy == null) {
Bus.get_proxy.begin<WMDBus> (BusType.SESSION, DBUS_NAME, DBUS_OBJECT_PATH, 0, null, on_gala_get);
}
}

private void perform_action (Gala.ActionType type) {
if (wm_proxy != null) {
try {
wm_proxy.perform_action (type);
} catch (Error e) {
warning ("Failed to perform Gala action over DBus: %s", e.message);
}
}
}

public void show_window_menu (Gala.WindowFlags flags, int display_width, int display_height, int x, int y) throws DBusError, IOError {
if (window_menu == null) {
window_menu = new WindowMenu ();
window_menu.perform_action.connect (perform_action);
}

window_menu.update (flags);

show_menu (window_menu, display_width, display_height, x, y, true);
}

public void show_desktop_menu (int display_width, int display_height, int x, int y) throws DBusError, IOError {
if (background_menu == null) {
background_menu = new BackgroundMenu ();
}

show_menu (background_menu, display_width, display_height, x, y, false);
}

private void show_menu (Gtk.Menu menu, int display_width, int display_height, int x, int y, bool ignore_first_release) {
var window = new Window (display_width, display_height);
window.present ();

menu.attach_to_widget (window.content, null);

Gdk.Rectangle rect = {
x,
y,
0,
0
};

menu.show_all ();
menu.popup_at_rect (window.get_window (), rect, NORTH, NORTH_WEST);

menu.deactivate.connect (window.close);

if (ignore_first_release) {
bool first = true;
menu.button_release_event.connect (() => {
if (first) {
first = false;
return Gdk.EVENT_STOP;
}

return Gdk.EVENT_PROPAGATE;
});
}
}

public void show_monitor_labels (MonitorLabelInfo[] label_infos) throws GLib.DBusError, GLib.IOError {
hide_monitor_labels ();

monitor_labels = new List<MonitorLabel> ();
foreach (var info in label_infos) {
var label = new MonitorLabel (info);
monitor_labels.append (label);
label.present ();
}
}

public void hide_monitor_labels () throws GLib.DBusError, GLib.IOError {
foreach (var monitor_label in monitor_labels) {
monitor_label.close ();
}
}
}
49 changes: 49 additions & 0 deletions daemon-gtk3/Main.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2024 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*/

public class Gala.Daemon.Application : Gtk.Application {
public Application () {
Object (application_id: "org.pantheon.gala.daemon");
}

public override void startup () {
base.startup ();

var granite_settings = Granite.Settings.get_default ();
var gtk_settings = Gtk.Settings.get_default ();

gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK;

granite_settings.notify["prefers-color-scheme"].connect (() => {
gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK;
});

var app_provider = new Gtk.CssProvider ();
app_provider.load_from_resource ("io/elementary/desktop/gala-daemon/gala-daemon.css");
Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), app_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
}

public override void activate () {
hold ();
}

public override bool dbus_register (DBusConnection connection, string object_path) throws Error {
base.dbus_register (connection, object_path);

connection.register_object (object_path, new DBus ());

return true;
}
}

public static int main (string[] args) {
GLib.Intl.setlocale (LocaleCategory.ALL, "");
GLib.Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
GLib.Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
GLib.Intl.textdomain (Config.GETTEXT_PACKAGE);

var app = new Gala.Daemon.Application ();
return app.run ();
}
62 changes: 62 additions & 0 deletions daemon-gtk3/MonitorLabel.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2024 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: LGPL-3.0-or-later
*/

public class Gala.Daemon.MonitorLabel : Hdy.Window {
private const int SPACING = 12;
private const string COLORED_STYLE_CSS = """
.%s {
background-color: alpha(%s, 0.8);
color: %s;
}
""";

public MonitorLabelInfo info { get; construct; }

public MonitorLabel (MonitorLabelInfo info) {
Object (info: info);
}

construct {
child = new Gtk.Label (info.label);

title = "LABEL-%i".printf (info.monitor);

input_shape_combine_region (null);
accept_focus = false;
decorated = false;
resizable = false;
deletable = false;
can_focus = false;
skip_taskbar_hint = true;
skip_pager_hint = true;
type_hint = Gdk.WindowTypeHint.TOOLTIP;
set_keep_above (true);

stick ();

var scale_factor = get_style_context ().get_scale ();
move (
(int) (info.x / scale_factor) + SPACING,
(int) (info.y / scale_factor) + SPACING
);

var provider = new Gtk.CssProvider ();
try {
provider.load_from_data (COLORED_STYLE_CSS.printf (title, info.background_color, info.text_color));
get_style_context ().add_class (title);
get_style_context ().add_class ("monitor-label");

Gtk.StyleContext.add_provider_for_screen (
Gdk.Screen.get_default (),
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
} catch (Error e) {
warning ("Failed to load CSS: %s", e.message);
}

show_all ();
}
}
50 changes: 50 additions & 0 deletions daemon-gtk3/Window.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2024 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <[email protected]>
*/

public class Gala.Daemon.Window : Gtk.Window {
public Gtk.Box content { get; construct; }

public Window (int width, int height) {
Object (
default_width: width,
default_height: height
);
}

class construct {
set_css_name ("daemon-window");
}

construct {
decorated = false;
resizable = false;
deletable = false;
can_focus = false;
input_shape_combine_region (null);
accept_focus = false;
skip_taskbar_hint = true;
skip_pager_hint = true;
type_hint = Gdk.WindowTypeHint.DOCK;
set_keep_above (true);

title = "MODAL";
child = content = new Gtk.Box (HORIZONTAL, 0) {
hexpand = true,
vexpand = true
};

set_visual (get_screen ().get_rgba_visual ());

show_all ();
move (0, 0);

button_press_event.connect (() => {
close ();
return Gdk.EVENT_STOP;
});
}
}
Loading

0 comments on commit 3a81898

Please sign in to comment.