From 36999de123ac921b4e30bb88c090a685bec0ca6b Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 20 Oct 2019 01:11:23 -0400 Subject: [PATCH 1/6] placement: Stop detecting screen objects using `type(o.geometry)`. All object type will now use tables instead of function, so this check will break. --- lib/awful/placement.lua | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 173ce7bea..1522cb306 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -392,31 +392,29 @@ local function geometry_common(obj, args, new_geo, ignore_border_width) and obj.coords(new_geo) or obj.coords() return {x=coords.x, y=coords.y, width=0, height=0} elseif obj.geometry then - local geo = obj.geometry - - -- It is either a drawable or something that implement its API - if type(geo) == "function" then - local dgeo = area_common( - obj, fix_new_geometry(new_geo, args), ignore_border_width, args - ) - - -- Apply the margins - if args.margins then - local delta = get_decoration(args) - - return { - x = dgeo.x - (delta.left or 0), - y = dgeo.y - (delta.top or 0), - width = dgeo.width + (delta.left or 0) + (delta.right or 0), - height = dgeo.height + (delta.top or 0) + (delta.bottom or 0), - } - end - - return dgeo + if obj.get_bounding_geometry then + -- It is a screen, it doesn't support setting new sizes. + return obj:get_bounding_geometry(args) end - -- It is a screen, it doesn't support setting new sizes. - return obj:get_bounding_geometry(args) + -- It is either a drawable or something that implement its API + local dgeo = area_common( + obj, fix_new_geometry(new_geo, args), ignore_border_width, args + ) + + -- Apply the margins + if args.margins then + local delta = get_decoration(args) + + return { + x = dgeo.x - (delta.left or 0), + y = dgeo.y - (delta.top or 0), + width = dgeo.width + (delta.left or 0) + (delta.right or 0), + height = dgeo.height + (delta.top or 0) + (delta.bottom or 0), + } + end + + return dgeo else assert(false, "Invalid object") end @@ -1462,7 +1460,7 @@ function placement.next_to(d, args) args = add_context(args, "next_to") d = d or capi.client.focus - local osize = type(d.geometry) == "function" and d:geometry() or nil + local osize = type(d.geometry) == "function" and d:geometry() or d.geometry local original_pos, original_anchors = args.preferred_positions, args.preferred_anchors if type(original_pos) == "string" then From 0d1b34e54a1ca5f565b25b803b614da9ecbd0e03 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 20 Oct 2019 01:49:44 -0400 Subject: [PATCH 2/6] placement: Remove a nearly unused dependency. `awful.client` was only used once and the function exists as a screen method. This will help untangle the dependencies a bit... To tangle them even more after that... --- lib/awful/placement.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 1522cb306..e7cd547d9 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -89,7 +89,6 @@ local capi = mouse = mouse, client = client } -local client = require("awful.client") local layout = require("awful.layout") local a_screen = require("awful.screen") local grect = require("gears.geometry").rectangle @@ -938,7 +937,7 @@ function placement.no_overlap(c, args) local screen = get_screen(c.screen or a_screen.getbycoord(geometry.x, geometry.y)) local cls, curlay if client_on_selected_tags(c) then - cls = client.visible(screen) + cls = screen:get_clients(false) curlay = layout.get() else -- When placing a client on unselected tags, place it as if all tags of From 44cdde57a91e2e771b41f31fe8477134be2be76a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 20 Oct 2019 01:52:38 -0400 Subject: [PATCH 3/6] awful.mouse: Do not depend on awful.layout. It was only used to check if its the floating layout, there is a less intrusive dependency to check that. --- lib/awful/mouse/init.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/awful/mouse/init.lua b/lib/awful/mouse/init.lua index 0d4554a62..5275dee07 100644 --- a/lib/awful/mouse/init.lua +++ b/lib/awful/mouse/init.lua @@ -7,7 +7,7 @@ --------------------------------------------------------------------------- -- Grab environment we need -local layout = require("awful.layout") +local floating = require("awful.layout.suit.floating") local aplace = require("awful.placement") local gdebug = require("gears.debug") local type = type @@ -241,7 +241,7 @@ function mouse.resize_handler(c, context, hints) local t = c.screen.selected_tag local lay = t and t.layout or nil - if (lay and lay == layout.suit.floating) or c.floating then + if (lay and lay == floating) or c.floating then c:geometry { x = hints.x, y = hints.y, @@ -262,9 +262,9 @@ mouse.resize.add_enter_callback(function(c, args) --luacheck: no unused args if c.floating then return end local l = c.screen.selected_tag and c.screen.selected_tag.layout or nil - if l == layout.suit.floating then return end + if l == floating then return end - if l ~= layout.suit.floating and l.mouse_resize_handler then + if l.mouse_resize_handler then capi.mousegrabber.stop() local geo, corner = aplace.closest_corner(capi.mouse, {parent=c}) From 1fe90513bedc32cc6dc9194f26d34435d238b3b8 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 20 Oct 2019 01:56:28 -0400 Subject: [PATCH 4/6] placement: Do not depend on `awful.layout`. --- lib/awful/placement.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index e7cd547d9..18f204b7d 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -89,7 +89,7 @@ local capi = mouse = mouse, client = client } -local layout = require("awful.layout") +local floating = require("awful.layout.suit.floating") local a_screen = require("awful.screen") local grect = require("gears.geometry").rectangle local gdebug = require("gears.debug") @@ -938,7 +938,8 @@ function placement.no_overlap(c, args) local cls, curlay if client_on_selected_tags(c) then cls = screen:get_clients(false) - curlay = layout.get() + local t = screen.selected_tag + curlay = t.layout or floating else -- When placing a client on unselected tags, place it as if all tags of -- that client are selected. @@ -955,7 +956,7 @@ function placement.no_overlap(c, args) for _, cl in pairs(cls) do if cl ~= c and cl.type ~= "desktop" - and (cl.floating or curlay == layout.suit.floating) + and (cl.floating or curlay == floating) and not (cl.maximized or cl.fullscreen) then areas = grect.area_remove(areas, area_common(cl)) end From a4e463fd55bfeeb2d6b37e8d2c0567634983459f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 20 Oct 2019 02:09:51 -0400 Subject: [PATCH 5/6] awful.mouse: Move more code into submodules. Just like 5 years ago, the dependency mess caused by the giant `awful.client`, `awful.tag` and `awful.placement` requires to split the code into small files with less dependencies and include those. In this case, the goal is to use the `awful.mouse.client` functions from `awful.client`. --- lib/awful/mouse/client.lua | 143 ++++++++++++++++++++++++ lib/awful/mouse/init.lua | 220 ++++++------------------------------- lib/awful/mouse/resize.lua | 25 ++++- 3 files changed, 200 insertions(+), 188 deletions(-) create mode 100644 lib/awful/mouse/client.lua diff --git a/lib/awful/mouse/client.lua b/lib/awful/mouse/client.lua new file mode 100644 index 000000000..0b1536d98 --- /dev/null +++ b/lib/awful/mouse/client.lua @@ -0,0 +1,143 @@ +--- Client related mouse operations. +-- +-- @author Emmanuel Lepage Vallee <elv1313@gmail.com> +-- @copyright 2016 Emmanuel Lepage Vallee +-- @submodule mouse + +local aplace = require("awful.placement") +local capi = { mouse = mouse, client = client } +local mresize = require("awful.mouse.resize") +local gdebug = require("gears.debug") + +local module = {} + +--- Move a client. +-- @staticfct awful.mouse.client.move +-- @param c The client to move, or the focused one if nil. +-- @param snap The pixel to snap clients. +-- @param finished_cb Deprecated, do not use +function module.move(c, snap, finished_cb) --luacheck: no unused args + if finished_cb then + gdebug.deprecate("The mouse.client.move `finished_cb` argument is no longer".. + " used, please use awful.mouse.resize.add_leave_callback(f, 'mouse.move')", {deprecated_in=4}) + end + + c = c or capi.client.focus + + if not c + or c.fullscreen + or c.maximized + or c.type == "desktop" + or c.type == "splash" + or c.type == "dock" then + return + end + + -- Compute the offset + local coords = capi.mouse.coords() + local geo = aplace.centered(capi.mouse,{parent=c, pretend=true}) + + local offset = { + x = geo.x - coords.x, + y = geo.y - coords.y, + } + + mresize(c, "mouse.move", { + placement = aplace.under_mouse, + offset = offset, + snap = snap + }) +end + +module.dragtotag = { } + +--- Move a client to a tag by dragging it onto the left / right side of the screen. +-- @deprecated awful.mouse.client.dragtotag.border +-- @param c The client to move +function module.dragtotag.border(c) + gdebug.deprecate("Use awful.mouse.snap.drag_to_tag_enabled = true instead ".. + "of awful.mouse.client.dragtotag.border(c). It will now be enabled.", {deprecated_in=4}) + + -- Enable drag to border + require("awful.mouse.snap").drag_to_tag_enabled = true + + return module.move(c) +end + +--- Get a client corner coordinates. +-- @deprecated awful.mouse.client.corner +-- @tparam[opt=client.focus] client c The client to get corner from, focused one by default. +-- @tparam string corner The corner to use: auto, top_left, top_right, bottom_left, +-- bottom_right, left, right, top bottom. Default is auto, and auto find the +-- nearest corner. +-- @treturn string The corner name +-- @treturn number x The horizontal position +-- @treturn number y The vertical position +function module.corner(c, corner) + gdebug.deprecate( + "Use awful.placement.closest_corner(mouse) or awful.placement[corner](mouse)".. + " instead of awful.mouse.client.corner", {deprecated_in=4} + ) + + c = c or capi.client.focus + if not c then return end + + local ngeo = nil + + if (not corner) or corner == "auto" then + ngeo, corner = aplace.closest_corner(mouse, {parent = c}) + elseif corner and aplace[corner] then + ngeo = aplace[corner](mouse, {parent = c}) + end + + return corner, ngeo and ngeo.x or nil, ngeo and ngeo.y or nil +end + +--- Resize a client. +-- @staticfct awful.mouse.client.resize +-- @param c The client to resize, or the focused one by default. +-- @tparam string corner The corner to grab on resize. Auto detected by default. +-- @tparam[opt={}] table args A set of `awful.placement` arguments +-- @treturn string The corner (or side) name +function module.resize(c, corner, args) + c = c or capi.client.focus + + if not c then return end + + if c.fullscreen + or c.maximized + or c.type == "desktop" + or c.type == "splash" + or c.type == "dock" then + return + end + + -- Set some default arguments + local new_args = setmetatable( + { + include_sides = (not args) or args.include_sides ~= false + }, + { + __index = args or {} + } + ) + + -- Move the mouse to the corner + if corner and aplace[corner] then + aplace[corner](capi.mouse, {parent=c}) + else + local _ + _, corner = aplace.closest_corner(capi.mouse, { + parent = c, + include_sides = new_args.include_sides ~= false, + }) + end + + new_args.corner = corner + + mresize(c, "mouse.resize", new_args) + + return corner +end + +return module diff --git a/lib/awful/mouse/init.lua b/lib/awful/mouse/init.lua index 5275dee07..f4f526e9f 100644 --- a/lib/awful/mouse/init.lua +++ b/lib/awful/mouse/init.lua @@ -22,13 +22,13 @@ local capi = } local mouse = { - resize = require("awful.mouse.resize"), snap = require("awful.mouse.snap"), + client = require("awful.mouse.client"), + resize = require("awful.mouse.resize"), drag_to_tag = require("awful.mouse.drag_to_tag") } mouse.object = {} -mouse.client = {} mouse.wibox = {} --- The default snap distance. @@ -71,189 +71,6 @@ function mouse.client_under_pointer() return mouse.object.get_current_client() end ---- Move a client. --- @staticfct awful.mouse.client.move --- @param c The client to move, or the focused one if nil. --- @param snap The pixel to snap clients. --- @param finished_cb Deprecated, do not use -function mouse.client.move(c, snap, finished_cb) --luacheck: no unused args - if finished_cb then - gdebug.deprecate("The mouse.client.move `finished_cb` argument is no longer".. - " used, please use awful.mouse.resize.add_leave_callback(f, 'mouse.move')", {deprecated_in=4}) - end - - c = c or capi.client.focus - - if not c - or c.fullscreen - or c.maximized - or c.type == "desktop" - or c.type == "splash" - or c.type == "dock" then - return - end - - -- Compute the offset - local coords = capi.mouse.coords() - local geo = aplace.centered(capi.mouse,{parent=c, pretend=true}) - - local offset = { - x = geo.x - coords.x, - y = geo.y - coords.y, - } - - mouse.resize(c, "mouse.move", { - placement = aplace.under_mouse, - offset = offset, - snap = snap - }) -end - -mouse.client.dragtotag = { } - ---- Move a client to a tag by dragging it onto the left / right side of the screen. --- @deprecated awful.mouse.client.dragtotag.border --- @param c The client to move -function mouse.client.dragtotag.border(c) - gdebug.deprecate("Use awful.mouse.snap.drag_to_tag_enabled = true instead ".. - "of awful.mouse.client.dragtotag.border(c). It will now be enabled.", {deprecated_in=4}) - - -- Enable drag to border - mouse.snap.drag_to_tag_enabled = true - - return mouse.client.move(c) -end - ---- Move the wibox under the cursor. --- @staticfct awful.mouse.wibox.move ---@tparam wibox w The wibox to move, or none to use that under the pointer -function mouse.wibox.move(w) - w = w or mouse.current_wibox - if not w then return end - - if not w - or w.type == "desktop" - or w.type == "splash" - or w.type == "dock" then - return - end - - -- Compute the offset - local coords = capi.mouse.coords() - local geo = aplace.centered(capi.mouse,{parent=w, pretend=true}) - - local offset = { - x = geo.x - coords.x, - y = geo.y - coords.y, - } - - mouse.resize(w, "mouse.move", { - placement = aplace.under_mouse, - offset = offset - }) -end - ---- Get a client corner coordinates. --- @deprecated awful.mouse.client.corner --- @tparam[opt=client.focus] client c The client to get corner from, focused one by default. --- @tparam string corner The corner to use: auto, top_left, top_right, bottom_left, --- bottom_right, left, right, top bottom. Default is auto, and auto find the --- nearest corner. --- @treturn string The corner name --- @treturn number x The horizontal position --- @treturn number y The vertical position -function mouse.client.corner(c, corner) - gdebug.deprecate( - "Use awful.placement.closest_corner(mouse) or awful.placement[corner](mouse)".. - " instead of awful.mouse.client.corner", {deprecated_in=4} - ) - - c = c or capi.client.focus - if not c then return end - - local ngeo = nil - - if (not corner) or corner == "auto" then - ngeo, corner = aplace.closest_corner(mouse, {parent = c}) - elseif corner and aplace[corner] then - ngeo = aplace[corner](mouse, {parent = c}) - end - - return corner, ngeo and ngeo.x or nil, ngeo and ngeo.y or nil -end - ---- Resize a client. --- @staticfct awful.mouse.client.resize --- @param c The client to resize, or the focused one by default. --- @tparam string corner The corner to grab on resize. Auto detected by default. --- @tparam[opt={}] table args A set of `awful.placement` arguments --- @treturn string The corner (or side) name -function mouse.client.resize(c, corner, args) - c = c or capi.client.focus - - if not c then return end - - if c.fullscreen - or c.maximized - or c.type == "desktop" - or c.type == "splash" - or c.type == "dock" then - return - end - - -- Set some default arguments - local new_args = setmetatable( - { - include_sides = (not args) or args.include_sides ~= false - }, - { - __index = args or {} - } - ) - - -- Move the mouse to the corner - if corner and aplace[corner] then - aplace[corner](capi.mouse, {parent=c}) - else - local _ - _, corner = aplace.closest_corner(capi.mouse, { - parent = c, - include_sides = new_args.include_sides ~= false, - }) - end - - new_args.corner = corner - - mouse.resize(c, "mouse.resize", new_args) - - return corner -end - ---- Default handler for `request::geometry` signals with "mouse.resize" context. --- @signalhandler awful.mouse.resize_handler --- @tparam client c The client --- @tparam string context The context --- @tparam[opt={}] table hints The hints to pass to the handler -function mouse.resize_handler(c, context, hints) - if hints and context and context:find("mouse.*") then - -- This handler only handle the floating clients. If the client is tiled, - -- then it let the layouts handle it. - local t = c.screen.selected_tag - local lay = t and t.layout or nil - - if (lay and lay == floating) or c.floating then - c:geometry { - x = hints.x, - y = hints.y, - width = hints.width, - height = hints.height, - } - elseif lay and lay.resize_handler then - lay.resize_handler(c, context, hints) - end - end -end - -- Older layouts implement their own mousegrabber. -- @tparam client c The client -- @tparam table args Additional arguments @@ -358,6 +175,35 @@ function mouse.object.get_current_widget_geometries() return ret end +--- Move the wibox under the cursor. +-- @staticfct awful.mouse.wibox.move +--@tparam wibox w The wibox to move, or none to use that under the pointer +function mouse.wibox.move(w) + w = w or mouse.current_wibox + if not w then return end + + if not w + or w.type == "desktop" + or w.type == "splash" + or w.type == "dock" then + return + end + + -- Compute the offset + local coords = capi.mouse.coords() + local geo = aplace.centered(capi.mouse,{parent=w, pretend=true}) + + local offset = { + x = geo.x - coords.x, + y = geo.y - coords.y, + } + + mouse.resize(w, "mouse.move", { + placement = aplace.under_mouse, + offset = offset + }) +end + --- True if the left mouse button is pressed. -- @property is_left_mouse_button_pressed -- @param boolean @@ -486,8 +332,6 @@ for _, b in ipairs {"left", "right", "middle"} do end end -capi.client.connect_signal("request::geometry", mouse.resize_handler) - -- Set the cursor at startup capi.root.cursor("left_ptr") @@ -538,6 +382,8 @@ function mouse._get_client_mousebindings() return default_buttons end +mouse.resize_handler = mouse.resize._resize_handler + return mouse -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/awful/mouse/resize.lua b/lib/awful/mouse/resize.lua index 751e5cbf9..16542e4e1 100644 --- a/lib/awful/mouse/resize.lua +++ b/lib/awful/mouse/resize.lua @@ -10,8 +10,9 @@ --------------------------------------------------------------------------- local aplace = require("awful.placement") -local capi = {mousegrabber = mousegrabber} +local capi = {mousegrabber = mousegrabber, client = client} local beautiful = require("beautiful") +local floating = require("awful.layout.suit.floating") local module = {} @@ -229,6 +230,28 @@ local function handler(_, client, context, args) --luacheck: no unused_args end, cursor) end +function module._resize_handler(c, context, hints) + if hints and context and context:find("mouse.*") then + -- This handler only handle the floating clients. If the client is tiled, + -- then it let the layouts handle it. + local t = c.screen.selected_tag + local lay = t and t.layout or nil + + if (lay and lay == floating) or c.floating then + c:geometry { + x = hints.x, + y = hints.y, + width = hints.width, + height = hints.height, + } + elseif lay and lay.resize_handler then + lay.resize_handler(c, context, hints) + end + end +end + +capi.client.connect_signal("request::geometry", module._resize_handler) + return setmetatable(module, {__call=handler}) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From b48527b672ead0df504dcd74477b7b8ae3ebd58f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 6 Dec 2019 01:24:31 -0500 Subject: [PATCH 6/6] tests: Test more of awful.mouse --- tests/test-resize.lua | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/test-resize.lua b/tests/test-resize.lua index d1d4e6027..7cff90fb0 100644 --- a/tests/test-resize.lua +++ b/tests/test-resize.lua @@ -1,6 +1,7 @@ local test_client = require("_client") local placement = require("awful.placement") local amouse = require("awful.mouse") +local wibox = require("wibox") local rounded_rect = require("gears.shape").rounded_rect local steps = {} @@ -523,6 +524,51 @@ table.insert(steps, function() return true end) +-- Test the wibox move. +table.insert(steps, function() + local w = wibox { + visible = true, + width = 100, + height = 100, + bg = "#ff00ff" + } + + placement.centered(w) + placement.centered(mouse) + + root.fake_input("button_press",1) + amouse.wibox.move(w) + mouse.coords {x = 100, y = 100} + root.fake_input("button_release",1) + + return true +end) + +-- Trigger floating client the mouse tiling. +table.insert(steps, function() + -- Disable deprecation. + require("gears.debug").deprecate = function() end + + local c = client.get()[1] + + root.fake_input("button_press",1) + amouse.client.dragtotag.border(c, 10, function() end) + mouse.coords {x = c:geometry().x+10, y= c:geometry().y+10} + root.fake_input("button_release",1) + + root.fake_input("button_press",1) + amouse.client.corner(c, "top_left") + mouse.coords {x = c:geometry().x+100, y= c:geometry().y+100} + root.fake_input("button_release",1) + + root.fake_input("button_press",1) + amouse.client.corner(c, "auto") + mouse.coords {x = c:geometry().x+10, y= c:geometry().y+10} + root.fake_input("button_release",1) + + return true +end) + require("_runner").run_steps(steps) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80