[Feature] Click outside Control Center to close (#133)

* Initial implementation

* Fixed linter errors

* Fixed Ubuntu build error

* Added comment to .blank-window css class, formatted file with prettier

* Use packaged css file as backup
This commit is contained in:
Erik Reider 2022-06-16 17:44:57 +02:00 committed by GitHub
parent 8a96948e1b
commit 8425afbfa8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 165 additions and 12 deletions

View File

@ -0,0 +1,55 @@
namespace SwayNotificationCenter {
public class BlankWindow : Gtk.Window {
unowned Gdk.Display display;
unowned Gdk.Monitor monitor;
unowned SwayncDaemon daemon;
Gtk.Button button;
public BlankWindow (Gdk.Display disp,
Gdk.Monitor mon,
SwayncDaemon dae) {
display = disp;
monitor = mon;
daemon = dae;
// Use button click event instead of Window button_press_event due
// to Gtk layer shell bug. This would grab focus instead of ControlCenter
button = new Gtk.Button () {
expand = true,
opacity = 0,
relief = Gtk.ReliefStyle.NONE,
visible = true,
};
button.clicked.connect (() => {
try {
daemon.set_visibility (false);
} catch (Error e) {
stderr.printf ("BlankWindow Click Error: %s\n", e.message);
}
});
add (button);
if (!GtkLayerShell.is_supported ()) {
stderr.printf ("GTKLAYERSHELL IS NOT SUPPORTED!\n");
stderr.printf ("Swaync only works on Wayland!\n");
stderr.printf ("If running waylans session, try running:\n");
stderr.printf ("\tGDK_BACKEND=wayland swaync\n");
Process.exit (1);
}
GtkLayerShell.init_for_window (this);
GtkLayerShell.set_monitor (this, monitor);
GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.TOP, true);
GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.BOTTOM, true);
GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.LEFT, true);
GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.RIGHT, true);
GtkLayerShell.set_exclusive_zone (this, -1);
GtkLayerShell.set_layer (this, GtkLayerShell.Layer.TOP);
get_style_context ().add_class ("blank-window");
}
}
}

View File

@ -275,6 +275,7 @@ namespace SwayNotificationCenter {
if (noti != null) noti.set_time ();
}
}
swaync_daemon.set_blank_window_visibility (this.visible);
swaync_daemon.subscribe (notification_count (),
noti_daemon.dnd,
this.visible);

View File

