Skip to content
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

[RFC] client: Rewrite the client stacking code in Lua. #3751

Open
wants to merge 1 commit into
base: master
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
10 changes: 8 additions & 2 deletions event.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,8 +830,14 @@ event_handle_maprequest(xcb_map_request_event_t *ev)
luaA_object_push(L, c);
client_set_minimized(L, -1, false);
lua_pop(L, 1);
/* it will be raised, so just update ourself */
client_raise(c);

lua_pushstring(L, "maprequest");
lua_newtable(L);
lua_pushstring(L, "client");
luaA_object_push(L, c);
lua_rawset(L, -3);

luaA_object_emit_signal(L, -3, "request::raise", 2);
}
}
else
Expand Down
1 change: 0 additions & 1 deletion event.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ awesome_refresh(void)
drawin_refresh();
client_refresh();
banning_refresh();
stack_refresh();
client_destroy_later();
return xcb_flush(globalconf.connection);
}
Expand Down
115 changes: 111 additions & 4 deletions lib/awful/layout/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@
local ipairs = ipairs
local type = type
local capi = {
screen = screen,
mouse = mouse,
screen = screen,
mouse = mouse,
awesome = awesome,
client = client,
tag = tag
client = client,
drawin = drawin,
tag = tag,
root = root,
}
local tag = require("awful.tag")
local client = require("awful.client")
Expand All @@ -55,6 +57,9 @@ end

local layout = {}

-- Avoid restacking the clients and drawins too often.
local need_restack = true

