Skip to content

Add blur #390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions blur-protocol/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
dep_scanner = dependency('wayland-scanner', native: true)
prog_scanner = find_program(dep_scanner.get_variable(pkgconfig: 'wayland_scanner'))

blur_protocol_file = files('pantheon-blur-v1.xml')

pantheon_blur_sources = []
pantheon_blur_sources += custom_target(
'pantheon-blur-client-protocol.h',
command: [ prog_scanner, 'client-header', '@INPUT@', '@OUTPUT@' ],
input: blur_protocol_file,
output: 'pantheon-blur-client-protocol.h',
)

output_type = 'private-code'
if dep_scanner.version().version_compare('< 1.14.91')
output_type = 'code'
endif
pantheon_blur_sources += custom_target(
'pantheon-blur-protocol.c',
command: [ prog_scanner, output_type, '@INPUT@', '@OUTPUT@' ],
input: blur_protocol_file,
output: 'pantheon-blur-protocol.c',
)

pantheon_blur_lib = static_library(
'pantheon-blur',
pantheon_blur_sources,
dependencies: [
wayland_client_dep
],
)

pantheon_blur_dep = declare_dependency(
link_with: pantheon_blur_lib,
dependencies: [
meson.get_compiler('vala').find_library('pantheon-blur', dirs: meson.current_source_dir()),
wayland_client_dep,
],
include_directories: include_directories('.'),
sources: pantheon_blur_sources
)
45 changes: 45 additions & 0 deletions blur-protocol/pantheon-blur-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="pantheon_blur_v1">
<copyright><![CDATA[
SPDX-FileCopyrightText: 2025 elementary <https://elementary.io>
SPDX-License-Identifier: LGPL-2.1-or-later
]]></copyright>

<interface name="io_elementary_pantheon_blur_manager_v1" version="1">
<description summary="blur object factory">
This protocol provides a way for Pantheon applications to ask for background blur.
</description>

<request name="get_blur">
<description summary="get blur object">
Get blur object for the given wl_surface to blur background behind it.
If the given wl_surface already has a io_elementary_pantheon_blur_v1 object associated,
an error will be raised.
</description>
<arg name="output" type="new_id" interface="io_elementary_pantheon_blur_v1"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
</interface>

<interface name="io_elementary_pantheon_blur_v1" version="1">
<description summary="blur object for surface">
This interface provides a way for Pantheon applications to specify region of the window to be blurred.
By default the region to blur is considered to be null.
</description>

<request name="destroy" type="destructor"/>

<request name="set_region">
<description summary="set blur region">
Tell the window manager to crop blur to a given region.
The coordinates must be relative to the associated surface.
</description>

<arg name="x" type="uint"/>
<arg name="y" type="uint"/>
<arg name="width" type="uint"/>
<arg name="height" type="uint"/>
<arg name="clip_radius" type="uint"/>
</request>
</interface>
</protocol>
1 change: 1 addition & 0 deletions blur-protocol/pantheon-blur.deps
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
wayland-server
29 changes: 29 additions & 0 deletions blur-protocol/pantheon-blur.vapi
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2025 elementary, Inc. <https://elementary.io>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

namespace PantheonBlur {
[CCode (cheader_filename = "pantheon-blur-client-protocol.h", cname = "struct io_elementary_pantheon_blur_manager_v1", cprefix = "io_elementary_pantheon_blur_manager_v1_")]
public class BlurManager : Wl.Proxy {
[CCode (cheader_filename = "pantheon-blur-client-protocol.h", cname = "io_elementary_pantheon_blur_manager_v1_interface")]
public static Wl.Interface iface;
public void set_user_data (void* user_data);
public void* get_user_data ();
public uint32 get_version ();
public void destroy ();
public PantheonBlur.Blur get_blur (Wl.Surface surface);

}

[CCode (cheader_filename = "pantheon-blur-client-protocol.h", cname = "struct io_elementary_pantheon_blur_v1", cprefix = "io_elementary_pantheon_blur_v1_")]
public class Blur : Wl.Proxy {
[CCode (cheader_filename = "pantheon-blur-client-protocol.h", cname = "io_elementary_pantheon_blur_v1_interface")]
public static Wl.Interface iface;
public void set_user_data (void* user_data);
public void* get_user_data ();
public uint32 get_version ();
public void destroy ();
public void set_region (uint x, uint y, uint width, uint height, uint clip_radius);
}
}
2 changes: 1 addition & 1 deletion data/Application.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dock {
0 0 0 1px @borders,
0 1px 3px alpha(black, 0.2),
0 3px 9px alpha(black, 0.3);
opacity: 0.6;
opacity: 0.3;
padding: 9px;
}

Expand Down
8 changes: 5 additions & 3 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ x11_dep = dependency('x11')
granite_dep = dependency('granite-7')
adw_dep = dependency('libadwaita-1')
m_dep = cc.find_library('m')
wl_client_dep = dependency('wayland-client')
wayland_client_dep = dependency('wayland-client')

subdir('protocol')
subdir('blur-protocol')

