From 90342b62c61260d3ab74d19f2d661c11a0764051 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Dec 2018 21:19:59 -0500 Subject: [PATCH 01/14] shims: Make sure the wibox boolean properties are set Also make some changes to support tooltips. --- tests/examples/shims/drawin.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/examples/shims/drawin.lua b/tests/examples/shims/drawin.lua index 121a7a8d..be5a6ff7 100644 --- a/tests/examples/shims/drawin.lua +++ b/tests/examples/shims/drawin.lua @@ -11,6 +11,10 @@ local function new_drawin(_, args) ret.y=0 ret.width=1 ret.height=1 + ret.border_width=0 + ret.ontop = false + ret.below = false + ret.above = false ret.geometry = function(_, new) new = new or {} From c3302c4bbeb8bb5a04b96eb585387dbb83424391 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 10 Aug 2017 00:27:09 -0400 Subject: [PATCH 02/14] tests: Improve the awful example template * Support async operations * Support `awful.popup` * Support minimized clients --- tests/examples/awful/template.lua | 145 +++++++++++++++++------------- 1 file changed, 84 insertions(+), 61 deletions(-) diff --git a/tests/examples/awful/template.lua b/tests/examples/awful/template.lua index 9f84404f..a6a824b3 100644 --- a/tests/examples/awful/template.lua +++ b/tests/examples/awful/template.lua @@ -11,6 +11,11 @@ local wibox = require( "wibox" ) -- Run the test local args = loadfile(file_path)() or {} +-- Emulate the event loop for 5 iterations +for _ = 1, 5 do + awesome.emit_signal("refresh") +end + -- Draw the result local img = cairo.SvgSurface.create(image_path..".svg", screen._get_extents() ) @@ -30,26 +35,28 @@ local function draw_mouse(x, y) end -- Print an outline for the screens -for _, s in ipairs(screen) do - cr:save() - -- Draw the screen outline - cr:set_source(color("#00000044")) - cr:set_line_width(1.5) - cr:set_dash({10,4},1) - cr:rectangle(s.geometry.x+0.75,s.geometry.y+0.75,s.geometry.width-1.5,s.geometry.height-1.5) - cr:stroke() +if not screen.no_outline then + for _, s in ipairs(screen) do + cr:save() + -- Draw the screen outline + cr:set_source(color("#00000044")) + cr:set_line_width(1.5) + cr:set_dash({10,4},1) + cr:rectangle(s.geometry.x+0.75,s.geometry.y+0.75,s.geometry.width-1.5,s.geometry.height-1.5) + cr:stroke() - -- Draw the workarea outline - cr:set_source(color("#00000033")) - cr:rectangle(s.workarea.x,s.workarea.y,s.workarea.width,s.workarea.height) - cr:stroke() + -- Draw the workarea outline + cr:set_source(color("#00000033")) + cr:rectangle(s.workarea.x,s.workarea.y,s.workarea.width,s.workarea.height) + cr:stroke() - -- Draw the padding outline - --TODO - cr:restore() + -- Draw the padding outline + --TODO + cr:restore() + end end -cr:set_line_width(beautiful.border_width) +cr:set_line_width(beautiful.border_width/2) cr:set_source(color(beautiful.border_color)) @@ -125,11 +132,7 @@ local function client_widget(c, col, label) return wibox.widget { { - { - l, - margins = bw + 1, -- +1 because the the SVG AA - layout = wibox.container.margin - }, + l, { text = label or "", align = "center", @@ -138,22 +141,40 @@ local function client_widget(c, col, label) }, layout = wibox.layout.stack }, - shape_border_width = bw*2, + shape_border_width = bw, shape_border_color = beautiful.border_color, shape_clip = true, fg = beautiful.fg_normal or "#000000", bg = col, - forced_width = geo.width + 2*bw, - forced_height = geo.height + 2*bw, shape = function(cr2, w, h) return shape.rounded_rect(cr2, w, h, args.radius or 5) end, - widget = wibox.container.background, + forced_width = geo.width + 2*bw, + forced_height = geo.height + 2*bw, + widget = wibox.container.background, } end -- Add all wiboxes + +-- Fix the wibox geometries that have a dependency on their content +for _, d in ipairs(drawin.get()) do + local w = d.get_wibox and d:get_wibox() or nil + if w then + -- Force a full layout first as widgets with as the awful.popup have + -- interdependencies between the content and the container + if w._apply_size_now then + w:_apply_size_now() + end + end +end + +-- Emulate the event loop for another 5 iterations +for _ = 1, 5 do + awesome.emit_signal("refresh") +end + for _, d in ipairs(drawin.get()) do local w = d.get_wibox and d:get_wibox() or nil if w then @@ -164,43 +185,45 @@ end -- Loop each clients geometry history and paint it for _, c in ipairs(client.get()) do - local pgeo = nil - for _, geo in ipairs(c._old_geo) do - if not geo._hide then - total_area:add_at( - client_widget(c, c.color or geo._color or beautiful.bg_normal, geo._label), - {x=geo.x, y=geo.y} - ) + if not c.minimized then + local pgeo = nil + for _, geo in ipairs(c._old_geo) do + if not geo._hide then + total_area:add_at( + client_widget(c, c.color or geo._color or beautiful.bg_normal, geo._label), + {x=geo.x, y=geo.y} + ) + end + + -- Draw lines between the old and new corners + if pgeo and not args.hide_lines then + cr:save() + cr:set_source_rgba(0,0,0,.1) + + -- Top left + cr:move_to(pgeo.x, pgeo.y) + cr:line_to(geo.x, geo.y) + cr:stroke() + + -- Top right + cr:move_to(pgeo.x+pgeo.width, pgeo.y) + cr:line_to(geo.x+pgeo.width, geo.y) + + -- Bottom left + cr:move_to(pgeo.x, pgeo.y+pgeo.height) + cr:line_to(geo.x, geo.y+geo.height) + cr:stroke() + + -- Bottom right + cr:move_to(pgeo.x+pgeo.width, pgeo.y+pgeo.height) + cr:line_to(geo.x+pgeo.width, geo.y+geo.height) + cr:stroke() + + cr:restore() + end + + pgeo = geo end - - -- Draw lines between the old and new corners - if pgeo and not args.hide_lines then - cr:save() - cr:set_source_rgba(0,0,0,.1) - - -- Top left - cr:move_to(pgeo.x, pgeo.y) - cr:line_to(geo.x, geo.y) - cr:stroke() - - -- Top right - cr:move_to(pgeo.x+pgeo.width, pgeo.y) - cr:line_to(geo.x+pgeo.width, geo.y) - - -- Bottom left - cr:move_to(pgeo.x, pgeo.y+pgeo.height) - cr:line_to(geo.x, geo.y+geo.height) - cr:stroke() - - -- Bottom right - cr:move_to(pgeo.x+pgeo.width, pgeo.y+pgeo.height) - cr:line_to(geo.x+pgeo.width, geo.y+geo.height) - cr:stroke() - - cr:restore() - end - - pgeo = geo end end From 3fa42f3b1ae5a4b7fd014728340ef08cfe2b11dd Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 9 Jan 2018 00:39:53 -0500 Subject: [PATCH 03/14] placement: Fix `border_width` for `next_to` All previous users used client side borders so the issue went unnoticed. This code will be unit tested by the `popup` module in a few commits. --- lib/awful/placement.lua | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 3cc2ceb0..96abc056 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -644,7 +644,6 @@ local function get_cross_sections(abs_geo, mode) } elseif mode == "geometry" then -- The widget geometry extended to reach the end of the drawable - return { h = { x = abs_geo.drawable_geo.x , @@ -702,23 +701,35 @@ local function get_relative_regions(geo, mode, is_absolute) end end - -- Get the drawable geometry - local dpos = geo.drawable and ( - geo.drawable.drawable and - geo.drawable.drawable:geometry() - or geo.drawable:geometry() - ) or {x=0, y=0} + -- Get the parent geometry using one way or another depending on the object + -- Type + local bw, dgeo = 0, {x=0, y=0, width=1, height=1} + + -- Detect various types of geometry table and (try) to get rid of the + -- differences so the code below don't have to care anymore. + if geo.drawin then + bw, dgeo = geo.drawin.border_width, geo.drawin:geometry() + elseif geo.drawable and geo.drawable.get_wibox then + bw = geo.drawable.get_wibox().border_width + dgeo = geo.drawable.get_wibox():geometry() + elseif geo.drawable and geo.drawable.drawable then + bw, dgeo = 0, geo.drawable.drawable:geometry() + end + + -- Add the infamous border size + dgeo.width = dgeo.width + 2*bw + dgeo.height = dgeo.height + 2*bw -- Compute the absolute widget geometry - local abs_widget_geo = is_absolute and geo or { - x = dpos.x + geo.x , - y = dpos.y + geo.y , - width = geo.width , - height = geo.height , - drawable = geo.drawable , + local abs_widget_geo = is_absolute and dgeo or { + x = dgeo.x + geo.x + bw, + y = dgeo.y + geo.y + bw, + width = geo.width , + height = geo.height , + drawable = geo.drawable , } - abs_widget_geo.drawable_geo = geo.drawable and dpos or geo + abs_widget_geo.drawable_geo = geo.drawable and dgeo or geo -- Get the point for comparison. local center_point = mode:match("cursor") and capi.mouse.coords() or { From f1145af49d5965495aa0b9a782db61a8e8f496c2 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 9 Jan 2018 08:40:19 -0500 Subject: [PATCH 04/14] placement: Allow to configure the next_to anchors They were previously hardcoded to match the classic context menu behavior. It isn't flexible enough for some popup type. --- lib/awful/placement.lua | 69 +++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 96abc056..47ee330e 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -262,16 +262,19 @@ local resize_to_point_map = { } -- Outer position matrix --- 1=best case, 2=fallback local outer_positions = { - left1 = function(r, w, _) return {x=r.x-w , y=r.y }, "down" end, - left2 = function(r, w, h) return {x=r.x-w , y=r.y-h+r.height }, "up" end, - right1 = function(r, _, _) return {x=r.x , y=r.y }, "down" end, - right2 = function(r, _, h) return {x=r.x , y=r.y-h+r.height }, "up" end, - top1 = function(r, _, h) return {x=r.x , y=r.y-h }, "right" end, - top2 = function(r, w, h) return {x=r.x-w+r.width, y=r.y-h }, "left" end, - bottom1 = function(r, _, _) return {x=r.x , y=r.y }, "right" end, - bottom2 = function(r, w, _) return {x=r.x-w+r.width, y=r.y }, "left" end, + left_front = function(r, w, _) return {x=r.x-w , y=r.y }, "front" end, + left_back = function(r, w, h) return {x=r.x-w , y=r.y-h+r.height }, "back" end, + left_middle = function(r, w, h) return {x=r.x-w , y=r.y-h/2+r.height/2 }, "middle" end, + right_front = function(r, _, _) return {x=r.x , y=r.y }, "front" end, + right_back = function(r, _, h) return {x=r.x , y=r.y-h+r.height }, "back" end, + right_middle = function(r, _, h) return {x=r.x , y=r.y-h/2+r.height/2 }, "middle" end, + top_front = function(r, _, h) return {x=r.x , y=r.y-h }, "front" end, + top_back = function(r, w, h) return {x=r.x-w+r.width , y=r.y-h }, "back" end, + top_middle = function(r, w, h) return {x=r.x-w/2+r.width/2, y=r.y-h }, "middle" end, + bottom_front = function(r, _, _) return {x=r.x , y=r.y }, "front" end, + bottom_back = function(r, w, _) return {x=r.x-w+r.width , y=r.y }, "back" end, + bottom_middle = function(r, w, _) return {x=r.x-w/2+r.width/2, y=r.y }, "middle" end, } --- Add a context to the arguments. @@ -1353,28 +1356,55 @@ end --- Move a drawable to a relative position next to another one. -- +-- This placement function offers two additional settings to align the drawable +-- alongside the parent geometry. The first one, the position, sets the side +-- relative to the parent. The second one, the anchor, set the alignment within +-- the side selected by the `preferred_positions`. Both settings are tables of +-- priorities. The first available slot will be used. If there isn't enough +-- space, then it will fallback to the next until it is possible to fit the +-- drawable. This is meant to avoid going offscreen. +-- -- The `args.preferred_positions` look like this: -- -- {"top", "right", "left", "bottom"} -- +-- The `args.preferred_anchors` are: +-- +-- * "front": The closest to the origin (0,0) +-- * "middle": Centered aligned with the parent +-- * "back": The opposite side compared to `front` +-- -- In that case, if there is room on the top of the geometry, then it will have -- priority, followed by all the others, in order. -- -- @tparam drawable d A wibox or client -- @tparam table args -- @tparam string args.mode The mode --- @tparam string args.preferred_positions The preferred positions (in order) +-- @tparam string|table args.preferred_positions The preferred positions (in order) +-- @tparam string|table args.preferred_anchors The preferred anchor(s) (in order) -- @tparam string args.geometry A geometry inside the other drawable -- @treturn table The new geometry --- @treturn string The choosen position --- @treturn string The choosen direction +-- @treturn string The choosen position ("left", "right", "top" or "bottom") +-- @treturn string The choosen anchor ("front", "middle" or "back") function placement.next_to(d, args) args = add_context(args, "next_to") d = d or capi.client.focus - local preferred_positions = {} + local original_pos, original_anchors = args.preferred_positions, args.preferred_anchors - for k, v in ipairs(args.preferred_positions or {}) do + if type(original_pos) == "string" then + original_pos = {original_pos} + end + + if type(original_anchors) == "string" then + original_anchors = {original_anchors} + end + + local preferred_positions = {} + local preferred_anchors = #(original_anchors or {}) > 0 and + original_anchors or {"front", "back", "middle"} + + for k, v in ipairs(original_pos or {}) do preferred_positions[v] = k end @@ -1406,15 +1436,14 @@ function placement.next_to(d, args) -- and order them by preferred_positions local does_fit = {} for k,v in pairs(regions) do - local geo, dir = outer_positions[k.."1"](v, dgeo.width, dgeo.height) - geo.width, geo.height = dgeo.width, dgeo.height - local fit = fit_in_bounding(v.screen, geo, args) + local geo, dir, fit - -- Try the other compatible geometry - if not fit then - geo, dir = outer_positions[k.."2"](v, dgeo.width, dgeo.height) + -- Try each anchor until one that fits is found + for _, anchor in ipairs(preferred_anchors) do + geo, dir = outer_positions[k.."_"..anchor](v, dgeo.width, dgeo.height) geo.width, geo.height = dgeo.width, dgeo.height fit = fit_in_bounding(v.screen, geo, args) + if fit then break end end does_fit[k] = fit and {geo, dir} or nil From 33a39ce38d8aa1d207aa3c209ee3204086abdf57 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 16 Jan 2018 02:38:17 -0500 Subject: [PATCH 05/14] placement: Make sure `next_to` result is consistent across calls It depended on a hash `pairs` iteration. This caused an issue only when the primary position wasn't available. --- lib/awful/placement.lua | 48 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 47ee330e..26f95e10 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -1432,39 +1432,65 @@ function placement.next_to(d, args) local regions = get_relative_regions(wgeo, mode, is_absolute) + -- Order the regions with the preferred_positions, then the defaults + local sorted_regions, default_positions = {}, {"left", "right", "bottom", "top"} + + for _, pos in ipairs(original_pos or {}) do + for idx, def in ipairs(default_positions) do + if def == pos then + table.remove(default_positions, idx) + break + end + end + + table.insert(sorted_regions, {name = pos, region = regions[pos]}) + end + + for _, pos in ipairs(default_positions) do + table.insert(sorted_regions, {name = pos, region = regions[pos]}) + end + -- Check each possible slot around the drawable (8 total), see what fits -- and order them by preferred_positions local does_fit = {} - for k,v in pairs(regions) do + for _, pos in ipairs(sorted_regions) do local geo, dir, fit -- Try each anchor until one that fits is found for _, anchor in ipairs(preferred_anchors) do - geo, dir = outer_positions[k.."_"..anchor](v, dgeo.width, dgeo.height) + geo, dir = outer_positions[pos.name.."_"..anchor](pos.region, dgeo.width, dgeo.height) + geo.width, geo.height = dgeo.width, dgeo.height - fit = fit_in_bounding(v.screen, geo, args) + + fit = fit_in_bounding(pos.region.screen, geo, args) + if fit then break end end - does_fit[k] = fit and {geo, dir} or nil + does_fit[pos.name] = fit and {geo, dir} or nil - if fit and preferred_positions[k] and preferred_positions[k] < pref_idx then - pref_idx = preferred_positions[k] - pref_name = k + if fit and preferred_positions[pos.name] and preferred_positions[pos.name] < pref_idx then + pref_idx = preferred_positions[pos.name] + pref_name = pos.name end -- No need to continue - if fit and preferred_positions[k] == 1 then break end + if fit then break end end - local pos_name = pref_name or next(does_fit) - local ngeo, dir = unpack(does_fit[pos_name] or {}) --FIXME why does this happen + local ngeo, dir = unpack(does_fit[pref_name] or {}) --FIXME why does this happen + + -- The requested placement isn't possible due to the lack of space, better + -- do nothing an try random things + if not ngeo then return end + + remove_border(d, args, ngeo) geometry_common(d, args, ngeo) attach(d, placement.next_to, args) - return fix_new_geometry(ngeo, args, true), pos_name, dir + return fix_new_geometry(ngeo, args, true), pref_name, dir end --- Restore the geometry. From d8a7782bf442dd03e9e43b55ad31cb6b2a938326 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 9 Jan 2018 09:26:00 -0500 Subject: [PATCH 06/14] tests: Add an awful.placement.next_to test It was overdue --- lib/awful/placement.lua | 2 + tests/examples/awful/placement/next_to.lua | 61 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/examples/awful/placement/next_to.lua diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 26f95e10..57cc3ed7 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -1377,6 +1377,8 @@ end -- In that case, if there is room on the top of the geometry, then it will have -- priority, followed by all the others, in order. -- +--@DOC_awful_placement_next_to_EXAMPLE@ +-- -- @tparam drawable d A wibox or client -- @tparam table args -- @tparam string args.mode The mode diff --git a/tests/examples/awful/placement/next_to.lua b/tests/examples/awful/placement/next_to.lua new file mode 100644 index 00000000..ae355728 --- /dev/null +++ b/tests/examples/awful/placement/next_to.lua @@ -0,0 +1,61 @@ +--DOC_GEN_IMAGE --DOC_HIDE +local awful = { placement = require("awful.placement") }--DOC_HIDE +screen[1]._resize {x= 0, width = 640, height=200} --DOC_HIDE + +local parent_client = client.gen_fake {x = 0, y = 0, width=350, height=70} --DOC_HIDE +parent_client:_hide() --DOC_HIDE +awful.placement.centered(client.focus) --DOC_HIDE +parent_client:set_label("Parent client") --DOC_HIDE + +for _, pos in ipairs{"left", "right", "top", "bottom"} do + for _, anchor in ipairs{"front", "middle", "back"} do + local c1 = client.gen_fake {x = 0, y = 0, width=80, height=20} --DOC_HIDE + c1:_hide() --DOC_HIDE + local _,p,a = --DOC_HIDE + awful.placement.next_to( + client.focus, + { + preferred_positions = pos, + preferred_anchors = anchor, + geometry = parent_client, + } + ) + c1:set_label(pos.."+"..anchor) --DOC_HIDE + assert(pos == p) --DOC_HIDE + assert(anchor == a) --DOC_HIDE + + --DOC_HIDE Make sure the border are correctly applied + if pos == "left" then --DOC_HIDE + assert(c1.x + c1.width + 2*c1.border_width == parent_client.x) --DOC_HIDE + end --DOC_HIDE + if pos == "right" then --DOC_HIDE + assert(c1.x == parent_client.x+parent_client.width+2*parent_client.border_width) --DOC_HIDE + end --DOC_HIDE + if pos == "top" then --DOC_HIDE + assert(c1.y + c1.height + 2*c1.border_width == parent_client.y) --DOC_HIDE + end --DOC_HIDE + if pos == "bottom" then --DOC_HIDE + assert(c1.y == parent_client.y+parent_client.height+2*parent_client.border_width)--DOC_HIDE + end --DOC_HIDE + + --DOC_HIDE Make sure the "children" don't overshoot the parent geometry + if pos ~= "right" then --DOC_HIDE + assert(c1.x+c1.width+2*c1.border_width--DOC_HIDE + <= parent_client.x+parent_client.width+2*parent_client.border_width) --DOC_HIDE + end --DOC_HIDE + if pos ~= "bottom" then --DOC_HIDE + assert(c1.y+c1.height+2*c1.border_width --DOC_HIDE + <= parent_client.y+parent_client.height+2*parent_client.border_width) --DOC_HIDE + end --DOC_HIDE + if pos ~= "left" then --DOC_HIDE + assert(c1.x >= parent_client.x) --DOC_HIDE + end --DOC_HIDE + if pos ~= "top" then --DOC_HIDE + assert(c1.y >= parent_client.y) --DOC_HIDE + end --DOC_HIDE + end +end + +return {hide_lines=true} --DOC_HIDE + +--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 7d6f52c4dca11f4a83e1605ba50bacb923cf7b45 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 10 Jan 2018 07:49:35 -0500 Subject: [PATCH 07/14] wibox: Add the wibox reference to `find_widgets` This is necessary to compute the widget real position on screen because it's the only way to know the border_width offset. --- lib/wibox/init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/wibox/init.lua b/lib/wibox/init.lua index a8037954..00840560 100644 --- a/lib/wibox/init.lua +++ b/lib/wibox/init.lua @@ -253,6 +253,10 @@ local function new(args) ret._drawable = wibox.drawable(w.drawable, { wibox = ret }, "wibox drawable (" .. object.modulename(3) .. ")") + function ret._drawable.get_wibox() + return ret + end + ret._drawable:_inform_visible(w.visible) w:connect_signal("property::visible", function() ret._drawable:_inform_visible(w.visible) From 3380fd85fccc5279f4adbbd0c02806e797eff8f8 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Dec 2018 21:29:56 -0500 Subject: [PATCH 08/14] tooltip: Add alignment options. It's a list of preferred alignments because sometime the best one wont fit in the screen. --- lib/awful/tooltip.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index 39aa0910..df0a35db 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -124,6 +124,7 @@ local function apply_outside_mode(self) local _, position = a_placement.next_to(w, { geometry = self._private.widget_geometry, preferred_positions = self.preferred_positions, + preferred_anchors = self.preferred_alignments, honor_workarea = true, }) @@ -326,6 +327,18 @@ function tooltip:set_preferred_positions(value) set_geometry(self) end + +function tooltip:get_preferred_alignments() + return self._private.preferred_alignments or + {"front", "back", "middle"} +end + +function tooltip:set_preferred_alignments(value) + self._private.preferred_alignments = value + + set_geometry(self) +end + --- Change displayed text. -- -- @property text From 68bfde45e152468e160684d0334d258bee1cba90 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Dec 2018 21:31:26 -0500 Subject: [PATCH 09/14] tooltip: Cleanup the margin API. Make it closer to other APIs across Awesome. --- lib/awful/tooltip.lua | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index df0a35db..af5ae373 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -398,8 +398,13 @@ end -- @tparam number New margins value function tooltip:set_margin_leftright(val) - self.marginbox.left = val - self.marginbox.right = val + self.marginbox:set_left(val) + self.marginbox:set_right(val) +end + +--TODO v5 deprecate this +function tooltip:set_margins_leftright(val) + self:set_margin_leftright(val) end --- Set the margins around the top and bottom of the tooltip textbox @@ -409,8 +414,13 @@ end -- @tparam number New margins value function tooltip:set_margin_topbottom(val) - self.marginbox.top = val - self.marginbox.bottom = val + self.marginbox:set_top(val) + self.marginbox:set_bottom(val) +end + +--TODO v5 deprecate this +function tooltip:set_margins_topbottom(val) + self:set_margin_topbottom(val) end --- Add tooltip to an object. From 2b52926b4882c6499485843e882d8f8f7b19cdda Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Dec 2018 21:32:19 -0500 Subject: [PATCH 10/14] tooltip: Pass the parent object to awful.placement, not the position. By passing the geometry, important information used by awful.placement.next_to were "lost". Given `next_to` supports both widget position, the mouse and client/wibox relative positioning, it has to know the object type. --- lib/awful/tooltip.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index af5ae373..dbab6d3f 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -532,7 +532,7 @@ function tooltip.new(args) function self.show(other, geo) -- Auto detect clients and wiboxes if other.drawable or other.pid then - geo = other:geometry() + geo = other end -- Cache the geometry in case it is needed later From 52f62b712ceb2a53755949f3b64d0350ca8ee28f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Dec 2018 21:34:29 -0500 Subject: [PATCH 11/14] tooltip: Allow the border to be configured. Given the tooltip border is "client side" instead of X11 to allow anti-aliasing to work when a shape is used, it doesn't use the wibox border. --- lib/awful/tooltip.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index dbab6d3f..2490fd19 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -391,6 +391,16 @@ function tooltip:set_margins(val) self.marginbox:set_margins(val) end + +function tooltip:set_border_width(val) + self.widget.shape_border_width = val +end + + +function tooltip:set_border_color(val) + self.widget.shape_border_color = val +end + --- Set the margins around the left and right of the tooltip textbox -- -- @property margins_leftright From 89867386c55f3681653f7780231418803a464921 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 30 Sep 2018 02:12:57 -0400 Subject: [PATCH 12/14] tests: Add images to the tooltip documentation It also add some properties such as `border_width`, `border_color` and `preferred_alignments`. It also fix a documentation bug where the `margin_topleft` was called `margins_topleft`. To conform to the documentation, both are now valid but one should be removed the next time the API changes. Fixes #1978 --- lib/awful/tooltip.lua | 100 ++++++++++++++++-- tests/examples/awful/tooltip/align.lua | 30 ++++++ tests/examples/awful/tooltip/align2.lua | 30 ++++++ tests/examples/awful/tooltip/border_color.lua | 32 ++++++ tests/examples/awful/tooltip/border_width.lua | 32 ++++++ tests/examples/awful/tooltip/margins.lua | 32 ++++++ .../awful/tooltip/margins_leftright.lua | 32 ++++++ .../awful/tooltip/margins_topbottom.lua | 32 ++++++ tests/examples/awful/tooltip/mode.lua | 23 ++++ tests/examples/awful/tooltip/mode2.lua | 24 +++++ tests/examples/awful/tooltip/mouse.lua | 20 ++++ .../awful/tooltip/preferred_alignment.lua | 29 +++++ .../awful/tooltip/preferred_alignment2.lua | 29 +++++ .../awful/tooltip/preferred_alignment3.lua | 29 +++++ .../awful/tooltip/preferred_positions.lua | 28 +++++ tests/examples/awful/tooltip/shape.lua | 34 ++++++ tests/examples/awful/tooltip/textclock.lua | 31 ++++++ tests/examples/awful/tooltip/textclock2.lua | 32 ++++++ tests/examples/shims/awesome.lua | 3 + tests/examples/shims/drawin.lua | 6 ++ tests/examples/shims/mouse.lua | 24 +++++ 21 files changed, 623 insertions(+), 9 deletions(-) create mode 100644 tests/examples/awful/tooltip/align.lua create mode 100644 tests/examples/awful/tooltip/align2.lua create mode 100644 tests/examples/awful/tooltip/border_color.lua create mode 100644 tests/examples/awful/tooltip/border_width.lua create mode 100644 tests/examples/awful/tooltip/margins.lua create mode 100644 tests/examples/awful/tooltip/margins_leftright.lua create mode 100644 tests/examples/awful/tooltip/margins_topbottom.lua create mode 100644 tests/examples/awful/tooltip/mode.lua create mode 100644 tests/examples/awful/tooltip/mode2.lua create mode 100644 tests/examples/awful/tooltip/mouse.lua create mode 100644 tests/examples/awful/tooltip/preferred_alignment.lua create mode 100644 tests/examples/awful/tooltip/preferred_alignment2.lua create mode 100644 tests/examples/awful/tooltip/preferred_alignment3.lua create mode 100644 tests/examples/awful/tooltip/preferred_positions.lua create mode 100644 tests/examples/awful/tooltip/shape.lua create mode 100644 tests/examples/awful/tooltip/textclock.lua create mode 100644 tests/examples/awful/tooltip/textclock2.lua diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index 2490fd19..62970d96 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -10,13 +10,16 @@ -- How to create a tooltip? -- --- -- --- myclock = wibox.widget.textclock("%T", 1) --- myclock_t = awful.tooltip({ --- objects = { myclock }, --- timer_function = function() --- return os.date("Today is %A %B %d %Y\nThe time is %T") --- end, --- }) +-- @DOC_awful_tooltip_textclock_EXAMPLE@ +-- +-- Alternatively, you can use `mouse::enter` signal: +-- +-- @DOC_awful_tooltip_textclock2_EXAMPLE@ +-- +-- How to create a tooltip without objects? +-- --- +-- +-- @DOC_awful_tooltip_mouse_EXAMPLE@ -- -- How to add the same tooltip to multiple objects? -- --- @@ -229,6 +232,13 @@ end --- The horizontal alignment. -- +-- This is valid for the mouse mode only. For the outside mode, use +-- `preferred_positions`. +-- +-- @DOC_awful_tooltip_align_EXAMPLE@ +-- +-- @DOC_awful_tooltip_align2_EXAMPLE@ +-- -- The following values are valid: -- -- * top_left @@ -242,6 +252,8 @@ end -- -- @property align -- @see beautiful.tooltip_align +-- @see mode +-- @see preferred_positions --- The default tooltip alignment. -- @beautiful beautiful.tooltip_align @@ -265,6 +277,9 @@ end --- The shape of the tooltip window. -- If the shape require some parameters, use `set_shape`. +-- +-- @DOC_awful_tooltip_shape_EXAMPLE@ +-- -- @property shape -- @see gears.shape -- @see set_shape @@ -275,7 +290,6 @@ end -- @tparam gears.shape s The shape -- @see shape -- @see gears.shape - function tooltip:set_shape(s) self.backgroundbox:set_shape(s) end @@ -285,6 +299,14 @@ end -- close to the mouse cursor. It is also possible to place the tooltip relative -- to the widget geometry. -- +-- **mouse:** +-- +-- @DOC_awful_tooltip_mode_EXAMPLE@ +-- +-- **outside:** +-- +-- @DOC_awful_tooltip_mode2_EXAMPLE@ +-- -- Valid modes are: -- -- * "mouse": Next to the mouse cursor @@ -306,8 +328,17 @@ end --- The preferred positions when in `outside` mode. -- +-- @DOC_awful_tooltip_preferred_positions_EXAMPLE@ +-- -- If the tooltip fits on multiple sides of the drawable, then this defines the --- priority +-- priority. +-- +-- The valid table values are: +-- +-- * "top" +-- * "right" +-- * "left" +-- * "bottom" -- -- The default is: -- @@ -315,6 +346,9 @@ end -- -- @property preferred_positions -- @tparam table preferred_positions The position, ordered by priorities +-- @see align +-- @see mode +-- @see preferred_alignments function tooltip:get_preferred_positions() return self._private.preferred_positions or @@ -327,6 +361,36 @@ function tooltip:set_preferred_positions(value) set_geometry(self) end +--- The preferred alignment when using the `outside` mode. +-- +-- The values of the table are ordered by priority, the first one that fits +-- will be used. +-- +-- **front:** +-- +-- @DOC_awful_tooltip_preferred_alignment_EXAMPLE@ +-- +-- **middle:** +-- +-- @DOC_awful_tooltip_preferred_alignment2_EXAMPLE@ +-- +-- **back:** +-- +-- @DOC_awful_tooltip_preferred_alignment3_EXAMPLE@ +-- +-- The valid table values are: +-- +-- * front +-- * middle +-- * back +-- +-- The default is: +-- +-- {"front", "back", "middle"} +-- +-- @property preferred_alignments +-- @param string +-- @see preferred_positions function tooltip:get_preferred_alignments() return self._private.preferred_alignments or @@ -383,6 +447,8 @@ end --- Set all margins around the tooltip textbox -- +-- @DOC_awful_tooltip_margins_EXAMPLE@ +-- -- @property margins -- @tparam tooltip self A tooltip object -- @tparam number New margins value @@ -391,11 +457,23 @@ function tooltip:set_margins(val) self.marginbox:set_margins(val) end +--- The border width. +-- +-- @DOC_awful_tooltip_border_width_EXAMPLE@ +-- +-- @property border_width +-- @param number function tooltip:set_border_width(val) self.widget.shape_border_width = val end +--- The border color. +-- +-- @DOC_awful_tooltip_border_color_EXAMPLE@ +-- +-- @property border_color +-- @param gears.color function tooltip:set_border_color(val) self.widget.shape_border_color = val @@ -403,6 +481,8 @@ end --- Set the margins around the left and right of the tooltip textbox -- +-- @DOC_awful_tooltip_margins_leftright_EXAMPLE@ +-- -- @property margins_leftright -- @tparam tooltip self A tooltip object -- @tparam number New margins value @@ -419,6 +499,8 @@ end --- Set the margins around the top and bottom of the tooltip textbox -- +-- @DOC_awful_tooltip_margins_topbottom_EXAMPLE@ +-- -- @property margins_topbottom -- @tparam tooltip self A tooltip object -- @tparam number New margins value diff --git a/tests/examples/awful/tooltip/align.lua b/tests/examples/awful/tooltip/align.lua new file mode 100644 index 00000000..da6b5e86 --- /dev/null +++ b/tests/examples/awful/tooltip/align.lua @@ -0,0 +1,30 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 300, height = 75} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +-- mouse.coords{x=50, y= 10} + + local wb = wibox { + width = 100, height = 44, x = 100, y = 10, visible = true, bg = "#00000000" + } + +awesome.emit_signal("refresh") + +for _, side in ipairs{ "top_left", "bottom_left", "top_right", "bottom_right"} do + local tt = awful.tooltip { + text = side, + objects = {wb}, + mode = "mouse", + align = side, + } + tt.bg = beautiful.bg_normal +end + +mouse.coords{x=125, y= 35} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/align2.lua b/tests/examples/awful/tooltip/align2.lua new file mode 100644 index 00000000..a0540f52 --- /dev/null +++ b/tests/examples/awful/tooltip/align2.lua @@ -0,0 +1,30 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 300, height = 75} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +-- mouse.coords{x=50, y= 10} + + local wb = wibox { + width = 100, height = 44, x = 100, y = 10, visible = true, bg = "#00000000" + } + +awesome.emit_signal("refresh") + +for _, side in ipairs{ "left", "right", "bottom", "top" } do + local tt = awful.tooltip { + text = side, + objects = {wb}, + mode = "mouse", + align = side, + } + tt.bg = beautiful.bg_normal +end + +mouse.coords{x=125, y= 35} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/border_color.lua b/tests/examples/awful/tooltip/border_color.lua new file mode 100644 index 00000000..452eec13 --- /dev/null +++ b/tests/examples/awful/tooltip/border_color.lua @@ -0,0 +1,32 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 640, height = 55} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") + +-- mouse.coords{x=50, y= 10} + +awesome.emit_signal("refresh") + +local x_offset = 0 + +for _, color in ipairs{ "#ff0000", "#00ff00", "#0000ff", "#00ffff" } do + local tt = awful.tooltip { + text = color, + mode = "mouse", + border_width = 2, + border_color = color, + } + tt.bg = beautiful.bg_normal + awesome.emit_signal("refresh") + tt:show() + awesome.emit_signal("refresh") + tt.wibox.x = x_offset + x_offset = x_offset + 640/5 +end + +mouse.coords{x=125, y= 0} +-- mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/border_width.lua b/tests/examples/awful/tooltip/border_width.lua new file mode 100644 index 00000000..633f27f8 --- /dev/null +++ b/tests/examples/awful/tooltip/border_width.lua @@ -0,0 +1,32 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 640, height = 55} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") + +-- mouse.coords{x=50, y= 10} + +awesome.emit_signal("refresh") + +local x_offset = 0 + +for _, width in ipairs{ 1,2,4,6 } do + local tt = awful.tooltip { + text = "width: "..width, + mode = "mouse", + border_width = width, + border_color = beautiful.border_color, + } + tt.bg = beautiful.bg_normal + awesome.emit_signal("refresh") + tt:show() + awesome.emit_signal("refresh") + tt.wibox.x = x_offset + x_offset = x_offset + 640/5 +end + +mouse.coords{x=125, y= 0} +-- mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/margins.lua b/tests/examples/awful/tooltip/margins.lua new file mode 100644 index 00000000..65fd743a --- /dev/null +++ b/tests/examples/awful/tooltip/margins.lua @@ -0,0 +1,32 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 640, height = 55} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") + +-- mouse.coords{x=50, y= 10} + +awesome.emit_signal("refresh") + +local x_offset = 0 + +for _, width in ipairs{ 1,2,4,6 } do + local tt = awful.tooltip { + text = "margins: "..width, + mode = "mouse", + margins = width, + border_color = beautiful.border_color, + } + tt.bg = beautiful.bg_normal + awesome.emit_signal("refresh") + tt:show() + awesome.emit_signal("refresh") + tt.wibox.x = x_offset + x_offset = x_offset + 640/5 +end + +mouse.coords{x=125, y= 0} +-- mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/margins_leftright.lua b/tests/examples/awful/tooltip/margins_leftright.lua new file mode 100644 index 00000000..21ef3aeb --- /dev/null +++ b/tests/examples/awful/tooltip/margins_leftright.lua @@ -0,0 +1,32 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 640, height = 55} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") + +-- mouse.coords{x=50, y= 10} + +awesome.emit_signal("refresh") + +local x_offset = 0 + +for _, width in ipairs{ 1,2,4,6 } do + local tt = awful.tooltip { + text = "margins: "..width, + mode = "mouse", + margins_leftright = width, + border_color = beautiful.border_color, + } + tt.bg = beautiful.bg_normal + awesome.emit_signal("refresh") + tt:show() + awesome.emit_signal("refresh") + tt.wibox.x = x_offset + x_offset = x_offset + 640/5 +end + +mouse.coords{x=125, y= 0} +-- mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/margins_topbottom.lua b/tests/examples/awful/tooltip/margins_topbottom.lua new file mode 100644 index 00000000..c815c955 --- /dev/null +++ b/tests/examples/awful/tooltip/margins_topbottom.lua @@ -0,0 +1,32 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 640, height = 55} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") + +-- mouse.coords{x=50, y= 10} + +awesome.emit_signal("refresh") + +local x_offset = 0 + +for _, width in ipairs{ 1,2,4,6 } do + local tt = awful.tooltip { + text = "margins: "..width, + mode = "mouse", + margins_topbottom = width, + border_color = beautiful.border_color, + } + tt.bg = beautiful.bg_normal + awesome.emit_signal("refresh") + tt:show() + awesome.emit_signal("refresh") + tt.wibox.x = x_offset + x_offset = x_offset + 640/5 +end + +mouse.coords{x=125, y= 0} +-- mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/mode.lua b/tests/examples/awful/tooltip/mode.lua new file mode 100644 index 00000000..9102e37a --- /dev/null +++ b/tests/examples/awful/tooltip/mode.lua @@ -0,0 +1,23 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 200, height = 100} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +mouse.coords{x=50, y= 10} + + local wb = wibox {width = 100, height = 44, x = 50, y = 25, visible = true} + +awesome.emit_signal("refresh") +local tt = awful.tooltip { + text = "A tooltip!", + objects = {wb}, +} +tt.bg = beautiful.bg_normal + +mouse.coords{x=75, y= 35} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/mode2.lua b/tests/examples/awful/tooltip/mode2.lua new file mode 100644 index 00000000..ec1736a7 --- /dev/null +++ b/tests/examples/awful/tooltip/mode2.lua @@ -0,0 +1,24 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 200, height = 100} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +mouse.coords{x=50, y= 10} + + local wb = wibox {width = 100, height = 44, x = 50, y = 25, visible = true} + +awesome.emit_signal("refresh") +local tt = awful.tooltip { + text = "A tooltip!", + objects = {wb}, + mode = "outside", +} +tt.bg = beautiful.bg_normal + +mouse.coords{x=75, y= 35} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/mouse.lua b/tests/examples/awful/tooltip/mouse.lua new file mode 100644 index 00000000..348d2e40 --- /dev/null +++ b/tests/examples/awful/tooltip/mouse.lua @@ -0,0 +1,20 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +screen[1]._resize {width = 200, height = 50} --DOC_HIDE +screen.no_outline = true --DOC_HIDE +local awful = {tooltip = require("awful.tooltip")} --DOC_HIDE +local beautiful = require("beautiful") --DOC_HIDE + +mouse.coords{x=50, y= 10} --DOC_HIDE +mouse.push_history() --DOC_HIDE + + local tt = awful.tooltip { + text = "A tooltip!", + visible = true, + } + +--DOC_NEWLINE + + tt.bg = beautiful.bg_normal + +--DOC_NEWLINE diff --git a/tests/examples/awful/tooltip/preferred_alignment.lua b/tests/examples/awful/tooltip/preferred_alignment.lua new file mode 100644 index 00000000..dca897f2 --- /dev/null +++ b/tests/examples/awful/tooltip/preferred_alignment.lua @@ -0,0 +1,29 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 300, height = 150} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +-- mouse.coords{x=50, y= 10} + + local wb = wibox {width = 100, height = 44, x = 100, y = 50, visible = true} + +awesome.emit_signal("refresh") + +for _, side in ipairs{ "left", "right", "bottom", "top" } do + local tt = awful.tooltip { + text = side, + objects = {wb}, + mode = "outside", + preferred_positions = {side}, + preferred_alignments = {"front"}, + } + tt.bg = beautiful.bg_normal +end + +mouse.coords{x=125, y= 75} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/preferred_alignment2.lua b/tests/examples/awful/tooltip/preferred_alignment2.lua new file mode 100644 index 00000000..1040c00a --- /dev/null +++ b/tests/examples/awful/tooltip/preferred_alignment2.lua @@ -0,0 +1,29 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 300, height = 150} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +-- mouse.coords{x=50, y= 10} + + local wb = wibox {width = 100, height = 44, x = 100, y = 50, visible = true} + +awesome.emit_signal("refresh") + +for _, side in ipairs{ "left", "right", "bottom", "top" } do + local tt = awful.tooltip { + text = side, + objects = {wb}, + mode = "outside", + preferred_positions = {side}, + preferred_alignments = {"middle"}, + } + tt.bg = beautiful.bg_normal +end + +mouse.coords{x=125, y= 75} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/preferred_alignment3.lua b/tests/examples/awful/tooltip/preferred_alignment3.lua new file mode 100644 index 00000000..288e963e --- /dev/null +++ b/tests/examples/awful/tooltip/preferred_alignment3.lua @@ -0,0 +1,29 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 300, height = 150} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +-- mouse.coords{x=50, y= 10} + + local wb = wibox {width = 100, height = 44, x = 100, y = 50, visible = true} + +awesome.emit_signal("refresh") + +for _, side in ipairs{ "left", "right", "bottom", "top" } do + local tt = awful.tooltip { + text = side, + objects = {wb}, + mode = "outside", + preferred_positions = {side}, + preferred_alignments = {"back"}, + } + tt.bg = beautiful.bg_normal +end + +mouse.coords{x=125, y= 75} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/preferred_positions.lua b/tests/examples/awful/tooltip/preferred_positions.lua new file mode 100644 index 00000000..1000d387 --- /dev/null +++ b/tests/examples/awful/tooltip/preferred_positions.lua @@ -0,0 +1,28 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 300, height = 150} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local wibox = require("wibox") + +-- mouse.coords{x=50, y= 10} + + local wb = wibox {width = 100, height = 44, x = 100, y = 50, visible = true} + +awesome.emit_signal("refresh") + +for _, side in ipairs{ "left", "right", "bottom", "top" } do + local tt = awful.tooltip { + text = side, + objects = {wb}, + mode = "outside", + preferred_positions = {side}, + } + tt.bg = beautiful.bg_normal +end + +mouse.coords{x=125, y= 75} +mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/shape.lua b/tests/examples/awful/tooltip/shape.lua new file mode 100644 index 00000000..b83a3893 --- /dev/null +++ b/tests/examples/awful/tooltip/shape.lua @@ -0,0 +1,34 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +--DOC_HIDE_ALL +screen[1]._resize {width = 640, height = 55} +screen.no_outline = true +local awful = {tooltip = require("awful.tooltip")} +local beautiful = require("beautiful") +local gears = {shape = require("gears.shape")} + +-- mouse.coords{x=50, y= 10} + +awesome.emit_signal("refresh") + +local x_offset = 0 + +for _, shape in ipairs{ "rounded_rect", "rounded_bar", "octogon", "infobubble"} do + local tt = awful.tooltip { + text = shape, + mode = "mouse", + border_width = 2, + shape = gears.shape[shape], + border_color = beautiful.border_color, + } + tt.bg = beautiful.bg_normal + awesome.emit_signal("refresh") + tt:show() + awesome.emit_signal("refresh") + tt.wibox.x = x_offset + x_offset = x_offset + 640/5 +end + +mouse.coords{x=125, y= 0} +-- mouse.push_history() +awesome.emit_signal("refresh") diff --git a/tests/examples/awful/tooltip/textclock.lua b/tests/examples/awful/tooltip/textclock.lua new file mode 100644 index 00000000..00f32dcc --- /dev/null +++ b/tests/examples/awful/tooltip/textclock.lua @@ -0,0 +1,31 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +screen[1]._resize {width = 300, height = 75} --DOC_HIDE +local awful = {tooltip = require("awful.tooltip"), wibar = require("awful.wibar")} --DOC_HIDE +local wibox = { widget = { textclock = require("wibox.widget.textclock") }, --DOC_HIDE + layout = { align = require("wibox.layout.align") } } --DOC_HIDE + + local mytextclock = wibox.widget.textclock() + +--DOC_NEWLINE + +local wb = awful.wibar { position = "top" } --DOC_HIDE + +wb:setup { layout = wibox.layout.align.horizontal, --DOC_HIDE + nil, nil, mytextclock} --DOC_HIDE + +awesome.emit_signal("refresh") --DOC_HIDE the hierarchy is async + + local myclock_t = awful.tooltip { + objects = { mytextclock }, + timer_function = function() + return os.date("Today is %A %B %d %Y\nThe time is %T") + end, + } + +awesome.emit_signal("refresh") --DOC_HIDE + +mouse.coords{x=250, y= 10} --DOC_HIDE +mouse.push_history() --DOC_HIDE + +assert(myclock_t.wibox and myclock_t.wibox.visible) --DOC_HIDE diff --git a/tests/examples/awful/tooltip/textclock2.lua b/tests/examples/awful/tooltip/textclock2.lua new file mode 100644 index 00000000..6aeec3fb --- /dev/null +++ b/tests/examples/awful/tooltip/textclock2.lua @@ -0,0 +1,32 @@ +--DOC_GEN_IMAGE +--DOC_NO_USAGE +screen[1]._resize {width = 300, height = 75} --DOC_HIDE +local awful = {tooltip = require("awful.tooltip"), wibar = require("awful.wibar")} --DOC_HIDE +local wibox = { widget = { textclock = require("wibox.widget.textclock") }, --DOC_HIDE + layout = { align = require("wibox.layout.align") } } --DOC_HIDE + + local mytextclock = wibox.widget.textclock() + +--DOC_NEWLINE + +local wb = awful.wibar { position = "top" } --DOC_HIDE + +wb:setup { layout = wibox.layout.align.horizontal, --DOC_HIDE + nil, nil, mytextclock} --DOC_HIDE + +awesome.emit_signal("refresh") --DOC_HIDE the hierarchy is async + + local myclock_t = awful.tooltip { } +--DOC_NEWLINE + myclock_t:add_to_object(mytextclock) +--DOC_NEWLINE + mytextclock:connect_signal("mouse::enter", function() + myclock_t.text = os.date("Today is %A %B %d %Y\nThe time is %T") + end) + +awesome.emit_signal("refresh") --DOC_HIDE + +mouse.coords{x=250, y= 10} --DOC_HIDE +mouse.push_history() --DOC_HIDE + +assert(myclock_t.wibox and myclock_t.wibox.visible) --DOC_HIDE diff --git a/tests/examples/shims/awesome.lua b/tests/examples/shims/awesome.lua index 6af6f0e9..d162fd06 100644 --- a/tests/examples/shims/awesome.lua +++ b/tests/examples/shims/awesome.lua @@ -63,6 +63,9 @@ end -- Always show deprecated messages awesome.version = "v9999" +-- SVG are composited. Without it we need a root surface +awesome.composite_manager_running = true + return awesome -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/tests/examples/shims/drawin.lua b/tests/examples/shims/drawin.lua index be5a6ff7..1f1e8436 100644 --- a/tests/examples/shims/drawin.lua +++ b/tests/examples/shims/drawin.lua @@ -2,6 +2,7 @@ local gears_obj = require("gears.object") local drawin, meta = awesome._shim_fake_class() local drawins = setmetatable({}, {__mode="v"}) +local cairo = require("lgi").cairo local function new_drawin(_, args) local ret = gears_obj() @@ -30,6 +31,11 @@ local function new_drawin(_, args) } end + ret.data.drawable.valid = true + ret.data.drawable.surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0) + ret.data.drawable.geometry = ret.geometry + ret.data.drawable.refresh = function() end + for _, k in pairs{ "buttons", "struts", "get_xproperty", "set_xproperty" } do ret[k] = function() end end diff --git a/tests/examples/shims/mouse.lua b/tests/examples/shims/mouse.lua index c4766f3b..20c35f0d 100644 --- a/tests/examples/shims/mouse.lua +++ b/tests/examples/shims/mouse.lua @@ -7,10 +7,34 @@ local mouse = { history = {}, } +-- Avoid gears when possible +local function contains(rect, point) + return point.x >= rect.x and point.x < rect.x+rect.width and + point.y >= rect.y and point.y < rect.y+rect.height +end + function mouse.coords(args) if args then + local old = {x = coords.x, y = coords.y} coords.x, coords.y = args.x, args.y table.insert(mouse.history, {x=coords.x, y=coords.y}) + + for _, d in ipairs(drawin.get()) do + local geo = d.geometry() + local was_in, is_in = contains(geo, old), contains(geo, coords) + local sig = {(is_in and not was_in) and "mouse::enter" or + (was_in and not is_in) and "mouse::leave" or "mouse::move"} + + -- Enter is also a move, otherwise drawable.handle_motion isn't called + if sig[1] == "mouse::enter" then + table.insert(sig, "mouse::move") + end + + for _, s in ipairs(sig) do + d:emit_signal(s, coords.x - geo.x, coords.y - geo.y) + d.drawable:emit_signal(s, coords.x - geo.x, coords.y - geo.y) + end + end end return coords From 8bcdd0b79492e80e76680151fa7cde5ed723e745 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Dec 2018 21:09:24 -0500 Subject: [PATCH 13/14] placement: Add some extra checks to limit the risk of regressions. Given noone understand this code, this will prevent some semi likely regressions from going unnoticed. The main risk is the shims not producing the exact same results as the real implementation and cause different code paths to be taken. As of this commit, both the "real" and "shim" implementation were given the same set of tests with print() at every step of next_to. The resulting log was then checksummed to ensure both are identical. --- lib/awful/placement.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 57cc3ed7..578280fb 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -717,6 +717,10 @@ local function get_relative_regions(geo, mode, is_absolute) dgeo = geo.drawable.get_wibox():geometry() elseif geo.drawable and geo.drawable.drawable then bw, dgeo = 0, geo.drawable.drawable:geometry() + else + -- The placement isn't done on an object at all, having no border is + -- normal. + assert(mode == "geometry") end -- Add the infamous border size @@ -1392,6 +1396,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 original_pos, original_anchors = args.preferred_positions, args.preferred_anchors if type(original_pos) == "string" then @@ -1492,7 +1497,14 @@ function placement.next_to(d, args) attach(d, placement.next_to, args) - return fix_new_geometry(ngeo, args, true), pref_name, dir + local ret = fix_new_geometry(ngeo, args, true) + + -- Make sure the geometry didn't change, it would indicate an + -- "off by border" issue. + assert((not osize.width) or ret.width == d.width) + assert((not osize.height) or ret.height == d.height) + + return ret, pref_name, dir end --- Restore the geometry. From e2f164208c1c1665fa992f50f5a6788220bce9a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 24 Dec 2018 21:52:08 -0500 Subject: [PATCH 14/14] doc: Better document awful.placement.next_to --- lib/awful/placement.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 578280fb..cc77d7ce 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -1383,6 +1383,14 @@ end -- --@DOC_awful_placement_next_to_EXAMPLE@ -- +-- The `args.mode` parameters allows to control from which `next_to` takes its +-- source object from. The valid values are: +-- +-- * geometry: Next to this geometry, `args.geometry` has to be set. +-- * cursor: Next to the mouse. +-- * cursor_inside +-- * geometry_inside +-- -- @tparam drawable d A wibox or client -- @tparam table args -- @tparam string args.mode The mode