Skip to content
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
149 changes: 149 additions & 0 deletions data/mobi.phosh.shell.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,154 @@
Apps in this list will not appear in the launcher or app drawer.
</description>
</key>

<key name="glass-theme" type="b">
<default>false</default>
<summary>Use the FuriOS glass theme</summary>
<description>
Whether to style the shell as frosted glass. Off leaves phosh with
its own stylesheet untouched; on loads the FuriOS variant of it and
gives GTK4 applications a matching one. The keys below only take
effect while this is on.
</description>
</key>

<key name="accent-color-custom" type="s">
<default>''</default>
<summary>Custom accent colour</summary>
<description>
A free-form accent colour for the shell, as any colour GDK can parse,
for example '#3584e4'. When set this overrides the accent chosen in
Settings, so the shell is not limited to the nine preset swatches.
Empty means follow that setting. Note that GTK4 applications only
understand the presets, so a custom colour applies to the shell alone.
</description>
</key>

<key name="glass-text-color" type="s">
<default>''</default>
<summary>Shell text colour</summary>
<description>
A free-form colour for the shell's text and icons, as any colour GDK
can parse. Every piece of shell text follows this, including text
drawn on an accent fill. Empty follows the theme, which is near-white
on the dark variant and near-black on the light one.
</description>
</key>

<key name="glass-accent-text-color" type="s">
<default>''</default>
<summary>Colour of text drawn on the accent</summary>
<description>
The colour of labels and icons sitting on top of an accent fill -- a
selected quick setting, a pressed keypad key, a card. This is a
different question from the main text colour only if you want it to
be. Empty follows the main text colour, so all of the shell's text
matches unless this is set deliberately.
</description>
</key>

<key name="glass-text-shadow-color" type="s">
<default>''</default>
<summary>Colour of the drop shadow behind shell text</summary>
<description>
The colour of the small drop shadow carried by the shell's text and
icons, most visibly the lock screen clock, date and status labels,
which sit over a wallpaper the shell does not choose. Empty follows
the text colour in use and takes the opposite of it, so light text
gets a dark shadow and dark text a light one. Changing glass-text-color
is therefore enough on its own; this key is for the case where the
wallpaper wants a shadow that is neither.
</description>
</key>

<key name="glass-text-shadow" type="d">
<default>0.7</default>
<range min="0.0" max="1.0"/>
<summary>Strength of the drop shadow behind shell text</summary>
<description>
How opaque that shadow is. 0 turns it off entirely. The offset stays
small and fixed -- one to three pixels depending on the size of the
text, always more than the blur under it, because a blur wider than
its offset is a glow rather than a shadow. It is there to hold text
legible against an arbitrary wallpaper, not to be seen in its own
right.
</description>
</key>

<key name="glass-text-opacity" type="d">
<default>1.0</default>
<range min="0.2" max="1.0"/>
<summary>Shell text opacity</summary>
<description>
How opaque the shell's text and icons are. Lower values let the
frosted backdrop show through the text itself. The floor is deliberate:
text that can be turned fully invisible is a way to make the shell
unusable with no obvious way back.
</description>
</key>

<key name="lockscreen-tint" type="b">
<default>true</default>
<summary>Tint the wallpaper behind the lock screen clock</summary>
<description>
Whether the lock screen lays its translucent sheet over the wallpaper
on the page showing the clock and date. On, the wallpaper is dimmed and
the clock stays legible over a bright or busy picture. Off, the picture
is shown as it is.

The keypad page keeps its sheet either way: the keys and the passcode
entry need a surface to sit on.
</description>
</key>

<key name="glass-blur-radius" type="u">
<default>100</default>
<range min="0" max="200"/>
<summary>Background blur radius</summary>
<description>
How strongly the compositor blurs what is behind the shell's glass
surfaces: the top panel, the settings drawer and the lock screen.
0 turns the blur off. Needs a compositor that supports background
blur; without one this has no effect.
</description>
</key>

<key name="glass-opacity" type="d">
<default>0.15</default>
<range min="0.0" max="1.0"/>
<summary>Glass opacity</summary>
<description>
How solid the shell's glass surfaces are. 0.0 is fully transparent
and 1.0 is opaque, hiding the blur behind it entirely. Other glass
surfaces are scaled from this, keeping their relative weights.
Application windows keep a small minimum whatever this is set to,
since a window with no background at all leaves its text floating on
the wallpaper.
</description>
</key>

<key name="glass-lightness" type="d">
<default>0.15</default>
<range min="0.0" max="1.0"/>
<summary>Glass lightness</summary>
<description>
How much white is mixed into the glass, for a frostier and paler
look. 0.0 keeps the theme's own background colour.
</description>
</key>

