Merge pull request #1748 from Elv13/fix_maximize_again

Fix maximize again
This commit is contained in:
Daniel Hahler 2017-05-23 23:56:29 +02:00 committed by GitHub
commit b98ca2ec98
5 changed files with 290 additions and 10 deletions

32
event.c
View File

@ -341,6 +341,8 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev)
uint16_t deco_bottom = bw + tb_bottom;
int16_t diff_w = 0, diff_h = 0, diff_border = 0;
lua_State *L = globalconf_get_lua_State();
if(ev->value_mask & XCB_CONFIG_WINDOW_X)
{
int16_t diff = 0;
@ -373,8 +375,6 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev)
}
if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
{
lua_State *L = globalconf_get_lua_State();
diff_border = ev->border_width - bw;
diff_h += diff_border;
diff_w += diff_border;
@ -396,7 +396,33 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev)
}
c->got_configure_request = true;
client_resize(c, geometry, false);
/* Request the changes to be applied */
luaA_object_push(L, c);
lua_pushstring(L, "ewmh"); /* context */
lua_newtable(L); /* props */
/* area, it needs to be directly in the `hints` table to comply with
the "protocol"
*/
lua_pushstring(L, "x");
lua_pushinteger(L, geometry.x);
lua_rawset(L, -3);
lua_pushstring(L, "y");
lua_pushinteger(L, geometry.y);
lua_rawset(L, -3);
lua_pushstring(L, "width");
lua_pushinteger(L, geometry.width);
lua_rawset(L, -3);
lua_pushstring(L, "height");
lua_pushinteger(L, geometry.height);
lua_rawset(L, -3);
luaA_object_emit_signal(L, -3, "request::geometry", 2);
lua_pop(L, 1);
}
else if (xembed_getbywin(&globalconf.embedded, ev->window))
{

63
ewmh.c
View File

@ -207,6 +207,28 @@ ewmh_init(void)
father, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &i);
}
static void
ewmh_update_maximize(bool h, bool status, bool toggle)
{
lua_State *L = globalconf_get_lua_State();
if (h)
lua_pushstring(L, "client_maximize_horizontal");
else
lua_pushstring(L, "client_maximize_vertical");
/* Create table argument with raise=true. */
lua_newtable(L);
lua_pushstring(L, "toggle");
lua_pushboolean(L, toggle);
lua_settable(L, -3);
lua_pushstring(L, "status");
lua_pushboolean(L, status);
lua_settable(L, -3);
luaA_object_emit_signal(L, -3, "request::geometry", 2);
}
void
ewmh_init_lua(void)
{
@ -333,20 +355,20 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
else if(state == _NET_WM_STATE_MAXIMIZED_HORZ)
{
if(set == _NET_WM_STATE_REMOVE)
client_set_maximized_horizontal(L, -1, false);
ewmh_update_maximize(true, false, false);
else if(set == _NET_WM_STATE_ADD)
client_set_maximized_horizontal(L, -1, true);
ewmh_update_maximize(true, true, false);
else if(set == _NET_WM_STATE_TOGGLE)
client_set_maximized_horizontal(L, -1, !c->maximized_horizontal);
ewmh_update_maximize(true, false, true);
}
else if(state == _NET_WM_STATE_MAXIMIZED_VERT)
{
if(set == _NET_WM_STATE_REMOVE)
client_set_maximized_vertical(L, -1, false);
ewmh_update_maximize(false, false, false);
else if(set == _NET_WM_STATE_ADD)
client_set_maximized_vertical(L, -1, true);
ewmh_update_maximize(false, true, false);
else if(set == _NET_WM_STATE_TOGGLE)
client_set_maximized_vertical(L, -1, !c->maximized_vertical);
ewmh_update_maximize(false, false, true);
}
else if(state == _NET_WM_STATE_ABOVE)
{
@ -554,6 +576,8 @@ ewmh_client_check_hints(client_t *c)
void *data = NULL;
xcb_get_property_cookie_t c0, c1, c2;
xcb_get_property_reply_t *reply;
bool is_h_max = false;
bool is_v_max = false;
/* Send the GetProperty requests which will be processed later */
c0 = xcb_get_property_unchecked(globalconf.connection, false, c->window,
@ -578,9 +602,36 @@ ewmh_client_check_hints(client_t *c)
{
state = (xcb_atom_t *) data;
for(int i = 0; i < xcb_get_property_value_length(reply) / ssizeof(xcb_atom_t); i++)
if (state[i] == _NET_WM_STATE_MAXIMIZED_HORZ)
is_h_max = true;
else if (state[i] == _NET_WM_STATE_MAXIMIZED_VERT)
is_v_max = true;
else
ewmh_process_state_atom(c, state[i], _NET_WM_STATE_ADD);
}
/* Check maximization manually */
if (is_h_max && is_v_max) {
lua_State *L = globalconf_get_lua_State();
luaA_object_push(L, c);
client_set_maximized(L, -1, true);
lua_pop(L, 1);
}
else if(is_h_max)
{
lua_State *L = globalconf_get_lua_State();
luaA_object_push(L, c);
client_set_maximized_horizontal(L, -1, true);
lua_pop(L, 1);
}
else if(is_v_max)
{
lua_State *L = globalconf_get_lua_State();
luaA_object_push(L, c);
client_set_maximized_vertical(L, -1, true);
lua_pop(L, 1);
}
p_delete(&reply);
reply = xcb_get_property_reply(globalconf.connection, c2, NULL);

View File

@ -9,6 +9,7 @@
local client = client
local screen = screen
local ipairs = ipairs
local timer = require("gears.timer")
local gtable = require("gears.table")
local aclient = require("awful.client")
local aplace = require("awful.placement")
@ -302,10 +303,88 @@ function ewmh.geometry(c, context, hints)
end
end
--- Merge the 2 requests sent by clients wanting to be maximized.
--
-- The X clients set 2 flags (atoms) when they want to be maximized. This caused
-- 2 request::geometry to be sent. This code gives some time for them to arrive
-- and send a new `request::geometry` (through the property change) with the
-- combined state.
--
-- @signalhandler awful.ewmh.merge_maximization
-- @tparam client c The client
-- @tparam string context The context
-- @tparam[opt={}] table hints The hints to pass to the handler
function ewmh.merge_maximization(c, context, hints)
if context ~= "client_maximize_horizontal" and context ~= "client_maximize_vertical" then
return
end
if not c._delay_maximization then
c._delay_maximization = function()
-- This ignores unlikely corner cases like mismatching toggles.
-- That's likely to be an accident anyway.
if c._delayed_max_h and c._delayed_max_v then
c.maximized = c._delayed_max_h or c._delayed_max_v
elseif c._delayed_max_h then
c.maximized_horizontal = c._delayed_max_h
elseif c._delayed_max_v then
c.maximized_vertical = c._delayed_max_v
end
end
timer {
timeout = 1/60,
autostart = true,
single_shot = true,
callback = function()
if not c.valid then return end
c._delay_maximization(c)
c._delay_maximization = nil
c._delayed_max_h = nil
c._delayed_max_v = nil
end
}
end
local function get_value(suffix, long_suffix)
if hints.toggle and c["_delayed_max_"..suffix] ~= nil then
return not c["_delayed_max_"..suffix]
elseif hints.toggle then
return not c["maximized_"..long_suffix]
else
return hints.status
end
end
if context == "client_maximize_horizontal" then
c._delayed_max_h = get_value("h", "horizontal")
elseif context == "client_maximize_vertical" then
c._delayed_max_v = get_value("v", "vertical")
end
end
--- Allow the client to move itself.
--
-- This is the default geometry request handler when the context is `ewmh`.
--
-- @signalhandler awful.ewmh.client_geometry_requests
-- @tparam client c The client
-- @tparam string context The context
-- @tparam[opt={}] table hints The hints to pass to the handler
function ewmh.client_geometry_requests(c, context, hints)
if context == "ewmh" and hints then
c:geometry(hints)
end
end
client.connect_signal("request::activate", ewmh.activate)
client.connect_signal("request::tag", ewmh.tag)
client.connect_signal("request::urgent", ewmh.urgent)
client.connect_signal("request::geometry", ewmh.geometry)
client.connect_signal("request::geometry", ewmh.merge_maximization)
client.connect_signal("request::geometry", ewmh.client_geometry_requests)
client.connect_signal("property::border_width", repair_geometry)
client.connect_signal("property::screen", repair_geometry)
screen.connect_signal("property::workarea", function(s)

View File

@ -32,8 +32,19 @@ local function open_window(class, title, options)
}
window:set_geometry_hints(nil, geom, Gdk.WindowHints.RESIZE_INC)
end
if options.maximize_before then
window:maximize()
end
window:set_wmclass(class, class)
window:show_all()
if options.maximize_after then
window:maximize()
end
if options.resize_after_width and options.resize_after_height then
window:resize(
tonumber(options.resize_after_width), tonumber(options.resize_after_height)
)
end
end
local function parse_options(options)
@ -124,10 +135,26 @@ return function(class, title, sn_rules, callback, resize_increment, args)
if resize_increment then
options = options .. "resize_increment,"
end
if args.maximize_before then
options = options .. "maximize_before,"
end
if args.maximize_after then
options = options .. "maximize_after,"
end
if args.resize then
options = table.concat {
options,
"resize_after_width=",
args.resize.height, ",",
"resize_after_height=",
args.resize.width, ","
}
end
if args.gravity then
assert(type(args.gravity)=="number","Use `lgi.Gdk.Gravity.NORTH_WEST`")
options = options .. "gravity=" .. args.gravity .. ","
end
local data = class .. "\n" .. title .. "\n" .. options .. "\n"
local success, msg = pipe:write_all(data)
assert(success, tostring(msg))

View File

@ -12,6 +12,17 @@ end
local original_geo = nil
local counter = 0
local function geometry_handler(c, context, hints)
hints = hints or {}
assert(type(c) == "client")
assert(type(context) == "string")
assert(type(hints.toggle) == "boolean")
assert(type(hints.status) == "boolean")
counter = counter + 1
end
local steps = {
function(count)
if count == 1 then
@ -142,6 +153,92 @@ local steps = {
assert(geo_to_str(original_geo) == geo_to_str(new_geo),
geo_to_str(original_geo) .. " == " .. geo_to_str(new_geo))
c:kill()
return true
end,
-- Now, start some clients maximized
function()
if #client.get() > 0 then return end
test_client(nil,nil,nil,nil,nil,{maximize_before=true})
return true
end,
function()
local c = client.get()[1]
if not c then return end
assert(not c.maximized_horizontal)
assert(not c.maximized_vertical)
assert(c.maximized)
c:kill()
return true
end,
function()
if #client.get() > 0 then return end
test_client(nil,nil,nil,nil,nil,{maximize_after=true})
return true
end,
function()
local c = client.get()[1]
if not c then return end
assert(not c.maximized_horizontal)
assert(not c.maximized_vertical)
-- It might happen in the second try
if not c.maximized then return end
c:kill()
return true
end,
function()
if #client.get() > 0 then return end
-- Test if resizing requests work
test_client(nil,nil,nil,nil,nil,{resize={width=400, height=400}})
return true
end,
function()
if #client.get() ~= 1 then return end
local c = client.get()[1]
local _, size = c:titlebar_top()
if c.width ~= 400 or c.height ~= 400+size then return end
c:kill()
return true
end,
function()
if #client.get() > 0 then return end
-- Remove the default handler and replace it with a testing one.
-- **WARNING**: add tests **BEFORE** this function if you want them
-- to be relevant.
client.disconnect_signal("request::geometry", awful.ewmh.geometry)
client.disconnect_signal("request::geometry", awful.ewmh.merge_maximization)
client.connect_signal("request::geometry", geometry_handler)
test_client(nil,nil,nil,nil,nil,{maximize_after=true})
return true
end,
function()
local c = client.get()[1]
if not c or counter ~= 2 then return end
return true
end
}