-- Support `table.insert()` to avoid breaking old code.
local default_layouts = setmetatable({}, {
__newindex = function(self, key, value)
Expand All @@ -64,6 +69,17 @@ local default_layouts = setmetatable({}, {
end
})

local x11_layers_ordered, x11_layers_keys = {
"WINDOW_LAYER_IGNORE",
"WINDOW_LAYER_DESKTOP",
"WINDOW_LAYER_BELOW",
"WINDOW_LAYER_NORMAL",
"WINDOW_LAYER_ABOVE",
"WINDOW_LAYER_FULLSCREEN",
"WINDOW_LAYER_ONTOP"
}, {}

for k, v in ipairs(x11_layers_ordered) do x11_layers_keys[v] = k end

layout.suit = require("awful.layout.suit")

Expand Down Expand Up @@ -108,6 +124,27 @@ local arrange_lock = false
-- Delay one arrange call per screen.
local delayed_arrange = {}

local function client_to_layer(o)
if o.type == "desktop" then
return x11_layers_keys.WINDOW_LAYER_DESKTOP
elseif o.ontop then
-- first deal with user set attributes
return x11_layers_keys.WINDOW_LAYER_ONTOP;
elseif o.fullscreen and capi.client.focus == o then
-- Fullscreen windows only get their own layer when they have the focus
return x11_layers_keys.WINDOW_LAYER_FULLSCREEN;
elseif o.above then
return x11_layers_keys.WINDOW_LAYER_ABOVE;
elseif o.below then
return x11_layers_keys.WINDOW_LAYER_BELOW;
elseif o.transient_for then
-- check for transient attr
return x11_layers_keys.WINDOW_LAYER_IGNORE;
else
return x11_layers_keys.WINDOW_LAYER_NORMAL
end
end

--- Get the current layout.
-- @tparam screen screen The screen.
-- @return The layout function.
Expand Down Expand Up @@ -237,6 +274,7 @@ end
-- @tparam screen screen The screen to arrange.
-- @noreturn
-- @staticfct awful.layout.arrange
-- @see restack
function layout.arrange(screen)
screen = get_screen(screen)
if not screen or delayed_arrange[screen] then return end
Expand Down Expand Up @@ -417,8 +455,77 @@ function layout.move_handler(c, context, hints) --luacheck: no unused args
end
end

-- [UNDOCUMENTED] Handler for `request::restack`.
--
-- @signalhandler awful.layout.move_handler
-- @tparam string context The context
-- @tparam table hints Additional hints
-- @tparam[opt=nil] client|nil hints.client The client
-- @tparam[opt=nil] drawin|nil hints.drawin Additional hints
function layout._restack_handler(context, hints) -- luacheck: no unused args
--TODO Support permissions
need_restack = true
end

--- Arrange the clients on the Z axis.
-- @staticfct awful.layout.restack
-- @noreturn
-- @see arrange
function layout.restack()

local layers = {}

local function append(o)
local layer = client_to_layer(o)
layers[layer] = layers[layer] or {}
table.insert(layers[layer], 1, o.drawin and o.drawin or o)
end

local drawins, clients = capi.drawin.get(), capi.client.get(nil, true)

for _, c in ipairs(clients) do append(c) end
for i=#drawins, 1, -1 do append(drawins[i].get_wibox()) end
Comment on lines +486 to +487
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two lines should be swapped, as in the original C code, drawins are rendered under clients. (plus it kinda ruins the point of ontop)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this, swapping those line breaks quite a few things. For example, the client go on top of the wibar in the "old" builds. If I swap these, the wibox goes on top. That doesn't mean it didn't break anything. It's after all not exactly what it did before. What did you witness being in the wrong order?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That must've been a mistake on my end. Wiboxes do indeed go on top when these two lines are swapped. I just thought that it would be the other way around. Didn't notice line 482 inserting into the table at index 1 lol

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO client should go over wibar only if it have c.ontop == true


local result = {}

for i = 1, #x11_layers_ordered do
if layers[i] then
for _, v in ipairs(layers[i] or {}) do
table.insert(result, v)
end
end
end

capi.root.set_stacking_order(result)
end

capi.client.connect_signal("request::geometry", layout.move_handler)

-- Translate the `request::raise`, which will trigger a `"request::restack"`.
capi.client.connect_signal("request::raise", function(c, context, hints) --luacheck: no unused args
hints.client:raise()
end)

capi.client.connect_signal("request::restack", layout._restack_handler)

-- Check if the type is `"desktop"`, which goes below everything.
for _, class in ipairs(capi.client, capi.drawin) do
class.connect_signal("property::type", function(o)
capi.client.emit_signal("request::restack", "type", {
client = o.modal ~= nil and o or nil,
drawin = o.modal == nil and o or nil,
})
end)
end

-- Place the clients and drawin on top of each other.
capi.awesome.connect_signal("refresh", function()
if need_restack then
layout.restack()
need_restack = false
end
end)

-- When a screen is moved, make (floating) clients follow it
capi.screen.connect_signal("property::geometry", function(s, old_geom)
local geom = s.geometry
Expand Down
44 changes: 33 additions & 11 deletions objects/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2241,7 +2241,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at
ewmh_client_check_hints(c);

/* Push client in stack */
stack_client_push(c);
stack_client_push(L, c, "manage");

/* Request our response */
xcb_get_property_reply_t *reply =
Expand Down Expand Up @@ -2717,7 +2717,7 @@ client_set_fullscreen(lua_State *L, int cidx, bool s)
luaA_object_emit_signal(L, abs_cidx, "property::fullscreen", 0);
/* Force a client resize, so that titlebars get shown/hidden */
client_resize_do(c, c->geometry);
stack_windows();
stack_windows(L, "fullscreen", c, NULL);
}
}

Expand Down Expand Up @@ -2768,7 +2768,7 @@ client_set_maximized_common(lua_State *L, int cidx, bool s, const char* type, co
if(max_before != c->maximized)
luaA_object_emit_signal(L, abs_cidx, "property::maximized", 0);

stack_windows();
stack_windows(L, "maximized", c, NULL);
}
}

Expand Down Expand Up @@ -2816,7 +2816,7 @@ client_set_above(lua_State *L, int cidx, bool s)
client_set_fullscreen(L, cidx, false);
}
c->above = s;
stack_windows();
stack_windows(L, "above", c, NULL);
luaA_object_emit_signal(L, cidx, "property::above", 0);
}
}
Expand All @@ -2841,7 +2841,7 @@ client_set_below(lua_State *L, int cidx, bool s)
client_set_fullscreen(L, cidx, false);
}
c->below = s;
stack_windows();
stack_windows(L, "below", c, NULL);
luaA_object_emit_signal(L, cidx, "property::below", 0);
}
}
Expand All @@ -2859,7 +2859,7 @@ client_set_modal(lua_State *L, int cidx, bool s)
if(c->modal != s)
{
c->modal = s;
stack_windows();
stack_windows(L, "modal", c, NULL);
luaA_object_emit_signal(L, cidx, "property::modal", 0);
}
}
Expand All @@ -2884,7 +2884,7 @@ client_set_ontop(lua_State *L, int cidx, bool s)
client_set_fullscreen(L, cidx, false);
}
c->ontop = s;
stack_windows();
stack_windows(L, "ontop", c, NULL);
luaA_object_emit_signal(L, cidx, "property::ontop", 0);
}
}
Expand Down Expand Up @@ -2942,7 +2942,7 @@ client_unmanage(client_t *c, client_unmanage_t reason)
client_array_remove(&globalconf.clients, elem);
break;
}
stack_client_remove(c);
stack_client_remove(L, c, false, "unmanage");
for(int i = 0; i < globalconf.tags.len; i++)
untag_client(c, globalconf.tags.tab[i]);