dependencies = [
gee_dep,
Expand All @@ -43,8 +44,9 @@ dependencies = [
granite_dep,
adw_dep,
m_dep,
wl_client_dep,
pantheon_desktop_shell_dep
wayland_client_dep,
pantheon_desktop_shell_dep,
pantheon_blur_dep
]

gnome.post_install(glib_compile_schemas: true)
Expand Down
2 changes: 1 addition & 1 deletion protocol/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pantheon_desktop_shell_sources += custom_target(
pantheon_desktop_shell_dep = declare_dependency(
dependencies: [
vala.find_library('pantheon-desktop-shell', dirs: meson.current_source_dir()),
dependency('wayland-client'),
wayland_client_dep,
],
include_directories: include_directories('.'),
sources: pantheon_desktop_shell_sources
Expand Down
95 changes: 68 additions & 27 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
}
}

// Keep in sync with CSS
private const int TOP_PADDING = 64;
private const int BORDER_RADIUS = 9;

private Settings transparency_settings;
private static Settings settings = new Settings ("io.elementary.dock");

private Pantheon.Desktop.Shell? desktop_shell;
private Pantheon.Desktop.Panel? panel;
private PantheonBlur.Blur? blur;

private Gtk.Box main_box;
private int height = 0;
private int full_height = 0;
private int visible_width = 0;
private int visible_height = 0;

class construct {
set_css_name ("dock-window");
Expand Down Expand Up @@ -63,7 +70,7 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
if (panel != null) {
panel.set_hide_mode (settings.get_enum ("autohide-mode"));
} else {
update_panel_x11 ();
update_x11_hints ();
}
});

Expand All @@ -84,33 +91,39 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
}
}

public void registry_handle_global (Wl.Registry wl_registry, uint32 name, string @interface, uint32 version) {
if (@interface == "io_elementary_pantheon_shell_v1") {
desktop_shell = wl_registry.bind<Pantheon.Desktop.Shell> (name, ref Pantheon.Desktop.Shell.iface, uint32.min (version, 1));
unowned var surface = get_surface ();
if (surface is Gdk.Wayland.Surface) {
unowned var wl_surface = ((Gdk.Wayland.Surface) surface).get_wl_surface ();
panel = desktop_shell.get_panel (wl_surface);
panel.set_anchor (BOTTOM);
panel.set_hide_mode (settings.get_enum ("autohide-mode"));
}
}
}

private static Wl.RegistryListener registry_listener;
private void init_panel () {
get_surface ().layout.connect_after (() => {
var new_height = main_box.get_height ();
if (new_height == height) {
return;
var new_full_height = main_box.get_height ();
if (new_full_height != full_height) {
full_height = new_full_height;

if (panel != null) {
panel.set_size (-1, full_height);
} else {
update_x11_hints ();
}
}

height = new_height;

if (panel != null) {
panel.set_size (-1, height);
} else {
update_panel_x11 ();
unowned var item_manager = ItemManager.get_default ();
var new_visible_width = item_manager.get_width ();
var new_visible_height = item_manager.get_height ();

if (new_visible_width != visible_width || new_visible_height != visible_height) {
visible_width = new_visible_width;
visible_height = new_visible_height;

if (blur != null) {
blur.set_region (
0,
TOP_PADDING,
visible_width,
visible_height,
BORDER_RADIUS
);
} else {
update_x11_hints ();
}
}
});

Expand All @@ -128,11 +141,31 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
return;
}
} else {
update_panel_x11 ();
update_x11_hints ();
}
}

private void update_panel_x11 () {
public void registry_handle_global (Wl.Registry wl_registry, uint32 name, string @interface, uint32 version) {
if (@interface == "io_elementary_pantheon_shell_v1") {
desktop_shell = wl_registry.bind<Pantheon.Desktop.Shell> (name, ref Pantheon.Desktop.Shell.iface, uint32.min (version, 1));
unowned var surface = get_surface ();
if (surface is Gdk.Wayland.Surface) {
unowned var wl_surface = ((Gdk.Wayland.Surface) surface).get_wl_surface ();
panel = desktop_shell.get_panel (wl_surface);
panel.set_anchor (BOTTOM);
panel.set_hide_mode (settings.get_enum ("autohide-mode"));
}
} else if (@interface == "io_elementary_pantheon_blur_manager_v1") {
var blur_manager = wl_registry.bind<PantheonBlur.BlurManager> (name, ref PantheonBlur.BlurManager.iface, uint32.min (version, 1));
unowned var surface = get_surface ();
if (surface is Gdk.Wayland.Surface) {
unowned var wl_surface = ((Gdk.Wayland.Surface) surface).get_wl_surface ();
blur = blur_manager.get_blur (wl_surface);
}
}
}

private void update_x11_hints () {
var display = Gdk.Display.get_default ();
if (display is Gdk.X11.Display) {
unowned var xdisplay = ((Gdk.X11.Display) display).get_xdisplay ();
Expand All @@ -141,7 +174,15 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {

var prop = xdisplay.intern_atom ("_MUTTER_HINTS", false);

var value = "anchor=8:hide-mode=%d:size=-1,%d".printf (settings.get_enum ("autohide-mode"), height);
var value = "anchor=8:hide-mode=%d:size=-1,%d:blur=%d,%d,%d,%d,%d".printf (
settings.get_enum ("autohide-mode"),
full_height,
0,
TOP_PADDING,
visible_width,
visible_height,
BORDER_RADIUS
);

xdisplay.change_property (window, prop, X.XA_STRING, 8, 0, (uchar[]) value, value.length);
}
Expand Down