@ -1,5 +1,15 @@
namespace SwayNotificationCenter {
public class Functions {
private static Gtk.CssProvider system_css_provider;
private static Gtk.CssProvider user_css_provider;
private Functions () {}
public static void init () {
system_css_provider = new Gtk.CssProvider ();
user_css_provider = new Gtk.CssProvider ();
}
public static void set_image_path (owned string path,
Gtk.Image img,
int icon_size,
@ -55,29 +65,45 @@ namespace SwayNotificationCenter {
img.set_from_surface (surface);
}
/** Load the package provided CSS file as a base.
* Without this, an empty user CSS file would result in widgets
* with default GTK style properties
*/
public static bool load_css (string ? style_path) {
try {
Gtk.CssProvider css_provider = new Gtk.CssProvider ();
css_provider.load_from_path (get_style_path (style_path));
// Load packaged CSS as backup
string system_css = get_style_path (null, true);
system_css_provider.load_from_path (system_css);
Gtk.StyleContext.add_provider_for_screen (
Gdk.Screen.get_default (),
css_provider,
system_css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
// Load user CSS
string user_css = get_style_path (style_path);
user_css_provider.load_from_path (user_css);
Gtk.StyleContext.add_provider_for_screen (
Gdk.Screen.get_default (),
user_css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
return true;
} catch (Error e) {
print ("Error: %s\n", e.message);
}
print ("Load CSS Error: %s\n", e.message);
return false;
}
}
public static string get_style_path (string ? custom_path) {
public static string get_style_path (string ? custom_path,
bool only_system = false) {
string[] paths = {};
if (custom_path != null && custom_path.length > 0) {
paths += custom_path;
}
if (!only_system) {
paths += Path.build_path (Path.DIR_SEPARATOR.to_string (),
GLib.Environment.get_user_config_dir (),
"swaync/style.css");
}
foreach (var path in GLib.Environment.get_system_config_dirs ()) {
paths += Path.build_path (Path.DIR_SEPARATOR.to_string (),

View File

@ -6,6 +6,7 @@ namespace SwayNotificationCenter {
public void main (string[] args) {
Gtk.init (ref args);
Hdy.init ();
Functions.init ();
if (args.length > 0) {
for (uint i = 1; i < args.length; i++) {

View File

@ -33,6 +33,7 @@ app_sources = [
'controlCenter/controlCenter.vala',
'controlCenter/topAction/topAction.vala',
'cacher/cacher.vala',
'blankWindow/blankWindow.vala',
'functions.vala',
constants,
]

View File

@ -25,8 +25,7 @@
.notification {
border-radius: 12px;
margin: 6px 12px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3),
0 1px 3px 1px rgba(0, 0, 0, 0.7),
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 3px 1px rgba(0, 0, 0, 0.7),
0 2px 6px 2px rgba(0, 0, 0, 0.3);
padding: 0;
}
@ -120,7 +119,8 @@
border-right: 1px solid @noti-border-color;
}
.image {}
.image {
}
.body-image {
margin-top: 6px;
@ -191,3 +191,8 @@
.floating-notifications {
background: transparent;
}
/* Window behind control center and on all other monitors */
.blank-window {
background: alpha(black, 0.25);
}

View File

@ -11,6 +11,9 @@ namespace SwayNotificationCenter {
public NotiDaemon noti_daemon;
private Array<BlankWindow> blank_windows = new Array<BlankWindow> ();
private unowned Gdk.Display ? display = Gdk.Display.get_default ();
public SwayncDaemon () {
this.cache_state = Cacher.instance.get_state_cache ();
this.cache_state.notify.connect ((x, r) => {
@ -51,6 +54,31 @@ namespace SwayNotificationCenter {
} catch (Error e) {
stderr.printf (e.message + "\n");
}
/// Blank windows
if (display == null) return;
init_blank_windows (false);
display.closed.connect ((is_error) => {
clear_blank_windows ();
if (is_error) stderr.printf ("Display closed due to error!\n");
});
display.opened.connect ((d) => {
bool visibility = noti_daemon.control_center.get_visibility ();
init_blank_windows (visibility);
});
display.monitor_added.connect ((d, m) => {
bool visibility = noti_daemon.control_center.get_visibility ();
add_blank_window (d, m, visibility);
});
display.monitor_removed.connect ((monitor) => {
bool visibility = noti_daemon.control_center.get_visibility ();
init_blank_windows (visibility);
});
}
private void on_noti_bus_aquired (DBusConnection conn) {
@ -63,6 +91,42 @@ namespace SwayNotificationCenter {
}
}
private void add_blank_window (Gdk.Display display,
Gdk.Monitor monitor,
bool visible) {
var win = new BlankWindow (display, monitor, this);
win.set_visible (visible);
blank_windows.append_val (win);
}
private void init_blank_windows (bool visible) {
clear_blank_windows ();
// Add a window to all monitors
for (int i = 0; i < display.get_n_monitors (); i++) {
unowned Gdk.Monitor ? monitor = display.get_monitor (i);
if (monitor == null) continue;
add_blank_window (display, monitor, visible);
}
}
private void clear_blank_windows () {
while (blank_windows.length > 0) {
uint i = blank_windows.length - 1;
unowned BlankWindow ? win = blank_windows.index (i);
win.close ();
blank_windows.remove_index (i);
}
}
[DBus (visible = false)]
public void set_blank_window_visibility (bool visibility) {
foreach (unowned BlankWindow win in blank_windows.data) {
win.set_visible (visibility);
}
}
/// DBus
/** Gets subscribe data but in one call */
[DBus (name = "GetSubscribeData")]
public Data get_subscribe_data () throws Error {