-
Notifications
You must be signed in to change notification settings - Fork 1
Client effects
To make window effects look nice and fancy without them becoming overly annoying or distracting, I added some tweaks making them more "responsive" to what you're doing. These tweaks consist of two main parts:
Whenever you maximize a client instance or enable full screen mode, three things will be done to it:
-
The border width will be set to
0
-
The shape will be set to
gears.shape.rectange
, effectively disabling the shape -
A special property will be added, causing
picom
to (temporarily) disable shadows for that client instance
When you un-maximize the client instance / disable full screen mode, all of these values will be restored to their previous values (not to defaults!).
Because it looks very weird (to me) to have cutout corners in the panel when a client instance is maximized / full screen, I also added a tweak that, whenever any client instance's maximized
or fullscreen
property, or the currently active tag changes, the bar will loop through each visible client instance and, if one of them has either a true
maximized
or fullscreen
property, the bar's shape will be set to gears.shape.rectange
.
The code for the client-side effects looks something like this (I intentionally omitted some details compared to the actually used code to keep this short, although there's little functional difference):
local awful = require("awful")
local gears = require("gears")
local function update_shape_of(c)
if c.maximized or c.fullscreen then
c.shape = gears.shape.rectangle
c.border_width = 0
awful.spawn { "xprop", "-id", tostring(c.window), "-f", "_PICOM_SHADOW", "32c", "-set", "_PICOM_SHADOW", "0" }
else
c.shape = function(cr, w, h)
gears.shape.rounded_rect(cr, w, h, 20)
end
c.border_width = 2
awful.spawn { "xprop", "-id", tostring(c.window), "-f", "_PICOM_SHADOW", "32c", "-set", "_PICOM_SHADOW", "1" }
end
end
for _, c in ipairs(client.get()) do
update_shape_of(c)
end
client.connect_signal("manage", update_shape_of)
client.connect_signal("property::fullscreen", update_shape_of)
client.connect_signal("property::maximized", update_shape_of)
Since that's quite noisy, let's go through that one by one.
-
First, we import
awful
andgears
. That should be done at the top of yourrc.lua
by default if you haven't changed anything, in which case you can omit the first 2 lines here. -
Next, we define a new local function called
update_shape_of
, which takes aclient
instance (an app window) as it's first parameter. A client instance has to be passed or it will crash. -
In this function, we check whether either the
maximized
orfullscreen
property or both is/aretrue
.-
If
true
, we make the client instance rectangular, set it's border width to0
(thus hiding it) and add a special property called_PICOM_SHADOW
to the client instance using thexprop
command line utility and set its value to0
to set it to off. In thepicom.conf
, we can react to this using theshadow-exclude
block: -
shadow-exclude = [ # ... "_PICOM_SHADOW@:32c = 0", # ... ]
-
If false, we set the shape and border width to the desired values. We also use
xprop
again here, to make sure that, when a client gets un-maximized / un-fullscreened, it also gets its shadow back.
-
-
After the function, we loop through each existing client instance to make sure that these rules are immediately applied to all already existing client instances.
-
Finally, we connect to some client signals, which makes sure that the correct style of a client instance is applied at its launch and changes when one of its properties does.
For the panel:
local awful = require("awful")
local gears = require("gears")
screen.connect_signal("request::desktop_decoration", function(s)
local my_panel = awful.wibar {
-- ...
}
local panel_shape
function s:update_bar_shape()
for _, c in pairs(self.clients) do
local screen_tags = self.selected_tags
local client_tags = c:tags()
for _, st in ipairs(screen_tags) do
for _, ct in ipairs(client_tags) do
if st == ct and c.maximized and c:isvisible() then
self.my_panel.shape = gears.shape.rectangle
self.my_panel.widget.shape = gears.shape.rectangle
return
end
end
end
end
self.my_panel.shape = panel_shape
self.my_panel.widget.shape = panel_shape
end
client.connect_signal("property::minimized", function(c) s:update_bar_shape() end)
client.connect_signal("property::maximized", function(c) s:update_bar_shape() end)
for _, t in pairs(s.tags) do
t:connect_signal("property::selected", function(c) s:update_bar_shape() end)
end
end
client.connect_signal("manage", function(c)
for s in screen do
s:update_bar_shape()
end
end)