Expand Down Expand Up @@ -3402,7 +3402,29 @@ luaA_client_raise(lua_State *L)
)
return 0;

client_raise(c);
client_t *tc = c;
int counter = 0;

/* Find number of transient layers. */
for(counter = 0; tc->transient_for; counter++)
tc = tc->transient_for;

/* Push them in reverse order. */
for(; counter > 0; counter--)
{
tc = c;
for(int i = 0; i < counter; i++)
tc = tc->transient_for;
stack_client_append(L, tc, "raise");
}

/* Push c on top of the stack. */
stack_client_append(L, c, "raise");

/* Notify the listeners */
luaA_object_push(L, c);
luaA_object_emit_signal(L, -1, "raised", 0);
lua_pop(L, 1);

return 0;
}
Expand All @@ -3426,11 +3448,11 @@ luaA_client_lower(lua_State *L)
if (globalconf.stack.len && globalconf.stack.tab[0] == c)
return 0;

stack_client_push(c);
stack_client_push(L, c, "lower");

/* Traverse all transient layers. */
for(client_t *tc = c->transient_for; tc; tc = tc->transient_for)
stack_client_push(tc);
stack_client_push(L, tc, "lower");

/* Notify the listeners */
luaA_object_push(L, c);
Expand Down
32 changes: 0 additions & 32 deletions objects/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,38 +258,6 @@ drawable_t *client_get_drawable(client_t *, int, int);
drawable_t *client_get_drawable_offset(client_t *, int *, int *);
area_t client_get_undecorated_geometry(client_t *);

/** Put client on top of the stack.
* \param c The client to raise.
*/
static inline void
client_raise(client_t *c)
{
client_t *tc = c;
int counter = 0;

/* Find number of transient layers. */
for(counter = 0; tc->transient_for; counter++)
tc = tc->transient_for;

/* Push them in reverse order. */
for(; counter > 0; counter--)
{
tc = c;
for(int i = 0; i < counter; i++)
tc = tc->transient_for;
stack_client_append(tc);
}

/* Push c on top of the stack. */
stack_client_append(c);

/* Notify the listeners */
lua_State *L = globalconf_get_lua_State();
luaA_object_push(L, c);
luaA_object_emit_signal(L, -1, "raised", 0);
lua_pop(L, 1);
}

/** Check if a client has fixed size.
* \param c A client.
* \return A boolean value, true if the client has a fixed size.
Expand Down
4 changes: 2 additions & 2 deletions objects/drawin.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ drawin_map(lua_State *L, int widx)
/* Deactivate BMA */
client_restore_enterleave_events();
/* Stack this drawin correctly */
stack_windows();
stack_windows(L, "append", NULL, drawin);
/* Add it to the list of visible drawins */
drawin_array_append(&globalconf.drawins, drawin);
/* Make sure it has a surface */
Expand Down Expand Up @@ -591,7 +591,7 @@ luaA_drawin_set_ontop(lua_State *L, drawin_t *drawin)
if(b != drawin->ontop)
{
drawin->ontop = b;
stack_windows();
stack_windows(L, "ontop", NULL, drawin);
luaA_object_emit_signal(L, -3, "property::ontop", 0);
}
return 0;
Expand Down
2 changes: 2 additions & 0 deletions root.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "objects/button.h"
#include "common/luaclass.h"
#include "xwindow.h"
#include "stack.h"

#include "math.h"

Expand Down Expand Up @@ -653,6 +654,7 @@ const struct luaL_Reg awesome_root_methods[] =
{ "tags", luaA_root_tags },
{ "__index", luaA_root_index },
{ "__newindex", luaA_root_newindex },
{ "set_stacking_order", luaA_set_stacking_order},
{ "set_index_miss_handler", luaA_root_set_index_miss_handler},
{ "set_call_handler", luaA_root_set_call_handler},
{ "set_newindex_miss_handler", luaA_root_set_newindex_miss_handler},
Expand Down
Loading