Skip to content

Commit

Permalink
feat: implement initial wayland support in panel, panel manager, popo…
Browse files Browse the repository at this point in the history
…vers, and Raven (#588)

* Start adding gtk-layer-shell support

* feat: add some helper functions

* feat: port panel off wnck directly

* hack: disable WM on wayland

* feat: new popover redux implementation, renaming everything for now (will be changed back)

added exclusion zone for panel

* fix: panel not being placed on primary monitor

* fix: raven in default position no longer fullscreen

tweaked animation of hide to be less glitchy. attempts for show were less successful.

* chore: cleanup popover manager code, rename redux back to non-redux

* feat: set popover location on show based on parent panel location

* hack: implement masked panel recreation during move to re-enable interactivity

* fix: padding due to our popover no longer having a container for content

* chore: update build.yml with gtklayershell pkgconfig install, todo for raven width change

* fix: remove comment

* fix: remove extraneous libxfce4windowing Wayland check

* fix: raven position being bork on left side

* fix: address feedback from Evan on lack of useful signals to consume in manager instead

also added a getter for windows instead of maintaining our own representation

* fix: raven sizing now that anchoring is fixed

* fix: remove taskfile, revert format change and warn-all

* fix: transparent popovers, ABI bump to 2.0 to indicate drop of X11 support, Night Light UI gen
  • Loading branch information
JoshStrobl committed Jul 3, 2024
1 parent 151ec20 commit f837a90
Show file tree
Hide file tree
Showing 33 changed files with 345 additions and 1,441 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
'pkgconfig(gnome-desktop-3.0)' \
'pkgconfig(gnome-settings-daemon)' \
'pkgconfig(gstreamer-1.0)' \
'pkgconfig(gtk-layer-shell-0)' \
'pkgconfig(ibus-1.0)' \
'pkgconfig(libcanberra)' \
'pkgconfig(libnotify)' \
Expand Down
1 change: 0 additions & 1 deletion docs/gtk/budgie-desktop.types
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ budgie_applet_get_type
budgie_panel_action_get_type
budgie_panel_position_get_type
budgie_plugin_get_type
budgie_popover_position_policy_get_type
budgie_popover_get_type
budgie_popover_manager_get_type
budgie_raven_plugin_get_type
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ dep_libuuid = dependency('uuid')
dep_vala = dependency('vapigen', version: '>= 0.52.5')
dep_gst = dependency('gstreamer-1.0')
dep_cairo = dependency('cairo')
dep_gtk_layer_shell = dependency('gtk-layer-shell-0', version: '>= 0.8.0')

# Needed for Budgie Menu
dep_cairo = dependency('cairo', version: '>= 1.15.10')
Expand Down
2 changes: 2 additions & 0 deletions src/lib/manager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ namespace Budgie {

public abstract void create_new_panel();
public abstract void delete_panel(string uuid);
public abstract void move_panel(string uuid, Budgie.PanelPosition position);
public abstract void remove_panel(string uuid, bool remove_from_dconf);

public abstract List<Peas.PluginInfo?> get_panel_plugins();
public abstract List<Peas.PluginInfo?> get_raven_plugins();
Expand Down
2 changes: 1 addition & 1 deletion src/panel/applets/budgie-menu/BudgieMenuWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* (at your option) any later version.
*/

public class BudgieMenuWindow : Budgie.Popover {
public class BudgieMenuWindow : Gtk.Popover {
protected Gtk.Box main_layout;
protected Gtk.SearchEntry search_entry;
protected ApplicationView view;
Expand Down
2 changes: 1 addition & 1 deletion src/panel/applets/icon-tasklist/widgets/ButtonPopover.vala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public interface SettingsRemote : GLib.Object {
public abstract async void Close() throws Error;
}

public class ButtonPopover : Budgie.Popover {
public class ButtonPopover : Gtk.Popover {
public Budgie.Application? app { get; construct; }
public Budgie.Windowing.WindowGroup? group { get; construct set; }

Expand Down
2 changes: 1 addition & 1 deletion src/panel/applets/night-light/IndicatorWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace NightLight {
[GtkTemplate (ui="/org/budgie-desktop/night-light/indicator_window.ui")]
class IndicatorWindow : Budgie.Popover {
class IndicatorWindow : Gtk.Popover {
[GtkChild]
private unowned Gtk.Switch? nightlight_switch;

Expand Down
2 changes: 1 addition & 1 deletion src/panel/applets/night-light/indicator_window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<property name="step_increment">100</property>
<property name="page_increment">1000</property>
</object>
<template class="NightLightIndicatorWindow" parent="BudgiePopover">
<template class="NightLightIndicatorWindow" parent="GtkPopover">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
Expand Down
4 changes: 2 additions & 2 deletions src/panel/applets/trash/trash_applet.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static void trash_applet_constructed(GObject* object) {
self->settings = budgie_applet_get_applet_settings(BUDGIE_APPLET(self), self->priv->uuid);

// Create our popover widget
self->priv->popover = budgie_popover_new(GTK_WIDGET(self->priv->icon_button));
self->priv->popover = (GtkWidget*)budgie_popover_new(GTK_WIDGET(self->priv->icon_button));
popover_body = trash_popover_new(self->settings);
gtk_container_add(GTK_CONTAINER(self->priv->popover), GTK_WIDGET(popover_body));

Expand Down Expand Up @@ -149,7 +149,7 @@ static void update_popovers(BudgieApplet* base, BudgiePopoverManager* manager) {
TrashApplet* self = TRASH_APPLET(base);
budgie_popover_manager_register_popover(manager,
GTK_WIDGET(self->priv->icon_button),
BUDGIE_POPOVER(self->priv->popover));
self->priv->popover);
self->priv->manager = manager;
}

Expand Down
168 changes: 83 additions & 85 deletions src/panel/manager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ namespace Budgie {
/* Manage all of the Budgie settings */
private Budgie.SettingsWindow? settings_window = null;

Wnck.Screen wnck_screen;
List<unowned Wnck.Window> window_list;
Budgie.Windowing.Windowing windowing;

private string default_layout = "default";

Expand Down Expand Up @@ -215,6 +214,8 @@ namespace Budgie {
public PanelManager(bool reset) {
Object();
this.reset = reset;
libxfce4windowing.set_client_type(libxfce4windowing.ClientType.PAGER);
windowing = new Budgie.Windowing.Windowing();
screens = new HashTable<int,Screen?>(direct_hash, direct_equal);
panels = new HashTable<string,Budgie.Panel?>(str_hash, str_equal);
}
Expand All @@ -224,98 +225,60 @@ namespace Budgie {
* Executed after the initial setup of the panel manager
*/
private void do_dynamic_transparency_setup() {
wnck_screen = Wnck.Screen.get_default();
window_list = new List<unowned Wnck.Window>();

wnck_screen.get_windows().foreach((window) => {
window_list.append(window);
window.state_changed.connect(() => {
if (window.is_skip_pager() || window.is_skip_tasklist()) {
return;
}
check_windows();
});
windowing.window_state_changed.connect((window) => {
if (window.is_skip_pager() || window.is_skip_tasklist()) return;
check_windows();
});

wnck_screen.window_opened.connect(window_opened);
wnck_screen.window_closed.connect(window_closed);
wnck_screen.active_window_changed.connect(active_window_changed);
wnck_screen.active_workspace_changed.connect(check_windows);
windowing.window_added.connect(window_opened);
windowing.window_removed.connect(check_windows);
windowing.active_window_changed.connect(active_window_changed);
windowing.active_workspace_changed.connect(check_windows);
}

private void active_window_changed() {
// Handle transparency
check_windows();

check_window_intersections(wnck_screen.get_active_window());
libxfce4windowing.Window? window = windowing.get_active_window();
if (window == null) return;
check_window_intersections(window);
}

/*
* Callback for newly opened, not yet tracked windows
*/
private void window_opened(Wnck.Window window) {
unowned List<weak Wnck.Window>? element = window_list.find(window);
if (element != null) {
return;
}

window_list.append(window);

private void window_opened(libxfce4windowing.Window window) {
window.state_changed.connect(() => {
if (window.is_skip_pager() || window.is_skip_tasklist()) {
return;
}
if (window.is_skip_pager() || window.is_skip_tasklist()) return;
check_windows();
});

window.geometry_changed.connect_after((window) => {
if (window.is_skip_pager() || window.is_skip_tasklist()) {
return;
}
if (window.is_skip_pager() || window.is_skip_tasklist()) return;
this.check_window_intersections(window);
});

check_windows();
}

/*
* Callback for closed windows
*/
private void window_closed(Wnck.Window window) {
unowned List<weak Wnck.Window>? element = window_list.find(window);
if (element == null) {
return;
}

window_list.remove_all(window);
check_windows();
}

/**
* Determine if the given panel and window intersect in geometry.
* The panel is buffered by a predetermined pad amount which allows
* for intelligent hiding behavior, i.e. when the window gets close to
* the panel, it should start the hide.
*/
private bool window_intersects_panel(Budgie.Toplevel? panel, Wnck.Window? window) {
private bool window_intersects_panel(Budgie.Toplevel? panel, libxfce4windowing.Window? window) {
const int pad_amount = 15;
Gdk.Rectangle win = Gdk.Rectangle();
Gdk.Rectangle pan = Gdk.Rectangle();

if (window == null && this.window_list.is_empty()) {
return false;
}
if (window == null && !windowing.has_windows) return false;

if (window != wnck_screen.get_active_window()) {
return false;
}
if (window != windowing.get_active_window()) return false;

if (window.is_skip_pager() || window.is_skip_tasklist()) {
return false;
}
if (window.is_skip_pager() || window.is_skip_tasklist()) return false;

// Figure out where the window is
window.get_geometry(out win.x, out win.y, out win.width, out win.height);
Gdk.Rectangle win = window.get_geometry();
Gdk.Rectangle pan = Gdk.Rectangle();

// Figure out where the toplevel is
panel.get_position(out pan.x, out pan.y);
Expand All @@ -337,7 +300,7 @@ namespace Budgie {
* An intersection is classified by a buffer zone match to allow dodging
* "near" windows automatically.
*/
void check_window_intersections(Wnck.Window? window) {
void check_window_intersections(libxfce4windowing.Window? window) {
Budgie.Panel? panel = null;
var iter = HashTableIter<string,Budgie.Panel?>(panels);

Expand All @@ -358,11 +321,10 @@ namespace Budgie {
/**
* Determine if the window is on the primary screen, i.e. where the main
* budgie panels will show
* note wnck window geometry includes scale factors
* note libxfce4windowing window geometry includes scale factors
*/
bool window_on_primary(Wnck.Window? window) {
Gdk.Rectangle area = Gdk.Rectangle();
window.get_geometry(out area.x, out area.y, out area.width, out area.height);
bool window_on_primary(libxfce4windowing.Window? window) {
Gdk.Rectangle area = window.get_geometry();
var primary = screens.lookup(this.primary_monitor);

// get the geometry of the primary monitor including the scale factor
Expand Down Expand Up @@ -390,19 +352,13 @@ namespace Budgie {
}
bool found = false;

window_list.foreach((window) => {
bool is_maximized = (window.is_maximized_horizontally() || window.is_maximized_vertically());
libxfce4windowing.Workspace? active_workspace = windowing.get_active_workspace();

if (window.get_workspace() != wnck_screen.get_active_workspace()) {
return;
}
if (window.is_skip_pager() || window.is_skip_tasklist()) {
return;
}
if (!this.window_on_primary(window)) {
return;
}
if ((is_maximized && !window.is_minimized())) {
windowing.windows.foreach((window) => {
if (window.is_skip_pager()) return;
if (!this.window_on_primary(window)) return;
if (active_workspace == null || active_workspace != null && !window.is_on_workspace(active_workspace)) return;
if ((window.is_maximized() && !window.is_minimized())) {
found = true;
return;
}
Expand Down Expand Up @@ -616,9 +572,6 @@ namespace Budgie {
raven = new Budgie.Raven(this, raven_plugin_manager);
raven.request_settings_ui.connect(this.on_settings_requested);

/* Ensure we only have wnck initialised once otherwise everything goes cranky */
Wnck.set_client_type(Wnck.ClientType.PAGER);

this.on_monitors_changed();

/* Some applets might want raven */
Expand Down Expand Up @@ -744,6 +697,7 @@ namespace Budgie {
*/
void load_panel(string uuid, bool configure = false) {
if (panels.contains(uuid)) {
warning("Asked to load already loaded panel: %s", uuid);
return;
}

Expand Down Expand Up @@ -1096,6 +1050,7 @@ namespace Budgie {
bool load_panels() {
string[] panels = this.settings.get_strv(Budgie.ROOT_KEY_PANELS);
if (panels.length == 0) {
warning("No panels to load");
return false;
}

Expand Down Expand Up @@ -1128,12 +1083,7 @@ namespace Budgie {
this.panel_deleted(uuid);

var spath = this.create_panel_path(panel.uuid);
panels.steal(panel.uuid);
set_panels();
update_screen();
panel.destroy_children();
panel.destroy();

remove_panel(uuid, true);

var psettings = new Settings.with_path(Budgie.TOPLEVEL_SCHEMA, spath);
this.reset_dconf_path(psettings);
Expand Down Expand Up @@ -1242,6 +1192,54 @@ namespace Budgie {
this.panel_added(uuid, panel);
}

public override void remove_panel(string uuid, bool remove_from_dconf = true) {
Budgie.Panel? panel = panels.lookup(uuid);
if (panel == null) {
warning("Asked to remove non-existent panel: %s", uuid);
return;
}
panels.steal(panel.uuid);
if (remove_from_dconf) {
set_panels();
update_screen();
panel.destroy_children();
panel.destroy();
}
}

public override void move_panel(string uuid, PanelPosition position) {
Budgie.Panel? panel = panels.lookup(uuid);
if (panel == null) {
warning("Asked to move non-existent panel: %s", uuid);
return;
}

// This is horrible and I know it
// This will destroy and recreate the panel to re-enable interactivity under Wayland

// Start by hiding the panel to mask recreation
panel.hide();
// Move the panel to the new position
set_placement(uuid, position);

// Ensure panel position is saved
panel.set_position_setting(position);

// Close the panel
panel.close();
// Steal so we can add new panel entry
panels.steal(panel.uuid);

// Load panel again
load_panel(uuid, true);

// Look up again
panel = panels.lookup(uuid);

// Show moved panel
panel.show();
}

/**
* Update our known panels
*/
Expand Down
6 changes: 5 additions & 1 deletion src/panel/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ panel_deps = [
libpanelplugin_vapi,
dep_giounix,
dep_gtk3,
dep_gtk_layer_shell,
dep_peas,
dep_libuuid,
dep_wnck,
dep_xfce4windowing,
link_libconfig,
link_libsession,
link_libbudgieprivate,
Expand All @@ -57,6 +58,7 @@ panel_deps = [
link_libravenplugin,
libravenplugin_vapi,
link_libraven,
link_libwindowing,
gvc.get_variable('libgvc_dep'),
]

Expand All @@ -73,6 +75,8 @@ budgie_panel_vala_args = [
'--pkg', 'gtk+-3.0',
'--pkg', 'gdk-x11-3.0',
'--pkg', 'gio-unix-2.0',
'--pkg', 'gtk-layer-shell-0',
'--pkg', 'libxfce4windowing-0',
# Make gresource work
'--target-glib=2.38',
'--gresources=' + gresource,
Expand Down
Loading

0 comments on commit f837a90

Please sign in to comment.