<key name="glass-accent-wash" type="d">
<default>0.15</default>
<range min="0.0" max="1.0"/>
<summary>Accent wash strength</summary>
<description>
How much of the accent colour is washed into the glass surfaces, so
that the drawer, lock screen and overview carry the accent chosen in
Settings. 0.0 leaves them neutral. The light theme uses a lower
proportion of this, since a tint reads more strongly against a pale
background.
</description>
</key>
</schema>
</schemalist>
1 change: 1 addition & 0 deletions protocol/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ wl_protos = [
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
['input-method-unstable-v2.xml'],
['phoc-device-state-unstable-v1.xml'],
['phoc-furios-layer-shell-effects-unstable-v1.xml'],
['phoc-layer-shell-effects-unstable-v1.xml'],
['phosh-private.xml'],
['virtual-keyboard-unstable-v1.xml'],
Expand Down
93 changes: 93 additions & 0 deletions protocol/phoc-furios-layer-shell-effects-unstable-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="phoc_furios_layer_shell_effects_unstable_v1">
<copyright>
Copyright © 2026 FuriLabs

Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.

THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>

<interface name="zphoc_furios_layer_shell_effects_v1" version="1">
<description summary="FuriOS additions to layer surface effects">
Assigns FuriOS specific features to layer surfaces.

This is deliberately a protocol of its own rather than additions to
zphoc_layer_shell_effects_v1, which phoc owns: extending that interface
here would collide with any version phoc adds upstream, and a client
could not then tell the two apart.

Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible changes
may be added together with the corresponding interface version bump.
Backward incompatible changes are done by bumping the version number in
the protocol and interface names and resetting the interface version.
Once the protocol is to be declared stable, the 'z' prefix and the
version number in the protocol and interface names are removed and the
interface version number is reset.
</description>

<enum name="error">
<entry name="bad_surface" value="0" summary="layer surface is not committed"/>
</enum>

<request name="destroy" type="destructor">
<description summary="destroy the effects object">
This doesn't destroy the objects created via this interface.
</description>
</request>

<request name="get_blur_layer_surface">
<description summary="Blur the background behind a layer_surface">
Requests that the compositor blurs the content rendered beneath
the layer surface so that translucent parts of the surface appear
frosted.
</description>
<arg name="id" type="new_id" interface="zphoc_furios_blur_layer_surface_v1"/>
<arg name="layer_surface" type="object" interface="zwlr_layer_surface_v1"/>
</request>
</interface>

<interface name="zphoc_furios_blur_layer_surface_v1" version="1">
<description summary="A layer surface with a blurred backdrop">
This interface gives a layer surface a blurred backdrop. The blur is
only visible through the translucent parts of the surface.
</description>

<request name="set_blur">
<description summary="Set the blur strength">
Set the strength of the blur applied to the content beneath the
surface. A value of 0 disables blur; higher values increase the
blur radius. The compositor maps the value onto its blur
implementation; useful values are in the range 0 to 100.

Blur is double-buffered, see wl_surface.commit.
</description>
<arg name="radius" type="uint"/>
</request>

<request name="destroy" type="destructor">
<description summary="destroy the blur_layer_surface">
This request destroys the blur layer surface and removes the
blur from the underlying surface.
</description>
</request>
</interface>
</protocol>
2 changes: 2 additions & 0 deletions src/layersurface-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ int phosh_layer_surface_get_configured_width (Pho
int phosh_layer_surface_get_configured_height (PhoshLayerSurface *self);
void phosh_layer_surface_set_alpha (PhoshLayerSurface *self,
double alpha);
void phosh_layer_surface_set_blur (PhoshLayerSurface *self,
guint radius);
void phosh_layer_surface_set_stacked_above (PhoshLayerSurface *self,
PhoshLayerSurface *target);
void phosh_layer_surface_set_stacked_below (PhoshLayerSurface *self,
Expand Down
56 changes: 56 additions & 0 deletions src/layersurface.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ typedef struct {
struct wl_surface *wl_surface;
struct zwlr_layer_surface_v1 *layer_surface;
struct zphoc_alpha_layer_surface_v1 *alpha_surface;
struct zphoc_furios_blur_layer_surface_v1 *blur_surface;
struct zphoc_stacked_layer_surface_v1 *stacked_surface;

/* Properties */
Expand All @@ -72,6 +73,8 @@ typedef struct {
struct wl_output *wl_output;
/* alpha_layer_surface_v1 */
double alpha;
/* blur_layer_surface_v1 */
guint blur_radius;
/* stacked_layer_surface_v1 */
PhoshLayerSurface *stack_target;
gboolean stack_above;
Expand Down Expand Up @@ -153,6 +156,21 @@ set_alpha (PhoshLayerSurface *self, double alpha)
}


static void
set_blur (PhoshLayerSurface *self, guint radius)
{
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);

priv->blur_radius = radius;

if (!priv->blur_surface)
return;

zphoc_furios_blur_layer_surface_v1_set_blur (priv->blur_surface, radius);
wl_surface_commit (priv->wl_surface);
}


static void
phosh_layer_surface_set_stacked (PhoshLayerSurface *self, PhoshLayerSurface *target, gboolean above)
{
Expand Down Expand Up @@ -354,6 +372,7 @@ phosh_layer_surface_map (GtkWidget *widget)
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
PhoshWayland *wl = phosh_wayland_get_default ();
struct zphoc_layer_shell_effects_v1 *layer_shell_effects;
struct zphoc_furios_layer_shell_effects_v1 *furios_layer_shell_effects;

GTK_WIDGET_CLASS (phosh_layer_surface_parent_class)->map (widget);

Expand Down Expand Up @@ -396,11 +415,23 @@ phosh_layer_surface_map (GtkWidget *widget)
priv->stacked_surface =
zphoc_layer_shell_effects_v1_get_stacked_layer_surface (layer_shell_effects,
priv->layer_surface);
/* Blur is ours rather than phoc's, so it comes from a global of its own. A
* compositor without it leaves blur_surface NULL and set_blur() does nothing. */
furios_layer_shell_effects = phosh_wayland_get_zphoc_furios_layer_shell_effects_v1 (wl);
if (furios_layer_shell_effects) {
priv->blur_surface =
zphoc_furios_layer_shell_effects_v1_get_blur_layer_surface (furios_layer_shell_effects,
priv->layer_surface);
}

/* Catch up with alpha values set before map */
if (!G_APPROX_VALUE (priv->alpha, 1.0, FLT_EPSILON))
set_alpha (self, priv->alpha);

/* Catch up with blur values set before map */
if (priv->blur_radius > 0)
set_blur (self, priv->blur_radius);

/* Catch up with stackings set before map */
if (priv->stacked_surface)
phosh_layer_surface_set_stacked (self, priv->stack_target, priv->stack_above);
Expand All @@ -414,6 +445,7 @@ phosh_layer_surface_unmap (GtkWidget *widget)
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);

g_clear_pointer (&priv->alpha_surface, zphoc_alpha_layer_surface_v1_destroy);
g_clear_pointer (&priv->blur_surface, zphoc_furios_blur_layer_surface_v1_destroy);
g_clear_pointer (&priv->stacked_surface, zphoc_stacked_layer_surface_v1_destroy);
g_clear_pointer (&priv->layer_surface, zwlr_layer_surface_v1_destroy);
priv->wl_surface = NULL;
Expand All @@ -437,6 +469,7 @@ phosh_layer_surface_dispose (GObject *object)

phosh_layer_surface_set_stacked (self, NULL, FALSE);
g_clear_pointer (&priv->alpha_surface, zphoc_alpha_layer_surface_v1_destroy);
g_clear_pointer (&priv->blur_surface, zphoc_furios_blur_layer_surface_v1_destroy);
g_clear_pointer (&priv->stacked_surface, zphoc_stacked_layer_surface_v1_destroy);
g_clear_pointer (&priv->layer_surface, zwlr_layer_surface_v1_destroy);
g_clear_pointer (&priv->namespace, g_free);
Expand Down Expand Up @@ -968,6 +1001,29 @@ phosh_layer_surface_set_alpha (PhoshLayerSurface *self, double alpha)
set_alpha (self, alpha);
}

/**
* phosh_layer_surface_set_blur:
* @self: The layer surface
* @radius: The blur radius, 0 disables blur
*
* Requests that the compositor blurs the content behind the surface
* so translucent parts appear frosted. Needs a compositor supporting
* the blur layer surface protocol, otherwise it has no effect.
*/
void
phosh_layer_surface_set_blur (PhoshLayerSurface *self, guint radius)
{
PhoshLayerSurfacePrivate *priv;

g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
priv = phosh_layer_surface_get_instance_private (self);

if (priv->blur_radius == radius)
return;

set_blur (self, radius);
}

/**
* phosh_layer_surface_set_stacked_above:
* @self: The surface to be stacked
Expand Down
Loading