Skip to content
Closed
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
)
46 changes: 46 additions & 0 deletions blur-protocol/pantheon-blur-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?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);
}
}
113 changes: 113 additions & 0 deletions lib/BlurSurface.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2025 elementary, Inc. <https://elementary.io>
* SPDX-License-Identifier: LGPL-3.0-or-later
*/

/**
* This interface is used for asking window manager to provide background blur for the surface.
*/
public interface Granite.BlurSurface : Gtk.Widget, Gtk.Native {
/**
* Returns whether application is running with Wayland backend
*/
public bool is_wayland () {
return Gdk.Display.get_default () is Gdk.Wayland.Display;
}

/**
* Initializes blur support. Uses default `blur_registry_handle_global` and `get_x11_blur_hints`.
* Use if you are not using other Wayland/X11 protocols.
*/
public void simple_blur_init () {
if (is_wayland ()) {
init_wayland (blur_registry_handle_global);
} else {
update_x11_hints (get_x11_blur_hints (0, 0, 0, 0, 0));
}
}

private static Wl.RegistryListener registry_listener;

/**
* Initializes blur support on Wayland.
* Use this method only if you need to manually initialize support of multiple
* Wayland protocols. Otherwise use `simple_blur_init`.
*/
public void init_wayland (Wl.RegistryListenerGlobal registry_handle_global) requires (is_wayland ()) {
registry_listener.global = registry_handle_global;
unowned var display = (Gdk.Wayland.Display) Gdk.Display.get_default ();
unowned var wl_display = display.get_wl_display ();
var wl_registry = wl_display.get_registry ();
wl_registry.add_listener (
registry_listener,
this
);

if (wl_display.roundtrip () < 0) {
return;
}
}

/**
* Registers the window as user of blur protocol. Use with `init_wayland` method.
*/
public void blur_registry_handle_global (Wl.Registry wl_registry, uint32 name, string @interface, uint32 version) {
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 ();
set_data ("-pantheon-wayland-blur", blur_manager.get_blur (wl_surface));
}
}
}

/**
* Request background blur. Use if you use blur Wayland/X11 protocol only.
* Otherwise manually request blur using `request_blur_wayland` and `update_x11_hints` with `get_x11_blur_hints`.
*/
public void simple_request_blur (uint x, uint y, uint width, uint height, uint clip_radius) {
if (is_wayland ()) {
request_blur_wayland (x, y, width, height, clip_radius);
} else {
update_x11_hints (get_x11_blur_hints (x, y, width, height, clip_radius));
}
}

/**
* Request background blur on wayland.
* Use this method only if you use multiple Wayland protocols. Otherwise use `simple_request_blur`.
*/
public void request_blur_wayland (uint x, uint y, uint width, uint height, uint clip_radius) {
if (!is_wayland ()) {
warning ("BlurSurface.request_blur_wayland: Ignoring, not on Wayland");
}

unowned PantheonBlur.Blur? blur = get_data ("-pantheon-wayland-blur");
if (blur != null) {
blur.set_region (x, y, width, height, clip_radius);
} else {
debug ("Couldn't request blur: Blur surface was null. Did you forget to register blur interface?");
}
}

/**
* Updates X11 hints that Gala (Pantheon window manager) uses for its protocols for X11 windows.
* Use only if you support multiple X11 Gala protocols.
*/
public void update_x11_hints (string value) requires (!is_wayland ()) {
unowned var display = (Gdk.X11.Display) Gdk.Display.get_default ();
unowned var xdisplay = display.get_xdisplay ();
var xid = ((Gdk.X11.Surface) get_surface ()).get_xid ();
var prop = xdisplay.intern_atom ("_MUTTER_HINTS", false);
xdisplay.change_property (xid, prop, X.XA_STRING, 8, 0, (uchar[]) value, value.length);
}

/**
* Returns string that can be used in `update_x11_hints` to request blur.
* Use only if you support multiple X11 Gala protocols.
*/
public string get_x11_blur_hints (uint x, uint y, uint width, uint height, uint clip_radius) {
return "blur=%u,%u,%u,%u,%u:".printf (x, y, width, height, clip_radius);
}
}
6 changes: 4 additions & 2 deletions lib/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ subdir('Icons')
subdir('Styles')

libgranite_sources = files(
'DateTime.vala',
'BlurSurface.vala',
'Constants.vala',
'DateTime.vala',
'Init.vala',

'Services/Application.vala',
Expand Down Expand Up @@ -70,7 +71,8 @@ libgranite = library(
dependencies: [
libgranite_deps,
meson.get_compiler('c').find_library('m'),
meson.get_compiler('vala').find_library('posix')
meson.get_compiler('vala').find_library('posix'),
pantheon_blur_dep
],

vala_header: 'granite-7.h',
Expand Down
6 changes: 6 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,25 @@ add_project_arguments(
language: ['vala']
)

wayland_client_dep = dependency('wayland-client')

libgranite_deps = [
dependency('gee-0.8'),
dependency('gio-2.0', version: '>=' + glib_min_version),
gio_os_dep,
dependency('glib-2.0', version: '>=' + glib_min_version),
dependency('gobject-2.0', version: '>=' + glib_min_version),
dependency('gtk4', version: '>=4.4'),
dependency('gtk4-wayland', version: '>=4.4'),
dependency('gtk4-x11', version: '>=4.4'),
wayland_client_dep
]

pkgconfig = import('pkgconfig')
gnome = import('gnome')
i18n = import('i18n')

subdir('blur-protocol')
subdir('lib')
subdir('data')
subdir('po')
Expand Down