diff options
Diffstat (limited to 'awesome/lib')
117 files changed, 0 insertions, 35883 deletions
diff --git a/awesome/lib/awful/autofocus.lua b/awesome/lib/awful/autofocus.lua deleted file mode 100644 index 5fcd220..0000000 --- a/awesome/lib/awful/autofocus.lua +++ /dev/null @@ -1,64 +0,0 @@ ---------------------------------------------------------------------------- ---- Autofocus functions. --- --- When loaded, this module makes sure that there's always a client that will --- have focus on events such as tag switching, client unmanaging, etc. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.autofocus ---------------------------------------------------------------------------- - -local client = client -local aclient = require("awful.client") -local timer = require("gears.timer") - ---- Give focus when clients appear/disappear. --- --- @param obj An object that should have a .screen property. -local function check_focus(obj) - if not obj.screen.valid then return end - -- When no visible client has the focus... - if not client.focus or not client.focus:isvisible() then - local c = aclient.focus.history.get(screen[obj.screen], 0, aclient.focus.filter) - if c then - c:emit_signal("request::activate", "autofocus.check_focus", - {raise=false}) - end - end -end - ---- Check client focus (delayed). --- @param obj An object that should have a .screen property. -local function check_focus_delayed(obj) - timer.delayed_call(check_focus, {screen = obj.screen}) -end - ---- Give focus on tag selection change. --- --- @param tag A tag object -local function check_focus_tag(t) - local s = t.screen - if (not s) or (not s.valid) then return end - s = screen[s] - check_focus({ screen = s }) - if client.focus and screen[client.focus.screen] ~= s then - local c = aclient.focus.history.get(s, 0, aclient.focus.filter) - if c then - c:emit_signal("request::activate", "autofocus.check_focus_tag", - {raise=false}) - end - end -end - -tag.connect_signal("property::selected", function (t) - timer.delayed_call(check_focus_tag, t) -end) -client.connect_signal("unmanage", check_focus_delayed) -client.connect_signal("tagged", check_focus_delayed) -client.connect_signal("untagged", check_focus_delayed) -client.connect_signal("property::hidden", check_focus_delayed) -client.connect_signal("property::minimized", check_focus_delayed) -client.connect_signal("property::sticky", check_focus_delayed) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/button.lua b/awesome/lib/awful/button.lua deleted file mode 100644 index b50664d..0000000 --- a/awesome/lib/awful/button.lua +++ /dev/null @@ -1,61 +0,0 @@ ---------------------------------------------------------------------------- ---- Create easily new buttons objects ignoring certain modifiers. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod awful.button ---------------------------------------------------------------------------- - --- Grab environment we need -local setmetatable = setmetatable -local ipairs = ipairs -local capi = { button = button } -local util = require("awful.util") - -local button = { mt = {} } - ---- Modifiers to ignore. --- --- By default this is initialized as `{ "Lock", "Mod2" }` --- so the `Caps Lock` or `Num Lock` modifier are not taking into account by awesome --- when pressing keys. --- --- @table ignore_modifiers -local ignore_modifiers = { "Lock", "Mod2" } - ---- Create a new button to use as binding. --- --- This function is useful to create several buttons from one, because it will use --- the ignore_modifier variable to create more button with or without the ignored --- modifiers activated. --- --- For example if you want to ignore CapsLock in your buttonbinding (which is --- ignored by default by this function), creating button binding with this function --- will return 2 button objects: one with CapsLock on, and the other one with --- CapsLock off. --- --- @see button --- @treturn table A table with one or several button objects. -function button.new(mod, _button, press, release) - local ret = {} - local subsets = util.subsets(ignore_modifiers) - for _, set in ipairs(subsets) do - ret[#ret + 1] = capi.button({ modifiers = util.table.join(mod, set), - button = _button }) - if press then - ret[#ret]:connect_signal("press", function(_, ...) press(...) end) - end - if release then - ret[#ret]:connect_signal("release", function (_, ...) release(...) end) - end - end - return ret -end - -function button.mt:__call(...) - return button.new(...) -end - -return setmetatable(button, button.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/client.lua b/awesome/lib/awful/client.lua deleted file mode 100644 index 809c055..0000000 --- a/awesome/lib/awful/client.lua +++ /dev/null @@ -1,1238 +0,0 @@ ---------------------------------------------------------------------------- ---- Useful client manipulation functions. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module client ---------------------------------------------------------------------------- - --- Grab environment we need -local util = require("awful.util") -local spawn = require("awful.spawn") -local object = require("gears.object") -local grect = require("gears.geometry").rectangle -local pairs = pairs -local type = type -local ipairs = ipairs -local table = table -local math = math -local setmetatable = setmetatable -local capi = -{ - client = client, - mouse = mouse, - screen = screen, - awesome = awesome, -} - -local function get_screen(s) - return s and capi.screen[s] -end - --- We use a metatable to prevent circular dependency loops. -local screen -do - screen = setmetatable({}, { - __index = function(_, k) - screen = require("awful.screen") - return screen[k] - end, - __newindex = error -- Just to be sure in case anything ever does this - }) -end -local client = {object={}} - --- Private data -client.data = {} -client.data.marked = {} -client.data.persistent_properties_registered = {} -- keys are names of persistent properties, value always true - --- Functions -client.urgent = require("awful.client.urgent") -client.swap = {} -client.floating = {} -client.dockable = {} -client.property = {} -client.shape = require("awful.client.shape") -client.focus = require("awful.client.focus") - ---- Jump to the given client. --- Takes care of focussing the screen, the right tag, etc. --- --- @deprecated awful.client.jumpto --- @see client.jump_to --- @client c the client to jump to --- @tparam bool|function merge If true then merge tags (select the client's --- first tag additionally) when the client is not visible. --- If it is a function, it will be called with the client and its first --- tag as arguments. -function client.jumpto(c, merge) - util.deprecate("Use c:jump_to(merge) instead of awful.client.jumpto") - client.object.jump_to(c, merge) -end - ---- Jump to the given client. --- Takes care of focussing the screen, the right tag, etc. --- --- @function client.jump_to --- @tparam bool|function merge If true then merge tags (select the client's --- first tag additionally) when the client is not visible. --- If it is a function, it will be called with the client and its first --- tag as arguments. -function client.object.jump_to(self, merge) - local s = get_screen(screen.focused()) - -- focus the screen - if s ~= get_screen(self.screen) then - screen.focus(self.screen) - end - - self.minimized = false - - -- Try to make client visible, this also covers e.g. sticky. - if not self:isvisible() then - local t = self.first_tag - if merge then - if type(merge) == "function" then - merge(self, t) - elseif t then - t.selected = true - end - elseif t then - t:view_only() - end - end - - self:emit_signal("request::activate", "client.jumpto", {raise=true}) -end - ---- Get visible clients from a screen. --- --- @deprecated awful.client.visible --- @see screen.clients --- @tparam[opt] integer|screen s The screen, or nil for all screens. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) --- @treturn table A table with all visible clients. -function client.visible(s, stacked) - local cls = capi.client.get(s, stacked) - local vcls = {} - for _, c in pairs(cls) do - if c:isvisible() then - table.insert(vcls, c) - end - end - return vcls -end - ---- Get visible and tiled clients --- --- @deprecated awful.client.tiled --- @see screen.tiled_clients --- @tparam integer|screen s The screen, or nil for all screens. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) --- @treturn table A table with all visible and tiled clients. -function client.tiled(s, stacked) - local clients = client.visible(s, stacked) - local tclients = {} - -- Remove floating clients - for _, c in pairs(clients) do - if not client.object.get_floating(c) - and not c.fullscreen - and not c.maximized_vertical - and not c.maximized_horizontal then - table.insert(tclients, c) - end - end - return tclients -end - ---- Get a client by its relative index to another client. --- If no client is passed, the focused client will be used. --- --- @function awful.client.next --- @tparam int i The index. Use 1 to get the next, -1 to get the previous. --- @client[opt] sel The client. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) --- @return A client, or nil if no client is available. --- --- @usage -- focus the next window in the index --- awful.client.next(1) --- -- focus the previous --- awful.client.next(-1) -function client.next(i, sel, stacked) - -- Get currently focused client - sel = sel or capi.client.focus - if sel then - -- Get all visible clients - local cls = client.visible(sel.screen, stacked) - local fcls = {} - -- Remove all non-normal clients - for _, c in ipairs(cls) do - if client.focus.filter(c) or c == sel then - table.insert(fcls, c) - end - end - cls = fcls - -- Loop upon each client - for idx, c in ipairs(cls) do - if c == sel then - -- Cycle - return cls[util.cycle(#cls, idx + i)] - end - end - end -end - ---- Swap a client with another client in the given direction. --- @function awful.client.swap.bydirection --- @tparam string dir The direction, can be either "up", "down", "left" or "right". --- @client[opt=focused] c The client. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) -function client.swap.bydirection(dir, c, stacked) - local sel = c or capi.client.focus - if sel then - local cltbl = client.visible(sel.screen, stacked) - local geomtbl = {} - for i,cl in ipairs(cltbl) do - geomtbl[i] = cl:geometry() - end - local target = grect.get_in_direction(dir, geomtbl, sel:geometry()) - - -- If we found a client to swap with, then go for it - if target then - cltbl[target]:swap(sel) - end - end -end - ---- Swap a client with another client in the given direction. Swaps across screens. --- @function awful.client.swap.global_bydirection --- @param dir The direction, can be either "up", "down", "left" or "right". --- @client[opt] sel The client. -function client.swap.global_bydirection(dir, sel) - sel = sel or capi.client.focus - local scr = get_screen(sel and sel.screen or screen.focused()) - - if sel then - -- move focus - client.focus.global_bydirection(dir, sel) - local c = capi.client.focus - - -- swapping inside a screen - if get_screen(sel.screen) == get_screen(c.screen) and sel ~= c then - c:swap(sel) - - -- swapping to an empty screen - elseif get_screen(sel.screen) ~= get_screen(c.screen) and sel == c then - sel:move_to_screen(screen.focused()) - - -- swapping to a nonempty screen - elseif get_screen(sel.screen) ~= get_screen(c.screen) and sel ~= c then - sel:move_to_screen(c.screen) - c:move_to_screen(scr) - end - - screen.focus(sel.screen) - sel:emit_signal("request::activate", "client.swap.global_bydirection", - {raise=false}) - end -end - ---- Swap a client by its relative index. --- @function awful.client.swap.byidx --- @param i The index. --- @client[opt] c The client, otherwise focused one is used. -function client.swap.byidx(i, c) - local sel = c or capi.client.focus - local target = client.next(i, sel) - if target then - target:swap(sel) - end -end - ---- Cycle clients. --- --- @function awful.client.cycle --- @param clockwise True to cycle clients clockwise. --- @param[opt] s The screen where to cycle clients. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) -function client.cycle(clockwise, s, stacked) - s = s or screen.focused() - local cls = client.visible(s, stacked) - -- We can't rotate without at least 2 clients, buddy. - if #cls >= 2 then - local c = table.remove(cls, 1) - if clockwise then - for i = #cls, 1, -1 do - c:swap(cls[i]) - end - else - for _, rc in pairs(cls) do - c:swap(rc) - end - end - end -end - ---- Get the master window. --- --- @legacylayout awful.client.getmaster --- @screen_or_idx[opt=awful.screen.focused()] s The screen. --- @return The master window. -function client.getmaster(s) - s = s or screen.focused() - return client.visible(s)[1] -end - ---- Set the client as master: put it at the beginning of other windows. --- --- @legacylayout awful.client.setmaster --- @client c The window to set as master. -function client.setmaster(c) - local cls = util.table.reverse(capi.client.get(c.screen)) - for _, v in pairs(cls) do - c:swap(v) - end -end - ---- Set the client as slave: put it at the end of other windows. --- @legacylayout awful.client.setslave --- @client c The window to set as slave. -function client.setslave(c) - local cls = capi.client.get(c.screen) - for _, v in pairs(cls) do - c:swap(v) - end -end - ---- Move/resize a client relative to current coordinates. --- @deprecated awful.client.moveresize --- @param x The relative x coordinate. --- @param y The relative y coordinate. --- @param w The relative width. --- @param h The relative height. --- @client[opt] c The client, otherwise focused one is used. --- @see client.relative_move -function client.moveresize(x, y, w, h, c) - util.deprecate("Use c:relative_move(x, y, w, h) instead of awful.client.moveresize") - client.object.relative_move(c or capi.client.focus, x, y, w, h) -end - ---- Move/resize a client relative to current coordinates. --- @function client.relative_move --- @see geometry --- @tparam[opt=c.x] number x The relative x coordinate. --- @tparam[opt=c.y] number y The relative y coordinate. --- @tparam[opt=c.width] number w The relative width. --- @tparam[opt=c.height] number h The relative height. -function client.object.relative_move(self, x, y, w, h) - local geometry = self:geometry() - geometry['x'] = geometry['x'] + x - geometry['y'] = geometry['y'] + y - geometry['width'] = geometry['width'] + w - geometry['height'] = geometry['height'] + h - self:geometry(geometry) -end - ---- Move a client to a tag. --- @deprecated awful.client.movetotag --- @param target The tag to move the client to. --- @client[opt] c The client to move, otherwise the focused one is used. --- @see client.move_to_tag -function client.movetotag(target, c) - util.deprecate("Use c:move_to_tag(target) instead of awful.client.movetotag") - client.object.move_to_tag(c or capi.client.focus, target) -end - ---- Move a client to a tag. --- @function client.move_to_tag --- @tparam tag target The tag to move the client to. -function client.object.move_to_tag(self, target) - local s = target.screen - if self and s then - if self == capi.client.focus then - self:emit_signal("request::activate", "client.movetotag", {raise=true}) - end - -- Set client on the same screen as the tag. - self.screen = s - self:tags({ target }) - end -end - ---- Toggle a tag on a client. --- @deprecated awful.client.toggletag --- @param target The tag to toggle. --- @client[opt] c The client to toggle, otherwise the focused one is used. --- @see client.toggle_tag -function client.toggletag(target, c) - util.deprecate("Use c:toggle_tag(target) instead of awful.client.toggletag") - client.object.toggle_tag(c or capi.client.focus, target) -end - ---- Toggle a tag on a client. --- @function client.toggle_tag --- @tparam tag target The tag to move the client to. -function client.object.toggle_tag(self, target) - -- Check that tag and client screen are identical - if self and get_screen(self.screen) == get_screen(target.screen) then - local tags = self:tags() - local index = nil; - for i, v in ipairs(tags) do - if v == target then - index = i - break - end - end - if index then - -- If it's the only tag for the window, stop. - if #tags == 1 then return end - tags[index] = nil - else - tags[#tags + 1] = target - end - self:tags(tags) - end -end - ---- Move a client to a screen. Default is next screen, cycling. --- @deprecated awful.client.movetoscreen --- @client c The client to move. --- @param s The screen, default to current + 1. --- @see screen --- @see client.move_to_screen -function client.movetoscreen(c, s) - util.deprecate("Use c:move_to_screen(s) instead of awful.client.movetoscreen") - client.object.move_to_screen(c or capi.client.focus, s) -end - ---- Move a client to a screen. Default is next screen, cycling. --- @function client.move_to_screen --- @tparam[opt=c.screen.index+1] screen s The screen, default to current + 1. --- @see screen --- @see request::activate -function client.object.move_to_screen(self, s) - if self then - local sc = capi.screen.count() - if not s then - s = self.screen.index + 1 - end - if type(s) == "number" then - if s > sc then s = 1 elseif s < 1 then s = sc end - end - s = get_screen(s) - if get_screen(self.screen) ~= s then - local sel_is_focused = self == capi.client.focus - self.screen = s - screen.focus(s) - - if sel_is_focused then - self:emit_signal("request::activate", "client.movetoscreen", - {raise=true}) - end - end - end -end - ---- Tag a client with the set of current tags. --- @function client.to_selected_tags --- @see screen.selected_tags -function client.object.to_selected_tags(self) - local tags = {} - - for _, t in ipairs(self:tags()) do - if get_screen(t.screen) == get_screen(self.screen) then - table.insert(tags, t) - end - end - - if self.screen then - if #tags == 0 then - tags = self.screen.selected_tags - end - - if #tags == 0 then - tags = self.screen.tags - end - end - - if #tags ~= 0 then - self:tags(tags) - end -end - ---- If a client is marked or not. --- --- **Signal:** --- --- * *marked* (for legacy reasons, use `property::marked`) --- * *unmarked* (for legacy reasons, use `property::marked`) --- * *property::marked* --- --- @property marked --- @param boolean - ---- The border color when the client is focused. --- --- @beautiful beautiful.border_marked --- @param string --- - -function client.object.set_marked(self, value) - local is_marked = self.marked - - if value == false and is_marked then - for k, v in pairs(client.data.marked) do - if self == v then - table.remove(client.data.marked, k) - end - end - self:emit_signal("unmarked") - elseif not is_marked and value then - self:emit_signal("marked") - table.insert(client.data.marked, self) - end - - client.property.set(self, "marked", value) -end - -function client.object.get_marked(self) - return client.property.get(self, "marked") -end - ---- Mark a client, and then call 'marked' hook. --- @deprecated awful.client.mark --- @client c The client to mark, the focused one if not specified. -function client.mark(c) - util.deprecate("Use c.marked = true instead of awful.client.mark") - client.object.set_marked(c or capi.client.focus, true) -end - ---- Unmark a client and then call 'unmarked' hook. --- @deprecated awful.client.unmark --- @client c The client to unmark, or the focused one if not specified. -function client.unmark(c) - util.deprecate("Use c.marked = false instead of awful.client.unmark") - client.object.set_marked(c or capi.client.focus, false) -end - ---- Check if a client is marked. --- @deprecated awful.client.ismarked --- @client c The client to check, or the focused one otherwise. -function client.ismarked(c) - util.deprecate("Use c.marked instead of awful.client.ismarked") - return client.object.get_marked(c or capi.client.focus) -end - ---- Toggle a client as marked. --- @deprecated awful.client.togglemarked --- @client c The client to toggle mark. -function client.togglemarked(c) - util.deprecate("Use c.marked = not c.marked instead of awful.client.togglemarked") - c = c or capi.client.focus - if c then - c.marked = not c.marked - end -end - ---- Return the marked clients and empty the marked table. --- @function awful.client.getmarked --- @return A table with all marked clients. -function client.getmarked() - local copy = util.table.clone(client.data.marked, false) - - for _, v in pairs(copy) do - client.property.set(v, "marked", false) - v:emit_signal("unmarked") - end - - client.data.marked = {} - - return copy -end - ---- Set a client floating state, overriding auto-detection. --- Floating client are not handled by tiling layouts. --- @deprecated awful.client.floating.set --- @client c A client. --- @param s True or false. -function client.floating.set(c, s) - util.deprecate("Use c.floating = true instead of awful.client.floating.set") - client.object.set_floating(c, s) -end - --- Set a client floating state, overriding auto-detection. --- Floating client are not handled by tiling layouts. --- @client c A client. --- @param s True or false. -function client.object.set_floating(c, s) - c = c or capi.client.focus - if c and client.property.get(c, "floating") ~= s then - client.property.set(c, "floating", s) - local scr = c.screen - if s == true then - c:geometry(client.property.get(c, "floating_geometry")) - end - c.screen = scr - end -end - -local function store_floating_geometry(c) - if client.object.get_floating(c) then - client.property.set(c, "floating_geometry", c:geometry()) - end -end - --- Store the initial client geometry. -capi.client.connect_signal("new", function(cl) - local function store_init_geometry(c) - client.property.set(c, "floating_geometry", c:geometry()) - c:disconnect_signal("property::border_width", store_init_geometry) - end - cl:connect_signal("property::border_width", store_init_geometry) -end) - -capi.client.connect_signal("property::geometry", store_floating_geometry) - ---- Return if a client has a fixed size or not. --- This function is deprecated, use `c.is_fixed` --- @client c The client. --- @deprecated awful.client.isfixed --- @see is_fixed --- @see size_hints_honor -function client.isfixed(c) - util.deprecate("Use c.is_fixed instead of awful.client.isfixed") - c = c or capi.client.focus - return client.object.is_fixed(c) -end - ---- Return if a client has a fixed size or not. --- --- **Signal:** --- --- * *property::is_fixed* --- --- This property is read only. --- @property is_fixed --- @param boolean The floating state --- @see size_hints --- @see size_hints_honor - -function client.object.is_fixed(c) - if not c then return end - local h = c.size_hints - if h.min_width and h.max_width - and h.max_height and h.min_height - and h.min_width > 0 and h.max_width > 0 - and h.max_height > 0 and h.min_height > 0 - and h.min_width == h.max_width - and h.min_height == h.max_height then - return true - end - return false -end - ---- Get a client floating state. --- @client c A client. --- @see floating --- @deprecated awful.client.floating.get --- @return True or false. Note that some windows might be floating even if you --- did not set them manually. For example, windows with a type different than --- normal. -function client.floating.get(c) - util.deprecate("Use c.floating instead of awful.client.floating.get") - return client.object.get_floating(c) -end - ---- The client floating state. --- If the client is part of the tiled layout or free floating. --- --- Note that some windows might be floating even if you --- did not set them manually. For example, windows with a type different than --- normal. --- --- **Signal:** --- --- * *property::floating* --- --- @property floating --- @param boolean The floating state - -function client.object.get_floating(c) - c = c or capi.client.focus - if c then - local value = client.property.get(c, "floating") - if value ~= nil then - return value - end - if c.type ~= "normal" - or c.fullscreen - or c.maximized_vertical - or c.maximized_horizontal - or client.object.is_fixed(c) then - return true - end - return false - end -end - ---- Toggle the floating state of a client between 'auto' and 'true'. --- Use `c.floating = not c.floating` --- @deprecated awful.client.floating.toggle --- @client c A client. --- @see floating -function client.floating.toggle(c) - c = c or capi.client.focus - -- If it has been set to floating - client.object.set_floating(c, not client.object.get_floating(c)) -end - --- Remove the floating information on a client. --- @client c The client. -function client.floating.delete(c) - client.object.set_floating(c, nil) -end - ---- The x coordinates. --- --- **Signal:** --- --- * *property::x* --- --- @property x --- @param integer - ---- The y coordinates. --- --- **Signal:** --- --- * *property::y* --- --- @property y --- @param integer - ---- The width of the wibox. --- --- **Signal:** --- --- * *property::width* --- --- @property width --- @param width - ---- The height of the wibox. --- --- **Signal:** --- --- * *property::height* --- --- @property height --- @param height - --- Add the geometry helpers to match the wibox API -for _, v in ipairs {"x", "y", "width", "height"} do - client.object["get_"..v] = function(c) - return c:geometry()[v] - end - - client.object["set_"..v] = function(c, value) - return c:geometry({[v] = value}) - end -end - - ---- Restore (=unminimize) a random client. --- @function awful.client.restore --- @param s The screen to use. --- @return The restored client if some client was restored, otherwise nil. -function client.restore(s) - s = s or screen.focused() - local cls = capi.client.get(s) - local tags = s.selected_tags - for _, c in pairs(cls) do - local ctags = c:tags() - if c.minimized then - for _, t in ipairs(tags) do - if util.table.hasitem(ctags, t) then - c.minimized = false - return c - end - end - end - end - return nil -end - ---- Normalize a set of numbers to 1 --- @param set the set of numbers to normalize --- @param num the number of numbers to normalize -local function normalize(set, num) - num = num or #set - local total = 0 - if num then - for i = 1,num do - total = total + set[i] - end - for i = 1,num do - set[i] = set[i] / total - end - else - for _,v in ipairs(set) do - total = total + v - end - - for i,v in ipairs(set) do - set[i] = v / total - end - end -end - ---- Calculate a client's column number, index in that column, and --- number of visible clients in this column. --- --- @legacylayout awful.client.idx --- @client c the client --- @return col the column number --- @return idx index of the client in the column --- @return num the number of visible clients in the column -function client.idx(c) - c = c or capi.client.focus - if not c then return end - - -- Only check the tiled clients, the others un irrelevant - local clients = client.tiled(c.screen) - local idx = nil - for k, cl in ipairs(clients) do - if cl == c then - idx = k - break - end - end - - local t = c.screen.selected_tag - local nmaster = t.master_count - - -- This will happen for floating or maximized clients - if not idx then return nil end - - if idx <= nmaster then - return {idx = idx, col=0, num=nmaster} - end - local nother = #clients - nmaster - idx = idx - nmaster - - -- rather than regenerate the column number we can calculate it - -- based on the how the tiling algorithm places clients we calculate - -- the column, we could easily use the for loop in the program but we can - -- calculate it. - local ncol = t.column_count - -- minimum number of clients per column - local percol = math.floor(nother / ncol) - -- number of columns with an extra client - local overcol = math.fmod(nother, ncol) - -- number of columns filled with [percol] clients - local regcol = ncol - overcol - - local col = math.floor( (idx - 1) / percol) + 1 - if col > regcol then - -- col = math.floor( (idx - (percol*regcol) - 1) / (percol + 1) ) + regcol + 1 - -- simplified - col = math.floor( (idx + regcol + percol) / (percol+1) ) - -- calculate the index in the column - idx = idx - percol*regcol - (col - regcol - 1) * (percol+1) - percol = percol+1 - else - idx = idx - percol*(col-1) - end - - return {idx = idx, col=col, num=percol} -end - - ---- Set the window factor of a client --- --- @legacylayout awful.client.setwfact --- @param wfact the window factor value --- @client c the client -function client.setwfact(wfact, c) - -- get the currently selected window - c = c or capi.client.focus - if not c or not c:isvisible() then return end - - local w = client.idx(c) - - if not w then return end - - local t = c.screen.selected_tag - - -- n is the number of windows currently visible for which we have to be concerned with the properties - local data = t.windowfact or {} - local colfact = data[w.col] - - local need_normalize = colfact ~= nil - - if not need_normalize then - colfact = {} - end - - colfact[w.idx] = wfact - - if not need_normalize then - t:emit_signal("property::windowfact") - return - end - - local rest = 1-wfact - - -- calculate the current denominator - local total = 0 - for i = 1,w.num do - if i ~= w.idx then - total = total + colfact[i] - end - end - - -- normalize the windows - for i = 1,w.num do - if i ~= w.idx then - colfact[i] = (colfact[i] * rest) / total - end - end - - t:emit_signal("property::windowfact") -end - ---- Change window factor of a client. --- --- @legacylayout awful.client.incwfact --- @tparam number add Amount to increase/decrease the client's window factor. --- Should be between `-current_window_factor` and something close to --- infinite. The normalisation then ensures that the sum of all factors is 1. --- @client c the client -function client.incwfact(add, c) - c = c or capi.client.focus - if not c then return end - - local t = c.screen.selected_tag - local w = client.idx(c) - local data = t.windowfact or {} - local colfact = data[w.col] or {} - local curr = colfact[w.idx] or 1 - colfact[w.idx] = curr + add - - -- keep our ratios normalized - normalize(colfact, w.num) - - t:emit_signal("property::windowfact") -end - ---- Get a client dockable state. --- --- @client c A client. --- @return True or false. Note that some windows might be dockable even if you --- did not set them manually. For example, windows with a type "utility", --- "toolbar" or "dock" --- @deprecated awful.client.dockable.get -function client.dockable.get(c) - util.deprecate("Use c.dockable instead of awful.client.dockable.get") - return client.object.get_dockable(c) -end - ---- If the client is dockable. --- A dockable client is an application confined to the edge of the screen. The --- space it occupy is substracted from the `screen.workarea`. --- --- **Signal:** --- --- * *property::dockable* --- --- @property dockable --- @param boolean The dockable state - -function client.object.get_dockable(c) - local value = client.property.get(c, "dockable") - - -- Some sane defaults - if value == nil then - if (c.type == "utility" or c.type == "toolbar" or c.type == "dock") then - value = true - else - value = false - end - end - - return value -end - ---- Set a client dockable state, overriding auto-detection. --- With this enabled you can dock windows by moving them from the center --- to the edge of the workarea. --- --- @client c A client. --- @param value True or false. --- @deprecated awful.client.dockable.set -function client.dockable.set(c, value) - util.deprecate("Use c.dockable = value instead of awful.client.dockable.set") - client.property.set(c, "dockable", value) -end - ---- Get a client property. --- --- This method is deprecated. It is now possible to use `c.value` directly. --- --- @client c The client. --- @param prop The property name. --- @return The property. --- @deprecated awful.client.property.get -function client.property.get(c, prop) - if not c.data._persistent_properties_loaded then - c.data._persistent_properties_loaded = true - for p in pairs(client.data.persistent_properties_registered) do - local value = c:get_xproperty("awful.client.property." .. p) - if value ~= nil then - client.property.set(c, p, value) - end - end - end - if c.data.awful_client_properties then - return c.data.awful_client_properties[prop] - end -end - ---- Set a client property. --- --- This method is deprecated. It is now possible to use `c.value = value` --- directly. --- --- @client c The client. --- @param prop The property name. --- @param value The value. --- @deprecated awful.client.property.set -function client.property.set(c, prop, value) - if not c.data.awful_client_properties then - c.data.awful_client_properties = {} - end - if c.data.awful_client_properties[prop] ~= value then - if client.data.persistent_properties_registered[prop] then - c:set_xproperty("awful.client.property." .. prop, value) - end - c.data.awful_client_properties[prop] = value - c:emit_signal("property::" .. prop) - end -end - ---- Set a client property to be persistent across restarts (via X properties). --- --- @function awful.client.property.persist --- @param prop The property name. --- @param kind The type (used for register_xproperty). --- One of "string", "number" or "boolean". -function client.property.persist(prop, kind) - local xprop = "awful.client.property." .. prop - capi.awesome.register_xproperty(xprop, kind) - client.data.persistent_properties_registered[prop] = true - - -- Make already-set properties persistent - for c in pairs(capi.client.get()) do - if c.data.awful_client_properties and c.data.awful_client_properties[prop] ~= nil then - c:set_xproperty(xprop, c.data.awful_client_properties[prop]) - end - end -end - ---- --- Returns an iterator to cycle through, starting from the client in focus or --- the given index, all clients that match a given criteria. --- --- @param filter a function that returns true to indicate a positive match --- @param start what index to start iterating from. Defaults to using the --- index of the currently focused client. --- @param s which screen to use. nil means all screens. --- --- @function awful.client.iterate --- @usage -- un-minimize all urxvt instances --- local urxvt = function (c) --- return awful.rules.match(c, {class = "URxvt"}) --- end --- --- for c in awful.client.iterate(urxvt) do --- c.minimized = false --- end -function client.iterate(filter, start, s) - local clients = capi.client.get(s) - local focused = capi.client.focus - start = start or util.table.hasitem(clients, focused) - return util.table.iterate(clients, filter, start) -end - ---- Switch to a client matching the given condition if running, else spawn it. --- If multiple clients match the given condition then the next one is --- focussed. --- --- @param cmd the command to execute --- @param matcher a function that returns true to indicate a matching client --- @tparam bool|function merge If true then merge tags (select the client's --- first tag additionally) when the client is not visible. --- If it is a function, it will be called with the client as argument. --- --- @function awful.client.run_or_raise --- @usage -- run or raise urxvt (perhaps, with tabs) on modkey + semicolon --- awful.key({ modkey, }, 'semicolon', function () --- local matcher = function (c) --- return awful.rules.match(c, {class = 'URxvt'}) --- end --- awful.client.run_or_raise('urxvt', matcher) --- end); -function client.run_or_raise(cmd, matcher, merge) - local clients = capi.client.get() - local findex = util.table.hasitem(clients, capi.client.focus) or 1 - local start = util.cycle(#clients, findex + 1) - - local c = client.iterate(matcher, start)() - if c then - c:jump_to(merge) - else - -- client not found, spawn it - spawn(cmd) - end -end - ---- Get a matching transient_for client (if any). --- @deprecated awful.client.get_transient_for_matching --- @see client.get_transient_for_matching --- @client c The client. --- @tparam function matcher A function that should return true, if --- a matching parent client is found. --- @treturn client.client|nil The matching parent client or nil. -function client.get_transient_for_matching(c, matcher) - util.deprecate("Use c:get_transient_for_matching(matcher) instead of".. - "awful.client.get_transient_for_matching") - - return client.object.get_transient_for_matching(c, matcher) -end - ---- Get a matching transient_for client (if any). --- @function client.get_transient_for_matching --- @tparam function matcher A function that should return true, if --- a matching parent client is found. --- @treturn client.client|nil The matching parent client or nil. -function client.object.get_transient_for_matching(self, matcher) - local tc = self.transient_for - while tc do - if matcher(tc) then - return tc - end - tc = tc.transient_for - end - return nil -end - ---- Is a client transient for another one? --- @deprecated awful.client.is_transient_for --- @see client.is_transient_for --- @client c The child client (having transient_for). --- @client c2 The parent client to check. --- @treturn client.client|nil The parent client or nil. -function client.is_transient_for(c, c2) - util.deprecate("Use c:is_transient_for(c2) instead of".. - "awful.client.is_transient_for") - return client.object.is_transient_for(c, c2) -end - ---- Is a client transient for another one? --- @function client.is_transient_for --- @client c2 The parent client to check. --- @treturn client.client|nil The parent client or nil. -function client.object.is_transient_for(self, c2) - local tc = self - while tc.transient_for do - if tc.transient_for == c2 then - return tc - end - tc = tc.transient_for - end - return nil -end - --- Register standards signals - ---- The last geometry when client was floating. --- @signal property::floating_geometry - ---- Emited when a client need to get a titlebar. --- @signal request::titlebars --- @tparam[opt=nil] string content The context (like "rules") --- @tparam[opt=nil] table hints Some hints. - ---- The client marked signal (deprecated). --- @signal .marked - ---- The client unmarked signal (deprecated). --- @signal unmarked - --- Add clients during startup to focus history. --- This used to happen through ewmh.activate, but that only handles visible --- clients now. -capi.client.connect_signal("manage", function (c) - if awesome.startup then - client.focus.history.add(c) - end -end) -capi.client.connect_signal("unmanage", client.focus.history.delete) - -capi.client.connect_signal("unmanage", client.floating.delete) - --- Connect to "focus" signal, and allow to disable tracking. -do - local disabled_count = 1 - --- Disable history tracking. - -- - -- See `awful.client.focus.history.enable_tracking` to enable it again. - -- @treturn int The internal value of `disabled_count` (calls to this - -- function without calling `awful.client.focus.history.enable_tracking`). - -- @function awful.client.focus.history.disable_tracking - function client.focus.history.disable_tracking() - disabled_count = disabled_count + 1 - if disabled_count == 1 then - capi.client.disconnect_signal("focus", client.focus.history.add) - end - return disabled_count - end - - --- Enable history tracking. - -- - -- This is the default, but can be disabled - -- through `awful.client.focus.history.disable_tracking`. - -- @treturn boolean True if history tracking has been enabled. - -- @function awful.client.focus.history.enable_tracking - function client.focus.history.enable_tracking() - assert(disabled_count > 0) - disabled_count = disabled_count - 1 - if disabled_count == 0 then - capi.client.connect_signal("focus", client.focus.history.add) - end - return disabled_count == 0 - end - - --- Is history tracking enabled? - -- @treturn bool True if history tracking is enabled. - -- @treturn int The number of times that tracking has been disabled. - -- @function awful.client.focus.history.is_enabled - function client.focus.history.is_enabled() - return disabled_count == 0, disabled_count - end -end -client.focus.history.enable_tracking() - --- Register persistent properties -client.property.persist("floating", "boolean") - --- Extend the luaobject -object.properties(capi.client, { - getter_class = client.object, - setter_class = client.object, - getter_fallback = client.property.get, - setter_fallback = client.property.set, -}) - -return client - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/client/focus.lua b/awesome/lib/awful/client/focus.lua deleted file mode 100644 index a8b04f2..0000000 --- a/awesome/lib/awful/client/focus.lua +++ /dev/null @@ -1,215 +0,0 @@ ---------------------------------------------------------------------------- ---- Keep track of the focused clients. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @submodule client ---------------------------------------------------------------------------- -local grect = require("gears.geometry").rectangle - -local capi = -{ - screen = screen, - client = client, -} - --- We use a metatable to prevent circular dependency loops. -local screen -do - screen = setmetatable({}, { - __index = function(_, k) - screen = require("awful.screen") - return screen[k] - end, - __newindex = error -- Just to be sure in case anything ever does this - }) -end - -local client -do - client = setmetatable({}, { - __index = function(_, k) - client = require("awful.client") - return client[k] - end, - __newindex = error -- Just to be sure in case anything ever does this - }) -end - -local focus = {history = {list = {}}} - -local function get_screen(s) - return s and capi.screen[s] -end - ---- Remove a client from the focus history --- --- @client c The client that must be removed. --- @function awful.client.focus.history.delete -function focus.history.delete(c) - for k, v in ipairs(focus.history.list) do - if v == c then - table.remove(focus.history.list, k) - break - end - end -end - ---- Focus a client by its relative index. --- --- @function awful.client.focus.byidx --- @param i The index. --- @client[opt] c The client. -function focus.byidx(i, c) - local target = client.next(i, c) - if target then - target:emit_signal("request::activate", "client.focus.byidx", - {raise=true}) - end -end - ---- Filter out window that we do not want handled by focus. --- This usually means that desktop, dock and splash windows are --- not registered and cannot get focus. --- --- @client c A client. --- @return The same client if it's ok, nil otherwise. --- @function awful.client.focus.filter -function focus.filter(c) - if c.type == "desktop" - or c.type == "dock" - or c.type == "splash" - or not c.focusable then - return nil - end - return c -end - ---- Update client focus history. --- --- @client c The client that has been focused. --- @function awful.client.focus.history.add -function focus.history.add(c) - -- Remove the client if its in stack - focus.history.delete(c) - -- Record the client has latest focused - table.insert(focus.history.list, 1, c) -end - ---- Get the latest focused client for a screen in history. --- --- @tparam int|screen s The screen to look for. --- @tparam int idx The index: 0 will return first candidate, --- 1 will return second, etc. --- @tparam function filter An optional filter. If no client is found in the --- first iteration, `awful.client.focus.filter` is used by default to get any --- client. --- @treturn client.object A client. --- @function awful.client.focus.history.get -function focus.history.get(s, idx, filter) - s = get_screen(s) - -- When this counter is equal to idx, we return the client - local counter = 0 - local vc = client.visible(s, true) - for _, c in ipairs(focus.history.list) do - if get_screen(c.screen) == s then - if not filter or filter(c) then - for _, vcc in ipairs(vc) do - if vcc == c then - if counter == idx then - return c - end - -- We found one, increment the counter only. - counter = counter + 1 - break - end - end - end - end - end - -- Argh nobody found in history, give the first one visible if there is one - -- that passes the filter. - filter = filter or focus.filter - if counter == 0 then - for _, v in ipairs(vc) do - if filter(v) then - return v - end - end - end -end - ---- Focus the previous client in history. --- @function awful.client.focus.history.previous -function focus.history.previous() - local sel = capi.client.focus - local s = sel and sel.screen or screen.focused() - local c = focus.history.get(s, 1) - if c then - c:emit_signal("request::activate", "client.focus.history.previous", - {raise=false}) - end -end - ---- Focus a client by the given direction. --- --- @tparam string dir The direction, can be either --- `"up"`, `"down"`, `"left"` or `"right"`. --- @client[opt] c The client. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) --- @function awful.client.focus.bydirection -function focus.bydirection(dir, c, stacked) - local sel = c or capi.client.focus - if sel then - local cltbl = client.visible(sel.screen, stacked) - local geomtbl = {} - for i,cl in ipairs(cltbl) do - geomtbl[i] = cl:geometry() - end - - local target = grect.get_in_direction(dir, geomtbl, sel:geometry()) - - -- If we found a client to focus, then do it. - if target then - cltbl[target]:emit_signal("request::activate", - "client.focus.bydirection", {raise=false}) - end - end -end - ---- Focus a client by the given direction. Moves across screens. --- --- @param dir The direction, can be either "up", "down", "left" or "right". --- @client[opt] c The client. --- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom) --- @function awful.client.focus.global_bydirection -function focus.global_bydirection(dir, c, stacked) - local sel = c or capi.client.focus - local scr = get_screen(sel and sel.screen or screen.focused()) - - -- change focus inside the screen - focus.bydirection(dir, sel) - - -- if focus not changed, we must change screen - if sel == capi.client.focus then - screen.focus_bydirection(dir, scr) - if scr ~= get_screen(screen.focused()) then - local cltbl = client.visible(screen.focused(), stacked) - local geomtbl = {} - for i,cl in ipairs(cltbl) do - geomtbl[i] = cl:geometry() - end - local target = grect.get_in_direction(dir, geomtbl, scr.geometry) - - if target then - cltbl[target]:emit_signal("request::activate", - "client.focus.global_bydirection", - {raise=false}) - end - end - end -end - -return focus - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/client/shape.lua b/awesome/lib/awful/client/shape.lua deleted file mode 100644 index e51d873..0000000 --- a/awesome/lib/awful/client/shape.lua +++ /dev/null @@ -1,93 +0,0 @@ ---------------------------------------------------------------------------- ---- Handle client shapes. --- --- @author Uli Schlachter <psychon@znc.in> --- @copyright 2014 Uli Schlachter --- @submodule client ---------------------------------------------------------------------------- - --- Grab environment we need -local surface = require("gears.surface") -local cairo = require("lgi").cairo -local capi = -{ - client = client, -} - -local shape = {} -shape.update = {} - ---- Get one of a client's shapes and transform it to include window decorations. --- @function awful.shape.get_transformed --- @client c The client whose shape should be retrieved --- @tparam string shape_name Either "bounding" or "clip" -function shape.get_transformed(c, shape_name) - local border = shape_name == "bounding" and c.border_width or 0 - local shape_img = surface.load_silently(c["client_shape_" .. shape_name], false) - if not shape_img then return end - - -- Get information about various sizes on the client - local geom = c:geometry() - local _, t = c:titlebar_top() - local _, b = c:titlebar_bottom() - local _, l = c:titlebar_left() - local _, r = c:titlebar_right() - - -- Figure out the size of the shape that we need - local img_width = geom.width + 2*border - local img_height = geom.height + 2*border - local result = cairo.ImageSurface(cairo.Format.A1, img_width, img_height) - local cr = cairo.Context(result) - - -- Fill everything (this paints the titlebars and border) - cr:paint() - - -- Draw the client's shape in the middle - cr:set_operator(cairo.Operator.SOURCE) - cr:set_source_surface(shape_img, border + l, border + t) - cr:rectangle(border + l, border + t, geom.width - l - r, geom.height - t - b) - cr:fill() - - return result -end - ---- Update a client's bounding shape from the shape the client set itself. --- @function awful.shape.update.bounding --- @client c The client to act on -function shape.update.bounding(c) - local res = shape.get_transformed(c, "bounding") - c.shape_bounding = res and res._native - -- Free memory - if res then - res:finish() - end -end - ---- Update a client's clip shape from the shape the client set itself. --- @function awful.shape.update.clip --- @client c The client to act on -function shape.update.clip(c) - local res = shape.get_transformed(c, "clip") - c.shape_clip = res and res._native - -- Free memory - if res then - res:finish() - end -end - ---- Update all of a client's shapes from the shapes the client set itself. --- @function awful.shape.update.all --- @client c The client to act on -function shape.update.all(c) - shape.update.bounding(c) - shape.update.clip(c) -end - -capi.client.connect_signal("property::shape_client_bounding", shape.update.bounding) -capi.client.connect_signal("property::shape_client_clip", shape.update.clip) -capi.client.connect_signal("property::width", shape.update.all) -capi.client.connect_signal("property::height", shape.update.all) - -return shape - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/client/urgent.lua b/awesome/lib/awful/client/urgent.lua deleted file mode 100644 index 22f6a6d..0000000 --- a/awesome/lib/awful/client/urgent.lua +++ /dev/null @@ -1,88 +0,0 @@ ---------------------------------------------------------------------------- ---- Keep track of the urgent clients. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @submodule client ---------------------------------------------------------------------------- - -local urgent = {} - -local capi = -{ - client = client, -} - -local client -do - client = setmetatable({}, { - __index = function(_, k) - client = require("awful.client") - return client[k] - end, - __newindex = error -- Just to be sure in case anything ever does this - }) -end - -local data = setmetatable({}, { __mode = 'k' }) - ---- Get the first client that got the urgent hint. --- --- @function awful.urgent.get --- @treturn client.object The first urgent client. -function urgent.get() - if #data > 0 then - return data[1] - else - -- fallback behaviour: iterate through clients and get the first urgent - local clients = capi.client.get() - for _, cl in pairs(clients) do - if cl.urgent then - return cl - end - end - end -end - ---- Jump to the client that received the urgent hint first. --- --- @function awful.urgent.jumpto --- @tparam bool|function merge If true then merge tags (select the client's --- first tag additionally) when the client is not visible. --- If it is a function, it will be called with the client as argument. -function urgent.jumpto(merge) - local c = client.urgent.get() - if c then - c:jump_to(merge) - end -end - ---- Adds client to urgent stack. --- --- @function awful.urgent.add --- @client c The client object. --- @param prop The property which is updated. -function urgent.add(c, prop) - if type(c) == "client" and prop == "urgent" and c.urgent then - table.insert(data, c) - end -end - ---- Remove client from urgent stack. --- --- @function awful.urgent.delete --- @client c The client object. -function urgent.delete(c) - for k, cl in ipairs(data) do - if c == cl then - table.remove(data, k) - break - end - end -end - -capi.client.connect_signal("property::urgent", urgent.add) -capi.client.connect_signal("focus", urgent.delete) -capi.client.connect_signal("unmanage", urgent.delete) - -return urgent diff --git a/awesome/lib/awful/completion.lua b/awesome/lib/awful/completion.lua deleted file mode 100644 index 3462ed1..0000000 --- a/awesome/lib/awful/completion.lua +++ /dev/null @@ -1,201 +0,0 @@ ---------------------------------------------------------------------------- ---- Completion module. --- --- This module store a set of function using shell to complete commands name. --- --- @author Julien Danjou <julien@danjou.info> --- @author Sébastien Gross <seb-awesome@chezwam.org> --- @copyright 2008 Julien Danjou, Sébastien Gross --- @module awful.completion ---------------------------------------------------------------------------- - --- Grab environment we need -local io = io -local os = os -local table = table -local math = math -local print = print -local pairs = pairs -local string = string - -local completion = {} - --- mapping of command/completion function -local bashcomp_funcs = {} -local bashcomp_src = "/etc/bash_completion" - ---- Enable programmable bash completion in awful.completion.bash at the price of --- a slight overhead. --- @param src The bash completion source file, /etc/bash_completion by default. -function completion.bashcomp_load(src) - if src then bashcomp_src = src end - local c, err = io.popen("/usr/bin/env bash -c 'source " .. bashcomp_src .. "; complete -p'") - if c then - while true do - local line = c:read("*line") - if not line then break end - -- if a bash function is used for completion, register it - if line:match(".* -F .*") then - bashcomp_funcs[line:gsub(".* (%S+)$","%1")] = line:gsub(".*-F +(%S+) .*$", "%1") - end - end - c:close() - else - print(err) - end -end - -local function bash_escape(str) - str = str:gsub(" ", "\\ ") - str = str:gsub("%[", "\\[") - str = str:gsub("%]", "\\]") - str = str:gsub("%(", "\\(") - str = str:gsub("%)", "\\)") - return str -end - ---- Use shell completion system to complete command and filename. --- @param command The command line. --- @param cur_pos The cursor position. --- @param ncomp The element number to complete. --- @param shell The shell to use for completion (bash (default) or zsh). --- @return The new command, the new cursor position, the table of all matches. -function completion.shell(command, cur_pos, ncomp, shell) - local wstart = 1 - local wend = 1 - local words = {} - local cword_index = 0 - local cword_start = 0 - local cword_end = 0 - local i = 1 - local comptype = "file" - - -- do nothing if we are on a letter, i.e. not at len + 1 or on a space - if cur_pos ~= #command + 1 and command:sub(cur_pos, cur_pos) ~= " " then - return command, cur_pos - elseif #command == 0 then - return command, cur_pos - end - - while wend <= #command do - wend = command:find(" ", wstart) - if not wend then wend = #command + 1 end - table.insert(words, command:sub(wstart, wend - 1)) - if cur_pos >= wstart and cur_pos <= wend + 1 then - cword_start = wstart - cword_end = wend - cword_index = i - end - wstart = wend + 1 - i = i + 1 - end - - if cword_index == 1 and not string.find(words[cword_index], "/") then - comptype = "command" - end - - local shell_cmd - if shell == "zsh" or (not shell and os.getenv("SHELL"):match("zsh$")) then - if comptype == "file" then - -- NOTE: ${~:-"..."} turns on GLOB_SUBST, useful for expansion of - -- "~/" ($HOME). ${:-"foo"} is the string "foo" as var. - shell_cmd = "/usr/bin/env zsh -c 'local -a res; res=( ${~:-" - .. string.format('%q', words[cword_index]) .. "}* ); " - .. "print -ln -- ${res[@]}'" - else - -- check commands, aliases, builtins, functions and reswords - shell_cmd = "/usr/bin/env zsh -c 'local -a res; ".. - "res=( ".. - "\"${(k)commands[@]}\" \"${(k)aliases[@]}\" \"${(k)builtins[@]}\" \"${(k)functions[@]}\" \"${(k)reswords[@]}\" ".. - "${PWD}/*(:t)".. - "); ".. - "print -ln -- ${(M)res[@]:#" .. string.format('%q', words[cword_index]) .. "*}'" - end - else - if bashcomp_funcs[words[1]] then - -- fairly complex command with inline bash script to get the possible completions - shell_cmd = "/usr/bin/env bash -c 'source " .. bashcomp_src .. "; " .. - "__print_completions() { for ((i=0;i<${#COMPREPLY[*]};i++)); do echo ${COMPREPLY[i]}; done }; " .. - "COMP_WORDS=(" .. command .."); COMP_LINE=\"" .. command .. "\"; " .. - "COMP_COUNT=" .. cur_pos .. "; COMP_CWORD=" .. cword_index-1 .. "; " .. - bashcomp_funcs[words[1]] .. "; __print_completions'" - else - shell_cmd = "/usr/bin/env bash -c 'compgen -A " .. comptype .. " " - .. string.format('%q', words[cword_index]) .. "'" - end - end - local c, err = io.popen(shell_cmd .. " | sort -u") - local output = {} - if c then - while true do - local line = c:read("*line") - if not line then break end - if os.execute("test -d " .. string.format('%q', line)) == 0 then - line = line .. "/" - end - table.insert(output, bash_escape(line)) - end - - c:close() - else - print(err) - end - - -- no completion, return - if #output == 0 then - return command, cur_pos - end - - -- cycle - while ncomp > #output do - ncomp = ncomp - #output - end - - local str = command:sub(1, cword_start - 1) .. output[ncomp] .. command:sub(cword_end) - cur_pos = cword_end + #output[ncomp] + 1 - - return str, cur_pos, output -end - ---- Run a generic completion. --- For this function to run properly the awful.completion.keyword table should --- be fed up with all keywords. The completion is run against these keywords. --- @param text The current text the user had typed yet. --- @param cur_pos The current cursor position. --- @param ncomp The number of yet requested completion using current text. --- @param keywords The keywords table uised for completion. --- @return The new match, the new cursor position, the table of all matches. -function completion.generic(text, cur_pos, ncomp, keywords) -- luacheck: no unused args - -- The keywords table may be empty - if #keywords == 0 then - return text, #text + 1 - end - - -- if no text had been typed yet, then we could start cycling around all - -- keywords with out filtering and move the cursor at the end of keyword - if text == nil or #text == 0 then - ncomp = math.fmod(ncomp - 1, #keywords) + 1 - return keywords[ncomp], #keywords[ncomp] + 2 - end - - -- Filter out only keywords starting with text - local matches = {} - for _, x in pairs(keywords) do - if x:sub(1, #text) == text then - table.insert(matches, x) - end - end - - -- if there are no matches just leave out with the current text and position - if #matches == 0 then - return text, #text + 1, matches - end - - -- cycle around all matches - ncomp = math.fmod(ncomp - 1, #matches) + 1 - return matches[ncomp], #matches[ncomp] + 1, matches -end - -return completion - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/dbus.lua b/awesome/lib/awful/dbus.lua deleted file mode 100644 index 8660dce..0000000 --- a/awesome/lib/awful/dbus.lua +++ /dev/null @@ -1,19 +0,0 @@ ---------------------------------------------------------------------------- ---- D-Bus module for awful. --- --- This module simply request the org.awesomewm.awful name on the D-Bus --- for futur usage by other awful modules. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.dbus ---------------------------------------------------------------------------- - --- Grab environment we need -local dbus = dbus - -if dbus then - dbus.request_name("session", "org.awesomewm.awful") -end - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/ewmh.lua b/awesome/lib/awful/ewmh.lua deleted file mode 100644 index eb72a16..0000000 --- a/awesome/lib/awful/ewmh.lua +++ /dev/null @@ -1,295 +0,0 @@ ---------------------------------------------------------------------------- ---- Implements EWMH requests handling. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.ewmh ---------------------------------------------------------------------------- - -local client = client -local screen = screen -local ipairs = ipairs -local util = require("awful.util") -local aclient = require("awful.client") -local aplace = require("awful.placement") -local asuit = require("awful.layout.suit") - -local ewmh = { - generic_activate_filters = {}, - contextual_activate_filters = {}, -} - ---- The list of all registered generic request::activate (focus stealing) --- filters. If a filter is added to only one context, it will be in --- `ewmh.contextual_activate_filters`["context_name"]. --- @table[opt={}] generic_activate_filters --- @see ewmh.activate --- @see ewmh.add_activate_filter --- @see ewmh.remove_activate_filter - ---- The list of all registered contextual request::activate (focus stealing) --- filters. If a filter is added to only one context, it will be in --- `ewmh.generic_activate_filters`. --- @table[opt={}] contextual_activate_filters --- @see ewmh.activate --- @see ewmh.add_activate_filter --- @see ewmh.remove_activate_filter - ---- Update a client's settings when its geometry changes, skipping signals --- resulting from calls within. -local geometry_change_lock = false -local function geometry_change(window) - if geometry_change_lock then return end - geometry_change_lock = true - - -- Fix up the geometry in case this window needs to cover the whole screen. - local bw = window.border_width or 0 - local g = window.screen.workarea - if window.maximized_vertical then - window:geometry { height = g.height - 2*bw, y = g.y } - end - if window.maximized_horizontal then - window:geometry { width = g.width - 2*bw, x = g.x } - end - if window.fullscreen then - window.border_width = 0 - window:geometry(window.screen.geometry) - end - - geometry_change_lock = false -end - ---- Activate a window. --- --- This sets the focus only if the client is visible. --- --- It is the default signal handler for `request::activate` on a `client`. --- --- @signalhandler awful.ewmh.activate --- @client c A client to use --- @tparam string context The context where this signal was used. --- @tparam[opt] table hints A table with additional hints: --- @tparam[opt=false] boolean hints.raise should the client be raised? -function ewmh.activate(c, context, hints) -- luacheck: no unused args - hints = hints or {} - - if c.focusable == false and not hints.force then return end - - local found, ret = false - - -- Execute the filters until something handle the request - for _, tab in ipairs { - ewmh.contextual_activate_filters[context] or {}, - ewmh.generic_activate_filters - } do - for i=#tab, 1, -1 do - ret = tab[i](c, context, hints) - if ret ~= nil then found=true; break end - end - - if found then break end - end - - if ret ~= false and c:isvisible() then - client.focus = c - elseif ret == false and not hints.force then - return - end - - if hints and hints.raise then - c:raise() - if not awesome.startup and not c:isvisible() then - c.urgent = true - end - end -end - ---- Add an activate (focus stealing) filter function. --- --- The callback takes the following parameters: --- --- * **c** (*client*) The client requesting the activation --- * **context** (*string*) The activation context. --- * **hints** (*table*) Some additional hints (depending on the context) --- --- If the callback returns `true`, the client will be activated unless the `force` --- hint is set. If the callback returns `false`, the activation request is --- cancelled. If the callback returns `nil`, the previous callback will be --- executed. This will continue until either a callback handles the request or --- when it runs out of callbacks. In that case, the request will be granted if --- the client is visible. --- --- For example, to block Firefox from stealing the focus, use: --- --- awful.ewmh.add_activate_filter(function(c, "ewmh") --- if c.class == "Firefox" then return false end --- end) --- --- @tparam function f The callback --- @tparam[opt] string context The `request::activate` context --- @see generic_activate_filters --- @see contextual_activate_filters --- @see remove_activate_filter -function ewmh.add_activate_filter(f, context) - if not context then - table.insert(ewmh.generic_activate_filters, f) - else - ewmh.contextual_activate_filters[context] = - ewmh.contextual_activate_filters[context] or {} - - table.insert(ewmh.contextual_activate_filters[context], f) - end -end - ---- Remove an activate (focus stealing) filter function. --- This is an helper to avoid dealing with `ewmh.add_activate_filter` directly. --- @tparam function f The callback --- @tparam[opt] string context The `request::activate` context --- @treturn boolean If the callback existed --- @see generic_activate_filters --- @see contextual_activate_filters --- @see add_activate_filter -function ewmh.remove_activate_filter(f, context) - local tab = context and (ewmh.contextual_activate_filters[context] or {}) - or ewmh.generic_activate_filters - - for k, v in ipairs(tab) do - if v == f then - table.remove(tab, k) - - -- In case the callback is there multiple time. - ewmh.remove_activate_filter(f, context) - - return true - end - end - - return false -end - --- Get tags that are on the same screen as the client. This should _almost_ --- always return the same content as c:tags(). -local function get_valid_tags(c, s) - local tags, new_tags = c:tags(), {} - - for _, t in ipairs(tags) do - if s == t.screen then - table.insert(new_tags, t) - end - end - - return new_tags -end - ---- Tag a window with its requested tag. --- --- It is the default signal handler for `request::tag` on a `client`. --- --- @signalhandler awful.ewmh.tag --- @client c A client to tag --- @tparam[opt] tag|boolean t A tag to use. If true, then the client is made sticky. --- @tparam[opt={}] table hints Extra information -function ewmh.tag(c, t, hints) --luacheck: no unused - -- There is nothing to do - if not t and #get_valid_tags(c, c.screen) > 0 then return end - - if not t then - if c.transient_for then - c.screen = c.transient_for.screen - if not c.sticky then - c:tags(c.transient_for:tags()) - end - else - c:to_selected_tags() - end - elseif type(t) == "boolean" and t then - c.sticky = true - else - c.screen = t.screen - c:tags({ t }) - end -end - ---- Handle client urgent request --- @signalhandler awful.ewmh.urgent --- @client c A client --- @tparam boolean urgent If the client should be urgent -function ewmh.urgent(c, urgent) - if c ~= client.focus and not aclient.property.get(c,"ignore_urgent") then - c.urgent = urgent - end -end - --- Map the state to the action name -local context_mapper = { - maximized_vertical = "maximize_vertically", - maximized_horizontal = "maximize_horizontally", - fullscreen = "maximize" -} - ---- Move and resize the client. --- --- This is the default geometry request handler. --- --- @signalhandler awful.ewmh.geometry --- @tparam client c The client --- @tparam string context The context --- @tparam[opt={}] table hints The hints to pass to the handler -function ewmh.geometry(c, context, hints) - local layout = c.screen.selected_tag and c.screen.selected_tag.layout or nil - - -- Setting the geometry wont work unless the client is floating. - if (not c.floating) and (not layout == asuit.floating) then - return - end - - context = context or "" - - local original_context = context - - -- Now, map it to something useful - context = context_mapper[context] or context - - local props = util.table.clone(hints or {}, false) - props.store_geometry = props.store_geometry==nil and true or props.store_geometry - - -- If it is a known placement function, then apply it, otherwise let - -- other potential handler resize the client (like in-layout resize or - -- floating client resize) - if aplace[context] then - - -- Check if it correspond to a boolean property - local state = c[original_context] - - -- If the property is boolean and it correspond to the undo operation, - -- restore the stored geometry. - if state == false then - aplace.restore(c,{context=context}) - return - end - - local honor_default = original_context ~= "fullscreen" - - if props.honor_workarea == nil then - props.honor_workarea = honor_default - end - - aplace[context](c, props) - 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("property::border_width", geometry_change) -client.connect_signal("property::geometry", geometry_change) -screen.connect_signal("property::workarea", function(s) - for _, c in pairs(client.get(s)) do - geometry_change(c) - end -end) - -return ewmh - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/hotkeys_popup/init.lua b/awesome/lib/awful/hotkeys_popup/init.lua deleted file mode 100644 index cb8c8be..0000000 --- a/awesome/lib/awful/hotkeys_popup/init.lua +++ /dev/null @@ -1,17 +0,0 @@ ---------------------------------------------------------------------------- ---- Popup widget which shows current hotkeys and their descriptions. --- --- @author Yauheni Kirylau <yawghen@gmail.com> --- @copyright 2014-2015 Yauheni Kirylau --- @module awful.hotkeys_popup ---------------------------------------------------------------------------- - - -local hotkeys_popup = { - widget = require("awful.hotkeys_popup.widget"), - keys = require("awful.hotkeys_popup.keys") -} -hotkeys_popup.show_help = hotkeys_popup.widget.show_help -return hotkeys_popup - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/hotkeys_popup/keys/init.lua b/awesome/lib/awful/hotkeys_popup/keys/init.lua deleted file mode 100644 index cbcbb62..0000000 --- a/awesome/lib/awful/hotkeys_popup/keys/init.lua +++ /dev/null @@ -1,15 +0,0 @@ ---------------------------------------------------------------------------- ---- Additional hotkeys for awful.hotkeys_widget --- --- @author Yauheni Kirylau <yawghen@gmail.com> --- @copyright 2014-2015 Yauheni Kirylau --- @module awful.hotkeys_popup.keys ---------------------------------------------------------------------------- - - -local keys = { - vim = require("awful.hotkeys_popup.keys.vim") -} -return keys - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/hotkeys_popup/keys/vim.lua b/awesome/lib/awful/hotkeys_popup/keys/vim.lua deleted file mode 100644 index 69d21e9..0000000 --- a/awesome/lib/awful/hotkeys_popup/keys/vim.lua +++ /dev/null @@ -1,173 +0,0 @@ ---------------------------------------------------------------------------- ---- VIM hotkeys for awful.hotkeys_widget --- --- @author Yauheni Kirylau <yawghen@gmail.com> --- @copyright 2014-2015 Yauheni Kirylau --- @module awful.hotkeys_popup.keys.vim ---------------------------------------------------------------------------- - -local hotkeys_popup = require("awful.hotkeys_popup.widget") - -local vim_rule_any = {name={"vim", "VIM"}} -for group_name, group_data in pairs({ - ["VIM: motion"] = { color="#009F00", rule_any=vim_rule_any }, - ["VIM: command"] = { color="#aFaF00", rule_any=vim_rule_any }, - ["VIM: command (insert)"] = { color="#cF4F40", rule_any=vim_rule_any }, - ["VIM: operator"] = { color="#aF6F00", rule_any=vim_rule_any }, - ["VIM: find"] = { color="#65cF9F", rule_any=vim_rule_any }, - ["VIM: scroll"] = { color="#659FdF", rule_any=vim_rule_any }, -}) do - hotkeys_popup.group_rules[group_name] = group_data -end - - -local vim_keys = { - - ["VIM: motion"] = {{ - modifiers = {}, - keys = { - ['`']="goto mark", - ['0']='"hard" BOL', - ['-']="prev line", - w="next word", - e="end word", - ['[']=". misc", - [']']=". misc", - ["'"]=". goto mk. BOL", - b="prev word", - ["|"]='BOL/goto col', - ["$"]='EOL', - ["%"]='goto matching bracket', - ["^"]='"soft" BOL', - ["("]='sentence begin', - [")"]='sentence end', - ["_"]='"soft" BOL down', - ["+"]='next line', - W='next WORD', - E='end WORD', - ['{']="paragraph begin", - ['}']="paragraph end", - G='EOF/goto line', - H='move cursor to screen top', - M='move cursor to screen middle', - L='move cursor to screen bottom', - B='prev WORD', - } - }, { - modifiers = {"Ctrl"}, - keys = { - u="half page up", - d="half page down", - b="page up", - f="page down", - o="prev mark", - } - }}, - - ["VIM: operator"] = {{ - modifiers = {}, - keys = { - ['=']="auto format", - y="yank", - d="delete", - c="change", - ["!"]='external filter', - ['<']='unindent', - ['>']='indent', - } - }}, - - ["VIM: command"] = {{ - modifiers = {}, - keys = { - ['~']="toggle case", - q=". record macro", - r=". replace char", - u="undo", - p="paste after", - gg="go to the top of file", - gf="open file under cursor", - x="delete char", - v="visual mode", - m=". set mark", - ['.']="repeat command", - ["@"]='. play macro', - ["&"]='repeat :s', - Q='ex mode', - Y='yank line', - U='undo line', - P='paste before cursor', - D='delete to EOL', - J='join lines', - K='help', - [':']='ex cmd line', - ['"']='. register spec', - ZZ='quit and save', - ZQ='quit discarding changes', - X='back-delete', - V='visual lines selection', - } - }, { - modifiers = {"Ctrl"}, - keys = { - w=". window operations", - r="redo", - ["["]="normal mode", - a="increase number", - x="decrease number", - g="file/cursor info", - z="suspend", - c="cancel/normal mode", - v="visual block selection", - } - }}, - - ["VIM: command (insert)"] = {{ - modifiers = {}, - keys = { - i="insert mode", - o="open below", - a="append", - s="subst char", - R='replace mode', - I='insert at BOL', - O='open above', - A='append at EOL', - S='subst line', - C='change to EOL', - } - }}, - - ["VIM: find"] = {{ - modifiers = {}, - keys = { - [';']="repeat t/T/f/F", - [',']="reverse t/T/f/F", - ['/']=". find", - ['?']='. reverse find', - n="next search match", - N='prev search match', - f=". find char", - F='. reverse find char', - t=". 'till char", - T=". reverse 'till char", - ["*"]='find word under cursor', - ["#"]='reverse find under cursor', - } - }}, - - ["VIM: scroll"] = {{ - modifiers = {}, - keys = { - e="scroll line up", - y="scroll line down", - zt="scroll cursor to the top", - zz="scroll cursor to the center", - zb="scroll cursor to the bottom", - } - }}, -} - -hotkeys_popup.add_hotkeys(vim_keys) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/hotkeys_popup/widget.lua b/awesome/lib/awful/hotkeys_popup/widget.lua deleted file mode 100644 index 62a2231..0000000 --- a/awesome/lib/awful/hotkeys_popup/widget.lua +++ /dev/null @@ -1,482 +0,0 @@ ---------------------------------------------------------------------------- ---- Popup widget which shows current hotkeys and their descriptions. --- --- @author Yauheni Kirylau <yawghen@gmail.com> --- @copyright 2014-2015 Yauheni Kirylau --- @module awful.hotkeys_popup.widget ---------------------------------------------------------------------------- - -local capi = { - screen = screen, - client = client, - keygrabber = keygrabber, -} -local awful = require("awful") -local wibox = require("wibox") -local beautiful = require("beautiful") -local dpi = beautiful.xresources.apply_dpi -local compute_textbox_width = require("menubar").utils.compute_textbox_width - - --- Stripped copy of this module https://github.com/copycat-killer/lain/blob/master/util/markup.lua: -local markup = {} --- Set the font. -function markup.font(font, text) - return '<span font="' .. tostring(font) .. '">' .. tostring(text) ..'</span>' -end --- Set the foreground. -function markup.fg(color, text) - return '<span foreground="' .. tostring(color) .. '">' .. tostring(text) .. '</span>' -end --- Set the background. -function markup.bg(color, text) - return '<span background="' .. tostring(color) .. '">' .. tostring(text) .. '</span>' -end - -local widget_module = { - group_rules = {}, -} - ---- Don't show hotkeys without descriptions. -widget_module.hide_without_description = true - ---- Merge hotkey records into one if they have the same modifiers and --- description. -widget_module.merge_duplicates = true - - -function widget_module.new() -local widget = { - hide_without_description = widget_module.hide_without_description, - merge_duplicates = widget_module.merge_duplicates, - group_rules = awful.util.table.clone(widget_module.group_rules), - title_font = "Monospace Bold 9", - description_font = "Monospace 8", - width = dpi(1200), - height = dpi(800), - border_width = beautiful.border_width or dpi(2), - modifiers_color = beautiful.bg_minimize or "#555555", - group_margin = dpi(6), - additional_hotkeys = {}, - labels = { - Mod4="Super", - Mod1="Alt", - Escape="Esc", - Insert="Ins", - Delete="Del", - Backspace="BackSpc", - Return="Enter", - Next="PgDn", - Prior="PgUp", - ['#108']="Alt Gr", - Left='←', - Up='↑', - Right='→', - Down='↓', - ['#67']="F1", - ['#68']="F2", - ['#69']="F3", - ['#70']="F4", - ['#71']="F5", - ['#72']="F6", - ['#73']="F7", - ['#74']="F8", - ['#75']="F9", - ['#76']="F10", - ['#95']="F11", - ['#96']="F12", - ['#10']="1", - ['#11']="2", - ['#12']="3", - ['#13']="4", - ['#14']="5", - ['#15']="6", - ['#16']="7", - ['#17']="8", - ['#18']="9", - ['#19']="0", - ['#20']="-", - ['#21']="=", - Control="Ctrl" - }, -} - -local cached_wiboxes = {} -local cached_awful_keys = nil -local colors_counter = {} -local colors = beautiful.xresources.get_current_theme() -local group_list = {} - - -local function get_next_color(id) - id = id or "default" - if colors_counter[id] then - colors_counter[id] = math.fmod(colors_counter[id] + 1, 15) + 1 - else - colors_counter[id] = 1 - end - return colors["color"..tostring(colors_counter[id], 15)] -end - - -local function join_plus_sort(modifiers) - if #modifiers<1 then return "none" end - table.sort(modifiers) - return table.concat(modifiers, '+') -end - - -local function add_hotkey(key, data, target) - if widget.hide_without_description and not data.description then return end - - local readable_mods = {} - for _, mod in ipairs(data.mod) do - table.insert(readable_mods, widget.labels[mod] or mod) - end - local joined_mods = join_plus_sort(readable_mods) - - local group = data.group or "none" - group_list[group] = true - if not target[group] then target[group] = {} end - local new_key = { - key = (widget.labels[key] or key), - mod = joined_mods, - description = data.description - } - local index = data.description or "none" -- or use its hash? - if not target[group][index] then - target[group][index] = new_key - else - if widget.merge_duplicates and joined_mods == target[group][index].mod then - target[group][index].key = target[group][index].key .. "/" .. new_key.key - else - while target[group][index] do - index = index .. " " - end - target[group][index] = new_key - end - end -end - - -local function sort_hotkeys(target) - -- @TODO: add sort by 12345qwertyasdf etc - for group, _ in pairs(group_list) do - if target[group] then - local sorted_table = {} - for _, key in pairs(target[group]) do - table.insert(sorted_table, key) - end - table.sort( - sorted_table, - function(a,b) return (a.mod or '')..a.key<(b.mod or '')..b.key end - ) - target[group] = sorted_table - end - end -end - - -local function import_awful_keys() - if cached_awful_keys then - return - end - cached_awful_keys = {} - for _, data in pairs(awful.key.hotkeys) do - add_hotkey(data.key, data, cached_awful_keys) - end - sort_hotkeys(cached_awful_keys) -end - - -local function group_label(group, color) - local textbox = wibox.widget.textbox( - markup.font(widget.title_font, - markup.bg( - color or (widget.group_rules[group] and - widget.group_rules[group].color or get_next_color("group_title") - ), - markup.fg(beautiful.bg_normal or "#000000", " "..group.." ") - ) - ) - ) - local margin = wibox.container.margin() - margin:set_widget(textbox) - margin:set_top(widget.group_margin) - return margin -end - -local function get_screen(s) - return s and capi.screen[s] -end - -local function create_wibox(s, available_groups) - s = get_screen(s) - - local wa = s.workarea - local height = (widget.height < wa.height) and widget.height or - (wa.height - widget.border_width * 2) - local width = (widget.width < wa.width) and widget.width or - (wa.width - widget.border_width * 2) - - -- arrange hotkey groups into columns - local line_height = beautiful.get_font_height(widget.title_font) - local group_label_height = line_height + widget.group_margin - -- -1 for possible pagination: - local max_height_px = height - group_label_height - local column_layouts = {} - for _, group in ipairs(available_groups) do - local keys = cached_awful_keys[group] or widget.additional_hotkeys[group] - local joined_descriptions = "" - for i, key in ipairs(keys) do - joined_descriptions = joined_descriptions .. key.description .. (i~=#keys and "\n" or "") - end - -- +1 for group label: - local items_height = awful.util.linecount(joined_descriptions) * line_height + group_label_height - local current_column - local available_height_px = max_height_px - local add_new_column = true - for i, column in ipairs(column_layouts) do - if ((column.height_px + items_height) < max_height_px) or - (i == #column_layouts and column.height_px < max_height_px / 2) - then - current_column = column - add_new_column = false - available_height_px = max_height_px - current_column.height_px - break - end - end - local overlap_leftovers - if items_height > available_height_px then - local new_keys = {} - overlap_leftovers = {} - -- +1 for group title and +1 for possible hyphen (v): - local available_height_items = (available_height_px - group_label_height*2) / line_height - for i=1,#keys do - table.insert(((i<available_height_items) and new_keys or overlap_leftovers), keys[i]) - end - keys = new_keys - table.insert(keys, {key=markup.fg(widget.modifiers_color, "▽"), description=""}) - end - if not current_column then - current_column = {layout=wibox.layout.fixed.vertical()} - end - current_column.layout:add(group_label(group)) - - local function insert_keys(_keys, _add_new_column) - local max_label_width = 0 - local max_label_content = "" - local joined_labels = "" - for i, key in ipairs(_keys) do - local length = string.len(key.key or '') + string.len(key.description or '') - local modifiers = key.mod - if not modifiers or modifiers == "none" then - modifiers = "" - else - length = length + string.len(modifiers) + 1 -- +1 for "+" character - modifiers = markup.fg(widget.modifiers_color, modifiers.."+") - end - local rendered_hotkey = markup.font(widget.title_font, - modifiers .. (key.key or "") .. " " - ) .. markup.font(widget.description_font, - key.description or "" - ) - if length > max_label_width then - max_label_width = length - max_label_content = rendered_hotkey - end - joined_labels = joined_labels .. rendered_hotkey .. (i~=#_keys and "\n" or "") - end - current_column.layout:add(wibox.widget.textbox(joined_labels)) - local max_width = compute_textbox_width(wibox.widget.textbox(max_label_content), s) + - widget.group_margin - if not current_column.max_width or max_width > current_column.max_width then - current_column.max_width = max_width - end - -- +1 for group label: - current_column.height_px = (current_column.height_px or 0) + - awful.util.linecount(joined_labels)*line_height + group_label_height - if _add_new_column then - table.insert(column_layouts, current_column) - end - end - - insert_keys(keys, add_new_column) - if overlap_leftovers then - current_column = {layout=wibox.layout.fixed.vertical()} - insert_keys(overlap_leftovers, true) - end - end - - -- arrange columns into pages - local available_width_px = width - local pages = {} - local columns = wibox.layout.fixed.horizontal() - for _, item in ipairs(column_layouts) do - if item.max_width > available_width_px then - columns.widgets[#columns.widgets]['widget']:add( - group_label("PgDn - Next Page", beautiful.fg_normal) - ) - table.insert(pages, columns) - columns = wibox.layout.fixed.horizontal() - available_width_px = width - item.max_width - local old_widgets = item.layout.widgets - item.layout.widgets = {group_label("PgUp - Prev Page", beautiful.fg_normal)} - awful.util.table.merge(item.layout.widgets, old_widgets) - else - available_width_px = available_width_px - item.max_width - end - local column_margin = wibox.container.margin() - column_margin:set_widget(item.layout) - column_margin:set_left(widget.group_margin) - columns:add(column_margin) - end - table.insert(pages, columns) - - local mywibox = wibox({ - ontop = true, - opacity = beautiful.notification_opacity or 1, - border_width = widget.border_width, - border_color = beautiful.fg_normal, - }) - mywibox:geometry({ - x = wa.x + math.floor((wa.width - width - widget.border_width*2) / 2), - y = wa.y + math.floor((wa.height - height - widget.border_width*2) / 2), - width = width, - height = height, - }) - mywibox:set_widget(pages[1]) - mywibox:buttons(awful.util.table.join( - awful.button({ }, 1, function () mywibox.visible=false end), - awful.button({ }, 3, function () mywibox.visible=false end) - )) - - local widget_obj = {} - widget_obj.current_page = 1 - widget_obj.wibox = mywibox - function widget_obj:page_next() - if self.current_page == #pages then return end - self.current_page = self.current_page + 1 - self.wibox:set_widget(pages[self.current_page]) - end - function widget_obj:page_prev() - if self.current_page == 1 then return end - self.current_page = self.current_page - 1 - self.wibox:set_widget(pages[self.current_page]) - end - function widget_obj:show() - self.wibox.visible = true - end - function widget_obj:hide() - self.wibox.visible = false - end - - return widget_obj -end - - ---- Show popup with hotkeys help. --- @tparam[opt] client c Client. --- @tparam[opt] screen s Screen. -function widget.show_help(c, s) - import_awful_keys() - c = c or capi.client.focus - s = s or (c and c.screen or awful.screen.focused()) - - local available_groups = {} - for group, _ in pairs(group_list) do - local need_match - for group_name, data in pairs(widget.group_rules) do - if group_name==group and ( - data.rule or data.rule_any or data.except or data.except_any - ) then - if not c or not awful.rules.matches(c, { - rule=data.rule, - rule_any=data.rule_any, - except=data.except, - except_any=data.except_any - }) then - need_match = true - break - end - end - end - if not need_match then table.insert(available_groups, group) end - end - - local joined_groups = join_plus_sort(available_groups) - if not cached_wiboxes[s] then - cached_wiboxes[s] = {} - end - if not cached_wiboxes[s][joined_groups] then - cached_wiboxes[s][joined_groups] = create_wibox(s, available_groups) - end - local help_wibox = cached_wiboxes[s][joined_groups] - help_wibox:show() - - return capi.keygrabber.run(function(_, key, event) - if event == "release" then return end - if key then - if key == "Next" then - help_wibox:page_next() - elseif key == "Prior" then - help_wibox:page_prev() - else - capi.keygrabber.stop() - help_wibox:hide() - end - end - end) -end - - ---- Add hotkey descriptions for third-party applications. --- @tparam table hotkeys Table with bindings, --- see `awful.hotkeys_popup.key.vim` as an example. -function widget.add_hotkeys(hotkeys) - for group, bindings in pairs(hotkeys) do - for _, binding in ipairs(bindings) do - local modifiers = binding.modifiers - local keys = binding.keys - for key, description in pairs(keys) do - add_hotkey(key, { - mod=modifiers, - description=description, - group=group}, - widget.additional_hotkeys - ) - end - end - end - sort_hotkeys(widget.additional_hotkeys) -end - - -return widget -end - -local function get_default_widget() - if not widget_module.default_widget then - widget_module.default_widget = widget_module.new() - end - return widget_module.default_widget -end - ---- Show popup with hotkeys help (default widget instance will be used). --- @tparam[opt] client c Client. --- @tparam[opt] screen s Screen. -function widget_module.show_help(...) - return get_default_widget().show_help(...) -end - ---- Add hotkey descriptions for third-party applications --- (default widget instance will be used). --- @tparam table hotkeys Table with bindings, --- see `awful.hotkeys_popup.key.vim` as an example. -function widget_module.add_hotkeys(...) - return get_default_widget().add_hotkeys(...) -end - -return widget_module - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/init.lua b/awesome/lib/awful/init.lua deleted file mode 100644 index 840897e..0000000 --- a/awesome/lib/awful/init.lua +++ /dev/null @@ -1,64 +0,0 @@ ---------------------------------------------------------------------------- ---- AWesome Functions very UsefuL --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful ---------------------------------------------------------------------------- - --- TODO: This is a hack for backwards-compatibility with 3.5, remove! -local util = require("awful.util") -local gtimer = require("gears.timer") -function timer(...) -- luacheck: ignore - util.deprecate("gears.timer") - return gtimer(...) -end - ---TODO: This is a hack for backwards-compatibility with 3.5, remove! --- Set awful.util.spawn* and awful.util.pread. -local spawn = require("awful.spawn") - -util.spawn = function(...) - util.deprecate("awful.spawn") - return spawn.spawn(...) -end - -util.spawn_with_shell = function(...) - util.deprecate("awful.spawn.with_shell") - return spawn.with_shell(...) -end - -util.pread = function() - util.deprecate("Use io.popen() directly or look at awful.spawn.easy_async() " - .. "for an asynchronous alternative") - return "" -end - -return -{ - client = require("awful.client"); - completion = require("awful.completion"); - layout = require("awful.layout"); - placement = require("awful.placement"); - prompt = require("awful.prompt"); - screen = require("awful.screen"); - tag = require("awful.tag"); - util = require("awful.util"); - widget = require("awful.widget"); - keygrabber = require("awful.keygrabber"); - menu = require("awful.menu"); - mouse = require("awful.mouse"); - remote = require("awful.remote"); - key = require("awful.key"); - button = require("awful.button"); - wibar = require("awful.wibar"); - wibox = require("awful.wibox"); - startup_notification = require("awful.startup_notification"); - tooltip = require("awful.tooltip"); - ewmh = require("awful.ewmh"); - titlebar = require("awful.titlebar"); - rules = require("awful.rules"); - spawn = spawn; -} - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/key.lua b/awesome/lib/awful/key.lua deleted file mode 100644 index c3ce359..0000000 --- a/awesome/lib/awful/key.lua +++ /dev/null @@ -1,136 +0,0 @@ ---------------------------------------------------------------------------- ---- Create easily new key objects ignoring certain modifiers. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.key ---------------------------------------------------------------------------- - --- Grab environment we need -local setmetatable = setmetatable -local ipairs = ipairs -local capi = { key = key, root = root } -local util = require("awful.util") - - - -local key = { mt = {}, hotkeys = {} } - - ---- Modifiers to ignore. --- By default this is initialized as { "Lock", "Mod2" } --- so the Caps Lock or Num Lock modifier are not taking into account by awesome --- when pressing keys. --- @name awful.key.ignore_modifiers --- @class table -key.ignore_modifiers = { "Lock", "Mod2" } - ---- Convert the modifiers into pc105 key names -local conversion = { - mod4 = "Super_L", - control = "Control_L", - shift = "Shift_L", - mod1 = "Alt_L", -} - ---- Execute a key combination. --- If an awesome keybinding is assigned to the combination, it should be --- executed. --- @see root.fake_input --- @tparam table mod A modified table. Valid modifiers are: Any, Mod1, --- Mod2, Mod3, Mod4, Mod5, Shift, Lock and Control. --- @tparam string k The key -function key.execute(mod, k) - for _, v in ipairs(mod) do - local m = conversion[v:lower()] - if m then - root.fake_input("key_press", m) - end - end - - root.fake_input("key_press" , k) - root.fake_input("key_release", k) - - for _, v in ipairs(mod) do - local m = conversion[v:lower()] - if m then - root.fake_input("key_release", m) - end - end -end - ---- Create a new key to use as binding. --- This function is useful to create several keys from one, because it will use --- the ignore_modifier variable to create several keys with and without the --- ignored modifiers activated. --- For example if you want to ignore CapsLock in your keybinding (which is --- ignored by default by this function), creating a key binding with this --- function will return 2 key objects: one with CapsLock on, and another one --- with CapsLock off. --- @see key.key --- @tparam table mod A list of modifier keys. Valid modifiers are: Any, Mod1, --- Mod2, Mod3, Mod4, Mod5, Shift, Lock and Control. --- @tparam string _key The key to trigger an event. --- @tparam function press Callback for when the key is pressed. --- @tparam[opt] function release Callback for when the key is released. --- @tparam table data User data for key, --- for example {description="select next tag", group="tag"}. --- @treturn table A table with one or several key objects. -function key.new(mod, _key, press, release, data) - if type(release)=='table' then - data=release - release=nil - end - local ret = {} - local subsets = util.subsets(key.ignore_modifiers) - for _, set in ipairs(subsets) do - ret[#ret + 1] = capi.key({ modifiers = util.table.join(mod, set), - key = _key }) - if press then - ret[#ret]:connect_signal("press", function(_, ...) press(...) end) - end - if release then - ret[#ret]:connect_signal("release", function(_, ...) release(...) end) - end - end - - -- append custom userdata (like description) to a hotkey - data = data or {} - data.mod = mod - data.key = _key - table.insert(key.hotkeys, data) - data.execute = function(_) key.execute(mod, _key) end - - return ret -end - ---- Compare a key object with modifiers and key. --- @param _key The key object. --- @param pressed_mod The modifiers to compare with. --- @param pressed_key The key to compare with. -function key.match(_key, pressed_mod, pressed_key) - -- First, compare key. - if pressed_key ~= _key.key then return false end - -- Then, compare mod - local mod = _key.modifiers - -- For each modifier of the key object, check that the modifier has been - -- pressed. - for _, m in ipairs(mod) do - -- Has it been pressed? - if not util.table.hasitem(pressed_mod, m) then - -- No, so this is failure! - return false - end - end - -- If the number of pressed modifier is ~=, it is probably >, so this is not - -- the same, return false. - return #pressed_mod == #mod -end - -function key.mt:__call(...) - return key.new(...) -end - -return setmetatable(key, key.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/keygrabber.lua b/awesome/lib/awful/keygrabber.lua deleted file mode 100644 index 4351f5b..0000000 --- a/awesome/lib/awful/keygrabber.lua +++ /dev/null @@ -1,96 +0,0 @@ ---------------------------------------------------------------------------- ---- Keygrabber Stack --- --- @author dodo --- @copyright 2012 dodo --- @module awful.keygrabber ---------------------------------------------------------------------------- - -local ipairs = ipairs -local table = table -local capi = { - keygrabber = keygrabber } - -local keygrabber = {} - --- Private data -local grabbers = {} -local keygrabbing = false - - -local function grabber(mod, key, event) - for _, keygrabber_function in ipairs(grabbers) do - -- continue if the grabber explicitly returns false - if keygrabber_function(mod, key, event) ~= false then - break - end - end -end - ---- Stop grabbing the keyboard for the provided callback. --- When no callback is given, the last grabber gets removed (last one added to --- the stack). --- @param g The key grabber that must be removed. -function keygrabber.stop(g) - for i, v in ipairs(grabbers) do - if v == g then - table.remove(grabbers, i) - break - end - end - -- Stop the global key grabber if the last grabber disappears from stack. - if #grabbers == 0 then - keygrabbing = false - capi.keygrabber.stop() - end -end - ---- --- Grab keyboard input and read pressed keys, calling the least callback --- function from the stack at each keypress, until the stack is empty. --- --- Calling run with the same callback again will bring the callback --- to the top of the stack. --- --- The callback function receives three arguments: --- --- * a table containing modifiers keys --- * a string with the pressed key --- * a string with either "press" or "release" to indicate the event type --- --- A callback can return `false` to pass the events to the next --- keygrabber in the stack. --- @param g The key grabber callback that will get the key events until it will be deleted or a new grabber is added. --- @return the given callback `g`. --- @usage --- -- The following function can be bound to a key, and be used to resize a --- -- client using the keyboard. --- --- function resize(c) --- local grabber = awful.keygrabber.run(function(mod, key, event) --- if event == "release" then return end --- --- if key == 'Up' then awful.client.moveresize(0, 0, 0, 5, c) --- elseif key == 'Down' then awful.client.moveresize(0, 0, 0, -5, c) --- elseif key == 'Right' then awful.client.moveresize(0, 0, 5, 0, c) --- elseif key == 'Left' then awful.client.moveresize(0, 0, -5, 0, c) --- else awful.keygrabber.stop(grabber) --- end --- end) --- end -function keygrabber.run(g) - -- Remove the grabber if it is in the stack. - keygrabber.stop(g) - -- Record the grabber that has been added most recently. - table.insert(grabbers, 1, g) - -- Start the keygrabber if it is not running already. - if not keygrabbing then - keygrabbing = true - capi.keygrabber.run(grabber) - end - return g -end - -return keygrabber - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/init.lua b/awesome/lib/awful/layout/init.lua deleted file mode 100644 index dfce562..0000000 --- a/awesome/lib/awful/layout/init.lua +++ /dev/null @@ -1,323 +0,0 @@ ---------------------------------------------------------------------------- ---- Layout module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local type = type -local util = require("awful.util") -local capi = { - screen = screen, - mouse = mouse, - awesome = awesome, - client = client, - tag = tag -} -local tag = require("awful.tag") -local client = require("awful.client") -local ascreen = require("awful.screen") -local timer = require("gears.timer") - -local function get_screen(s) - return s and capi.screen[s] -end - -local layout = {} - -layout.suit = require("awful.layout.suit") - -layout.layouts = { - layout.suit.floating, - layout.suit.tile, - layout.suit.tile.left, - layout.suit.tile.bottom, - layout.suit.tile.top, - layout.suit.fair, - layout.suit.fair.horizontal, - layout.suit.spiral, - layout.suit.spiral.dwindle, - layout.suit.max, - layout.suit.max.fullscreen, - layout.suit.magnifier, - layout.suit.corner.nw, - layout.suit.corner.ne, - layout.suit.corner.sw, - layout.suit.corner.se, -} - ---- The default list of layouts. --- --- The default value is: --- --- awful.layout.suit.floating, --- awful.layout.suit.tile, --- awful.layout.suit.tile.left, --- awful.layout.suit.tile.bottom, --- awful.layout.suit.tile.top, --- awful.layout.suit.fair, --- awful.layout.suit.fair.horizontal, --- awful.layout.suit.spiral, --- awful.layout.suit.spiral.dwindle, --- awful.layout.suit.max, --- awful.layout.suit.max.fullscreen, --- awful.layout.suit.magnifier, --- awful.layout.suit.corner.nw, --- awful.layout.suit.corner.ne, --- awful.layout.suit.corner.sw, --- awful.layout.suit.corner.se, --- --- @field layout.layouts - - --- This is a special lock used by the arrange function. --- This avoids recurring call by emitted signals. -local arrange_lock = false --- Delay one arrange call per screen. -local delayed_arrange = {} - ---- Get the current layout. --- @param screen The screen. --- @return The layout function. -function layout.get(screen) - screen = screen or capi.mouse.screen - local t = get_screen(screen).selected_tag - return tag.getproperty(t, "layout") or layout.suit.floating -end - ---- Change the layout of the current tag. --- @param i Relative index. --- @param s The screen. --- @param[opt] layouts A table of layouts. -function layout.inc(i, s, layouts) - if type(i) == "table" then - -- Older versions of this function had arguments (layouts, i, s), but - -- this was changed so that 'layouts' can be an optional parameter - layouts, i, s = i, s, layouts - end - s = get_screen(s or ascreen.focused()) - local t = s.selected_tag - layouts = layouts or layout.layouts - if t then - local curlayout = layout.get(s) - local curindex - for k, v in ipairs(layouts) do - if v == curlayout or curlayout._type == v then - curindex = k - break - end - end - if not curindex then - -- Safety net: handle cases where another reference of the layout - -- might be given (e.g. when (accidentally) cloning it). - for k, v in ipairs(layouts) do - if v.name == curlayout.name then - curindex = k - break - end - end - end - if curindex then - local newindex = util.cycle(#layouts, curindex + i) - layout.set(layouts[newindex], t) - end - end -end - ---- Set the layout function of the current tag. --- @param _layout Layout name. --- @tparam[opt=mouse.screen.selected_tag] tag t The tag to modify. -function layout.set(_layout, t) - t = t or capi.mouse.screen.selected_tag - t.layout = _layout -end - ---- Get the layout parameters used for the screen --- --- This should give the same result as "arrange", but without the "geometries" --- parameter, as this is computed during arranging. --- --- If `t` is given, `screen` is ignored, if none are given, the mouse screen is --- used. --- --- @tparam[opt] tag t The tag to query --- @param[opt] screen The screen --- @treturn table A table with the workarea (x, y, width, height), the screen --- geometry (x, y, width, height), the clients, the screen and sometime, a --- "geometries" table with client as keys and geometry as value -function layout.parameters(t, screen) - screen = get_screen(screen) - t = t or screen.selected_tag - - screen = get_screen(t and t.screen or 1) - - local p = {} - - local clients = client.tiled(screen) - local gap_single_client = true - - if(t and t.gap_single_client ~= nil) then - gap_single_client = t.gap_single_client - end - - local min_clients = gap_single_client and 1 or 2 - local useless_gap = t and (#clients >= min_clients and t.gap or 0) or 0 - - p.workarea = screen:get_bounding_geometry { - honor_padding = true, - honor_workarea = true, - margins = useless_gap, - } - - p.geometry = screen.geometry - p.clients = clients - p.screen = screen.index - p.padding = screen.padding - p.useless_gap = useless_gap - - return p -end - ---- Arrange a screen using its current layout. --- @param screen The screen to arrange. -function layout.arrange(screen) - screen = get_screen(screen) - if not screen or delayed_arrange[screen] then return end - delayed_arrange[screen] = true - - timer.delayed_call(function() - if not screen.valid then - -- Screen was removed - delayed_arrange[screen] = nil - return - end - if arrange_lock then return end - arrange_lock = true - - local p = layout.parameters(nil, screen) - - local useless_gap = p.useless_gap - - p.geometries = setmetatable({}, {__mode = "k"}) - layout.get(screen).arrange(p) - for c, g in pairs(p.geometries) do - g.width = math.max(1, g.width - c.border_width * 2 - useless_gap * 2) - g.height = math.max(1, g.height - c.border_width * 2 - useless_gap * 2) - g.x = g.x + useless_gap - g.y = g.y + useless_gap - c:geometry(g) - end - arrange_lock = false - delayed_arrange[screen] = nil - - screen:emit_signal("arrange") - end) -end - ---- Get the current layout name. --- @param _layout The layout. --- @return The layout name. -function layout.getname(_layout) - _layout = _layout or layout.get() - return _layout.name -end - -local function arrange_prop_nf(obj) - if not client.object.get_floating(obj) then - layout.arrange(obj.screen) - end -end - -local function arrange_prop(obj) layout.arrange(obj.screen) end - -capi.client.connect_signal("property::size_hints_honor", arrange_prop_nf) -capi.client.connect_signal("property::struts", arrange_prop) -capi.client.connect_signal("property::minimized", arrange_prop_nf) -capi.client.connect_signal("property::sticky", arrange_prop_nf) -capi.client.connect_signal("property::fullscreen", arrange_prop_nf) -capi.client.connect_signal("property::maximized_horizontal", arrange_prop_nf) -capi.client.connect_signal("property::maximized_vertical", arrange_prop_nf) -capi.client.connect_signal("property::border_width", arrange_prop_nf) -capi.client.connect_signal("property::hidden", arrange_prop_nf) -capi.client.connect_signal("property::floating", arrange_prop) -capi.client.connect_signal("property::geometry", arrange_prop_nf) -capi.client.connect_signal("property::screen", function(c, old_screen) - if old_screen then - layout.arrange(old_screen) - end - layout.arrange(c.screen) -end) - -local function arrange_tag(t) - layout.arrange(t.screen) -end - -capi.tag.connect_signal("property::master_width_factor", arrange_tag) -capi.tag.connect_signal("property::master_count", arrange_tag) -capi.tag.connect_signal("property::column_count", arrange_tag) -capi.tag.connect_signal("property::layout", arrange_tag) -capi.tag.connect_signal("property::windowfact", arrange_tag) -capi.tag.connect_signal("property::selected", arrange_tag) -capi.tag.connect_signal("property::activated", arrange_tag) -capi.tag.connect_signal("property::useless_gap", arrange_tag) -capi.tag.connect_signal("property::master_fill_policy", arrange_tag) -capi.tag.connect_signal("tagged", arrange_tag) - -capi.screen.connect_signal("property::workarea", layout.arrange) -capi.screen.connect_signal("padding", layout.arrange) - -capi.client.connect_signal("raised", function(c) layout.arrange(c.screen) end) -capi.client.connect_signal("lowered", function(c) layout.arrange(c.screen) end) -capi.client.connect_signal("list", function() - for screen in capi.screen do - layout.arrange(screen) - end - end) - ---- Default handler for `request::geometry` signals for tiled clients with --- the "mouse.move" context. --- @tparam client c The client --- @tparam string context The context --- @tparam table hints Additional hints -function layout.move_handler(c, context, hints) --luacheck: no unused args - -- Quit if it isn't a mouse.move on a tiled layout, that's handled elsewhere - if c.floating then return end - if context ~= "mouse.move" then return end - - if capi.mouse.screen ~= c.screen then - c.screen = capi.mouse.screen - end - - local l = c.screen.selected_tag and c.screen.selected_tag.layout or nil - if l == layout.suit.floating then return end - - local c_u_m = capi.mouse.current_client - if c_u_m and not c_u_m.floating then - if c_u_m ~= c then - c:swap(c_u_m) - end - end -end - -capi.client.connect_signal("request::geometry", layout.move_handler) - --- When a screen is moved, make (floating) clients follow it -capi.screen.connect_signal("property::geometry", function(s, old_geom) - local geom = s.geometry - local xshift = geom.x - old_geom.x - local yshift = geom.y - old_geom.y - for _, c in ipairs(capi.client.get(s)) do - local cgeom = c:geometry() - c:geometry({ - x = cgeom.x + xshift, - y = cgeom.y + yshift - }) - end -end) - -return layout - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/corner.lua b/awesome/lib/awful/layout/suit/corner.lua deleted file mode 100644 index 4b746c9..0000000 --- a/awesome/lib/awful/layout/suit/corner.lua +++ /dev/null @@ -1,204 +0,0 @@ ---------------------------------------------------------------------------- --- Corner layout. --- Display master client in a corner of the screen, and slaves in one --- column and one row around the master. --- See Pull Request for example : https://github.com/awesomeWM/awesome/pull/251 --- @module awful.layout --- @author Alexis Brenon <brenon.alexis+awesomewm@gmail.com> --- @copyright 2015 Alexis Brenon - --- Grab environment we need -local ipairs = ipairs -local math = math -local capi = {screen = screen} - ---- The cornernw layout layoutbox icon. --- @beautiful beautiful.layout_cornernw --- @param surface --- @see gears.surface - ---- The cornerne layout layoutbox icon. --- @beautiful beautiful.layout_cornerne --- @param surface --- @see gears.surface - ---- The cornersw layout layoutbox icon. --- @beautiful beautiful.layout_cornersw --- @param surface --- @see gears.surface - ---- The cornerse layout layoutbox icon. --- @beautiful beautiful.layout_cornerse --- @param surface --- @see gears.surface - --- Actually arrange clients of p.clients for corner layout --- @param p Mandatory table containing required informations for layouts --- (clients to arrange, workarea geometry, etc.) --- @param orientation String indicating in which corner is the master window. --- Available values are : NE, NW, SW, SE -local function do_corner(p, orientation) - local t = p.tag or capi.screen[p.screen].selected_tag - local wa = p.workarea - local cls = p.clients - - if #cls == 0 then return end - - local master = {} - local column = {} - local row = {} - -- Use the nmaster field of the tag in a cheaty way - local row_privileged = ((cls[1].screen.selected_tag.master_count % 2) == 0) - - local master_factor = cls[1].screen.selected_tag.master_width_factor - master.width = master_factor * wa.width - master.height = master_factor * wa.height - - local number_privileged_win = math.ceil((#cls - 1)/2) - local number_unprivileged_win = (#cls - 1) - number_privileged_win - - -- Define some obvious parameters - column.width = wa.width - master.width - column.x_increment = 0 - row.height = wa.height - master.height - row.y_increment = 0 - - -- Place master at the right place and move row and column accordingly - column.y = wa.y - row.x = wa.x - if orientation:match('N.') then - master.y = wa.y - row.y = master.y + master.height - elseif orientation:match('S.') then - master.y = wa.y + wa.height - master.height - row.y = wa.y - end - if orientation:match('.W') then - master.x = wa.x - column.x = master.x + master.width - elseif orientation:match('.E') then - master.x = wa.x + wa.width - master.width - column.x = wa.x - end - -- At this point, master is in a corner - -- but row and column are overlayed in the opposite corner... - - -- Reduce the unprivileged slaves to remove overlay - -- and define actual width and height - if row_privileged then - row.width = wa.width - row.number_win = number_privileged_win - column.y = master.y - column.height = master.height - column.number_win = number_unprivileged_win - else - column.height = wa.height - column.number_win = number_privileged_win - row.x = master.x - row.width = master.width - row.number_win = number_unprivileged_win - end - - column.win_height = column.height/column.number_win - column.win_width = column.width - column.y_increment = column.win_height - column.win_idx = 0 - - row.win_width = row.width/row.number_win - row.win_height = row.height - row.x_increment = row.win_width - row.win_idx = 0 - - -- Extend master if there is only a few windows and "expand" policy is set - if #cls < 3 then - if row_privileged then - master.x = wa.x - master.width = wa.width - else - master.y = wa.y - master.height = wa.height - end - if #cls < 2 then - if t.master_fill_policy == "expand" then - master = wa - else - master.x = master.x + (wa.width - master.width)/2 - master.y = master.y + (wa.height - master.height)/2 - end - end - end - - for i, c in ipairs(cls) do - local g - -- Handle master window - if i == 1 then - g = { - x = master.x, - y = master.y, - width = master.width, - height = master.height - } - -- handle column windows - elseif i % 2 == 0 then - g = { - x = column.x + column.win_idx * column.x_increment, - y = column.y + column.win_idx * column.y_increment, - width = column.win_width, - height = column.win_height - } - column.win_idx = column.win_idx + 1 - else - g = { - x = row.x + row.win_idx * row.x_increment, - y = row.y + row.win_idx * row.y_increment, - width = row.win_width, - height = row.win_height - } - row.win_idx = row.win_idx + 1 - end - p.geometries[c] = g - end -end - -local corner = {} -corner.row_privileged = false - ---- Corner layout. --- Display master client in a corner of the screen, and slaves in one --- column and one row around the master. --- @clientlayout awful.layout.suit.corner.nw -corner.nw = { - name = "cornernw", - arrange = function (p) return do_corner(p, "NW") end - } - ---- Corner layout. --- Display master client in a corner of the screen, and slaves in one --- column and one row around the master. --- @clientlayout awful.layout.suit.corner.ne -corner.ne = { - name = "cornerne", - arrange = function (p) return do_corner(p, "NE") end - } - ---- Corner layout. --- Display master client in a corner of the screen, and slaves in one --- column and one row around the master. --- @clientlayout awful.layout.suit.corner.sw -corner.sw = { - name = "cornersw", - arrange = function (p) return do_corner(p, "SW") end - } - ---- Corner layout. --- Display master client in a corner of the screen, and slaves in one --- column and one row around the master. --- @clientlayout awful.layout.suit.corner.se -corner.se = { - name = "cornerse", - arrange = function (p) return do_corner(p, "SE") end - } - -return corner - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/fair.lua b/awesome/lib/awful/layout/suit/fair.lua deleted file mode 100644 index 161b6ed..0000000 --- a/awesome/lib/awful/layout/suit/fair.lua +++ /dev/null @@ -1,108 +0,0 @@ ---------------------------------------------------------------------------- ---- Fair layouts module for awful. --- --- @author Josh Komoroske --- @copyright 2012 Josh Komoroske --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local math = math - ---- The fairh layout layoutbox icon. --- @beautiful beautiful.layout_fairh --- @param surface --- @see gears.surface - ---- The fairv layout layoutbox icon. --- @beautiful beautiful.layout_fairv --- @param surface --- @see gears.surface - -local fair = {} - -local function do_fair(p, orientation) - local wa = p.workarea - local cls = p.clients - - -- Swap workarea dimensions, if our orientation is "east" - if orientation == 'east' then - wa.width, wa.height = wa.height, wa.width - wa.x, wa.y = wa.y, wa.x - end - - if #cls > 0 then - local rows, cols - if #cls == 2 then - rows, cols = 1, 2 - else - rows = math.ceil(math.sqrt(#cls)) - cols = math.ceil(#cls / rows) - end - - for k, c in ipairs(cls) do - k = k - 1 - local g = {} - - local row, col - row = k % rows - col = math.floor(k / rows) - - local lrows, lcols - if k >= rows * cols - rows then - lrows = #cls - (rows * cols - rows) - lcols = cols - else - lrows = rows - lcols = cols - end - - if row == lrows - 1 then - g.height = wa.height - math.ceil(wa.height / lrows) * row - g.y = wa.height - g.height - else - g.height = math.ceil(wa.height / lrows) - g.y = g.height * row - end - - if col == lcols - 1 then - g.width = wa.width - math.ceil(wa.width / lcols) * col - g.x = wa.width - g.width - else - g.width = math.ceil(wa.width / lcols) - g.x = g.width * col - end - - g.y = g.y + wa.y - g.x = g.x + wa.x - - -- Swap window dimensions, if our orientation is "east" - if orientation == 'east' then - g.width, g.height = g.height, g.width - g.x, g.y = g.y, g.x - end - - p.geometries[c] = g - end - end -end - ---- Horizontal fair layout. --- @param screen The screen to arrange. -fair.horizontal = {} -fair.horizontal.name = "fairh" -function fair.horizontal.arrange(p) - return do_fair(p, "east") -end - ---- Vertical fair layout. --- @param screen The screen to arrange. -fair.name = "fairv" -function fair.arrange(p) - return do_fair(p, "south") -end - -return fair - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/floating.lua b/awesome/lib/awful/layout/suit/floating.lua deleted file mode 100644 index b769435..0000000 --- a/awesome/lib/awful/layout/suit/floating.lua +++ /dev/null @@ -1,112 +0,0 @@ ---------------------------------------------------------------------------- ---- Dummy function for floating layout --- --- @author Gregor Best --- @copyright 2008 Gregor Best --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local capi = -{ - mouse = mouse, - mousegrabber = mousegrabber -} - ---- The floating layout layoutbox icon. --- @beautiful beautiful.layout_floating --- @param surface --- @see gears.surface - -local floating = {} - ---- Jump mouse cursor to the client's corner when resizing it. -floating.resize_jump_to_corner = true - -function floating.mouse_resize_handler(c, corner, x, y) - local g = c:geometry() - - -- Do not allow maximized clients to be resized by mouse - local fixed_x = c.maximized_horizontal - local fixed_y = c.maximized_vertical - - local prev_coords = {} - local coordinates_delta = {x=0,y=0} - if floating.resize_jump_to_corner then - -- Warp mouse pointer - capi.mouse.coords({ x = x, y = y }) - else - local corner_x, corner_y = x, y - local mouse_coords = capi.mouse.coords() - x = mouse_coords.x - y = mouse_coords.y - coordinates_delta = {x=corner_x-x,y=corner_y-y} - end - - capi.mousegrabber.run(function (_mouse) - if not c.valid then return false end - - _mouse.x = _mouse.x + coordinates_delta.x - _mouse.y = _mouse.y + coordinates_delta.y - for _, v in ipairs(_mouse.buttons) do - if v then - local ng - prev_coords = { x =_mouse.x, y = _mouse.y } - if corner == "bottom_right" then - ng = { width = _mouse.x - g.x, - height = _mouse.y - g.y } - elseif corner == "bottom_left" then - ng = { x = _mouse.x, - width = (g.x + g.width) - _mouse.x, - height = _mouse.y - g.y } - elseif corner == "top_left" then - ng = { x = _mouse.x, - width = (g.x + g.width) - _mouse.x, - y = _mouse.y, - height = (g.y + g.height) - _mouse.y } - else - ng = { width = _mouse.x - g.x, - y = _mouse.y, - height = (g.y + g.height) - _mouse.y } - end - if ng.width <= 0 then ng.width = nil end - if ng.height <= 0 then ng.height = nil end - if fixed_x then ng.width = g.width ng.x = g.x end - if fixed_y then ng.height = g.height ng.y = g.y end - c:geometry(ng) - -- Get real geometry that has been applied - -- in case we honor size hints - -- XXX: This should be rewritten when size - -- hints are available from Lua. - local rg = c:geometry() - - if corner == "bottom_right" then - ng = {} - elseif corner == "bottom_left" then - ng = { x = (g.x + g.width) - rg.width } - elseif corner == "top_left" then - ng = { x = (g.x + g.width) - rg.width, - y = (g.y + g.height) - rg.height } - else - ng = { y = (g.y + g.height) - rg.height } - end - c:geometry({ x = ng.x, y = ng.y }) - return true - end - end - return prev_coords.x == _mouse.x and prev_coords.y == _mouse.y - end, corner .. "_corner") -end - -function floating.arrange() -end - ---- The floating layout. --- @clientlayout awful.layout.suit. - -floating.name = "floating" - -return floating - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/init.lua b/awesome/lib/awful/layout/suit/init.lua deleted file mode 100644 index 57a49fa..0000000 --- a/awesome/lib/awful/layout/suit/init.lua +++ /dev/null @@ -1,19 +0,0 @@ ---------------------------------------------------------------------------- ---- Suits for awful --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful.layout ---------------------------------------------------------------------------- - -return -{ - corner = require("awful.layout.suit.corner"); - max = require("awful.layout.suit.max"); - tile = require("awful.layout.suit.tile"); - fair = require("awful.layout.suit.fair"); - floating = require("awful.layout.suit.floating"); - magnifier = require("awful.layout.suit.magnifier"); - spiral = require("awful.layout.suit.spiral"); -} - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/magnifier.lua b/awesome/lib/awful/layout/suit/magnifier.lua deleted file mode 100644 index f30d7ee..0000000 --- a/awesome/lib/awful/layout/suit/magnifier.lua +++ /dev/null @@ -1,147 +0,0 @@ ---------------------------------------------------------------------------- ---- Magnifier layout module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local math = math -local capi = -{ - client = client, - screen = screen, - mouse = mouse, - mousegrabber = mousegrabber -} - ---- The magnifier layout layoutbox icon. --- @beautiful beautiful.layout_magnifier --- @param surface --- @see gears.surface - -local magnifier = {} - -function magnifier.mouse_resize_handler(c, corner, x, y) - capi.mouse.coords({ x = x, y = y }) - - local wa = c.screen.workarea - local center_x = wa.x + wa.width / 2 - local center_y = wa.y + wa.height / 2 - local maxdist_pow = (wa.width^2 + wa.height^2) / 4 - - local prev_coords = {} - capi.mousegrabber.run(function (_mouse) - if not c.valid then return false end - - for _, v in ipairs(_mouse.buttons) do - if v then - prev_coords = { x =_mouse.x, y = _mouse.y } - local dx = center_x - _mouse.x - local dy = center_y - _mouse.y - local dist = dx^2 + dy^2 - - -- New master width factor - local mwfact = dist / maxdist_pow - c.screen.selected_tag.master_width_factor - = math.min(math.max(0.01, mwfact), 0.99) - return true - end - end - return prev_coords.x == _mouse.x and prev_coords.y == _mouse.y - end, corner .. "_corner") -end - -function magnifier.arrange(p) - -- Fullscreen? - local area = p.workarea - local cls = p.clients - local focus = p.focus or capi.client.focus - local t = p.tag or capi.screen[p.screen].selected_tag - local mwfact = t.master_width_factor - local fidx - - -- Check that the focused window is on the right screen - if focus and focus.screen ~= p.screen then focus = nil end - - -- If no window is focused or focused window is not tiled, take the first tiled one. - if (not focus or focus.floating) and #cls > 0 then - focus = cls[1] - fidx = 1 - end - - -- Abort if no clients are present - if not focus then return end - - local geometry = {} - if #cls > 1 then - geometry.width = area.width * math.sqrt(mwfact) - geometry.height = area.height * math.sqrt(mwfact) - geometry.x = area.x + (area.width - geometry.width) / 2 - geometry.y = area.y + (area.height - geometry.height) /2 - else - geometry.x = area.x - geometry.y = area.y - geometry.width = area.width - geometry.height = area.height - end - - local g = { - x = geometry.x, - y = geometry.y, - width = geometry.width, - height = geometry.height - } - p.geometries[focus] = g - - if #cls > 1 then - geometry.x = area.x - geometry.y = area.y - geometry.height = area.height / (#cls - 1) - geometry.width = area.width - - -- We don't know the focus window index. Try to find it. - if not fidx then - for k, c in ipairs(cls) do - if c == focus then - fidx = k - break - end - end - end - - -- First move clients that are before focused client. - for k = fidx + 1, #cls do - p.geometries[cls[k]] = { - x = geometry.x, - y = geometry.y, - width = geometry.width, - height = geometry.height - } - geometry.y = geometry.y + geometry.height - end - - -- Then move clients that are after focused client. - -- So the next focused window will be the one at the top of the screen. - for k = 1, fidx - 1 do - p.geometries[cls[k]] = { - x = geometry.x, - y = geometry.y, - width = geometry.width, - height = geometry.height - } - geometry.y = geometry.y + geometry.height - end - end -end - ---- The magnifier layout. --- @clientlayout awful.layout.suit.magnifier - -magnifier.name = "magnifier" - -return magnifier - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/max.lua b/awesome/lib/awful/layout/suit/max.lua deleted file mode 100644 index 2cd1812..0000000 --- a/awesome/lib/awful/layout/suit/max.lua +++ /dev/null @@ -1,61 +0,0 @@ ---------------------------------------------------------------------------- ---- Maximized and fullscreen layouts module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local pairs = pairs - -local max = {} - ---- The max layout layoutbox icon. --- @beautiful beautiful.layout_max --- @param surface --- @see gears.surface - ---- The fullscreen layout layoutbox icon. --- @beautiful beautiful.layout_fullscreen --- @param surface --- @see gears.surface - -local function fmax(p, fs) - -- Fullscreen? - local area - if fs then - area = p.geometry - else - area = p.workarea - end - - for _, c in pairs(p.clients) do - local g = { - x = area.x, - y = area.y, - width = area.width, - height = area.height - } - p.geometries[c] = g - end -end - ---- Maximized layout. --- @clientlayout awful.layout.suit.max.name -max.name = "max" -function max.arrange(p) - return fmax(p, false) -end - ---- Fullscreen layout. --- @clientlayout awful.layout.suit.max.fullscreen -max.fullscreen = {} -max.fullscreen.name = "fullscreen" -function max.fullscreen.arrange(p) - return fmax(p, true) -end - -return max - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/spiral.lua b/awesome/lib/awful/layout/suit/spiral.lua deleted file mode 100644 index 0a7eb9b..0000000 --- a/awesome/lib/awful/layout/suit/spiral.lua +++ /dev/null @@ -1,89 +0,0 @@ ---------------------------------------------------------------------------- ---- Dwindle and spiral layouts --- --- @author Uli Schlachter <psychon@znc.in> --- @copyright 2009 Uli Schlachter --- @copyright 2008 Julien Danjou --- --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local math = math - ---- The spiral layout layoutbox icon. --- @beautiful beautiful.layout_spiral --- @param surface --- @see gears.surface - ---- The dwindle layout layoutbox icon. --- @beautiful beautiful.layout_dwindle --- @param surface --- @see gears.surface - -local spiral = {} - -local function do_spiral(p, _spiral) - local wa = p.workarea - local cls = p.clients - local n = #cls - local old_width, old_height = wa.width, 2 * wa.height - - for k, c in ipairs(cls) do - if k % 2 == 0 then - wa.width, old_width = math.ceil(old_width / 2), wa.width - if k ~= n then - wa.height, old_height = math.floor(wa.height / 2), wa.height - end - else - wa.height, old_height = math.ceil(old_height / 2), wa.height - if k ~= n then - wa.width, old_width = math.floor(wa.width / 2), wa.width - end - end - - if k % 4 == 0 and _spiral then - wa.x = wa.x - wa.width - elseif k % 2 == 0 then - wa.x = wa.x + old_width - elseif k % 4 == 3 and k < n and _spiral then - wa.x = wa.x + math.ceil(old_width / 2) - end - - if k % 4 == 1 and k ~= 1 and _spiral then - wa.y = wa.y - wa.height - elseif k % 2 == 1 and k ~= 1 then - wa.y = wa.y + old_height - elseif k % 4 == 0 and k < n and _spiral then - wa.y = wa.y + math.ceil(old_height / 2) - end - - local g = { - x = wa.x, - y = wa.y, - width = wa.width, - height = wa.height - } - p.geometries[c] = g - end -end - ---- Dwindle layout. --- @clientlayout awful.layout.suit.spiral.dwindle -spiral.dwindle = {} -spiral.dwindle.name = "dwindle" -function spiral.dwindle.arrange(p) - return do_spiral(p, false) -end - ---- Spiral layout. --- @clientlayout awful.layout.suit.spiral.name -spiral.name = "spiral" -function spiral.arrange(p) - return do_spiral(p, true) -end - -return spiral - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/layout/suit/tile.lua b/awesome/lib/awful/layout/suit/tile.lua deleted file mode 100644 index 9fa263c..0000000 --- a/awesome/lib/awful/layout/suit/tile.lua +++ /dev/null @@ -1,348 +0,0 @@ ---------------------------------------------------------------------------- ---- Tiled layouts module for awful --- --- @author Donald Ephraim Curtis <dcurtis@cs.uiowa.edu> --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Donald Ephraim Curtis --- @copyright 2008 Julien Danjou --- @module awful.layout ---------------------------------------------------------------------------- - --- Grab environment we need -local tag = require("awful.tag") -local client = require("awful.client") -local ipairs = ipairs -local math = math -local capi = -{ - mouse = mouse, - screen = screen, - mousegrabber = mousegrabber -} - -local tile = {} - ---- The tile layout layoutbox icon. --- @beautiful beautiful.layout_tile --- @param surface --- @see gears.surface - ---- The tile top layout layoutbox icon. --- @beautiful beautiful.layout_tiletop --- @param surface --- @see gears.surface - ---- The tile bottom layout layoutbox icon. --- @beautiful beautiful.layout_tilebottom --- @param surface --- @see gears.surface - ---- The tile left layout layoutbox icon. --- @beautiful beautiful.layout_tileleft --- @param surface --- @see gears.surface - ---- Jump mouse cursor to the client's corner when resizing it. -tile.resize_jump_to_corner = true - -local function mouse_resize_handler(c, _, _, _, orientation) - orientation = orientation or "tile" - local wa = c.screen.workarea - local mwfact = c.screen.selected_tag.master_width_factor - local cursor - local g = c:geometry() - local offset = 0 - local corner_coords - local coordinates_delta = {x=0,y=0} - - if orientation == "tile" then - cursor = "cross" - if g.height+15 > wa.height then - offset = g.height * .5 - cursor = "sb_h_double_arrow" - elseif not (g.y+g.height+15 > wa.y+wa.height) then - offset = g.height - end - corner_coords = { x = wa.x + wa.width * mwfact, y = g.y + offset } - elseif orientation == "left" then - cursor = "cross" - if g.height+15 >= wa.height then - offset = g.height * .5 - cursor = "sb_h_double_arrow" - elseif not (g.y+g.height+15 > wa.y+wa.height) then - offset = g.height - end - corner_coords = { x = wa.x + wa.width * (1 - mwfact), y = g.y + offset } - elseif orientation == "bottom" then - cursor = "cross" - if g.width+15 >= wa.width then - offset = g.width * .5 - cursor = "sb_v_double_arrow" - elseif not (g.x+g.width+15 > wa.x+wa.width) then - offset = g.width - end - corner_coords = { y = wa.y + wa.height * mwfact, x = g.x + offset} - else - cursor = "cross" - if g.width+15 >= wa.width then - offset = g.width * .5 - cursor = "sb_v_double_arrow" - elseif not (g.x+g.width+15 > wa.x+wa.width) then - offset = g.width - end - corner_coords = { y = wa.y + wa.height * (1 - mwfact), x= g.x + offset } - end - if tile.resize_jump_to_corner then - capi.mouse.coords(corner_coords) - else - local mouse_coords = capi.mouse.coords() - coordinates_delta = { - x = corner_coords.x - mouse_coords.x, - y = corner_coords.y - mouse_coords.y, - } - end - - local prev_coords = {} - capi.mousegrabber.run(function (_mouse) - if not c.valid then return false end - - _mouse.x = _mouse.x + coordinates_delta.x - _mouse.y = _mouse.y + coordinates_delta.y - for _, v in ipairs(_mouse.buttons) do - if v then - prev_coords = { x =_mouse.x, y = _mouse.y } - local fact_x = (_mouse.x - wa.x) / wa.width - local fact_y = (_mouse.y - wa.y) / wa.height - local new_mwfact - - local geom = c:geometry() - - -- we have to make sure we're not on the last visible client where we have to use different settings. - local wfact - local wfact_x, wfact_y - if (geom.y+geom.height+15) > (wa.y+wa.height) then - wfact_y = (geom.y + geom.height - _mouse.y) / wa.height - else - wfact_y = (_mouse.y - geom.y) / wa.height - end - - if (geom.x+geom.width+15) > (wa.x+wa.width) then - wfact_x = (geom.x + geom.width - _mouse.x) / wa.width - else - wfact_x = (_mouse.x - geom.x) / wa.width - end - - - if orientation == "tile" then - new_mwfact = fact_x - wfact = wfact_y - elseif orientation == "left" then - new_mwfact = 1 - fact_x - wfact = wfact_y - elseif orientation == "bottom" then - new_mwfact = fact_y - wfact = wfact_x - else - new_mwfact = 1 - fact_y - wfact = wfact_x - end - - c.screen.selected_tag.master_width_factor - = math.min(math.max(new_mwfact, 0.01), 0.99) - client.setwfact(math.min(math.max(wfact,0.01), 0.99), c) - return true - end - end - return prev_coords.x == _mouse.x and prev_coords.y == _mouse.y - end, cursor) -end - -local function tile_group(gs, cls, wa, orientation, fact, group) - -- get our orientation right - local height = "height" - local width = "width" - local x = "x" - local y = "y" - if orientation == "top" or orientation == "bottom" then - height = "width" - width = "height" - x = "y" - y = "x" - end - - -- make this more generic (not just width) - local available = wa[width] - (group.coord - wa[x]) - - -- find our total values - local total_fact = 0 - local min_fact = 1 - local size = group.size - for c = group.first,group.last do - -- determine the width/height based on the size_hint - local i = c - group.first +1 - local size_hints = cls[c].size_hints - local size_hint = size_hints["min_"..width] or size_hints["base_"..width] or 0 - size = math.max(size_hint, size) - - -- calculate the height - if not fact[i] then - fact[i] = min_fact - else - min_fact = math.min(fact[i],min_fact) - end - total_fact = total_fact + fact[i] - end - size = math.max(1, math.min(size, available)) - - local coord = wa[y] - local used_size = 0 - local unused = wa[height] - for c = group.first,group.last do - local geom = {} - local hints = {} - local i = c - group.first +1 - geom[width] = size - geom[height] = math.max(1, math.floor(unused * fact[i] / total_fact)) - geom[x] = group.coord - geom[y] = coord - gs[cls[c]] = geom - hints.width, hints.height = cls[c]:apply_size_hints(geom.width, geom.height) - coord = coord + hints[height] - unused = unused - hints[height] - total_fact = total_fact - fact[i] - used_size = math.max(used_size, hints[width]) - end - - return used_size -end - -local function do_tile(param, orientation) - local t = param.tag or capi.screen[param.screen].selected_tag - orientation = orientation or "right" - - -- This handles all different orientations. - local width = "width" - local x = "x" - if orientation == "top" or orientation == "bottom" then - width = "height" - x = "y" - end - - local gs = param.geometries - local cls = param.clients - local nmaster = math.min(t.master_count, #cls) - local nother = math.max(#cls - nmaster,0) - - local mwfact = t.master_width_factor - local wa = param.workarea - local ncol = t.column_count - - local data = tag.getdata(t).windowfact - - if not data then - data = {} - tag.getdata(t).windowfact = data - end - - local coord = wa[x] - local place_master = true - if orientation == "left" or orientation == "top" then - -- if we are on the left or top we need to render the other windows first - place_master = false - end - - local grow_master = t.master_fill_policy == "expand" - -- this was easier than writing functions because there is a lot of data we need - for _ = 1,2 do - if place_master and nmaster > 0 then - local size = wa[width] - if nother > 0 or not grow_master then - size = math.min(wa[width] * mwfact, wa[width] - (coord - wa[x])) - end - if nother == 0 and not grow_master then - coord = coord + (wa[width] - size)/2 - end - if not data[0] then - data[0] = {} - end - coord = coord + tile_group(gs, cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size}) - end - - if not place_master and nother > 0 then - local last = nmaster - - -- we have to modify the work area size to consider left and top views - local wasize = wa[width] - if nmaster > 0 and (orientation == "left" or orientation == "top") then - wasize = wa[width] - wa[width]*mwfact - end - for i = 1,ncol do - -- Try to get equal width among remaining columns - local size = math.min( (wasize - (coord - wa[x])) / (ncol - i + 1) ) - local first = last + 1 - last = last + math.floor((#cls - last)/(ncol - i + 1)) - -- tile the column and update our current x coordinate - if not data[i] then - data[i] = {} - end - coord = coord + tile_group(gs, cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size }) - end - end - place_master = not place_master - end - -end - ---- The main tile algo, on the right. --- @param screen The screen number to tile. --- @clientlayout awful.layout.suit.tile.top -tile.right = {} -tile.right.name = "tile" -tile.right.arrange = do_tile -function tile.right.mouse_resize_handler(c, corner, x, y) - return mouse_resize_handler(c, corner, x, y) -end - ---- The main tile algo, on the left. --- @param screen The screen number to tile. --- @clientlayout awful.layout.suit.tile.left -tile.left = {} -tile.left.name = "tileleft" -function tile.left.arrange(p) - return do_tile(p, "left") -end -function tile.left.mouse_resize_handler(c, corner, x, y) - return mouse_resize_handler(c, corner, x, y, "left") -end - ---- The main tile algo, on the bottom. --- @param screen The screen number to tile. --- @clientlayout awful.layout.suit.tile.bottom -tile.bottom = {} -tile.bottom.name = "tilebottom" -function tile.bottom.arrange(p) - return do_tile(p, "bottom") -end -function tile.bottom.mouse_resize_handler(c, corner, x, y) - return mouse_resize_handler(c, corner, x, y, "bottom") -end - ---- The main tile algo, on the top. --- @param screen The screen number to tile. --- @clientlayout awful.layout.suit.tile.top -tile.top = {} -tile.top.name = "tiletop" -function tile.top.arrange(p) - return do_tile(p, "top") -end -function tile.top.mouse_resize_handler(c, corner, x, y) - return mouse_resize_handler(c, corner, x, y, "top") -end - -tile.arrange = tile.right.arrange -tile.mouse_resize_handler = tile.right.mouse_resize_handler -tile.name = tile.right.name - -return tile - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/menu.lua b/awesome/lib/awful/menu.lua deleted file mode 100644 index dcbc5fa..0000000 --- a/awesome/lib/awful/menu.lua +++ /dev/null @@ -1,723 +0,0 @@ --------------------------------------------------------------------------------- ---- A menu for awful --- --- @author Damien Leone <damien.leone@gmail.com> --- @author Julien Danjou <julien@danjou.info> --- @author dodo --- @copyright 2008, 2011 Damien Leone, Julien Danjou, dodo --- @module awful.menu --------------------------------------------------------------------------------- - -local wibox = require("wibox") -local button = require("awful.button") -local util = require("awful.util") -local spawn = require("awful.spawn") -local tags = require("awful.tag") -local keygrabber = require("awful.keygrabber") -local client_iterate = require("awful.client").iterate -local beautiful = require("beautiful") -local dpi = require("beautiful").xresources.apply_dpi -local object = require("gears.object") -local surface = require("gears.surface") -local protected_call = require("gears.protected_call") -local cairo = require("lgi").cairo -local setmetatable = setmetatable -local tonumber = tonumber -local string = string -local ipairs = ipairs -local pairs = pairs -local print = print -local table = table -local type = type -local math = math -local capi = { - screen = screen, - mouse = mouse, - client = client } -local screen = require("awful.screen") - - -local menu = { mt = {} } - - -local table_update = function (t, set) - for k, v in pairs(set) do - t[k] = v - end - return t -end - ---- The icon used for sub-menus. --- @beautiful beautiful.menu_submenu_icon - ---- The item height. --- @beautiful beautiful.menu_height --- @tparam[opt=16] number menu_height - ---- The default menu width. --- @beautiful beautiful.menu_width --- @tparam[opt=100] number menu_width - ---- The menu item border color. --- @beautiful beautiful.menu_border_color --- @tparam[opt=0] number menu_border_color - ---- The menu item border width. --- @beautiful beautiful.menu_border_width --- @tparam[opt=0] number menu_border_width - ---- The default focused item foreground (text) color. --- @beautiful beautiful.menu_fg_focus --- @param color --- @see gears.color - ---- The default focused item background color. --- @beautiful beautiful.menu_bg_focus --- @param color --- @see gears.color - ---- The default foreground (text) color. --- @beautiful beautiful.menu_fg_normal --- @param color --- @see gears.color - ---- The default background color. --- @beautiful beautiful.menu_bg_normal --- @param color --- @see gears.color - ---- The default sub-menu indicator if no menu_submenu_icon is provided. --- @beautiful beautiful.menu_submenu --- @tparam[opt="▶"] string menu_submenu The sub-menu text. --- @see beautiful.menu_submenu_icon - ---- Key bindings for menu navigation. --- Keys are: up, down, exec, enter, back, close. Value are table with a list of valid --- keys for the action, i.e. menu_keys.up = { "j", "k" } will bind 'j' and 'k' --- key to up action. This is common to all created menu. --- @class table --- @name menu_keys -menu.menu_keys = { up = { "Up", "k" }, - down = { "Down", "j" }, - back = { "Left", "h" }, - exec = { "Return" }, - enter = { "Right", "l" }, - close = { "Escape" } } - - -local function load_theme(a, b) - a = a or {} - b = b or {} - local ret = {} - local fallback = beautiful.get() - if a.reset then b = fallback end - if a == "reset" then a = fallback end - ret.border = a.border_color or b.menu_border_color or b.border_normal or - fallback.menu_border_color or fallback.border_normal - ret.border_width= a.border_width or b.menu_border_width or b.border_width or - fallback.menu_border_width or fallback.border_width or 0 - ret.fg_focus = a.fg_focus or b.menu_fg_focus or b.fg_focus or - fallback.menu_fg_focus or fallback.fg_focus - ret.bg_focus = a.bg_focus or b.menu_bg_focus or b.bg_focus or - fallback.menu_bg_focus or fallback.bg_focus - ret.fg_normal = a.fg_normal or b.menu_fg_normal or b.fg_normal or - fallback.menu_fg_normal or fallback.fg_normal - ret.bg_normal = a.bg_normal or b.menu_bg_normal or b.bg_normal or - fallback.menu_bg_normal or fallback.bg_normal - ret.submenu_icon= a.submenu_icon or b.menu_submenu_icon or b.submenu_icon or - fallback.menu_submenu_icon or fallback.submenu_icon - ret.submenu = a.submenu or b.menu_submenu or b.submenu or - fallback.menu_submenu or fallback.submenu or "▶" - ret.height = a.height or b.menu_height or b.height or - fallback.menu_height or 16 - ret.width = a.width or b.menu_width or b.width or - fallback.menu_width or 100 - ret.font = a.font or b.font or fallback.font - for _, prop in ipairs({"width", "height", "menu_width"}) do - if type(ret[prop]) ~= "number" then ret[prop] = tonumber(ret[prop]) end - end - return ret -end - - -local function item_position(_menu, child) - local a, b = "height", "width" - local dir = _menu.layout.dir or "y" - if dir == "x" then a, b = b, a end - - local in_dir, other = 0, _menu[b] - local num = util.table.hasitem(_menu.child, child) - if num then - for i = 0, num - 1 do - local item = _menu.items[i] - if item then - other = math.max(other, item[b]) - in_dir = in_dir + item[a] - end - end - end - local w, h = other, in_dir - if dir == "x" then w, h = h, w end - return w, h -end - - -local function set_coords(_menu, s, m_coords) - local s_geometry = s.workarea - local screen_w = s_geometry.x + s_geometry.width - local screen_h = s_geometry.y + s_geometry.height - - _menu.width = _menu.wibox.width - _menu.height = _menu.wibox.height - - _menu.x = _menu.wibox.x - _menu.y = _menu.wibox.y - - if _menu.parent then - local w, h = item_position(_menu.parent, _menu) - w = w + _menu.parent.theme.border_width - - _menu.y = _menu.parent.y + h + _menu.height > screen_h and - screen_h - _menu.height or _menu.parent.y + h - _menu.x = _menu.parent.x + w + _menu.width > screen_w and - _menu.parent.x - _menu.width or _menu.parent.x + w - else - if m_coords == nil then - m_coords = capi.mouse.coords() - m_coords.x = m_coords.x + 1 - m_coords.y = m_coords.y + 1 - end - _menu.y = m_coords.y < s_geometry.y and s_geometry.y or m_coords.y - _menu.x = m_coords.x < s_geometry.x and s_geometry.x or m_coords.x - - _menu.y = _menu.y + _menu.height > screen_h and - screen_h - _menu.height or _menu.y - _menu.x = _menu.x + _menu.width > screen_w and - screen_w - _menu.width or _menu.x - end - - _menu.wibox.x = _menu.x - _menu.wibox.y = _menu.y -end - - -local function set_size(_menu) - local in_dir, other, a, b = 0, 0, "height", "width" - local dir = _menu.layout.dir or "y" - if dir == "x" then a, b = b, a end - for _, item in ipairs(_menu.items) do - other = math.max(other, item[b]) - in_dir = in_dir + item[a] - end - _menu[a], _menu[b] = in_dir, other - if in_dir > 0 and other > 0 then - _menu.wibox[a] = in_dir - _menu.wibox[b] = other - return true - end - return false -end - - -local function check_access_key(_menu, key) - for i, item in ipairs(_menu.items) do - if item.akey == key then - _menu:item_enter(i) - _menu:exec(i, { exec = true }) - return - end - end - if _menu.parent then - check_access_key(_menu.parent, key) - end -end - - -local function grabber(_menu, _, key, event) - if event ~= "press" then return end - - local sel = _menu.sel or 0 - if util.table.hasitem(menu.menu_keys.up, key) then - local sel_new = sel-1 < 1 and #_menu.items or sel-1 - _menu:item_enter(sel_new) - elseif util.table.hasitem(menu.menu_keys.down, key) then - local sel_new = sel+1 > #_menu.items and 1 or sel+1 - _menu:item_enter(sel_new) - elseif sel > 0 and util.table.hasitem(menu.menu_keys.enter, key) then - _menu:exec(sel) - elseif sel > 0 and util.table.hasitem(menu.menu_keys.exec, key) then - _menu:exec(sel, { exec = true }) - elseif util.table.hasitem(menu.menu_keys.back, key) then - _menu:hide() - elseif util.table.hasitem(menu.menu_keys.close, key) then - menu.get_root(_menu):hide() - else - check_access_key(_menu, key) - end -end - - -function menu:exec(num, opts) - opts = opts or {} - local item = self.items[num] - if not item then return end - local cmd = item.cmd - if type(cmd) == "table" then - local action = cmd.cmd - if #cmd == 0 then - if opts.exec and action and type(action) == "function" then - action() - end - return - end - if not self.child[num] then - self.child[num] = menu.new(cmd, self) - end - local can_invoke_action = opts.exec and - action and type(action) == "function" and - (not opts.mouse or (opts.mouse and (self.auto_expand or - (self.active_child == self.child[num] and - self.active_child.wibox.visible)))) - if can_invoke_action then - local visible = action(self.child[num], item) - if not visible then - menu.get_root(self):hide() - return - else - self.child[num]:update() - end - end - if self.active_child and self.active_child ~= self.child[num] then - self.active_child:hide() - end - self.active_child = self.child[num] - if not self.active_child.wibox.visible then - self.active_child:show() - end - elseif type(cmd) == "string" then - menu.get_root(self):hide() - spawn(cmd) - elseif type(cmd) == "function" then - local visible, action = cmd(item, self) - if not visible then - menu.get_root(self):hide() - else - self:update() - if self.items[num] then - self:item_enter(num, opts) - end - end - if action and type(action) == "function" then - action() - end - end -end - -function menu:item_enter(num, opts) - opts = opts or {} - local item = self.items[num] - if num == nil or self.sel == num or not item then - return - elseif self.sel then - self:item_leave(self.sel) - end - --print("sel", num, menu.sel, item.theme.bg_focus) - item._background:set_fg(item.theme.fg_focus) - item._background:set_bg(item.theme.bg_focus) - self.sel = num - - if self.auto_expand and opts.hover then - if self.active_child then - self.active_child:hide() - self.active_child = nil - end - - if type(item.cmd) == "table" then - self:exec(num, opts) - end - end -end - - -function menu:item_leave(num) - --print("leave", num) - local item = self.items[num] - if item then - item._background:set_fg(item.theme.fg_normal) - item._background:set_bg(item.theme.bg_normal) - end -end - - ---- Show a menu. --- @param args The arguments --- @param args.coords Menu position defaulting to mouse.coords() -function menu:show(args) - args = args or {} - local coords = args.coords or nil - local s = capi.screen[screen.focused()] - - if not set_size(self) then return end - set_coords(self, s, coords) - - keygrabber.run(self._keygrabber) - self.wibox.visible = true -end - ---- Hide a menu popup. -function menu:hide() - -- Remove items from screen - for i = 1, #self.items do - self:item_leave(i) - end - if self.active_child then - self.active_child:hide() - self.active_child = nil - end - self.sel = nil - - keygrabber.stop(self._keygrabber) - self.wibox.visible = false -end - ---- Toggle menu visibility. --- @param args The arguments --- @param args.coords Menu position {x,y} -function menu:toggle(args) - if self.wibox.visible then - self:hide() - else - self:show(args) - end -end - ---- Update menu content -function menu:update() - if self.wibox.visible then - self:show({ coords = { x = self.x, y = self.y } }) - end -end - - ---- Get the elder parent so for example when you kill --- it, it will destroy the whole family. -function menu:get_root() - return self.parent and menu.get_root(self.parent) or self -end - ---- Add a new menu entry. --- args.* params needed for the menu entry constructor. --- @param args The item params --- @param args.new (Default: awful.menu.entry) The menu entry constructor. --- @param[opt] args.theme The menu entry theme. --- @param[opt] index The index where the new entry will inserted. -function menu:add(args, index) - if not args then return end - local theme = load_theme(args.theme or {}, self.theme) - args.theme = theme - args.new = args.new or menu.entry - local item = protected_call(args.new, self, args) - if (not item) or (not item.widget) then - print("Error while checking menu entry: no property widget found.") - return - end - item.parent = self - item.theme = item.theme or theme - item.width = item.width or theme.width - item.height = item.height or theme.height - wibox.widget.base.check_widget(item.widget) - item._background = wibox.container.background() - item._background:set_widget(item.widget) - item._background:set_fg(item.theme.fg_normal) - item._background:set_bg(item.theme.bg_normal) - - - -- Create bindings - item._background:buttons(util.table.join( - button({}, 3, function () self:hide() end), - button({}, 1, function () - local num = util.table.hasitem(self.items, item) - self:item_enter(num, { mouse = true }) - self:exec(num, { exec = true, mouse = true }) - end ))) - - - item._mouse = function () - local num = util.table.hasitem(self.items, item) - self:item_enter(num, { hover = true, moue = true }) - end - item.widget:connect_signal("mouse::enter", item._mouse) - - if index then - self.layout:reset() - table.insert(self.items, index, item) - for _, i in ipairs(self.items) do - self.layout:add(i._background) - end - else - table.insert(self.items, item) - self.layout:add(item._background) - end - if self.wibox then - set_size(self) - end - return item -end - ---- Delete menu entry at given position --- @param num The position in the table of the menu entry to be deleted; can be also the menu entry itself -function menu:delete(num) - if type(num) == "table" then - num = util.table.hasitem(self.items, num) - end - local item = self.items[num] - if not item then return end - item.widget:disconnect_signal("mouse::enter", item._mouse) - item.widget:set_visible(false) - table.remove(self.items, num) - if self.sel == num then - self:item_leave(self.sel) - self.sel = nil - end - self.layout:reset() - for _, i in ipairs(self.items) do - self.layout:add(i._background) - end - if self.child[num] then - self.child[num]:hide() - if self.active_child == self.child[num] then - self.active_child = nil - end - table.remove(self.child, num) - end - if self.wibox then - set_size(self) - end -end - --------------------------------------------------------------------------------- - ---- Build a popup menu with running clients and show it. --- @tparam[opt] table args Menu table, see `new()` for more information. --- @tparam[opt] table item_args Table that will be merged into each item, see --- `new()` for more information. --- @tparam[opt] func filter A function taking a client as an argument and --- returning `true` or `false` to indicate whether the client should be --- included in the menu. --- @return The menu. -function menu.clients(args, item_args, filter) - local cls_t = {} - for c in client_iterate(filter or function() return true end) do - cls_t[#cls_t + 1] = { - c.name or "", - function () - if not c:isvisible() then - tags.viewmore(c:tags(), c.screen) - end - c:emit_signal("request::activate", "menu.clients", {raise=true}) - end, - c.icon } - if item_args then - if type(item_args) == "function" then - util.table.merge(cls_t[#cls_t], item_args(c)) - else - util.table.merge(cls_t[#cls_t], item_args) - end - end - end - args = args or {} - args.items = args.items or {} - util.table.merge(args.items, cls_t) - - local m = menu.new(args) - m:show(args) - return m -end - --------------------------------------------------------------------------------- - ---- Default awful.menu.entry constructor --- @param parent The parent menu (TODO: This is apparently unused) --- @param args the item params --- @return table with 'widget', 'cmd', 'akey' and all the properties the user wants to change -function menu.entry(parent, args) -- luacheck: no unused args - args = args or {} - args.text = args[1] or args.text or "" - args.cmd = args[2] or args.cmd - args.icon = args[3] or args.icon - local ret = {} - -- Create the item label widget - local label = wibox.widget.textbox() - local key = '' - label:set_font(args.theme.font) - label:set_markup(string.gsub( - util.escape(args.text), "&(%w)", - function (l) - key = string.lower(l) - return "<u>" .. l .. "</u>" - end, 1)) - -- Set icon if needed - local icon, iconbox - local margin = wibox.container.margin() - margin:set_widget(label) - if args.icon then - icon = surface.load(args.icon) - end - if icon then - local iw = icon:get_width() - local ih = icon:get_height() - if iw > args.theme.width or ih > args.theme.height then - local w, h - if ((args.theme.height / ih) * iw) > args.theme.width then - w, h = args.theme.height, (args.theme.height / iw) * ih - else - w, h = (args.theme.height / ih) * iw, args.theme.height - end - -- We need to scale the image to size w x h - local img = cairo.ImageSurface(cairo.Format.ARGB32, w, h) - local cr = cairo.Context(img) - cr:scale(w / iw, h / ih) - cr:set_source_surface(icon, 0, 0) - cr:paint() - icon = img - end - iconbox = wibox.widget.imagebox() - if iconbox:set_image(icon) then - margin:set_left(dpi(2)) - else - iconbox = nil - end - end - if not iconbox then - margin:set_left(args.theme.height + dpi(2)) - end - -- Create the submenu icon widget - local submenu - if type(args.cmd) == "table" then - if args.theme.submenu_icon then - submenu = wibox.widget.imagebox() - submenu:set_image(args.theme.submenu_icon) - else - submenu = wibox.widget.textbox() - submenu:set_font(args.theme.font) - submenu:set_text(args.theme.submenu) - end - end - -- Add widgets to the wibox - local left = wibox.layout.fixed.horizontal() - if iconbox then - left:add(iconbox) - end - -- This contains the label - left:add(margin) - - local layout = wibox.layout.align.horizontal() - layout:set_left(left) - if submenu then - layout:set_right(submenu) - end - - return table_update(ret, { - label = label, - sep = submenu, - icon = iconbox, - widget = layout, - cmd = args.cmd, - akey = key, - }) -end - --------------------------------------------------------------------------------- - ---- Create a menu popup. --- @param args Table containing the menu informations. --- --- * Key items: Table containing the displayed items. Each element is a table by default (when element 'new' is awful.menu.entry) containing: item name, triggered action, submenu table or function, item icon (optional). --- * Keys theme.[fg|bg]_[focus|normal], theme.border_color, theme.border_width, theme.submenu_icon, theme.height and theme.width override the default display for your menu and/or of your menu entry, each of them are optional. --- * Key auto_expand controls the submenu auto expand behaviour by setting it to true (default) or false. --- --- @param parent Specify the parent menu if we want to open a submenu, this value should never be set by the user. --- @usage -- The following function builds and shows a menu of clients that match --- -- a particular rule. --- -- Bound to a key, it can be used to select from dozens of terminals open on --- -- several tags. --- -- When using @{rules.match_any} instead of @{rules.match}, --- -- a menu of clients with different classes could be build. --- --- function terminal_menu () --- terms = {} --- for i, c in pairs(client.get()) do --- if awful.rules.match(c, {class = "URxvt"}) then --- terms[i] = --- {c.name, --- function() --- c.first_tag:view_only() --- client.focus = c --- end, --- c.icon --- } --- end --- end --- awful.menu(terms):show() --- end -function menu.new(args, parent) - args = args or {} - args.layout = args.layout or wibox.layout.flex.vertical - local _menu = table_update(object(), { - item_enter = menu.item_enter, - item_leave = menu.item_leave, - get_root = menu.get_root, - delete = menu.delete, - update = menu.update, - toggle = menu.toggle, - hide = menu.hide, - show = menu.show, - exec = menu.exec, - add = menu.add, - child = {}, - items = {}, - parent = parent, - layout = args.layout(), - theme = load_theme(args.theme or {}, parent and parent.theme) }) - - if parent then - _menu.auto_expand = parent.auto_expand - elseif args.auto_expand ~= nil then - _menu.auto_expand = args.auto_expand - else - _menu.auto_expand = true - end - - -- Create items - for _, v in ipairs(args) do _menu:add(v) end - if args.items then - for _, v in pairs(args.items) do _menu:add(v) end - end - - _menu._keygrabber = function (...) - grabber(_menu, ...) - end - - _menu.wibox = wibox({ - ontop = true, - fg = _menu.theme.fg_normal, - bg = _menu.theme.bg_normal, - border_color = _menu.theme.border, - border_width = _menu.theme.border_width, - type = "popup_menu" }) - _menu.wibox.visible = false - _menu.wibox:set_widget(_menu.layout) - set_size(_menu) - - _menu.x = _menu.wibox.x - _menu.y = _menu.wibox.y - return _menu -end - -function menu.mt:__call(...) - return menu.new(...) -end - -return setmetatable(menu, menu.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/mouse/drag_to_tag.lua b/awesome/lib/awful/mouse/drag_to_tag.lua deleted file mode 100644 index 141456b..0000000 --- a/awesome/lib/awful/mouse/drag_to_tag.lua +++ /dev/null @@ -1,58 +0,0 @@ ---------------------------------------------------------------------------- ---- When the the mouse reach the end of the screen, then switch tag instead --- of screens. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @submodule mouse ---------------------------------------------------------------------------- - -local capi = {screen = screen, mouse = mouse} -local util = require("awful.util") -local tag = require("awful.tag") -local resize = require("awful.mouse.resize") - -local module = {} - -function module.drag_to_tag(c) - if (not c) or (not c.valid) then return end - - local coords = capi.mouse.coords() - - local dir = nil - - local wa = c.screen.workarea - - if coords.x >= wa.x + wa.width - 1 then - capi.mouse.coords({ x = wa.x + 2 }, true) - dir = "right" - elseif coords.x <= wa.x + 1 then - capi.mouse.coords({ x = wa.x + wa.width - 2 }, true) - dir = "left" - end - - local tags = c.screen.tags - local t = c.screen.selected_tag - local idx = t.index - - if dir then - - if dir == "right" then - local newtag = tags[util.cycle(#tags, idx + 1)] - c:move_to_tag(newtag) - tag.viewnext() - elseif dir == "left" then - local newtag = tags[util.cycle(#tags, idx - 1)] - c:move_to_tag(newtag) - tag.viewprev() - end - end -end - -resize.add_move_callback(function(c, _, _) - if module.enabled then - module.drag_to_tag(c) - end -end, "mouse.move") - -return setmetatable(module, {__call = function(_, ...) return module.drag_to_tag(...) end}) diff --git a/awesome/lib/awful/mouse/init.lua b/awesome/lib/awful/mouse/init.lua deleted file mode 100644 index 03f7e89..0000000 --- a/awesome/lib/awful/mouse/init.lua +++ /dev/null @@ -1,437 +0,0 @@ ---------------------------------------------------------------------------- ---- Mouse module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module mouse ---------------------------------------------------------------------------- - --- Grab environment we need -local layout = require("awful.layout") -local aplace = require("awful.placement") -local util = require("awful.util") -local type = type -local ipairs = ipairs -local capi = -{ - root = root, - mouse = mouse, - screen = screen, - client = client, - mousegrabber = mousegrabber, -} - -local mouse = { - resize = require("awful.mouse.resize"), - snap = require("awful.mouse.snap"), - drag_to_tag = require("awful.mouse.drag_to_tag") -} - -mouse.object = {} -mouse.client = {} -mouse.wibox = {} - ---- The default snap distance. --- @tfield integer awful.mouse.snap.default_distance --- @tparam[opt=8] integer default_distance --- @see awful.mouse.snap - ---- Enable screen edges snapping. --- @tfield[opt=true] boolean awful.mouse.snap.edge_enabled - ---- Enable client to client snapping. --- @tfield[opt=true] boolean awful.mouse.snap.client_enabled - ---- Enable changing tag when a client is dragged to the edge of the screen. --- @tfield[opt=false] integer awful.mouse.drag_to_tag.enabled - ---- The snap outline background color. --- @beautiful beautiful.snap_bg --- @tparam color|string|gradient|pattern color - ---- The snap outline width. --- @beautiful beautiful.snap_border_width --- @param integer - ---- The snap outline shape. --- @beautiful beautiful.snap_shape --- @tparam function shape A `gears.shape` compatible function - ---- Get the client object under the pointer. --- @deprecated awful.mouse.client_under_pointer --- @return The client object under the pointer, if one can be found. --- @see current_client -function mouse.client_under_pointer() - util.deprecate("Use mouse.current_client instead of awful.mouse.client_under_pointer()") - - return mouse.object.get_current_client() -end - ---- Move a client. --- @function 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 - util.deprecate("The mouse.client.move `finished_cb` argument is no longer".. - " used, please use awful.mouse.resize.add_leave_callback(f, 'mouse.move')") - end - - c = c or capi.client.focus - - if not c - or c.fullscreen - 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) - util.deprecate("Use awful.mouse.snap.drag_to_tag_enabled = true instead ".. - "of awful.mouse.client.dragtotag.border(c). It will now be enabled.") - - -- Enable drag to border - mouse.snap.drag_to_tag_enabled = true - - return mouse.client.move(c) -end - ---- Move the wibox under the cursor. --- @function 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.wibox_under_pointer() - 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) - util.deprecate( - "Use awful.placement.closest_corner(mouse) or awful.placement[corner](mouse)".. - " instead of awful.mouse.client.corner" - ) - - 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. --- @function 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.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 == layout.suit.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 --- @treturn boolean This return false when the resize need to be aborted -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 ~= layout.suit.floating and l.mouse_resize_handler then - capi.mousegrabber.stop() - - local geo, corner = aplace.closest_corner(capi.mouse, {parent=c}) - - l.mouse_resize_handler(c, corner, geo.x, geo.y) - - return false - end -end, "mouse.resize") - ---- Get the client currently under the mouse cursor. --- @property current_client --- @tparam client|nil The client - -function mouse.object.get_current_client() - local obj = capi.mouse.object_under_pointer() - if type(obj) == "client" then - return obj - end -end - ---- Get the wibox currently under the mouse cursor. --- @property current_wibox --- @tparam wibox|nil The wibox - -function mouse.object.get_current_wibox() - local obj = capi.mouse.object_under_pointer() - if type(obj) == "drawin" and obj.get_wibox then - return obj:get_wibox() - end -end - ---- Get the widgets currently under the mouse cursor. --- --- @property current_widgets --- @tparam nil|table list The widget list --- @treturn table The list of widgets.The first element is the biggest --- container while the last is the topmost widget. The table contains *x*, *y*, --- *width*, *height* and *widget*. --- @see wibox.find_widgets - -function mouse.object.get_current_widgets() - local w = mouse.object.get_current_wibox() - if w then - local geo, coords = w:geometry(), capi.mouse:coords() - - local list = w:find_widgets(coords.x - geo.x, coords.y - geo.y) - - local ret = {} - - for k, v in ipairs(list) do - ret[k] = v.widget - end - - return ret, list - end -end - ---- Get the topmost widget currently under the mouse cursor. --- @property current_widget --- @tparam widget|nil widget The widget --- @treturn ?widget The widget --- @see wibox.find_widgets --- @see current_widget_geometry - -function mouse.object.get_current_widget() - local wdgs, geos = mouse.object.get_current_widgets() - - if wdgs then - return wdgs[#wdgs], geos[#geos] - end -end - ---- Get the current widget geometry. --- @property current_widget_geometry --- @tparam ?table The geometry. --- @see current_widget - -function mouse.object.get_current_widget_geometry() - local _, ret = mouse.object.get_current_widget() - - return ret -end - ---- Get the current widget geometries. --- @property current_widget_geometries --- @tparam ?table A list of geometry tables. --- @see current_widgets - -function mouse.object.get_current_widget_geometries() - local _, ret = mouse.object.get_current_widgets() - - return ret -end - ---- True if the left mouse button is pressed. --- @property is_left_mouse_button_pressed --- @param boolean - ---- True if the right mouse button is pressed. --- @property is_right_mouse_button_pressed --- @param boolean - ---- True if the middle mouse button is pressed. --- @property is_middle_mouse_button_pressed --- @param boolean - -for _, b in ipairs {"left", "right", "middle"} do - mouse.object["is_".. b .."_mouse_button_pressed"] = function() - return capi.mouse.coords().buttons[1] - end -end - -capi.client.connect_signal("request::geometry", mouse.resize_handler) - --- Set the cursor at startup -capi.root.cursor("left_ptr") - --- Implement the custom property handler -local props = {} - -capi.mouse.set_newindex_miss_handler(function(_,key,value) - if mouse.object["set_"..key] then - mouse.object["set_"..key](value) - elseif not mouse.object["get_"..key] then - props[key] = value - else - -- If there is a getter, but no setter, then the property is read-only - error("Cannot set '" .. tostring(key) .. " because it is read-only") - end -end) - -capi.mouse.set_index_miss_handler(function(_,key) - if mouse.object["get_"..key] then - return mouse.object["get_"..key]() - else - return props[key] - end -end) - ---- Get or set the mouse coords. --- --- --- ---![Usage example](../images/AUTOGEN_awful_mouse_coords.svg) --- ---**Usage example output**: --- --- 235 --- --- --- @usage --- -- Get the position ---print(mouse.coords().x) --- -- Change the position ---mouse.coords { --- x = 185, --- y = 10 ---} --- --- @tparam[opt=nil] table coords_table None or a table with x and y keys as mouse --- coordinates. --- @tparam[opt=nil] integer coords_table.x The mouse horizontal position --- @tparam[opt=nil] integer coords_table.y The mouse vertical position --- @tparam[opt=false] boolean silent Disable mouse::enter or mouse::leave events that --- could be triggered by the pointer when moving. --- @treturn integer table.x The horizontal position --- @treturn integer table.y The vertical position --- @treturn table table.buttons Table containing the status of buttons, e.g. field [1] is true --- when button 1 is pressed. --- @function mouse.coords - - -return mouse - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/mouse/resize.lua b/awesome/lib/awful/mouse/resize.lua deleted file mode 100644 index edd278d..0000000 --- a/awesome/lib/awful/mouse/resize.lua +++ /dev/null @@ -1,229 +0,0 @@ ---------------------------------------------------------------------------- ---- An extandable mouse resizing handler. --- --- This module offer a resizing and moving mechanism for drawable such as --- clients and wiboxes. --- --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2016 Emmanuel Lepage Vallee --- @submodule mouse ---------------------------------------------------------------------------- - -local aplace = require("awful.placement") -local capi = {mousegrabber = mousegrabber} -local beautiful = require("beautiful") - -local module = {} - -local mode = "live" -local req = "request::geometry" -local callbacks = {enter={}, move={}, leave={}} - -local cursors = { - ["mouse.move" ] = "fleur", - ["mouse.resize" ] = "cross", - ["mouse.resize_left" ] = "sb_h_double_arrow", - ["mouse.resize_right" ] = "sb_h_double_arrow", - ["mouse.resize_top" ] = "sb_v_double_arrow", - ["mouse.resize_bottom" ] = "sb_v_double_arrow", - ["mouse.resize_top_left" ] = "top_left_corner", - ["mouse.resize_top_right" ] = "top_right_corner", - ["mouse.resize_bottom_left" ] = "bottom_left_corner", - ["mouse.resize_bottom_right"] = "bottom_right_corner", -} - ---- The resize cursor name. --- @beautiful beautiful.cursor_mouse_resize --- @tparam[opt=cross] string cursor - ---- The move cursor name. --- @beautiful beautiful.cursor_mouse_move --- @tparam[opt=fleur] string cursor - ---- Set the resize mode. --- The available modes are: --- --- * **live**: Resize the layout everytime the mouse move --- * **after**: Resize the layout only when the mouse is released --- --- Some clients, such as XTerm, may lose information if resized too often. --- --- @function awful.mouse.resize.set_mode --- @tparam string m The mode -function module.set_mode(m) - assert(m == "live" or m == "after") - mode = m -end - ---- Add an initialization callback. --- This callback will be executed before the mouse grabbing starts. --- @function awful.mouse.resize.add_enter_callback --- @tparam function cb The callback (or nil) --- @tparam[default=other] string context The callback context -function module.add_enter_callback(cb, context) - context = context or "other" - callbacks.enter[context] = callbacks.enter[context] or {} - table.insert(callbacks.enter[context], cb) -end - ---- Add a "move" callback. --- This callback is executed in "after" mode (see `set_mode`) instead of --- applying the operation. --- @function awful.mouse.resize.add_move_callback --- @tparam function cb The callback (or nil) --- @tparam[default=other] string context The callback context -function module.add_move_callback(cb, context) - context = context or "other" - callbacks.move[context] = callbacks.move[context] or {} - table.insert(callbacks.move[context], cb) -end - ---- Add a "leave" callback --- This callback is executed just before the `mousegrabber` stop --- @function awful.mouse.resize.add_leave_callback --- @tparam function cb The callback (or nil) --- @tparam[default=other] string context The callback context -function module.add_leave_callback(cb, context) - context = context or "other" - callbacks.leave[context] = callbacks.leave[context] or {} - table.insert(callbacks.leave[context], cb) -end - --- Resize, the drawable. --- --- Valid `args` are: --- --- * *enter_callback*: A function called before the `mousegrabber` start --- * *move_callback*: A function called when the mouse move --- * *leave_callback*: A function called before the `mousegrabber` is released --- * *mode*: The resize mode --- --- @function awful.mouse.resize --- @tparam client client A client --- @tparam[default=mouse.resize] string context The resizing context --- @tparam[opt={}] table args A set of `awful.placement` arguments - -local function handler(_, client, context, args) --luacheck: no unused_args - args = args or {} - context = context or "mouse.resize" - - local placement = args.placement - - if type(placement) == "string" and aplace[placement] then - placement = aplace[placement] - end - - -- Extend the table with the default arguments - args = setmetatable( - { - placement = placement or aplace.resize_to_mouse, - mode = args.mode or mode, - pretend = true, - }, - {__index = args or {}} - ) - - local geo - - for _, cb in ipairs(callbacks.enter[context] or {}) do - geo = cb(client, args) - - if geo == false then - return false - end - end - - if args.enter_callback then - geo = args.enter_callback(client, args) - - if geo == false then - return false - end - end - - geo = nil - - -- Select the cursor - local tcontext = context:gsub('[.]', '_') - local corner = args.corner and ("_".. args.corner) or "" - - local cursor = beautiful["cursor_"..tcontext] - or cursors[context..corner] - or cursors[context] - or "fleur" - - -- Execute the placement function and use request::geometry - capi.mousegrabber.run(function (_mouse) - if not client.valid then return end - - -- Resize everytime the mouse move (default behavior) - if args.mode == "live" then - -- Get the new geometry - geo = setmetatable(args.placement(client, args),{__index=args}) - end - - -- Execute the move callbacks. This can be used to add features such as - -- snap or adding fancy graphical effects. - for _, cb in ipairs(callbacks.move[context] or {}) do - -- If something is returned, assume it is a modified geometry - geo = cb(client, geo, args) or geo - - if geo == false then - return false - end - end - - if args.move_callback then - geo = args.move_callback(client, geo, args) - - if geo == false then - return false - end - end - - -- In case it was modified - setmetatable(geo,{__index=args}) - - if args.mode == "live" then - -- Ask the resizing handler to resize the client - client:emit_signal( req, context, geo) - end - - -- Quit when the button is released - for _,v in pairs(_mouse.buttons) do - if v then return true end - end - - -- Only resize after the mouse is released, this avoid losing content - -- in resize sensitive apps such as XTerm or allow external modules - -- to implement custom resizing. - if args.mode == "after" then - -- Get the new geometry - geo = args.placement(client, args) - - -- Ask the resizing handler to resize the client - client:emit_signal( req, context, geo) - end - - geo = nil - - for _, cb in ipairs(callbacks.leave[context] or {}) do - geo = cb(client, geo, args) - end - - if args.leave_callback then - geo = args.leave_callback(client, geo, args) - end - - if not geo then return false end - - -- In case it was modified - setmetatable(geo,{__index=args}) - - client:emit_signal( req, context, geo) - - return false - end, cursor) -end - -return setmetatable(module, {__call=handler}) diff --git a/awesome/lib/awful/mouse/snap.lua b/awesome/lib/awful/mouse/snap.lua deleted file mode 100644 index 048a679..0000000 --- a/awesome/lib/awful/mouse/snap.lua +++ /dev/null @@ -1,266 +0,0 @@ ---------------------------------------------------------------------------- ---- Mouse snapping related functions --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @submodule mouse ---------------------------------------------------------------------------- - -local aclient = require("awful.client") -local resize = require("awful.mouse.resize") -local aplace = require("awful.placement") -local wibox = require("wibox") -local beautiful = require("beautiful") -local color = require("gears.color") -local shape = require("gears.shape") -local cairo = require("lgi").cairo - -local capi = { - root = root, - mouse = mouse, - screen = screen, - client = client, - mousegrabber = mousegrabber, -} - -local module = { - default_distance = 8 -} - -local placeholder_w = nil - -local function show_placeholder(geo) - if not geo then - if placeholder_w then - placeholder_w.visible = false - end - return - end - - placeholder_w = placeholder_w or wibox { - ontop = true, - bg = color(beautiful.snap_bg or beautiful.bg_urgent or "#ff0000"), - } - - placeholder_w:geometry(geo) - - local img = cairo.ImageSurface(cairo.Format.A1, geo.width, geo.height) - local cr = cairo.Context(img) - - cr:set_operator(cairo.Operator.CLEAR) - cr:set_source_rgba(0,0,0,1) - cr:paint() - cr:set_operator(cairo.Operator.SOURCE) - cr:set_source_rgba(1,1,1,1) - - local line_width = beautiful.snap_border_width or 5 - cr:set_line_width(beautiful.xresources.apply_dpi(line_width)) - - local f = beautiful.snap_shape or function() - cr:translate(line_width,line_width) - shape.rounded_rect(cr,geo.width-2*line_width,geo.height-2*line_width, 10) - end - - f(cr, geo.width, geo.height) - - cr:stroke() - - placeholder_w.shape_bounding = img._native - - placeholder_w.visible = true -end - -local function build_placement(snap, axis) - return aplace.scale - + aplace[snap] - + ( - axis and aplace["maximize_"..axis] or nil - ) -end - -local function detect_screen_edges(c, snap) - local coords = capi.mouse.coords() - - local sg = c.screen.geometry - - local v, h = nil - - if math.abs(coords.x) <= snap + sg.x and coords.x >= sg.x then - h = "left" - elseif math.abs((sg.x + sg.width) - coords.x) <= snap then - h = "right" - end - - if math.abs(coords.y) <= snap + sg.y and coords.y >= sg.y then - v = "top" - elseif math.abs((sg.y + sg.height) - coords.y) <= snap then - v = "bottom" - end - - return v, h -end - -local current_snap, current_axis = nil - -local function detect_areasnap(c, distance) - local old_snap = current_snap - local v, h = detect_screen_edges(c, distance) - - if v and h then - current_snap = v.."_"..h - else - current_snap = v or h or nil - end - - if old_snap == current_snap then return end - - current_axis = ((v and not h) and "horizontally") - or ((h and not v) and "vertically") - or nil - - -- Show the expected geometry outline - show_placeholder( - current_snap and build_placement(current_snap, current_axis)(c, { - to_percent = 0.5, - honor_workarea = true, - pretend = true - }) or nil - ) - -end - -local function apply_areasnap(c, args) - if not current_snap then return end - - -- Remove the move offset - args.offset = {} - - placeholder_w.visible = false - - return build_placement(current_snap, current_axis)(c,{ - to_percent = 0.5, - honor_workarea = true, - }) -end - -local function snap_outside(g, sg, snap) - if g.x < snap + sg.x + sg.width and g.x > sg.x + sg.width then - g.x = sg.x + sg.width - elseif g.x + g.width < sg.x and g.x + g.width > sg.x - snap then - g.x = sg.x - g.width - end - if g.y < snap + sg.y + sg.height and g.y > sg.y + sg.height then - g.y = sg.y + sg.height - elseif g.y + g.height < sg.y and g.y + g.height > sg.y - snap then - g.y = sg.y - g.height - end - return g -end - -local function snap_inside(g, sg, snap) - local edgev = 'none' - local edgeh = 'none' - if math.abs(g.x) < snap + sg.x and g.x > sg.x then - edgev = 'left' - g.x = sg.x - elseif math.abs((sg.x + sg.width) - (g.x + g.width)) < snap then - edgev = 'right' - g.x = sg.x + sg.width - g.width - end - if math.abs(g.y) < snap + sg.y and g.y > sg.y then - edgeh = 'top' - g.y = sg.y - elseif math.abs((sg.y + sg.height) - (g.y + g.height)) < snap then - edgeh = 'bottom' - g.y = sg.y + sg.height - g.height - end - - -- What is the dominant dimension? - if g.width > g.height then - return g, edgeh - else - return g, edgev - end -end - ---- Snap a client to the closest client or screen edge. --- @function awful.mouse.snap --- @param c The client to snap. --- @param snap The pixel to snap clients. --- @param x The client x coordinate. --- @param y The client y coordinate. --- @param fixed_x True if the client isn't allowed to move in the x direction. --- @param fixed_y True if the client isn't allowed to move in the y direction. -function module.snap(c, snap, x, y, fixed_x, fixed_y) - snap = snap or module.default_distance - c = c or capi.client.focus - local cur_geom = c:geometry() - local geom = c:geometry() - geom.width = geom.width + (2 * c.border_width) - geom.height = geom.height + (2 * c.border_width) - local edge - geom.x = x or geom.x - geom.y = y or geom.y - - geom, edge = snap_inside(geom, c.screen.geometry, snap) - geom = snap_inside(geom, c.screen.workarea, snap) - - -- Allow certain windows to snap to the edge of the workarea. - -- Only allow docking to workarea for consistency/to avoid problems. - if c.dockable then - local struts = c:struts() - struts['left'] = 0 - struts['right'] = 0 - struts['top'] = 0 - struts['bottom'] = 0 - if edge ~= "none" and c.floating then - if edge == "left" or edge == "right" then - struts[edge] = cur_geom.width - elseif edge == "top" or edge == "bottom" then - struts[edge] = cur_geom.height - end - end - c:struts(struts) - end - - for _, snapper in ipairs(aclient.visible(c.screen)) do - if snapper ~= c then - local snapper_geom = snapper:geometry() - snapper_geom.width = snapper_geom.width + (2 * snapper.border_width) - snapper_geom.height = snapper_geom.height + (2 * snapper.border_width) - geom = snap_outside(geom, snapper_geom, snap) - end - end - - geom.width = geom.width - (2 * c.border_width) - geom.height = geom.height - (2 * c.border_width) - - -- It's easiest to undo changes afterwards if they're not allowed - if fixed_x then geom.x = cur_geom.x end - if fixed_y then geom.y = cur_geom.y end - - return geom -end - --- Enable edge snapping -resize.add_move_callback(function(c, geo, args) - -- Screen edge snapping (areosnap) - if (module.edge_enabled ~= false) - and args and (args.snap == nil or args.snap) then - detect_areasnap(c, 16) - end - - -- Snapping between clients - if (module.client_enabled ~= false) - and args and (args.snap == nil or args.snap) then - return module.snap(c, args.snap, geo.x, geo.y) - end -end, "mouse.move") - --- Apply the aerosnap -resize.add_leave_callback(function(c, _, args) - if module.edge_enabled == false then return end - return apply_areasnap(c, args) -end, "mouse.move") - -return setmetatable(module, {__call = function(_, ...) return module.snap(...) end}) diff --git a/awesome/lib/awful/placement.lua b/awesome/lib/awful/placement.lua deleted file mode 100644 index d288f49..0000000 --- a/awesome/lib/awful/placement.lua +++ /dev/null @@ -1,1694 +0,0 @@ ---------------------------------------------------------------------------- ---- Algorithms used to place various drawables. --- --- The functions provided by this module all follow the same arguments --- conventions. This allow: --- --- * To use them in various other module as --- [visitor objects](https://en.wikipedia.org/wiki/Visitor_pattern) --- * Turn each function into an API with various common customization parameters. --- * Re-use the same functions for the `mouse`, `client`s, `screen`s and `wibox`es --- --- --- <h3>Compositing</h3> --- --- It is possible to compose placement function using the `+` or `*` operator: --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_compose.svg) --- --- --- -- 'right' will be replaced by 'left' --- local f = (awful.placement.right + awful.placement.left) --- f(client.focus) --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_compose2.svg) --- --- --- -- Simulate Windows 7 'edge snap' (also called aero snap) feature --- local axis = 'vertically' --- local f = awful.placement.scale --- + awful.placement.left --- + (axis and awful.placement['maximize_'..axis] or nil) --- local geo = f(client.focus, {honor_workarea=true, to_percent = 0.5}) --- --- <h3>Common arguments</h3> --- --- **pretend** (*boolean*): --- --- Do not apply the new geometry. This is useful if only the return values is --- necessary. --- --- **honor_workarea** (*boolean*): --- --- Take workarea into account when placing the drawable (default: false) --- --- **honor_padding** (*boolean*): --- --- Take the screen padding into account (see `screen.padding`) --- --- **tag** (*tag*): --- --- Use a tag geometry --- --- **margins** (*number* or *table*): --- --- A table with left, right, top, bottom keys or a number --- --- **parent** (client, wibox, mouse or screen): --- --- A parent drawable to use a base geometry --- --- **bounding_rect** (table): --- --- A bounding rectangle --- --- **attach** (*boolean*): --- --- When the parent geometry (like the screen) changes, re-apply the placement --- function. This will add a `detach_callback` function to the drawable. Call --- this to detach the function. This will be called automatically when a new --- attached function is set. --- --- **offset** (*table or number*): --- --- The offset(s) to apply to the new geometry. --- --- **store_geometry** (*boolean*): --- --- Keep a single history of each type of placement. It can be restored using --- `awful.placement.restore` by setting the right `context` argument. --- --- When either the parent or the screen geometry change, call the placement --- function again. --- --- **update_workarea** (*boolean*): --- --- If *attach* is true, also update the screen workarea. --- --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou, Emmanuel Lepage Vallee 2016 --- @module awful.placement ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local pairs = pairs -local math = math -local table = table -local capi = -{ - screen = screen, - 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 -local util = require("awful.util") -local cairo = require( "lgi" ).cairo -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) - -local function get_screen(s) - return s and capi.screen[s] -end - -local wrap_client = nil -local placement - --- Store function -> keys -local reverse_align_map = {} - --- Forward declarations -local area_common -local wibox_update_strut -local attach - ---- Allow multiple placement functions to be daisy chained. --- This also allow the functions to be aware they are being chained and act --- upon the previous nodes results to avoid unnecessary processing or deduce --- extra paramaters/arguments. -local function compose(...) - local queue = {} - - local nodes = {...} - - -- Allow placement.foo + (var == 42 and placement.bar) - if not nodes[2] then - return nodes[1] - end - - -- nodes[1] == self, nodes[2] == other - for _, w in ipairs(nodes) do - -- Build an execution queue - if w.context and w.context == "compose" then - for _, elem in ipairs(w.queue or {}) do - table.insert(queue, elem) - end - else - table.insert(queue, w) - end - end - - local ret - ret = wrap_client(function(d, args, ...) - local rets = {} - local last_geo = nil - - -- As some functions may have to take into account results from - -- previously execued ones, add the `composition_results` hint. - args = setmetatable({composition_results=rets}, {__index=args}) - - -- Only apply the geometry once, not once per chain node, to do this, - -- Force the "pretend" argument and restore the original value for - -- the last node. - local attach_real = args.attach - args.pretend = true - args.attach = false - args.offset = {} - - for k, f in ipairs(queue) do - if k == #queue then - -- Let them fallback to the parent table - args.pretend = nil - args.offset = nil - end - - local r = {f(d, args, ...)} - last_geo = r[1] or last_geo - args.override_geometry = last_geo - - -- Keep the return value, store one per context - if f.context then - -- When 2 composition queue are executed, merge the return values - if f.context == "compose" then - for k2,v in pairs(r) do - rets[k2] = v - end - else - rets[f.context] = r - end - end - end - - if attach_real then - args.attach = true - attach(d, ret, args) - end - - return last_geo, rets - end, "compose") - - ret.queue = queue - - return ret -end - -wrap_client = function(f, context) - return setmetatable( - { - is_placement= true, - context = context, - }, - { - __call = function(_,...) return f(...) end, - __add = compose, -- Composition is usually defined as + - __mul = compose -- Make sense if you think of the functions as matrices - } - ) -end - -local placement_private = {} - --- The module is a proxy in front of the "real" functions. --- This allow syntax like: --- --- (awful.placement.no_overlap + awful.placement.no_offscreen)(c) --- -placement = setmetatable({}, { - __index = placement_private, - __newindex = function(_, k, f) - placement_private[k] = wrap_client(f, k) - end -}) - --- 3x3 matrix of the valid sides and corners -local corners3x3 = {{"top_left" , "top" , "top_right" }, - {"left" , nil , "right" }, - {"bottom_left", "bottom" , "bottom_right"}} - --- 2x2 matrix of the valid sides and corners -local corners2x2 = {{"top_left" , "top_right" }, - {"bottom_left", "bottom_right"}} - --- Compute the new `x` and `y`. --- The workarea position need to be applied by the caller -local align_map = { - top_left = function(_ , _ , _ , _ ) return {x=0 , y=0 } end, - top_right = function(sw, _ , dw, _ ) return {x=sw-dw , y=0 } end, - bottom_left = function(_ , sh, _ , dh) return {x=0 , y=sh-dh } end, - bottom_right = function(sw, sh, dw, dh) return {x=sw-dw , y=sh-dh } end, - left = function(_ , sh, _ , dh) return {x=0 , y=sh/2-dh/2} end, - right = function(sw, sh, dw, dh) return {x=sw-dw , y=sh/2-dh/2} end, - top = function(sw, _ , dw, _ ) return {x=sw/2-dw/2, y=0 } end, - bottom = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=sh-dh } end, - centered = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=sh/2-dh/2} end, - center_vertical = function(_ , sh, _ , dh) return {x= nil , y=sh-dh } end, - center_horizontal = function(sw, _ , dw, _ ) return {x=sw/2-dw/2, y= nil } end, -} - --- Some parameters to correctly compute the final size -local resize_to_point_map = { - -- Corners - top_left = {p1= nil , p2={1,1}, x_only=false, y_only=false, align="bottom_right"}, - top_right = {p1={0,1} , p2= nil , x_only=false, y_only=false, align="bottom_left" }, - bottom_left = {p1= nil , p2={1,0}, x_only=false, y_only=false, align="top_right" }, - bottom_right = {p1={0,0} , p2= nil , x_only=false, y_only=false, align="top_left" }, - - -- Sides - left = {p1= nil , p2={1,1}, x_only=true , y_only=false, align="top_right" }, - right = {p1={0,0} , p2= nil , x_only=true , y_only=false, align="top_left" }, - top = {p1= nil , p2={1,1}, x_only=false, y_only=true , align="bottom_left" }, - bottom = {p1={0,0} , p2= nil , x_only=false, y_only=true , align="top_left" }, -} - --- 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, -} - ---- Add a context to the arguments. --- This function extend the argument table. The context is used by some --- internal helper methods. If there already is a context, it has priority and --- is kept. -local function add_context(args, context) - return setmetatable({context = (args or {}).context or context }, {__index=args}) -end - -local data = setmetatable({}, { __mode = 'k' }) - ---- Store a drawable geometry (per context) in a weak table. --- @param d The drawin --- @tparam string reqtype The context. -local function store_geometry(d, reqtype) - if not data[d] then data[d] = {} end - if not data[d][reqtype] then data[d][reqtype] = {} end - data[d][reqtype] = d:geometry() - data[d][reqtype].screen = d.screen - data[d][reqtype].border_width = d.border_width -end - ---- Get the margins and offset --- @tparam table args The arguments --- @treturn table The margins --- @treturn table The offsets -local function get_decoration(args) - local offset = args.offset - - -- Offset are "blind" values added to the output - offset = type(offset) == "number" and { - x = offset, - y = offset, - width = offset, - height = offset, - } or args.offset or {} - - -- Margins are distances on each side to substract from the area` - local m = type(args.margins) == "table" and args.margins or { - left = args.margins or 0 , right = args.margins or 0, - top = args.margins or 0 , bottom = args.margins or 0 - } - - return m, offset -end - ---- Apply some modifications before applying the new geometry. --- @tparam table new_geo The new geometry --- @tparam table args The common arguments --- @tparam boolean force Always ajust the geometry, even in pretent mode. This --- should only be used when returning the final geometry as it would otherwise --- mess the pipeline. --- @treturn table|nil The new geometry -local function fix_new_geometry(new_geo, args, force) - if (args.pretend and not force) or not new_geo then return nil end - - local m, offset = get_decoration(args) - - return { - x = new_geo.x and (new_geo.x + (offset.x or 0) + (m.left or 0) ), - y = new_geo.y and (new_geo.y + (offset.y or 0) + (m.top or 0) ), - width = new_geo.width and math.max( - 1, (new_geo.width + (offset.width or 0) - (m.left or 0) - (m.right or 0) ) - ), - height = new_geo.height and math.max( - 1, (new_geo.height + (offset.height or 0) - (m.top or 0) - (m.bottom or 0) ) - ), - } -end - --- Get the area covered by a drawin. --- @param d The drawin --- @tparam[opt=nil] table new_geo A new geometry --- @tparam[opt=false] boolean ignore_border_width Ignore the border --- @tparam table args the method arguments --- @treturn The drawin's area. -area_common = function(d, new_geo, ignore_border_width, args) - -- The C side expect no arguments, nil isn't valid - local geometry = new_geo and d:geometry(new_geo) or d:geometry() - local border = ignore_border_width and 0 or d.border_width or 0 - - -- When using the placement composition along with the "pretend" - -- option, it is necessary to keep a "virtual" geometry. - if args and args.override_geometry then - geometry = util.table.clone(args.override_geometry) - end - - geometry.width = geometry.width + 2 * border - geometry.height = geometry.height + 2 * border - return geometry -end - ---- Get (and optionally set) an object geometry. --- Some elements, such as `mouse` and `screen` don't have a `:geometry()` --- methods. --- @param obj An object --- @tparam table args the method arguments --- @tparam[opt=nil] table new_geo A new geometry to replace the existing one --- @tparam[opt=false] boolean ignore_border_width Ignore the border --- @treturn table A table with *x*, *y*, *width* and *height*. -local function geometry_common(obj, args, new_geo, ignore_border_width) - -- Store the current geometry in a singleton-memento - if args.store_geometry and new_geo and args.context then - store_geometry(obj, args.context) - end - - -- It's a mouse - if obj.coords then - local coords = fix_new_geometry(new_geo, args) - 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 - end - - -- It is a screen, it doesn't support setting new sizes. - return obj:get_bounding_geometry(args) - else - assert(false, "Invalid object") - end -end - ---- Get the parent geometry from the standardized arguments API shared by all --- `awful.placement` methods. --- @param obj A screen or a drawable --- @tparam table args the method arguments --- @treturn table A table with *x*, *y*, *width* and *height*. -local function get_parent_geometry(obj, args) - -- Didable override_geometry, context and other to avoid mutating the state - -- or using the wrong geo. - - if args.bounding_rect then - return args.bounding_rect - elseif args.parent then - return geometry_common(args.parent, {}) - elseif obj.screen then - return geometry_common(obj.screen, { - honor_padding = args.honor_padding, - honor_workarea = args.honor_workarea - }) - else - return geometry_common(capi.screen[capi.mouse.screen], args) - end -end - ---- Move a point into an area. --- This doesn't change the *width* and *height* values, allowing the target --- area to be smaller than the source one. --- @tparam table source The (larger) geometry to move `target` into --- @tparam table target The area to move into `source` --- @treturn table A table with *x* and *y* keys -local function move_into_geometry(source, target) - local ret = {x = target.x, y = target.y} - - -- Horizontally - if ret.x < source.x then - ret.x = source.x - elseif ret.x > source.x + source.width then - ret.x = source.x + source.width - 1 - end - - -- Vertically - if ret.y < source.y then - ret.y = source.y - elseif ret.y > source.y + source.height then - ret.y = source.y + source.height - 1 - end - - return ret -end - --- Update the workarea -wibox_update_strut = function(d, position, args) - -- If the drawable isn't visible, remove the struts - if not d.visible then - d:struts { left = 0, right = 0, bottom = 0, top = 0 } - return - end - - -- Detect horizontal or vertical drawables - local geo = area_common(d) - local vertical = geo.width < geo.height - - -- Look into the `position` string to find the relevants sides to crop from - -- the workarea - local struts = { left = 0, right = 0, bottom = 0, top = 0 } - - local m = get_decoration(args) - - if vertical then - for _, v in ipairs {"right", "left"} do - if (not position) or position:match(v) then - struts[v] = geo.width + m[v] - end - end - else - for _, v in ipairs {"top", "bottom"} do - if (not position) or position:match(v) then - struts[v] = geo.height + m[v] - end - end - end - - -- Update the workarea - d:struts(struts) -end - --- Pin a drawable to a placement function. --- Automatically update the position when the size change. --- All other arguments will be passed to the `position` function (if any) --- @tparam[opt=client.focus] drawable d A drawable (like `client`, `mouse` --- or `wibox`) --- @param position_f A position name (see `align`) or a position function --- @tparam[opt={}] table args Other arguments -attach = function(d, position_f, args) - args = args or {} - - if args.pretend then return end - - if not args.attach then return end - - -- Avoid a connection loop - args = setmetatable({attach=false}, {__index=args}) - - d = d or capi.client.focus - if not d then return end - - if type(position_f) == "string" then - position_f = placement[position_f] - end - - if not position_f then return end - - -- If there is multiple attached function, there is an high risk of infinite - -- loop. While some combinaisons are harmless, other are very hard to debug. - -- - -- Use the placement composition to build explicit multi step attached - -- placement functions. - if d.detach_callback then - d.detach_callback() - d.detach_callback = nil - end - - local function tracker() - position_f(d, args) - end - - d:connect_signal("property::width" , tracker) - d:connect_signal("property::height" , tracker) - d:connect_signal("property::border_width", tracker) - - local function tracker_struts() - --TODO this is too fragile and doesn't work with all methods. - wibox_update_strut(d, d.position or reverse_align_map[position_f], args) - end - - local parent = args.parent or d.screen - - if args.update_workarea then - d:connect_signal("property::geometry" , tracker_struts) - d:connect_signal("property::visible" , tracker_struts) - capi.client.connect_signal("property::struts", tracker_struts) - - tracker_struts() - elseif parent == d.screen then - if args.honor_workarea then - parent:connect_signal("property::workarea", tracker) - end - - if args.honor_padding then - parent:connect_signal("property::padding", tracker) - end - end - - -- If there is a parent drawable, screen, also track it. - -- Note that tracking the mouse is not supported - if parent and parent.connect_signal then - parent:connect_signal("property::geometry" , tracker) - end - - -- Create a way to detach a placement function - function d.detach_callback() - d:disconnect_signal("property::width" , tracker) - d:disconnect_signal("property::height" , tracker) - d:disconnect_signal("property::border_width", tracker) - if parent then - parent:disconnect_signal("property::geometry" , tracker) - - if parent == d.screen then - if args.honor_workarea then - parent:disconnect_signal("property::workarea", tracker) - end - - if args.honor_padding then - parent:disconnect_signal("property::padding", tracker) - end - end - end - - if args.update_workarea then - d:disconnect_signal("property::geometry" , tracker_struts) - d:disconnect_signal("property::visible" , tracker_struts) - capi.client.disconnect_signal("property::struts", tracker_struts) - end - end -end - --- Convert 2 points into a rectangle -local function rect_from_points(p1x, p1y, p2x, p2y) - return { - x = p1x, - y = p1y, - width = p2x - p1x, - height = p2y - p1y, - } -end - --- Convert a rectangle and matrix info into a point -local function rect_to_point(rect, corner_i, corner_j) - return { - x = rect.x + corner_i * math.floor(rect.width ), - y = rect.y + corner_j * math.floor(rect.height), - } -end - --- Create a pair of rectangles used to set the relative areas. --- v=vertical, h=horizontal -local function get_cross_sections(abs_geo, mode) - if not mode or mode == "cursor" then - -- A 1px cross section centered around the mouse position - local coords = capi.mouse.coords() - return { - h = { - x = abs_geo.drawable_geo.x , - y = coords.y , - width = abs_geo.drawable_geo.width , - height = 1 , - }, - v = { - x = coords.x , - y = abs_geo.drawable_geo.y , - width = 1 , - height = abs_geo.drawable_geo.height, - } - } - elseif mode == "geometry" then - -- The widget geometry extended to reach the end of the drawable - - return { - h = { - x = abs_geo.drawable_geo.x , - y = abs_geo.y , - width = abs_geo.drawable_geo.width , - height = abs_geo.height , - }, - v = { - x = abs_geo.x , - y = abs_geo.drawable_geo.y , - width = abs_geo.width , - height = abs_geo.drawable_geo.height, - } - } - elseif mode == "cursor_inside" then - -- A 1x1 rectangle centered around the mouse position - - local coords = capi.mouse.coords() - coords.width,coords.height = 1,1 - return {h=coords, v=coords} - elseif mode == "geometry_inside" then - -- The widget absolute geometry, unchanged - - return {h=abs_geo, v=abs_geo} - end -end - --- When a rectangle is embedded into a bigger one, get the regions around --- the outline of the bigger rectangle closest to the smaller one (on each side) -local function get_relative_regions(geo, mode, is_absolute) - - -- Use the mouse position and the wibox/client under it - if not geo then - local draw = capi.mouse.current_wibox - geo = draw and draw:geometry() or capi.mouse.coords() - geo.drawable = draw - elseif is_absolute then - -- Some signals are a bit inconsistent in their arguments convention. - -- This little hack tries to mitigate the issue. - - geo.drawable = geo -- is a wibox or client, geometry and object are one - -- and the same. - elseif (not geo.drawable) and geo.x and geo.width then - local coords = capi.mouse.coords() - - -- Check if the mouse is in the rect - if coords.x > geo.x and coords.x < geo.x+geo.width and - coords.y > geo.y and coords.y < geo.y+geo.height then - geo.drawable = capi.mouse.current_wibox - end - - -- Maybe there is a client - if (not geo.drawable) and capi.mouse.current_client then - geo.drawable = capi.mouse.current_client - 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} - - -- 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 , - } - - abs_widget_geo.drawable_geo = geo.drawable and dpos or geo - - -- Get the point for comparison. - local center_point = mode:match("cursor") and capi.mouse.coords() or { - x = abs_widget_geo.x + abs_widget_geo.width / 2, - y = abs_widget_geo.y + abs_widget_geo.height / 2, - } - - -- Get widget regions for both axis - local cs = get_cross_sections(abs_widget_geo, mode) - - -- Get the 4 closest points from `center_point` around the wibox - local regions = { - left = {x = cs.h.x , y = cs.h.y }, - right = {x = cs.h.x+cs.h.width, y = cs.h.y }, - top = {x = cs.v.x , y = cs.v.y }, - bottom = {x = cs.v.x , y = cs.v.y+cs.v.height}, - } - - -- Assume the section is part of a single screen until someone complains. - -- It is much faster to compute and getting it wrong probably has no side - -- effects. - local s = geo.drawable and geo.drawable.screen or a_screen.getbycoord( - center_point.x, - center_point.y - ) - - -- Compute the distance (dp) between the `center_point` and the sides. - -- This is only relevant for "cursor" and "cursor_inside" modes. - for _, v in pairs(regions) do - local dx, dy = v.x - center_point.x, v.y - center_point.y - - v.distance = math.sqrt(dx*dx + dy*dy) - v.width = cs.v.width - v.height = cs.h.height - v.screen = capi.screen[s] - end - - return regions -end - --- Check if the proposed geometry fits the screen -local function fit_in_bounding(obj, geo, args) - local sgeo = get_parent_geometry(obj, args) - local region = cairo.Region.create_rectangle(cairo.RectangleInt(sgeo)) - - region:intersect(cairo.Region.create_rectangle( - cairo.RectangleInt(geo) - )) - - local geo2 = region:get_rectangle(0) - - -- If the geometry is the same then it fits, otherwise it will be cropped. - return geo2.width == geo.width and geo2.height == geo.height -end - ---- Move a drawable to the closest corner of the parent geometry (such as the --- screen). --- --- Valid arguments include the common ones and: --- --- * **include_sides**: Also include the left, right, top and bottom positions --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_closest_mouse.svg) --- ---**Usage example output**: --- --- Closest corner: top_left --- --- --- @usage --- -- Move the mouse to the closest corner of the focused client ---awful.placement.closest_corner(mouse, {include_sides=true, parent=c}) --- -- It is possible to emulate the mouse API to get the closest corner of --- -- random area ---local _, corner = awful.placement.closest_corner( --- {coords=function() return {x = 100, y=100} end}, --- {include_sides = true, bounding_rect = {x=0, y=0, width=200, height=200}} ---) ---print('Closest corner:', corner) --- @tparam[opt=client.focus] drawable d A drawable (like `client`, `mouse` --- or `wibox`) --- @tparam[opt={}] table args The arguments --- @treturn table The new geometry --- @treturn string The corner name -function placement.closest_corner(d, args) - args = add_context(args, "closest_corner") - d = d or capi.client.focus - - local sgeo = get_parent_geometry(d, args) - local dgeo = geometry_common(d, args) - - local pos = move_into_geometry(sgeo, dgeo) - - local corner_i, corner_j, n - - -- Use the product of 3 to get the closest point in a NxN matrix - local function f(_n, mat) - n = _n - -- The +1 is required to avoid a rounding error when - -- pos.x == sgeo.x+sgeo.width - corner_i = -math.ceil( ( (sgeo.x - pos.x) * n) / (sgeo.width + 1)) - corner_j = -math.ceil( ( (sgeo.y - pos.y) * n) / (sgeo.height + 1)) - return mat[corner_j + 1][corner_i + 1] - end - - -- Turn the area into a grid and snap to the cloest point. This size of the - -- grid will increase the accuracy. A 2x2 matrix only include the corners, - -- at 3x3, this include the sides too technically, a random size would work, - -- but without corner names. - local grid_size = args.include_sides and 3 or 2 - - -- If the point is in the center, use the closest corner - local corner = grid_size == 3 and f(3, corners3x3) or f(2, corners2x2) - - -- Transpose the corner back to the original size - local new_args = setmetatable({position = corner}, {__index=args}) - local ngeo = placement_private.align(d, new_args) - - return fix_new_geometry(ngeo, args, true), corner -end - ---- Place the client so no part of it will be outside the screen (workarea). --- --- ---![Usage example](../images/AUTOGEN_awful_placement_no_offscreen.svg) --- ---**Usage example output**: --- --- Before: x=-30, y=-30, width=100, height=100 --- After: x=10, y=10, width=100, height=100 --- --- --- @usage ---awful.placement.no_offscreen(c)--, {honor_workarea=true, margins=40}) --- @client c The client. --- @tparam[opt=client's screen] integer screen The screen. --- @treturn table The new client geometry. -function placement.no_offscreen(c, screen) - --HACK necessary for composition to work. The API will be changed soon - if type(screen) == "table" then - screen = nil - end - - c = c or capi.client.focus - local geometry = area_common(c) - screen = get_screen(screen or c.screen or a_screen.getbycoord(geometry.x, geometry.y)) - local screen_geometry = screen.workarea - - if geometry.x + geometry.width > screen_geometry.x + screen_geometry.width then - geometry.x = screen_geometry.x + screen_geometry.width - geometry.width - end - if geometry.x < screen_geometry.x then - geometry.x = screen_geometry.x - end - - if geometry.y + geometry.height > screen_geometry.y + screen_geometry.height then - geometry.y = screen_geometry.y + screen_geometry.height - geometry.height - end - if geometry.y < screen_geometry.y then - geometry.y = screen_geometry.y - end - - return c:geometry { - x = geometry.x, - y = geometry.y - } -end - ---- Place the client where there's place available with minimum overlap. --- --- ---![Usage example](../images/AUTOGEN_awful_placement_no_overlap.svg) --- --- @usage ---awful.placement.no_overlap(client.focus) ---local x,y = screen[4].geometry.x, screen[4].geometry.y --- @param c The client. --- @treturn table The new geometry -function placement.no_overlap(c) - c = c or capi.client.focus - local geometry = area_common(c) - local screen = get_screen(c.screen or a_screen.getbycoord(geometry.x, geometry.y)) - local cls = client.visible(screen) - local curlay = layout.get() - local areas = { screen.workarea } - for _, cl in pairs(cls) do - if cl ~= c and cl.type ~= "desktop" and (cl.floating or curlay == layout.suit.floating) then - areas = grect.area_remove(areas, area_common(cl)) - end - end - - -- Look for available space - local found = false - local new = { x = geometry.x, y = geometry.y, width = 0, height = 0 } - for _, r in ipairs(areas) do - if r.width >= geometry.width - and r.height >= geometry.height - and r.width * r.height > new.width * new.height then - found = true - new = r - -- Check if the client's current position is available - -- and prefer that one (why move it around pointlessly?) - if geometry.x >= r.x - and geometry.y >= r.y - and geometry.x + geometry.width <= r.x + r.width - and geometry.y + geometry.height <= r.y + r.height then - new.x = geometry.x - new.y = geometry.y - end - end - end - - -- We did not find an area with enough space for our size: - -- just take the biggest available one and go in. - -- This makes sure to have the whole screen's area in case it has been - -- removed. - if not found then - if #areas == 0 then - areas = { screen.workarea } - end - for _, r in ipairs(areas) do - if r.width * r.height > new.width * new.height then - new = r - end - end - end - - -- Restore height and width - new.width = geometry.width - new.height = geometry.height - - return c:geometry({ x = new.x, y = new.y }) -end - ---- Place the client under the mouse. --- --- ---![Usage example](../images/AUTOGEN_awful_placement_under_mouse.svg) --- --- @usage ---awful.placement.under_mouse(client.focus) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry -function placement.under_mouse(d, args) - args = add_context(args, "under_mouse") - d = d or capi.client.focus - - local m_coords = capi.mouse.coords() - - local ngeo = geometry_common(d, args) - ngeo.x = math.floor(m_coords.x - ngeo.width / 2) - ngeo.y = math.floor(m_coords.y - ngeo.height / 2) - - local bw = d.border_width or 0 - ngeo.width = ngeo.width - 2*bw - ngeo.height = ngeo.height - 2*bw - - geometry_common(d, args, ngeo) - - return fix_new_geometry(ngeo, args, true) -end - ---- Place the client next to the mouse. --- --- It will place `c` next to the mouse pointer, trying the following positions --- in this order: right, left, above and below. --- --- ---![Usage example](../images/AUTOGEN_awful_placement_next_to_mouse.svg) --- --- @usage ---awful.placement.next_to_mouse(client.focus) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry -function placement.next_to_mouse(d, args) - if type(args) == "number" then - util.deprecate( - "awful.placement.next_to_mouse offset argument is deprecated".. - " use awful.placement.next_to_mouse(c, {offset={x=...}})" - ) - args = nil - end - - local old_args = args or {} - - args = add_context(args, "next_to_mouse") - d = d or capi.client.focus - - local sgeo = get_parent_geometry(d, args) - - args.pretend = true - args.parent = capi.mouse - - local ngeo = placement.left(d, args) - - if ngeo.x + ngeo.width > sgeo.x+sgeo.width then - ngeo = placement.right(d, args) - else - -- It is _next_ to mouse, not under_mouse - ngeo.x = ngeo.x+1 - end - - args.pretend = old_args.pretend - - geometry_common(d, args, ngeo) - - attach(d, placement.next_to_mouse, old_args) - - return fix_new_geometry(ngeo, args, true) -end - ---- Resize the drawable to the cursor. --- --- Valid args: --- --- * *axis*: The axis (vertical or horizontal). If none is --- specified, then the drawable will be resized on both axis. --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_resize_to_mouse.svg) --- --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry -function placement.resize_to_mouse(d, args) - d = d or capi.client.focus - args = add_context(args, "resize_to_mouse") - - local coords = capi.mouse.coords() - local ngeo = geometry_common(d, args) - local h_only = args.axis == "horizontal" - local v_only = args.axis == "vertical" - - -- To support both growing and shrinking the drawable, it is necessary - -- to decide to use either "north or south" and "east or west" directions. - -- Otherwise, the result will always be 1x1 - local _, closest_corner = placement.closest_corner(capi.mouse, { - parent = d, - pretend = true, - include_sides = args.include_sides or false, - }) - - -- Given "include_sides" wasn't set, it will always return a name - -- with the 2 axis. If only one axis is needed, adjust the result - if h_only then - closest_corner = closest_corner:match("left") or closest_corner:match("right") - elseif v_only then - closest_corner = closest_corner:match("top") or closest_corner:match("bottom") - end - - -- Use p0 (mouse), p1 and p2 to create a rectangle - local pts = resize_to_point_map[closest_corner] - local p1 = pts.p1 and rect_to_point(ngeo, pts.p1[1], pts.p1[2]) or coords - local p2 = pts.p2 and rect_to_point(ngeo, pts.p2[1], pts.p2[2]) or coords - - -- Create top_left and bottom_right points, convert to rectangle - ngeo = rect_from_points( - pts.y_only and ngeo.x or math.min(p1.x, p2.x), - pts.x_only and ngeo.y or math.min(p1.y, p2.y), - pts.y_only and ngeo.x + ngeo.width or math.max(p2.x, p1.x), - pts.x_only and ngeo.y + ngeo.height or math.max(p2.y, p1.y) - ) - - local bw = d.border_width or 0 - - for _, a in ipairs {"width", "height"} do - ngeo[a] = ngeo[a] - 2*bw - end - - -- Now, correct the geometry by the given size_hints offset - if d.apply_size_hints then - local w, h = d:apply_size_hints( - ngeo.width, - ngeo.height - ) - local offset = align_map[pts.align](w, h, ngeo.width, ngeo.height) - ngeo.x = ngeo.x - offset.x - ngeo.y = ngeo.y - offset.y - end - - geometry_common(d, args, ngeo) - - return fix_new_geometry(ngeo, args, true) -end - ---- Move the drawable (client or wibox) `d` to a screen position or side. --- --- Supported args.positions are: --- --- * top_left --- * top_right --- * bottom_left --- * bottom_right --- * left --- * right --- * top --- * bottom --- * centered --- * center_vertical --- * center_horizontal --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_align.svg) --- --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry -function placement.align(d, args) - args = add_context(args, "align") - d = d or capi.client.focus - - if not d or not args.position then return end - - local sgeo = get_parent_geometry(d, args) - local dgeo = geometry_common(d, args) - local bw = d.border_width or 0 - - local pos = align_map[args.position]( - sgeo.width , - sgeo.height, - dgeo.width , - dgeo.height - ) - - local ngeo = { - x = (pos.x and math.ceil(sgeo.x + pos.x) or dgeo.x) , - y = (pos.y and math.ceil(sgeo.y + pos.y) or dgeo.y) , - width = math.ceil(dgeo.width ) - 2*bw, - height = math.ceil(dgeo.height ) - 2*bw, - } - - geometry_common(d, args, ngeo) - - attach(d, placement[args.position], args) - - return fix_new_geometry(ngeo, args, true) -end - --- Add the alias functions -for k in pairs(align_map) do - placement[k] = function(d, args) - args = add_context(args, k) - args.position = k - return placement_private.align(d, args) - end - reverse_align_map[placement[k]] = k -end - --- Add the documentation for align alias - ---- --- Align a client to the top left of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_top_left.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name top_left --- @class function --- --- @usage ---awful.placement.top_left(client.focus) - ---- --- Align a client to the top right of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_top_right.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name top_right --- @class function --- --- @usage ---awful.placement.top_right(client.focus) - ---- --- Align a client to the bottom left of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_bottom_left.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name bottom_left --- @class function --- --- @usage ---awful.placement.bottom_left(client.focus) - ---- --- Align a client to the bottom right of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_bottom_right.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name bottom_right --- @class function --- --- @usage ---awful.placement.bottom_right(client.focus) - ---- --- Align a client to the left of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_left.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name left --- @class function --- --- @usage ---awful.placement.left(client.focus) - ---- --- Align a client to the right of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_right.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name right --- @class function --- --- @usage ---awful.placement.right(client.focus) - ---- --- Align a client to the top of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_top.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name top --- @class function --- --- @usage ---awful.placement.top(client.focus) ---assert(c.x == screen[1].geometry.width/2-40/2-c.border_width) - ---- --- Align a client to the bottom of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_bottom.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name bottom --- @class function --- --- @usage ---awful.placement.bottom(client.focus) - ---- --- Align a client to the center of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_centered.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name centered --- @class function --- --- @usage ---awful.placement.centered(client.focus) - ---- --- Align a client to the vertical center of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_center_vertical.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @name center_vertical --- @class function --- --- @usage ---awful.placement.center_vertical(client.focus) - ---- --- Align a client to the horizontal center left of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_center_horizontal.svg) --- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @treturn table The new geometry --- @name center_horizontal --- @class function --- --- @usage ---awful.placement.center_horizontal(client.focus) - ---- Stretch a drawable in a specific direction. --- Valid args: --- --- * **direction**: The stretch direction (*left*, *right*, *up*, *down*) or --- a table with multiple directions. --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_stretch.svg) --- --- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args The arguments --- @treturn table The new geometry -function placement.stretch(d, args) - args = add_context(args, "stretch") - - d = d or capi.client.focus - if not d or not args.direction then return end - - -- In case there is multiple directions, call `stretch` for each of them - if type(args.direction) == "table" then - for _, dir in ipairs(args.direction) do - args.direction = dir - placement_private.stretch(dir, args) - end - return - end - - local sgeo = get_parent_geometry(d, args) - local dgeo = geometry_common(d, args) - local ngeo = geometry_common(d, args, nil, true) - local bw = d.border_width or 0 - - if args.direction == "left" then - ngeo.x = sgeo.x - ngeo.width = dgeo.width + (dgeo.x - ngeo.x) - elseif args.direction == "right" then - ngeo.width = sgeo.width - ngeo.x - 2*bw - elseif args.direction == "up" then - ngeo.y = sgeo.y - ngeo.height = dgeo.height + (dgeo.y - ngeo.y) - elseif args.direction == "down" then - ngeo.height = sgeo.height - dgeo.y - 2*bw - else - assert(false) - end - - -- Avoid negative sizes if args.parent isn't compatible - ngeo.width = math.max(args.minimim_width or 1, ngeo.width ) - ngeo.height = math.max(args.minimim_height or 1, ngeo.height) - - geometry_common(d, args, ngeo) - - attach(d, placement["stretch_"..args.direction], args) - - return fix_new_geometry(ngeo, args, true) -end - --- Add the alias functions -for _,v in ipairs {"left", "right", "up", "down"} do - placement["stretch_"..v] = function(d, args) - args = add_context(args, "stretch_"..v) - args.direction = v - return placement_private.stretch(d, args) - end -end - ---- --- Stretch the drawable to the left of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_stretch_left.svg) --- @tparam drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry --- @name stretch_left --- @class function --- --- @usage ---placement.stretch_left(client.focus) - ---- --- Stretch the drawable to the right of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_stretch_right.svg) --- @tparam drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry --- @name stretch_right --- @class function --- --- @usage ---placement.stretch_right(client.focus) - ---- --- Stretch the drawable to the top of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_stretch_up.svg) --- @tparam drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry --- @name stretch_up --- @class function --- --- @usage ---placement.stretch_up(client.focus) - ---- --- Stretch the drawable to the bottom of the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_stretch_down.svg) --- @tparam drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args Other arguments --- @treturn table The new geometry --- @name stretch_down --- @class function --- --- @usage ---placement.stretch_down(client.focus) - ---- Maximize a drawable horizontally, vertically or both. --- Valid args: --- --- * *axis*:The axis (vertical or horizontal). If none is --- specified, then the drawable will be maximized on both axis. --- --- --- ---![Usage example](../images/AUTOGEN_awful_placement_maximize.svg) --- --- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args The arguments --- @treturn table The new geometry -function placement.maximize(d, args) - args = add_context(args, "maximize") - d = d or capi.client.focus - - if not d then return end - - local sgeo = get_parent_geometry(d, args) - local ngeo = geometry_common(d, args, nil, true) - local bw = d.border_width or 0 - - if (not args.axis) or args.axis :match "vertical" then - ngeo.y = sgeo.y - ngeo.height = sgeo.height - 2*bw - end - - if (not args.axis) or args.axis :match "horizontal" then - ngeo.x = sgeo.x - ngeo.width = sgeo.width - 2*bw - end - - geometry_common(d, args, ngeo) - - attach(d, placement.maximize, args) - - return fix_new_geometry(ngeo, args, true) -end - --- Add the alias functions -for _, v in ipairs {"vertically", "horizontally"} do - placement["maximize_"..v] = function(d2, args) - args = add_context(args, "maximize_"..v) - args.axis = v - return placement_private.maximize(d2, args) - end -end - ---- --- Vetically maximize the drawable in the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_maximize_vertically.svg) --- @tparam drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @name maximize_vertically --- @class function --- --- @usage ---placement.maximize_vertically(c) - ---- --- Horizontally maximize the drawable in the parent area. --- ---![Usage example](../images/AUTOGEN_awful_placement_maximize_horizontally.svg) --- @tparam drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args Other arguments') --- @name maximize_horizontally --- @class function --- --- @usage ---placement.maximize_horizontally(c) - ---- Scale the drawable by either a relative or absolute percent. --- --- Valid args: --- --- **to_percent** : A number between 0 and 1. It represent a percent related to --- the parent geometry. --- **by_percent** : A number between 0 and 1. It represent a percent related to --- the current size. --- **direction**: Nothing or "left", "right", "up", "down". --- --- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args The arguments --- @treturn table The new geometry -function placement.scale(d, args) - args = add_context(args, "scale_to_percent") - d = d or capi.client.focus - - local to_percent = args.to_percent - local by_percent = args.by_percent - - local percent = to_percent or by_percent - - local direction = args.direction - - local sgeo = get_parent_geometry(d, args) - local ngeo = geometry_common(d, args, nil) - - local old_area = {width = ngeo.width, height = ngeo.height} - - if (not direction) or direction == "left" or direction == "right" then - ngeo.width = (to_percent and sgeo or ngeo).width*percent - - if direction == "left" then - ngeo.x = ngeo.x - (ngeo.width - old_area.width) - end - end - - if (not direction) or direction == "up" or direction == "down" then - ngeo.height = (to_percent and sgeo or ngeo).height*percent - - if direction == "up" then - ngeo.y = ngeo.y - (ngeo.height - old_area.height) - end - end - - local bw = d.border_width or 0 - ngeo.width = ngeo.width - 2*bw - ngeo.height = ngeo.height - 2*bw - - geometry_common(d, args, ngeo) - - attach(d, placement.maximize, args) - - return fix_new_geometry(ngeo, args, true) -end - ---- Move a drawable to a relative position next to another one. --- --- The `args.preferred_positions` look like this: --- --- {"top", "right", "left", "bottom"} --- --- In that case, if there is room on the top of the geomtry, 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 args.geometry A geometry inside the other drawable --- @treturn table The new geometry --- @treturn string The choosen position --- @treturn string The choosen direction -function placement.next_to(d, args) - args = add_context(args, "next_to") - d = d or capi.client.focus - - local preferred_positions = {} - - if #(args.preferred_positions or {}) then - for k, v in ipairs(args.preferred_positions) do - preferred_positions[v] = k - end - end - - local dgeo = geometry_common(d, args) - local pref_idx, pref_name = 99, nil - local mode,wgeo = args.mode - - if args.geometry then - mode = "geometry" - wgeo = args.geometry - else - local pos = capi.mouse.current_widget_geometry - - if pos then - wgeo, mode = pos, "cursor" - elseif capi.mouse.current_client then - wgeo, mode = capi.mouse.current_client:geometry(), "cursor" - end - end - - if not wgeo then return end - - -- See get_relative_regions comments - local is_absolute = wgeo.ontop ~= nil - - local regions = get_relative_regions(wgeo, mode, is_absolute) - - -- 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 - 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) - - -- Try the other compatible geometry - if not fit then - geo, dir = outer_positions[k.."2"](v, dgeo.width, dgeo.height) - geo.width, geo.height = dgeo.width, dgeo.height - fit = fit_in_bounding(v.screen, geo, args) - end - - does_fit[k] = 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 - end - - -- No need to continue - if fit and preferred_positions[k] == 1 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 - - geometry_common(d, args, ngeo) - - attach(d, placement.next_to, args) - - return fix_new_geometry(ngeo, args, true), pos_name, dir -end - ---- Restore the geometry. --- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`) --- @tparam[opt={}] table args The arguments --- @treturn boolean If the geometry was restored -function placement.restore(d, args) - if not args or not args.context then return false end - d = d or capi.client.focus - - if not data[d] then return false end - - local memento = data[d][args.context] - - if not memento then return false end - - memento.screen = nil --TODO use it - - d.border_width = memento.border_width - - d:geometry(memento) - return true -end - -return placement - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/prompt.lua b/awesome/lib/awful/prompt.lua deleted file mode 100644 index 9a86475..0000000 --- a/awesome/lib/awful/prompt.lua +++ /dev/null @@ -1,777 +0,0 @@ ---------------------------------------------------------------------------- ---- Prompt module for awful. --- --- By default, `rc.lua` will create one `awful.widget.prompt` per screen called --- `mypromptbox`. It is used for both the command execution (`mod4+r`) and --- Lua prompt (`mod4+x`). It can be re-used for random inputs using: --- --- -- Create a shortcut function --- local function echo_test() --- awful.prompt.run { --- prompt = "Echo: ", --- textbox = mouse.screen.mypromptbox.widget, --- exe_callback = function(input) --- if not input or #input == 0 then return end --- naughty.notify{ text = "The input was: "..input } --- end --- } --- end --- --- -- Then **IN THE globalkeys TABLE** add a new shortcut --- awful.key({ modkey }, "e", echo_test, --- {description = "Echo a string", group = "custom"}), --- --- Note that this assumes an `rc.lua` file based on the default one. The way --- to access the screen prompt may vary. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful.prompt ---------------------------------------------------------------------------- - --- Grab environment we need -local assert = assert -local io = io -local table = table -local math = math -local ipairs = ipairs -local pcall = pcall -local capi = -{ - selection = selection -} -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local keygrabber = require("awful.keygrabber") -local util = require("awful.util") -local beautiful = require("beautiful") -local akey = require("awful.key") - -local prompt = {} - ---- Private data -local data = {} -data.history = {} - -local search_term = nil -local function itera (inc,a, i) - i = i + inc - local v = a[i] - if v then return i,v end -end - ---- Load history file in history table --- @param id The data.history identifier which is the path to the filename. --- @param[opt] max The maximum number of entries in file. -local function history_check_load(id, max) - if id and id ~= "" and not data.history[id] then - data.history[id] = { max = 50, table = {} } - - if max then - data.history[id].max = max - end - - local f = io.open(id, "r") - if not f then return end - - -- Read history file - for line in f:lines() do - if util.table.hasitem(data.history[id].table, line) == nil then - table.insert(data.history[id].table, line) - if #data.history[id].table >= data.history[id].max then - break - end - end - end - f:close() - end -end - -local function is_word_char(c) - if string.find("[{[(,.:;_-+=@/ ]", c) then - return false - else - return true - end -end - -local function cword_start(s, pos) - local i = pos - if i > 1 then - i = i - 1 - end - while i >= 1 and not is_word_char(s:sub(i, i)) do - i = i - 1 - end - while i >= 1 and is_word_char(s:sub(i, i)) do - i = i - 1 - end - if i <= #s then - i = i + 1 - end - return i -end - -local function cword_end(s, pos) - local i = pos - while i <= #s and not is_word_char(s:sub(i, i)) do - i = i + 1 - end - while i <= #s and is_word_char(s:sub(i, i)) do - i = i + 1 - end - return i -end - ---- Save history table in history file --- @param id The data.history identifier -local function history_save(id) - if data.history[id] then - local f = io.open(id, "w") - if not f then - local i = 0 - for d in id:gmatch(".-/") do - i = i + #d - end - util.mkdir(id:sub(1, i - 1)) - f = assert(io.open(id, "w")) - end - for i = 1, math.min(#data.history[id].table, data.history[id].max) do - f:write(data.history[id].table[i] .. "\n") - end - f:close() - end -end - ---- Return the number of items in history table regarding the id --- @param id The data.history identifier --- @return the number of items in history table, -1 if history is disabled -local function history_items(id) - if data.history[id] then - return #data.history[id].table - else - return -1 - end -end - ---- Add an entry to the history file --- @param id The data.history identifier --- @param command The command to add -local function history_add(id, command) - if data.history[id] and command ~= "" then - local index = util.table.hasitem(data.history[id].table, command) - if index == nil then - table.insert(data.history[id].table, command) - - -- Do not exceed our max_cmd - if #data.history[id].table > data.history[id].max then - table.remove(data.history[id].table, 1) - end - - history_save(id) - else - -- Bump this command to the end of history - table.remove(data.history[id].table, index) - table.insert(data.history[id].table, command) - history_save(id) - end - end -end - - ---- Draw the prompt text with a cursor. --- @tparam table args The table of arguments. --- @field text The text. --- @field font The font. --- @field prompt The text prefix. --- @field text_color The text color. --- @field cursor_color The cursor color. --- @field cursor_pos The cursor position. --- @field cursor_ul The cursor underline style. --- @field selectall If true cursor is rendered on the entire text. -local function prompt_text_with_cursor(args) - local char, spacer, text_start, text_end, ret - local text = args.text or "" - local _prompt = args.prompt or "" - local underline = args.cursor_ul or "none" - - if args.selectall then - if #text == 0 then char = " " else char = util.escape(text) end - spacer = " " - text_start = "" - text_end = "" - elseif #text < args.cursor_pos then - char = " " - spacer = "" - text_start = util.escape(text) - text_end = "" - else - char = util.escape(text:sub(args.cursor_pos, args.cursor_pos)) - spacer = " " - text_start = util.escape(text:sub(1, args.cursor_pos - 1)) - text_end = util.escape(text:sub(args.cursor_pos + 1)) - end - - local cursor_color = util.ensure_pango_color(args.cursor_color) - local text_color = util.ensure_pango_color(args.text_color) - - ret = _prompt .. text_start .. "<span background=\"" .. cursor_color .. - "\" foreground=\"" .. text_color .. "\" underline=\"" .. underline .. - "\">" .. char .. "</span>" .. text_end .. spacer - return ret -end - ---- Run a prompt in a box. --- --- The following readline keyboard shortcuts are implemented as expected: --- <kbd>CTRL+A</kbd>, <kbd>CTRL+B</kbd>, <kbd>CTRL+C</kbd>, <kbd>CTRL+D</kbd>, --- <kbd>CTRL+E</kbd>, <kbd>CTRL+J</kbd>, <kbd>CTRL+M</kbd>, <kbd>CTRL+F</kbd>, --- <kbd>CTRL+H</kbd>, <kbd>CTRL+K</kbd>, <kbd>CTRL+U</kbd>, <kbd>CTRL+W</kbd>, --- <kbd>CTRL+BACKSPACE</kbd>, <kbd>SHIFT+INSERT</kbd>, <kbd>HOME</kbd>, --- <kbd>END</kbd> and arrow keys. --- --- The following shortcuts implement additional history manipulation commands --- where the search term is defined as the substring of the command from first --- character to cursor position. --- --- * <kbd>CTRL+R</kbd>: reverse history search, matches any history entry --- containing search term. --- * <kbd>CTRL+S</kbd>: forward history search, matches any history entry --- containing search term. --- * <kbd>CTRL+UP</kbd>: ZSH up line or search, matches any history entry --- starting with search term. --- * <kbd>CTRL+DOWN</kbd>: ZSH down line or search, matches any history --- entry starting with search term. --- * <kbd>CTRL+DELETE</kbd>: delete the currently visible history entry from --- history file. This does not delete new commands or history entries under --- user editing. --- --- @tparam[opt={}] table args A table with optional arguments --- @tparam[opt] gears.color args.fg_cursor --- @tparam[opt] gears.color args.bg_cursor --- @tparam[opt] gears.color args.ul_cursor --- @tparam[opt] widget args.prompt --- @tparam[opt] string args.text --- @tparam[opt] boolean args.selectall --- @tparam[opt] string args.font --- @tparam[opt] boolean args.autoexec --- @tparam widget args.textbox The textbox to use for the prompt. --- @tparam function args.exe_callback The callback function to call with command as argument --- when finished. --- @tparam function args.completion_callback The callback function to call to get completion. --- @tparam[opt] string args.history_path File path where the history should be --- saved, set nil to disable history --- @tparam[opt] function args.history_max Set the maximum entries in history --- file, 50 by default --- @tparam[opt] function args.done_callback The callback function to always call --- without arguments, regardless of whether the prompt was cancelled. --- @tparam[opt] function args.changed_callback The callback function to call --- with command as argument when a command was changed. --- @tparam[opt] function args.keypressed_callback The callback function to call --- with mod table, key and command as arguments when a key was pressed. --- @tparam[opt] function args.keyreleased_callback The callback function to call --- with mod table, key and command as arguments when a key was pressed. --- @tparam[opt] table args.hooks The "hooks" argument uses a syntax similar to --- `awful.key`. It will call a function for the matching modifiers + key. --- It receives the command (widget text/input) as an argument. --- If the callback returns a command, this will be passed to the --- `exe_callback`, otherwise nothing gets executed by default, and the hook --- needs to handle it. --- hooks = { --- -- Apply startup notification properties with Shift-Return. --- {{"Shift" }, "Return", function(command) --- awful.screen.focused().mypromptbox:spawn_and_handle_error( --- command, {floating=true}) --- end}, --- -- Override default behavior of "Return": launch commands prefixed --- -- with ":" in a terminal. --- {{}, "Return", function(command) --- if command:sub(1,1) == ":" then --- return terminal .. ' -e ' .. command:sub(2) --- end --- return command --- end} --- } --- @param textbox The textbox to use for the prompt. [**DEPRECATED**] --- @param exe_callback The callback function to call with command as argument --- when finished. [**DEPRECATED**] --- @param completion_callback The callback function to call to get completion. --- [**DEPRECATED**] --- @param[opt] history_path File path where the history should be --- saved, set nil to disable history [**DEPRECATED**] --- @param[opt] history_max Set the maximum entries in history --- file, 50 by default [**DEPRECATED**] --- @param[opt] done_callback The callback function to always call --- without arguments, regardless of whether the prompt was cancelled. --- [**DEPRECATED**] --- @param[opt] changed_callback The callback function to call --- with command as argument when a command was changed. [**DEPRECATED**] --- @param[opt] keypressed_callback The callback function to call --- with mod table, key and command as arguments when a key was pressed. --- [**DEPRECATED**] --- @see gears.color -function prompt.run(args, textbox, exe_callback, completion_callback, - history_path, history_max, done_callback, - changed_callback, keypressed_callback) - local grabber - local theme = beautiful.get() - if not args then args = {} end - local command = args.text or "" - local command_before_comp - local cur_pos_before_comp - local prettyprompt = args.prompt or "" - local inv_col = args.fg_cursor or theme.fg_focus or "black" - local cur_col = args.bg_cursor or theme.bg_focus or "white" - local cur_ul = args.ul_cursor - local text = args.text or "" - local font = args.font or theme.font - local selectall = args.selectall - local hooks = {} - - -- A function with 9 parameters deserve to die - if textbox then - util.deprecate("Use args.textbox instead of the textbox parameter") - end - if exe_callback then - util.deprecate( - "Use args.exe_callback instead of the exe_callback parameter" - ) - end - if completion_callback then - util.deprecate( - "Use args.completion_callback instead of the completion_callback parameter" - ) - end - if history_path then - util.deprecate( - "Use args.history_path instead of the history_path parameter" - ) - end - if history_max then - util.deprecate( - "Use args.history_max instead of the history_max parameter" - ) - end - if done_callback then - util.deprecate( - "Use args.done_callback instead of the done_callback parameter" - ) - end - if changed_callback then - util.deprecate( - "Use args.changed_callback instead of the changed_callback parameter" - ) - end - if keypressed_callback then - util.deprecate( - "Use args.keypressed_callback instead of the keypressed_callback parameter" - ) - end - - -- This function has already an absurd number of parameters, allow them - -- to be set using the args to avoid a "nil, nil, nil, nil, foo" scenario - keypressed_callback = keypressed_callback or args.keypressed_callback - changed_callback = changed_callback or args.changed_callback - done_callback = done_callback or args.done_callback - history_max = history_max or args.history_max - history_path = history_path or args.history_path - completion_callback = completion_callback or args.completion_callback - exe_callback = exe_callback or args.exe_callback - textbox = textbox or args.textbox - - search_term=nil - - history_check_load(history_path, history_max) - local history_index = history_items(history_path) + 1 - -- The cursor position - local cur_pos = (selectall and 1) or text:wlen() + 1 - -- The completion element to use on completion request. - local ncomp = 1 - if not textbox then - return - end - - -- Build the hook map - for _,v in ipairs(args.hooks or {}) do - if #v == 3 then - local _,key,callback = unpack(v) - if type(callback) == "function" then - hooks[key] = hooks[key] or {} - hooks[key][#hooks[key]+1] = v - else - assert("The hook's 3rd parameter has to be a function.") - end - else - assert("The hook has to have 3 parameters.") - end - end - - textbox:set_font(font) - textbox:set_markup(prompt_text_with_cursor{ - text = text, text_color = inv_col, cursor_color = cur_col, - cursor_pos = cur_pos, cursor_ul = cur_ul, selectall = selectall, - prompt = prettyprompt }) - - local function exec(cb, command_to_history) - textbox:set_markup("") - history_add(history_path, command_to_history) - keygrabber.stop(grabber) - if cb then cb(command) end - if done_callback then done_callback() end - end - - -- Update textbox - local function update() - textbox:set_font(font) - textbox:set_markup(prompt_text_with_cursor{ - text = command, text_color = inv_col, cursor_color = cur_col, - cursor_pos = cur_pos, cursor_ul = cur_ul, selectall = selectall, - prompt = prettyprompt }) - end - - grabber = keygrabber.run( - function (modifiers, key, event) - -- Convert index array to hash table - local mod = {} - for _, v in ipairs(modifiers) do mod[v] = true end - - if event ~= "press" then - if args.keyreleased_callback then - args.keyreleased_callback(mod, key, command) - end - - return - end - - -- Call the user specified callback. If it returns true as - -- the first result then return from the function. Treat the - -- second and third results as a new command and new prompt - -- to be set (if provided) - if keypressed_callback then - local user_catched, new_command, new_prompt = - keypressed_callback(mod, key, command) - if new_command or new_prompt then - if new_command then - command = new_command - end - if new_prompt then - prettyprompt = new_prompt - end - update() - end - if user_catched then - if changed_callback then - changed_callback(command) - end - return - end - end - - local filtered_modifiers = {} - - -- User defined cases - if hooks[key] then - -- Remove caps and num lock - for _, m in ipairs(modifiers) do - if not util.table.hasitem(akey.ignore_modifiers, m) then - table.insert(filtered_modifiers, m) - end - end - - for _,v in ipairs(hooks[key]) do - if #filtered_modifiers == #v[1] then - local match = true - for _,v2 in ipairs(v[1]) do - match = match and mod[v2] - end - if match then - local cb - local ret = v[3](command) - local original_command = command - if ret then - command = ret - cb = exe_callback - else - -- No callback. - cb = function() end - end - exec(cb, original_command) - return - end - end - end - end - - -- Get out cases - if (mod.Control and (key == "c" or key == "g")) - or (not mod.Control and key == "Escape") then - keygrabber.stop(grabber) - textbox:set_markup("") - history_save(history_path) - if done_callback then done_callback() end - return false - elseif (mod.Control and (key == "j" or key == "m")) - or (not mod.Control and key == "Return") - or (not mod.Control and key == "KP_Enter") then - exec(exe_callback, command) - -- We already unregistered ourselves so we don't want to return - -- true, otherwise we may unregister someone else. - return - end - - -- Control cases - if mod.Control then - selectall = nil - if key == "a" then - cur_pos = 1 - elseif key == "b" then - if cur_pos > 1 then - cur_pos = cur_pos - 1 - end - elseif key == "d" then - if cur_pos <= #command then - command = command:sub(1, cur_pos - 1) .. command:sub(cur_pos + 1) - end - elseif key == "p" then - if history_index > 1 then - history_index = history_index - 1 - - command = data.history[history_path].table[history_index] - cur_pos = #command + 2 - end - elseif key == "n" then - if history_index < history_items(history_path) then - history_index = history_index + 1 - - command = data.history[history_path].table[history_index] - cur_pos = #command + 2 - elseif history_index == history_items(history_path) then - history_index = history_index + 1 - - command = "" - cur_pos = 1 - end - elseif key == "e" then - cur_pos = #command + 1 - elseif key == "r" then - search_term = search_term or command:sub(1, cur_pos - 1) - for i,v in (function(a,i) return itera(-1,a,i) end), data.history[history_path].table, history_index do - if v:find(search_term,1,true) ~= nil then - command=v - history_index=i - cur_pos=#command+1 - break - end - end - elseif key == "s" then - search_term = search_term or command:sub(1, cur_pos - 1) - for i,v in (function(a,i) return itera(1,a,i) end), data.history[history_path].table, history_index do - if v:find(search_term,1,true) ~= nil then - command=v - history_index=i - cur_pos=#command+1 - break - end - end - elseif key == "f" then - if cur_pos <= #command then - cur_pos = cur_pos + 1 - end - elseif key == "h" then - if cur_pos > 1 then - command = command:sub(1, cur_pos - 2) .. command:sub(cur_pos) - cur_pos = cur_pos - 1 - end - elseif key == "k" then - command = command:sub(1, cur_pos - 1) - elseif key == "u" then - command = command:sub(cur_pos, #command) - cur_pos = 1 - elseif key == "Up" then - search_term = command:sub(1, cur_pos - 1) or "" - for i,v in (function(a,i) return itera(-1,a,i) end), data.history[history_path].table, history_index do - if v:find(search_term,1,true) == 1 then - command=v - history_index=i - break - end - end - elseif key == "Down" then - search_term = command:sub(1, cur_pos - 1) or "" - for i,v in (function(a,i) return itera(1,a,i) end), data.history[history_path].table, history_index do - if v:find(search_term,1,true) == 1 then - command=v - history_index=i - break - end - end - elseif key == "w" or key == "BackSpace" then - local wstart = 1 - local wend = 1 - local cword_start_pos = 1 - local cword_end_pos = 1 - while wend < cur_pos do - wend = command:find("[{[(,.:;_-+=@/ ]", wstart) - if not wend then wend = #command + 1 end - if cur_pos >= wstart and cur_pos <= wend + 1 then - cword_start_pos = wstart - cword_end_pos = cur_pos - 1 - break - end - wstart = wend + 1 - end - command = command:sub(1, cword_start_pos - 1) .. command:sub(cword_end_pos + 1) - cur_pos = cword_start_pos - elseif key == "Delete" then - -- delete from history only if: - -- we are not dealing with a new command - -- the user has not edited an existing entry - if command == data.history[history_path].table[history_index] then - table.remove(data.history[history_path].table, history_index) - if history_index <= history_items(history_path) then - command = data.history[history_path].table[history_index] - cur_pos = #command + 2 - elseif history_index > 1 then - history_index = history_index - 1 - - command = data.history[history_path].table[history_index] - cur_pos = #command + 2 - else - command = "" - cur_pos = 1 - end - end - end - elseif mod.Mod1 or mod.Mod3 then - if key == "b" then - cur_pos = cword_start(command, cur_pos) - elseif key == "f" then - cur_pos = cword_end(command, cur_pos) - elseif key == "d" then - command = command:sub(1, cur_pos - 1) .. command:sub(cword_end(command, cur_pos)) - elseif key == "BackSpace" then - local wstart = cword_start(command, cur_pos) - command = command:sub(1, wstart - 1) .. command:sub(cur_pos) - cur_pos = wstart - end - else - if completion_callback then - if key == "Tab" or key == "ISO_Left_Tab" then - if key == "ISO_Left_Tab" then - if ncomp == 1 then return end - if ncomp == 2 then - command = command_before_comp - textbox:set_font(font) - textbox:set_markup(prompt_text_with_cursor{ - text = command_before_comp, text_color = inv_col, cursor_color = cur_col, - cursor_pos = cur_pos, cursor_ul = cur_ul, selectall = selectall, - prompt = prettyprompt }) - return - end - - ncomp = ncomp - 2 - elseif ncomp == 1 then - command_before_comp = command - cur_pos_before_comp = cur_pos - end - local matches - command, cur_pos, matches = completion_callback(command_before_comp, cur_pos_before_comp, ncomp) - ncomp = ncomp + 1 - key = "" - -- execute if only one match found and autoexec flag set - if matches and #matches == 1 and args.autoexec then - exec(exe_callback) - return - end - else - ncomp = 1 - end - end - - -- Typin cases - if mod.Shift and key == "Insert" then - local selection = capi.selection() - if selection then - -- Remove \n - local n = selection:find("\n") - if n then - selection = selection:sub(1, n - 1) - end - command = command:sub(1, cur_pos - 1) .. selection .. command:sub(cur_pos) - cur_pos = cur_pos + #selection - end - elseif key == "Home" then - cur_pos = 1 - elseif key == "End" then - cur_pos = #command + 1 - elseif key == "BackSpace" then - if cur_pos > 1 then - command = command:sub(1, cur_pos - 2) .. command:sub(cur_pos) - cur_pos = cur_pos - 1 - end - elseif key == "Delete" then - command = command:sub(1, cur_pos - 1) .. command:sub(cur_pos + 1) - elseif key == "Left" then - cur_pos = cur_pos - 1 - elseif key == "Right" then - cur_pos = cur_pos + 1 - elseif key == "Up" then - if history_index > 1 then - history_index = history_index - 1 - - command = data.history[history_path].table[history_index] - cur_pos = #command + 2 - end - elseif key == "Down" then - if history_index < history_items(history_path) then - history_index = history_index + 1 - - command = data.history[history_path].table[history_index] - cur_pos = #command + 2 - elseif history_index == history_items(history_path) then - history_index = history_index + 1 - - command = "" - cur_pos = 1 - end - else - -- wlen() is UTF-8 aware but #key is not, - -- so check that we have one UTF-8 char but advance the cursor of # position - if key:wlen() == 1 then - if selectall then command = "" end - command = command:sub(1, cur_pos - 1) .. key .. command:sub(cur_pos) - cur_pos = cur_pos + #key - end - end - if cur_pos < 1 then - cur_pos = 1 - elseif cur_pos > #command + 1 then - cur_pos = #command + 1 - end - selectall = nil - end - - local success = pcall(update) - while not success do - -- TODO UGLY HACK TODO - -- Setting the text failed. Most likely reason is that the user - -- entered a multibyte character and pressed backspace which only - -- removed the last byte. Let's remove another byte. - if cur_pos <= 1 then - -- No text left?! - break - end - - command = command:sub(1, cur_pos - 2) .. command:sub(cur_pos) - cur_pos = cur_pos - 1 - success = pcall(update) - end - - if changed_callback then - changed_callback(command) - end - end) -end - -return prompt - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/remote.lua b/awesome/lib/awful/remote.lua deleted file mode 100644 index 7967f2f..0000000 --- a/awesome/lib/awful/remote.lua +++ /dev/null @@ -1,47 +0,0 @@ ---------------------------------------------------------------------------- ---- Remote control module allowing usage of awesome-client. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.remote ---------------------------------------------------------------------------- - --- Grab environment we need -require("awful.dbus") -local load = loadstring or load -- luacheck: globals loadstring (compatibility with Lua 5.1) -local tostring = tostring -local ipairs = ipairs -local table = table -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local dbus = dbus -local type = type - -if dbus then - dbus.connect_signal("org.awesomewm.awful.Remote", function(data, code) - if data.member == "Eval" then - local f, e = load(code) - if f then - local results = { f() } - local retvals = {} - for _, v in ipairs(results) do - local t = type(v) - if t == "boolean" then - table.insert(retvals, "b") - table.insert(retvals, v) - elseif t == "number" then - table.insert(retvals, "d") - table.insert(retvals, v) - else - table.insert(retvals, "s") - table.insert(retvals, tostring(v)) - end - end - return unpack(retvals) - elseif e then - return "s", e - end - end - end) -end - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/rules.lua b/awesome/lib/awful/rules.lua deleted file mode 100644 index dc44e00..0000000 --- a/awesome/lib/awful/rules.lua +++ /dev/null @@ -1,545 +0,0 @@ ---------------------------------------------------------------------------- ---- Apply rules to clients at startup. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.rules ---------------------------------------------------------------------------- - --- Grab environment we need -local client = client -local awesome = awesome -local screen = screen -local table = table -local type = type -local ipairs = ipairs -local pairs = pairs -local atag = require("awful.tag") -local util = require("awful.util") -local a_place = require("awful.placement") -local protected_call = require("gears.protected_call") - -local rules = {} - ---[[-- -This is the global rules table. - -You should fill this table with your rule and properties to apply. -For example, if you want to set xterm maximized at startup, you can add: - - { rule = { class = "xterm" }, - properties = { maximized_vertical = true, maximized_horizontal = true } } - -If you want to set mplayer floating at startup, you can add: - - { rule = { name = "MPlayer" }, - properties = { floating = true } } - -If you want to put Firefox on a specific tag at startup, you can add: - - { rule = { instance = "firefox" }, - properties = { tag = mytagobject } } - -Alternatively, you can specify the tag by name: - - { rule = { instance = "firefox" }, - properties = { tag = "3" } } - -If you want to put Thunderbird on a specific screen at startup, use: - - { rule = { instance = "Thunderbird" }, - properties = { screen = 1 } } - -Assuming that your X11 server supports the RandR extension, you can also specify -the screen by name: - - { rule = { instance = "Thunderbird" }, - properties = { screen = "VGA1" } } - -If you want to put Emacs on a specific tag at startup, and immediately switch -to that tag you can add: - - { rule = { class = "Emacs" }, - properties = { tag = mytagobject, switchtotag = true } } - -If you want to apply a custom callback to execute when a rule matched, -for example to pause playing music from mpd when you start dosbox, you -can add: - - { rule = { class = "dosbox" }, - callback = function(c) - awful.spawn('mpc pause') - end } - -Note that all "rule" entries need to match. If any of the entry does not -match, the rule won't be applied. - -If a client matches multiple rules, they are applied in the order they are -put in this global rules table. If the value of a rule is a string, then the -match function is used to determine if the client matches the rule. - -If the value of a property is a function, that function gets called and -function's return value is used for the property. - -To match multiple clients to a rule one need to use slightly different -syntax: - - { rule_any = { class = { "MPlayer", "Nitrogen" }, instance = { "xterm" } }, - properties = { floating = true } } - -To match multiple clients with an exception one can couple `rules.except` or -`rules.except_any` with the rules: - - { rule = { class = "Firefox" }, - except = { instance = "Navigator" }, - properties = {floating = true}, - }, - - { rule_any = { class = { "Pidgin", "Xchat" } }, - except_any = { role = { "conversation" } }, - properties = { tag = "1" } - } - - { rule = {}, - except_any = { class = { "Firefox", "Vim" } }, - properties = { floating = true } - } -]]-- -rules.rules = {} - ---- Check if a client matches a rule. --- @client c The client. --- @tab rule The rule to check. --- @treturn bool True if it matches, false otherwise. -function rules.match(c, rule) - if not rule then return false end - for field, value in pairs(rule) do - if c[field] then - if type(c[field]) == "string" then - if not c[field]:match(value) and c[field] ~= value then - return false - end - elseif c[field] ~= value then - return false - end - else - return false - end - end - return true -end - ---- Check if a client matches any part of a rule. --- @client c The client. --- @tab rule The rule to check. --- @treturn bool True if at least one rule is matched, false otherwise. -function rules.match_any(c, rule) - if not rule then return false end - for field, values in pairs(rule) do - if c[field] then - for _, value in ipairs(values) do - if c[field] == value then - return true - elseif type(c[field]) == "string" and c[field]:match(value) then - return true - end - end - end - end - return false -end - ---- Does a given rule entry match a client? --- @client c The client. --- @tab entry Rule entry (with keys `rule`, `rule_any`, `except` and/or --- `except_any`). --- @treturn bool -function rules.matches(c, entry) - return (rules.match(c, entry.rule) or rules.match_any(c, entry.rule_any)) and - (not rules.match(c, entry.except) and not rules.match_any(c, entry.except_any)) -end - ---- Get list of matching rules for a client. --- @client c The client. --- @tab _rules The rules to check. List with "rule", "rule_any", "except" and --- "except_any" keys. --- @treturn table The list of matched rules. -function rules.matching_rules(c, _rules) - local result = {} - for _, entry in ipairs(_rules) do - if (rules.matches(c, entry)) then - table.insert(result, entry) - end - end - return result -end - ---- Check if a client matches a given set of rules. --- @client c The client. --- @tab _rules The rules to check. List of tables with `rule`, `rule_any`, --- `except` and `except_any` keys. --- @treturn bool True if at least one rule is matched, false otherwise. -function rules.matches_list(c, _rules) - for _, entry in ipairs(_rules) do - if (rules.matches(c, entry)) then - return true - end - end - return false -end - ---- Apply awful.rules.rules to a client. --- @client c The client. -function rules.apply(c) - - local props = {} - local callbacks = {} - - for _, entry in ipairs(rules.matching_rules(c, rules.rules)) do - if entry.properties then - for property, value in pairs(entry.properties) do - props[property] = value - end - end - if entry.callback then - table.insert(callbacks, entry.callback) - end - end - - rules.execute(c, props, callbacks) -end - -local function add_to_tag(c, t) - if not t then return end - - local tags = c:tags() - table.insert(tags, t) - c:tags(tags) -end - ---- Extra rules properties. --- --- These properties are used in the rules only and are not sent to the client --- afterward. --- --- To add a new properties, just do: --- --- function awful.rules.extra_properties.my_new_property(c, value, props) --- -- do something --- end --- --- By default, the table has the following functions: --- --- * geometry --- * switchtotag --- --- @tfield table awful.rules.extra_properties -rules.extra_properties = {} - ---- Extra high priority properties. --- --- Some properties, such as anything related to tags, geometry or focus, will --- cause a race condition if set in the main property section. This is why --- they have a section for them. --- --- To add a new properties, just do: --- --- function awful.rules.high_priority_properties.my_new_property(c, value, props) --- -- do something --- end --- --- By default, the table has the following functions: --- --- * tag --- * new_tag --- --- @tfield table awful.rules.high_priority_properties -rules.high_priority_properties = {} - ---- Delayed properties. --- Properties applied after all other categories. --- @tfield table awful.rules.delayed_properties -rules.delayed_properties = {} - -local force_ignore = { - titlebars_enabled=true, focus=true, screen=true, x=true, - y=true, width=true, height=true, geometry=true,placement=true, - border_width=true,floating=true,size_hints_honor=true -} - -function rules.high_priority_properties.tag(c, value, props) - if value then - if type(value) == "string" then - value = atag.find_by_name(c.screen, value) - end - - -- In case the tag has been forced to another screen, move the client - if c.screen ~= value.screen then - c.screen = value.screen - props.screen = value.screen -- In case another rule query it - end - - c:tags{ value } - end -end - -function rules.delayed_properties.switchtotag(c, value) - if not value then return end - - local selected_tags = {} - - for _,v in ipairs(c.screen.selected_tags) do - selected_tags[v] = true - end - - local tags = c:tags() - - for _, t in ipairs(tags) do - t.selected = true - selected_tags[t] = nil - end - - for t in pairs(selected_tags) do - t.selected = false - end -end - -function rules.extra_properties.geometry(c, _, props) - local cur_geo = c:geometry() - - local new_geo = type(props.geometry) == "function" - and props.geometry(c, props) or props.geometry or {} - - for _, v in ipairs {"x", "y", "width", "height"} do - new_geo[v] = type(props[v]) == "function" and props[v](c, props) - or props[v] or new_geo[v] or cur_geo[v] - end - - c:geometry(new_geo) --TODO use request::geometry -end - ---- Create a new tag based on a rule. --- @tparam client c The client --- @tparam boolean|function|string value The value. --- @tparam table props The properties. --- @treturn tag The new tag -function rules.high_priority_properties.new_tag(c, value, props) - local ty = type(value) - local t = nil - - if ty == "boolean" then - -- Create a new tag named after the client class - t = atag.add(c.class or "N/A", {screen=c.screen, volatile=true}) - elseif ty == "string" then - -- Create a tag named after "value" - t = atag.add(value, {screen=c.screen, volatile=true}) - elseif ty == "table" then - -- Assume a table of tags properties. Set the right screen, but - -- avoid editing the original table - local values = value.screen and value or util.table.clone(value) - values.screen = values.screen or c.screen - - t = atag.add(value.name or c.class or "N/A", values) - - -- In case the tag has been forced to another screen, move the client - c.screen = t.screen - props.screen = t.screen -- In case another rule query it - else - assert(false) - end - - add_to_tag(c, t) - - return t -end - -function rules.extra_properties.placement(c, value) - -- Avoid problems - if awesome.startup and - (c.size_hints.user_position or c.size_hints.program_position) then - return - end - - local ty = type(value) - - local args = { - honor_workarea = true, - honor_padding = true - } - - if ty == "function" or (ty == "table" and - getmetatable(value) and getmetatable(value).__call - ) then - value(c, args) - elseif ty == "string" and a_place[value] then - a_place[value](c, args) - end -end - -function rules.extra_properties.tags(c, value, props) - local current = c:tags() - - local tags, s = {}, nil - - for _, t in ipairs(value) do - if type(t) == "string" then - t = atag.find_by_name(c.screen, t) - end - - if t and ((not s) or t.screen == s) then - table.insert(tags, t) - s = s or t.screen - end - end - - if s and s ~= c.screen then - c.screen = s - props.screen = s -- In case another rule query it - end - - if #current == 0 or (value[1] and value[1].screen ~= current[1].screen) then - c:tags(tags) - else - c:tags(util.table.merge(current, tags)) - end -end - ---- Apply properties and callbacks to a client. --- @client c The client. --- @tab props Properties to apply. --- @tab[opt] callbacks Callbacks to apply. -function rules.execute(c, props, callbacks) - -- This has to be done first, as it will impact geometry related props. - if props.titlebars_enabled then - c:emit_signal("request::titlebars", "rules", {properties=props}) - end - - -- Border width will also cause geometry related properties to fail - if props.border_width then - c.border_width = type(props.border_width) == "function" and - props.border_width(c, props) or props.border_width - end - - -- Size hints will be re-applied when setting width/height unless it is - -- disabled first - if props.size_hints_honor ~= nil then - c.size_hints_honor = type(props.size_hints_honor) == "function" and props.size_hints_honor(c,props) - or props.size_hints_honor - end - - -- Geometry will only work if floating is true, otherwise the "saved" - -- geometry will be restored. - if props.floating ~= nil then - c.floating = type(props.floating) == "function" and props.floating(c,props) - or props.floating - end - - -- Before requesting a tag, make sure the screen is right - if props.screen then - c.screen = type(props.screen) == "function" and screen[props.screen(c,props)] - or screen[props.screen] - end - - -- Some properties need to be handled first. For example, many properties - -- depend that the client is tagged, this isn't yet the case. - for prop, handler in pairs(rules.high_priority_properties) do - local value = props[prop] - - if value ~= nil then - if type(value) == "function" then - value = value(c, props) - end - - handler(c, value, props) - end - - end - - -- By default, rc.lua use no_overlap+no_offscreen placement. This has to - -- be executed before x/y/width/height/geometry as it would otherwise - -- always override the user specified position with the default rule. - if props.placement then - -- It may be a function, so this one doesn't execute it like others - rules.extra_properties.placement(c, props.placement, props) - end - - -- Make sure the tag is selected before the main rules are called. - -- Otherwise properties like "urgent" or "focus" may fail because they - -- will be overiden by various callbacks. - -- Previously, this was done in a second client.manage callback, but caused - -- a race condition where the order the require() would change the output. - c:emit_signal("request::tag", nil, {reason="rules"}) - - -- By default, rc.lua use no_overlap+no_offscreen placement. This has to - -- be executed before x/y/width/height/geometry as it would otherwise - -- always override the user specified position with the default rule. - if props.placement then - -- It may be a function, so this one doesn't execute it like others - rules.extra_properties.placement(c, props.placement, props) - end - - -- Now that the tags and screen are set, handle the geometry - if props.height or props.width or props.x or props.y or props.geometry then - rules.extra_properties.geometry(c, nil, props) - end - - -- As most race conditions should now have been avoided, apply the remaining - -- properties. - for property, value in pairs(props) do - if property ~= "focus" and type(value) == "function" then - value = value(c, props) - end - - local ignore = rules.high_priority_properties[property] or - rules.delayed_properties[property] or force_ignore[property] - - if not ignore then - if rules.extra_properties[property] then - rules.extra_properties[property](c, value, props) - elseif type(c[property]) == "function" then - c[property](c, value) - else - c[property] = value - end - end - end - - -- Apply all callbacks. - if callbacks then - for _, callback in pairs(callbacks) do - protected_call(callback, c) - end - end - - -- Apply the delayed properties - for prop, handler in pairs(rules.delayed_properties) do - if not force_ignore[prop] then - local value = props[prop] - - if value ~= nil then - if type(value) == "function" then - value = value(c, props) - end - - handler(c, value, props) - end - end - end - - -- Do this at last so we do not erase things done by the focus signal. - if props.focus and (type(props.focus) ~= "function" or props.focus(c)) then - c:emit_signal('request::activate', "rules", {raise=true}) - end -end - -function rules.completed_with_payload_callback(c, props, callbacks) - rules.execute(c, props, callbacks) -end - -client.connect_signal("spawn::completed_with_payload", rules.completed_with_payload_callback) - -client.connect_signal("manage", rules.apply) - -return rules - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/screen.lua b/awesome/lib/awful/screen.lua deleted file mode 100644 index e36e622..0000000 --- a/awesome/lib/awful/screen.lua +++ /dev/null @@ -1,477 +0,0 @@ ---------------------------------------------------------------------------- ---- Screen module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module screen ---------------------------------------------------------------------------- - --- Grab environment we need -local capi = -{ - mouse = mouse, - screen = screen, - client = client, - awesome = awesome, -} -local util = require("awful.util") -local object = require("gears.object") -local grect = require("gears.geometry").rectangle - -local function get_screen(s) - return s and capi.screen[s] -end - --- we use require("awful.client") inside functions to prevent circular dependencies. -local client - -local screen = {object={}} - -local data = {} -data.padding = {} - ---- Take an input geometry and substract/add a delta. --- @tparam table geo A geometry (width, height, x, y) table. --- @tparam table delta A delta table (top, bottom, x, y). --- @treturn table A geometry (width, height, x, y) table. -local function apply_geometry_ajustments(geo, delta) - return { - x = geo.x + (delta.left or 0), - y = geo.y + (delta.top or 0), - width = geo.width - (delta.left or 0) - (delta.right or 0), - height = geo.height - (delta.top or 0) - (delta.bottom or 0), - } -end - ---- Get the square distance between a `screen` and a point. --- @deprecated awful.screen.getdistance_sq --- @param s Screen --- @param x X coordinate of point --- @param y Y coordinate of point --- @return The squared distance of the screen to the provided point. --- @see screen.get_square_distance -function screen.getdistance_sq(s, x, y) - util.deprecate("Use s:get_square_distance(x, y) instead of awful.screen.getdistance_sq") - return screen.object.get_square_distance(s, x, y) -end - ---- Get the square distance between a `screen` and a point. --- @function screen.get_square_distance --- @tparam number x X coordinate of point --- @tparam number y Y coordinate of point --- @treturn number The squared distance of the screen to the provided point. -function screen.object.get_square_distance(self, x, y) - return grect.get_square_distance(get_screen(self).geometry, x, y) -end - ---- Return the screen index corresponding to the given (pixel) coordinates. --- --- The number returned can be used as an index into the global --- `screen` table/object. --- @function awful.screen.getbycoord --- @tparam number x The x coordinate --- @tparam number y The y coordinate --- @treturn ?number The screen index -function screen.getbycoord(x, y) - local s, sgeos = capi.screen.primary, {} - for scr in capi.screen do - sgeos[scr] = scr.geometry - end - s = grect.get_closest_by_coord(sgeos, x, y) or s - return s and s.index -end - ---- Move the focus to a screen. --- --- This moves the mouse pointer to the last known position on the new screen, --- or keeps its position relative to the current focused screen. --- @function awful.screen.focus --- @screen _screen Screen number (defaults / falls back to mouse.screen). -function screen.focus(_screen) - client = client or require("awful.client") - if type(_screen) == "number" and _screen > capi.screen.count() then _screen = screen.focused() end - _screen = get_screen(_screen) - - -- screen and pos for current screen - local s = get_screen(capi.mouse.screen) - local pos - - if not _screen.mouse_per_screen then - -- This is the first time we enter this screen, - -- keep relative mouse position on the new screen. - pos = capi.mouse.coords() - local relx = (pos.x - s.geometry.x) / s.geometry.width - local rely = (pos.y - s.geometry.y) / s.geometry.height - - pos.x = _screen.geometry.x + relx * _screen.geometry.width - pos.y = _screen.geometry.y + rely * _screen.geometry.height - else - -- restore mouse position - pos = _screen.mouse_per_screen - end - - -- save pointer position of current screen - s.mouse_per_screen = capi.mouse.coords() - - -- move cursor without triggering signals mouse::enter and mouse::leave - capi.mouse.coords(pos, true) - - local c = client.focus.history.get(_screen, 0) - if c then - c:emit_signal("request::activate", "screen.focus", {raise=false}) - end -end - ---- Move the focus to a screen in a specific direction. --- --- This moves the mouse pointer to the last known position on the new screen, --- or keeps its position relative to the current focused screen. --- @function awful.screen.focus_bydirection --- @param dir The direction, can be either "up", "down", "left" or "right". --- @param _screen Screen. -function screen.focus_bydirection(dir, _screen) - local sel = get_screen(_screen or screen.focused()) - if sel then - local geomtbl = {} - for s in capi.screen do - geomtbl[s] = s.geometry - end - local target = grect.get_in_direction(dir, geomtbl, sel.geometry) - if target then - return screen.focus(target) - end - end -end - ---- Move the focus to a screen relative to the current one, --- --- This moves the mouse pointer to the last known position on the new screen, --- or keeps its position relative to the current focused screen. --- --- @function awful.screen.focus_relative --- @tparam int offset Value to add to the current focused screen index. 1 to --- focus the next one, -1 to focus the previous one. -function screen.focus_relative(offset) - return screen.focus(util.cycle(capi.screen.count(), - screen.focused().index + offset)) -end - ---- Get or set the screen padding. --- --- @deprecated awful.screen.padding --- @param _screen The screen object to change the padding on --- @param[opt=nil] padding The padding, a table with 'top', 'left', 'right' and/or --- 'bottom' or a number value to apply set the same padding on all sides. Can be --- nil if you only want to retrieve padding --- @treturn table A table with left, right, top and bottom number values. --- @see padding -function screen.padding(_screen, padding) - util.deprecate("Use _screen.padding = value instead of awful.screen.padding") - if padding then - screen.object.set_padding(_screen, padding) - end - return screen.object.get_padding(_screen) -end - ---- The screen padding. --- --- This adds a "buffer" section on each side of the screen. --- --- **Signal:** --- --- * *property::padding* --- --- @property padding --- @param table --- @tfield integer table.left The padding on the left. --- @tfield integer table.right The padding on the right. --- @tfield integer table.top The padding on the top. --- @tfield integer table.bottom The padding on the bottom. - -function screen.object.get_padding(self) - local p = data.padding[self] or {} - -- Create a copy to avoid accidental mutation and nil values. - return { - left = p.left or 0, - right = p.right or 0, - top = p.top or 0, - bottom = p.bottom or 0, - } -end - -function screen.object.set_padding(self, padding) - if type(padding) == "number" then - padding = { - left = padding, - right = padding, - top = padding, - bottom = padding, - } - end - - self = get_screen(self) - if padding then - data.padding[self] = padding - self:emit_signal("padding") - end -end - ---- Get the preferred screen in the context of a client. --- --- This is exactly the same as `awful.screen.focused` except that it avoids --- clients being moved when Awesome is restarted. --- This is used in the default `rc.lua` to ensure clients get assigned to the --- focused screen by default. --- @tparam client c A client. --- @treturn screen The preferred screen. -function screen.preferred(c) - return capi.awesome.startup and c.screen or screen.focused() -end - ---- The defaults arguments for `awful.screen.focused`. --- @tfield[opt=nil] table awful.screen.default_focused_args - ---- Get the focused screen. --- --- It is possible to set `awful.screen.default_focused_args` to override the --- default settings. --- --- @function awful.screen.focused --- @tparam[opt] table args --- @tparam[opt=false] boolean args.client Use the client screen instead of the --- mouse screen. --- @tparam[opt=true] boolean args.mouse Use the mouse screen --- @treturn ?screen The focused screen object, or `nil` in case no screen is --- present currently. -function screen.focused(args) - args = args or screen.default_focused_args or {} - return get_screen( - args.client and capi.client.focus and capi.client.focus.screen or capi.mouse.screen - ) -end - ---- Get a placement bounding geometry. --- --- This method computes the different variants of the "usable" screen geometry. --- --- @function screen.get_bounding_geometry --- @tparam[opt={}] table args The arguments --- @tparam[opt=false] boolean args.honor_padding Whether to honor the screen's padding. --- @tparam[opt=false] boolean args.honor_workarea Whether to honor the screen's workarea. --- @tparam[opt] int|table args.margins Apply some margins on the output. --- This can either be a number or a table with *left*, *right*, *top* --- and *bottom* keys. --- @tag[opt] args.tag Use this tag's screen. --- @tparam[opt] drawable args.parent A parent drawable to use as base geometry. --- @tab[opt] args.bounding_rect A bounding rectangle. This parameter is --- incompatible with `honor_workarea`. --- @treturn table A table with *x*, *y*, *width* and *height*. --- @usage local geo = screen:get_bounding_geometry { --- honor_padding = true, --- honor_workarea = true, --- margins = { --- left = 20, --- }, --- } -function screen.object.get_bounding_geometry(self, args) - args = args or {} - - -- If the tag has a geometry, assume it is right - if args.tag then - self = args.tag.screen - end - - self = get_screen(self or capi.mouse.screen) - - local geo = args.bounding_rect or (args.parent and args.parent:geometry()) or - self[args.honor_workarea and "workarea" or "geometry"] - - if (not args.parent) and (not args.bounding_rect) and args.honor_padding then - local padding = self.padding - geo = apply_geometry_ajustments(geo, padding) - end - - if args.margins then - geo = apply_geometry_ajustments(geo, - type(args.margins) == "table" and args.margins or { - left = args.margins, right = args.margins, - top = args.margins, bottom = args.margins, - } - ) - end - return geo -end - ---- Get the list of visible clients for the screen. --- --- Minimized and unmanaged clients are not included in this list as they are --- technically not on the screen. --- --- The clients on tags that are currently not visible are not part of this list. --- --- @property clients --- @param table The clients list, ordered from top to bottom. --- @see all_clients --- @see hidden_clients --- @see client.get - -function screen.object.get_clients(s) - local cls = capi.client.get(s, true) - local vcls = {} - for _, c in pairs(cls) do - if c:isvisible() then - table.insert(vcls, c) - end - end - return vcls -end - ---- Get the list of clients assigned to the screen but not currently visible. --- --- This includes minimized clients and clients on hidden tags. --- --- @property hidden_clients --- @param table The clients list, ordered from top to bottom. --- @see clients --- @see all_clients --- @see client.get - -function screen.object.get_hidden_clients(s) - local cls = capi.client.get(s, true) - local vcls = {} - for _, c in pairs(cls) do - if not c:isvisible() then - table.insert(vcls, c) - end - end - return vcls -end - ---- Get all clients assigned to the screen. --- --- @property all_clients --- @param table The clients list, ordered from top to bottom. --- @see clients --- @see hidden_clients --- @see client.get - -function screen.object.get_all_clients(s) - return capi.client.get(s, true) -end - ---- Get the list of tiled clients for the screen. --- --- Same as `clients`, but excluding: --- --- * fullscreen clients --- * maximized clients --- * floating clients --- --- @property tiled_clients --- @param table The clients list, ordered from top to bottom. - -function screen.object.get_tiled_clients(s) - local clients = s.clients - local tclients = {} - -- Remove floating clients - for _, c in pairs(clients) do - if not c.floating - and not c.fullscreen - and not c.maximized_vertical - and not c.maximized_horizontal then - table.insert(tclients, c) - end - end - return tclients -end - ---- Call a function for each existing and created-in-the-future screen. --- --- @function awful.screen.connect_for_each_screen --- @tparam function func The function to call. --- @screen func.screen The screen. -function screen.connect_for_each_screen(func) - for s in capi.screen do - func(s) - end - capi.screen.connect_signal("added", func) -end - ---- Undo the effect of connect_for_each_screen. --- @function awful.screen.disconnect_for_each_screen --- @tparam function func The function that should no longer be called. -function screen.disconnect_for_each_screen(func) - capi.screen.disconnect_signal("added", func) -end - ---- A list of all tags on the screen. --- --- This property is read only, use `tag.screen`, `awful.tag.add`, --- `awful.tag.new` or `t:delete()` to alter this list. --- --- @property tags --- @param table --- @treturn table A table with all available tags. - -function screen.object.get_tags(s, unordered) - local tags = {} - - for _, t in ipairs(root.tags()) do - if get_screen(t.screen) == s then - table.insert(tags, t) - end - end - - -- Avoid infinite loop and save some time. - if not unordered then - table.sort(tags, function(a, b) - return (a.index or math.huge) < (b.index or math.huge) - end) - end - return tags -end - ---- A list of all selected tags on the screen. --- @property selected_tags --- @param table --- @treturn table A table with all selected tags. --- @see tag.selected --- @see client.to_selected_tags - -function screen.object.get_selected_tags(s) - local tags = screen.object.get_tags(s, true) - - local vtags = {} - for _, t in pairs(tags) do - if t.selected then - vtags[#vtags + 1] = t - end - end - return vtags -end - ---- The first selected tag. --- @property selected_tag --- @param table --- @treturn ?tag The first selected tag or nil. --- @see tag.selected --- @see selected_tags - -function screen.object.get_selected_tag(s) - return screen.object.get_selected_tags(s)[1] -end - - ---- When the tag history changed. --- @signal tag::history::update - --- Extend the luaobject -object.properties(capi.screen, { - getter_class = screen.object, - setter_class = screen.object, - auto_emit = true, -}) - -return screen - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/spawn.lua b/awesome/lib/awful/spawn.lua deleted file mode 100644 index bcfb68d..0000000 --- a/awesome/lib/awful/spawn.lua +++ /dev/null @@ -1,421 +0,0 @@ ---------------------------------------------------------------------------- ---- Spawning of programs. --- --- This module provides methods to start programs and supports startup --- notifications, which allows for callbacks and applying properties to the --- program after it has been launched. This requires currently that the --- applicaton supports them. --- --- **Rules of thumb when a shell is needed**: --- --- * A shell is required when the commands contain `&&`, `;`, `||`, `&` or --- any other unix shell language syntax --- * When shell variables are defined as part of the command --- * When the command is a shell alias --- --- Note that a shell is **not** a terminal emulator. A terminal emulator is --- something like XTerm, Gnome-terminal or Konsole. A shell is something like --- `bash`, `zsh`, `busybox sh` or `Debian ash`. --- --- If you wish to open a process in a terminal window, check that your terminal --- emulator supports the common `-e` option. If it does, then something like --- this should work: --- --- awful.spawn(terminal.." -e my_command") --- --- Note that some terminals, such as rxvt-unicode (urxvt) support full commands --- using quotes, while other terminal emulators require to use quoting. --- --- **Understanding clients versus PID versus commands versus class**: --- --- A *process* has a *PID* (process identifier). It can have 0, 1 or many --- *window*s. --- --- A *command* if what is used to start *process*(es). It has no direct relation --- with *process*, *client* or *window*. When a command is executed, it will --- usually start a *process* which keeps running until it exits. This however is --- not always the case as some applications use scripts as command and others --- use various single-instance mechanisms (usually client/server) and merge --- with an existing process. --- --- A *client* corresponds to a *window*. It is owned by a process. It can have --- both a parent and one or many children. A *client* has a *class*, an --- *instance*, a *role*, and a *type*. See `client.class`, `client.instance`, --- `client.role` and `client.type` for more information about these properties. --- --- **The startup notification protocol**: --- --- The startup notification protocol is an optional specification implemented --- by X11 applications to bridge the chain of knowledge between the moment a --- program is launched to the moment its window (client) is shown. It can be --- found [on the FreeDesktop.org website](https://www.freedesktop.org/wiki/Specifications/startup-notification-spec/). --- --- Awesome has support for the various events that are part of the protocol, but --- the most useful is the identifier, usually identified by its `SNID` acronym in --- the documentation. It isn't usually necessary to even know it exists, as it --- is all done automatically. However, if more control is required, the --- identifier can be specified by an environment variable called --- `DESKTOP_STARTUP_ID`. For example, let us consider execution of the following --- command: --- --- DESKTOP_STARTUP_ID="something_TIME$(date '+%s')" my_command --- --- This should (if the program correctly implements the protocol) result in --- `c.startup_id` to at least match `something`. --- This identifier can then be used in `awful.rules` to configure the client. --- --- Awesome can automatically set the `DESKTOP_STARTUP_ID` variable. This is used --- by `awful.spawn` to specify additional rules for the startup. For example: --- --- awful.spawn("urxvt -e maxima -name CALCULATOR", { --- floating = true, --- tag = mouse.screen.selected_tag, --- placement = awful.placement.bottom_right, --- }) --- --- This can also be used from the command line: --- --- awesome-client 'awful=require("awful"); --- awful.spawn("urxvt -e maxima -name CALCULATOR", { --- floating = true, --- tag = mouse.screen.selected_tag, --- placement = awful.placement.bottom_right, --- })' --- --- **Getting a command's output**: --- --- First, do **not** use `io.popen` **ever**. It is synchronous. Synchronous --- functions **block everything** until they are done. All visual applications --- lock (as Awesome no longer responds), you will probably lose some keyboard --- and mouse events and will have higher latency when playing games. This is --- also true when reading files synchronously, but this is another topic. --- --- Awesome provides a few ways to get output from commands. One is to use the --- `Gio` libraries directly. This is usually very complicated, but gives a lot --- of control on the command execution. --- --- This modules provides `with_line_callback` and `easy_async` for convenience. --- First, lets add this bash command to `rc.lua`: --- --- local noisy = [[bash -c ' --- for I in $(seq 1 5); do --- date --- echo err >&2 --- sleep 2 --- done --- ']] --- --- It prints a bunch of junk on the standard output (*stdout*) and error --- (*stderr*) streams. This command would block Awesome for 10 seconds if it --- were executed synchronously, but will not block it at all using the --- asynchronous functions. --- --- `with_line_callback` will execute the callbacks every time a new line is --- printed by the command: --- --- awful.spawn.with_line_callback(noisy, { --- stdout = function(line) --- naughty.notify { text = "LINE:"..line } --- end, --- stderr = function(line) --- naughty.notify { text = "ERR:"..line} --- end, --- }) --- --- If only the full output is needed, then `easy_async` is the right choice: --- --- awful.spawn.easy_async(noisy, function(stdout, stderr, reason, exit_code) --- naughty.notify { text = stdout } --- end) --- --- **Default applications**: --- --- If the intent is to open a file/document, then it is recommended to use the --- following standard command. The default application will be selected --- according to the [Shared MIME-info Database](https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html) --- specification. The `xdg-utils` package provided by most distributions --- includes the `xdg-open` command: --- --- awful.spawn({"xdg-open", "/path/to/file"}) --- --- Awesome **does not** manage, modify or otherwise influence the database --- for default applications. For information about how to do this, consult the --- [ARCH Linux Wiki](https://wiki.archlinux.org/index.php/default_applications). --- --- If you wish to change how the default applications behave, then consult the --- [Desktop Entry](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html) --- specification. --- --- @author Julien Danjou <julien@danjou.info> --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2008 Julien Danjou --- @copyright 2014 Emmanuel Lepage Vallee --- @module awful.spawn ---------------------------------------------------------------------------- - -local capi = -{ - awesome = awesome, - mouse = mouse, - client = client, -} -local lgi = require("lgi") -local Gio = lgi.Gio -local GLib = lgi.GLib -local util = require("awful.util") -local protected_call = require("gears.protected_call") - -local spawn = {} - - -local end_of_file -do - -- API changes, bug fixes and lots of fun. Figure out how a EOF is signalled. - local input - if not pcall(function() - -- No idea when this API changed, but some versions expect a string, - -- others a table with some special(?) entries - input = Gio.DataInputStream.new(Gio.MemoryInputStream.new_from_data("")) - end) then - input = Gio.DataInputStream.new(Gio.MemoryInputStream.new_from_data({})) - end - local line, length = input:read_line() - if not line then - -- Fixed in 2016: NULL on the C side is transformed to nil in Lua - end_of_file = function(arg) - return not arg - end - elseif tostring(line) == "" and #line ~= length then - -- "Historic" behaviour for end-of-file: - -- - NULL is turned into an empty string - -- - The length variable is not initialized - -- It's highly unlikely that the uninitialized variable has value zero. - -- Use this hack to detect EOF. - end_of_file = function(arg1, arg2) - return #arg1 ~= arg2 - end - else - assert(tostring(line) == "", "Cannot determine how to detect EOF") - -- The above uninitialized variable was fixed and thus length is - -- always 0 when line is NULL in C. We cannot tell apart an empty line and - -- EOF in this case. - require("gears.debug").print_warning("Cannot reliably detect EOF on an " - .. "GIOInputStream with this LGI version") - end_of_file = function(arg) - return tostring(arg) == "" - end - end -end - -spawn.snid_buffer = {} - -function spawn.on_snid_callback(c) - local entry = spawn.snid_buffer[c.startup_id] - if entry then - local props = entry[1] - local callback = entry[2] - c:emit_signal("spawn::completed_with_payload", props, callback) - spawn.snid_buffer[c.startup_id] = nil - end -end - -function spawn.on_snid_cancel(id) - if spawn.snid_buffer[id] then - spawn.snid_buffer[id] = nil - end -end - ---- Spawn a program, and optionally apply properties and/or run a callback. --- --- Applying properties or running a callback requires the program/client to --- support startup notifications. --- --- See `awful.rules.execute` for more details about the format of `sn_rules`. --- --- @tparam string|table cmd The command. --- @tparam[opt=true] table|boolean sn_rules A table of properties to be applied --- after startup; `false` to disable startup notifications. --- @tparam[opt] function callback A callback function to be run after startup. --- @treturn[1] integer The forked PID. --- @treturn[1] ?string The startup notification ID, if `sn` is not false, or --- a `callback` is provided. --- @treturn[2] string Error message. -function spawn.spawn(cmd, sn_rules, callback) - if cmd and cmd ~= "" then - local enable_sn = (sn_rules ~= false or callback) - enable_sn = not not enable_sn -- Force into a boolean. - local pid, snid = capi.awesome.spawn(cmd, enable_sn) - -- The snid will be nil in case of failure - if snid then - sn_rules = type(sn_rules) ~= "boolean" and sn_rules or {} - spawn.snid_buffer[snid] = { sn_rules, { callback } } - end - return pid, snid - end - -- For consistency - return "Error: No command to execute" -end - ---- Spawn a program using the shell. --- This calls `cmd` with `$SHELL -c` (via `awful.util.shell`). --- @tparam string cmd The command. -function spawn.with_shell(cmd) - if cmd and cmd ~= "" then - cmd = { util.shell, "-c", cmd } - return capi.awesome.spawn(cmd, false) - end -end - ---- Spawn a program and asynchronously capture its output line by line. --- @tparam string|table cmd The command. --- @tab callbacks Table containing callbacks that should be invoked on --- various conditions. --- @tparam[opt] function callbacks.stdout Function that is called with each --- line of output on stdout, e.g. `stdout(line)`. --- @tparam[opt] function callbacks.stderr Function that is called with each --- line of output on stderr, e.g. `stderr(line)`. --- @tparam[opt] function callbacks.output_done Function to call when no more --- output is produced. --- @tparam[opt] function callbacks.exit Function to call when the spawned --- process exits. This function gets the exit reason and code as its --- arguments. --- The reason can be "exit" or "signal". --- For "exit", the second argument is the exit code. --- For "signal", the second argument is the signal causing process --- termination. --- @treturn[1] Integer the PID of the forked process. --- @treturn[2] string Error message. -function spawn.with_line_callback(cmd, callbacks) - local stdout_callback, stderr_callback, done_callback, exit_callback = - callbacks.stdout, callbacks.stderr, callbacks.output_done, callbacks.exit - local have_stdout, have_stderr = stdout_callback ~= nil, stderr_callback ~= nil - local pid, _, stdin, stdout, stderr = capi.awesome.spawn(cmd, - false, false, have_stdout, have_stderr, exit_callback) - if type(pid) == "string" then - -- Error - return pid - end - - local done_before = false - local function step_done() - if have_stdout and have_stderr and not done_before then - done_before = true - return - end - if done_callback then - done_callback() - end - end - if have_stdout then - spawn.read_lines(Gio.UnixInputStream.new(stdout, true), - stdout_callback, step_done, true) - end - if have_stderr then - spawn.read_lines(Gio.UnixInputStream.new(stderr, true), - stderr_callback, step_done, true) - end - assert(stdin == nil) - return pid -end - ---- Asynchronously spawn a program and capture its output. --- (wraps `spawn.with_line_callback`). --- @tparam string|table cmd The command. --- @tab callback Function with the following arguments --- @tparam string callback.stdout Output on stdout. --- @tparam string callback.stderr Output on stderr. --- @tparam string callback.exitreason Exit Reason. --- The reason can be "exit" or "signal". --- @tparam integer callback.exitcode Exit code. --- For "exit" reason it's the exit code. --- For "signal" reason — the signal causing process termination. --- @treturn[1] Integer the PID of the forked process. --- @treturn[2] string Error message. --- @see spawn.with_line_callback -function spawn.easy_async(cmd, callback) - local stdout = '' - local stderr = '' - local exitcode, exitreason - local function parse_stdout(str) - stdout = stdout .. str .. "\n" - end - local function parse_stderr(str) - stderr = stderr .. str .. "\n" - end - local function done_callback() - return callback(stdout, stderr, exitreason, exitcode) - end - local exit_callback_fired = false - local output_done_callback_fired = false - local function exit_callback(reason, code) - exitcode = code - exitreason = reason - exit_callback_fired = true - if output_done_callback_fired then - return done_callback() - end - end - local function output_done_callback() - output_done_callback_fired = true - if exit_callback_fired then - return done_callback() - end - end - return spawn.with_line_callback( - cmd, { - stdout=parse_stdout, - stderr=parse_stderr, - exit=exit_callback, - output_done=output_done_callback - }) -end - ---- Read lines from a Gio input stream --- @tparam Gio.InputStream input_stream The input stream to read from. --- @tparam function line_callback Function that is called with each line --- read, e.g. `line_callback(line_from_stream)`. --- @tparam[opt] function done_callback Function that is called when the --- operation finishes (e.g. due to end of file). --- @tparam[opt=false] boolean close Should the stream be closed after end-of-file? -function spawn.read_lines(input_stream, line_callback, done_callback, close) - local stream = Gio.DataInputStream.new(input_stream) - local function done() - if close then - stream:close() - end - if done_callback then - protected_call(done_callback) - end - end - local start_read, finish_read - start_read = function() - stream:read_line_async(GLib.PRIORITY_DEFAULT, nil, finish_read) - end - finish_read = function(obj, res) - local line, length = obj:read_line_finish(res) - if type(length) ~= "number" then - -- Error - print("Error in awful.spawn.read_lines:", tostring(length)) - done() - elseif end_of_file(line, length) then - -- End of file - done() - else - -- Read a line - -- This needs tostring() for older lgi versions which returned - -- "GLib.Bytes" instead of Lua strings (I guess) - protected_call(line_callback, tostring(line)) - - -- Read the next line - start_read() - end - end - start_read() -end - -capi.awesome.connect_signal("spawn::canceled" , spawn.on_snid_cancel ) -capi.awesome.connect_signal("spawn::timeout" , spawn.on_snid_cancel ) -capi.client.connect_signal ("manage" , spawn.on_snid_callback ) - -return setmetatable(spawn, { __call = function(_, ...) return spawn.spawn(...) end }) --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/startup_notification.lua b/awesome/lib/awful/startup_notification.lua deleted file mode 100644 index 5f1c123..0000000 --- a/awesome/lib/awful/startup_notification.lua +++ /dev/null @@ -1,53 +0,0 @@ ---------------------------------------------------------------------------- ---- Startup notification module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @module awful.startup_notification ---------------------------------------------------------------------------- - --- Grab environment we need -local ipairs = ipairs -local table = table -local capi = -{ - awesome = awesome, - root = root -} - -local app_starting = {} - -local cursor_waiting = "watch" - -local function update_cursor() - if #app_starting > 0 then - capi.root.cursor(cursor_waiting) - else - capi.root.cursor("left_ptr") - end -end - -local function unregister_event(event_id) - for k, v in ipairs(app_starting) do - if v == event_id then - table.remove(app_starting, k) - update_cursor() - break - end - end -end - -local function register_event(event_id) - table.insert(app_starting, event_id) - update_cursor() -end - -local function unregister_hook(event) unregister_event(event.id) end -local function register_hook(event) register_event(event.id) end - -capi.awesome.connect_signal("spawn::initiated", register_hook) -capi.awesome.connect_signal("spawn::canceled", unregister_hook) -capi.awesome.connect_signal("spawn::completed", unregister_hook) -capi.awesome.connect_signal("spawn::timeout", unregister_hook) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/tag.lua b/awesome/lib/awful/tag.lua deleted file mode 100644 index dbf3a60..0000000 --- a/awesome/lib/awful/tag.lua +++ /dev/null @@ -1,1505 +0,0 @@ ---------------------------------------------------------------------------- ---- Useful functions for tag manipulation. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module tag ---------------------------------------------------------------------------- - --- Grab environment we need -local util = require("awful.util") -local ascreen = require("awful.screen") -local beautiful = require("beautiful") -local object = require("gears.object") -local timer = require("gears.timer") -local pairs = pairs -local ipairs = ipairs -local table = table -local setmetatable = setmetatable -local capi = -{ - tag = tag, - screen = screen, - mouse = mouse, - client = client, - root = root -} - -local function get_screen(s) - return s and capi.screen[s] -end - -local tag = {object = {}, mt = {} } - --- Private data -local data = {} -data.history = {} - --- History functions -tag.history = {} -tag.history.limit = 20 - --- Default values -local defaults = {} - --- The gap between clients (in points). -defaults.gap = 0 - --- The default gap_count. -defaults.gap_single_client = true - --- The default master fill policy. -defaults.master_fill_policy = "expand" - --- The default master width factor. -defaults.master_width_factor = 0.5 - --- The default master count. -defaults.master_count = 1 - --- The default column count. -defaults.column_count = 1 - --- screen.tags depend on index, it cannot be used by awful.tag -local function raw_tags(scr) - local tmp_tags = {} - for _, t in ipairs(root.tags()) do - if get_screen(t.screen) == scr then - table.insert(tmp_tags, t) - end - end - - return tmp_tags -end - ---- The number of elements kept in the history. --- @tfield integer awful.tag.history.limit --- @tparam[opt=20] integer limit - ---- The tag index. --- --- The index is the position as shown in the `awful.widget.taglist`. --- --- **Signal:** --- --- * *property::index* --- --- @property index --- @param integer --- @treturn number The tag index. - -function tag.object.set_index(self, idx) - local scr = get_screen(tag.getproperty(self, "screen")) - - -- screen.tags cannot be used as it depend on index - local tmp_tags = raw_tags(scr) - - -- sort the tags by index - table.sort(tmp_tags, function(a, b) - local ia, ib = tag.getproperty(a, "index"), tag.getproperty(b, "index") - return (ia or math.huge) < (ib or math.huge) - end) - - if (not idx) or (idx < 1) or (idx > #tmp_tags) then - return - end - - local rm_index = nil - - for i, t in ipairs(tmp_tags) do - if t == self then - table.remove(tmp_tags, i) - rm_index = i - break - end - end - - table.insert(tmp_tags, idx, self) - for i = idx < rm_index and idx or rm_index, #tmp_tags do - local tmp_tag = tmp_tags[i] - tag.object.set_screen(tmp_tag, scr) - tag.setproperty(tmp_tag, "index", i) - end -end - -function tag.object.get_index(query_tag) - - local idx = tag.getproperty(query_tag, "index") - - if idx then return idx end - - -- Get an unordered list of tags - local tags = raw_tags(query_tag.screen) - - -- Too bad, lets compute it - for i, t in ipairs(tags) do - if t == query_tag then - tag.setproperty(t, "index", i) - return i - end - end -end - ---- Move a tag to an absolute position in the screen[]:tags() table. --- @deprecated awful.tag.move --- @param new_index Integer absolute position in the table to insert. --- @param target_tag The tag that should be moved. If null, the currently --- selected tag is used. --- @see index -function tag.move(new_index, target_tag) - util.deprecate("Use t.index = new_index instead of awful.tag.move") - - target_tag = target_tag or ascreen.focused().selected_tag - tag.object.set_index(target_tag, new_index) -end - ---- Swap 2 tags --- @function tag.swap --- @param tag2 The second tag --- @see client.swap -function tag.object.swap(self, tag2) - local idx1, idx2 = tag.object.get_index(self), tag.object.get_index(tag2) - local scr2, scr1 = tag.getproperty(tag2, "screen"), tag.getproperty(self, "screen") - - -- If they are on the same screen, avoid recomputing the whole table - -- for nothing. - if scr1 == scr2 then - tag.setproperty(self, "index", idx2) - tag.setproperty(tag2, "index", idx1) - else - tag.object.set_screen(tag2, scr1) - tag.object.set_index (tag2, idx1) - tag.object.set_screen(self, scr2) - tag.object.set_index (self, idx2) - end -end - ---- Swap 2 tags --- @deprecated awful.tag.swap --- @see tag.swap --- @param tag1 The first tag --- @param tag2 The second tag -function tag.swap(tag1, tag2) - util.deprecate("Use t:swap(tag2) instead of awful.tag.swap") - - tag.object.swap(tag1, tag2) -end - ---- Add a tag. --- --- This function allow to create tags from a set of properties: --- --- local t = awful.tag.add("my new tag", { --- screen = screen.primary, --- layout = awful.layout.suit.max, --- }) --- --- @function awful.tag.add --- @param name The tag name, a string --- @param props The tags inital properties, a table --- @return The created tag --- @see tag.delete -function tag.add(name, props) - local properties = props or {} - - -- Be sure to set the screen before the tag is activated to avoid function - -- connected to property::activated to be called without a valid tag. - -- set properties cannot be used as this has to be set before the first - -- signal is sent - properties.screen = get_screen(properties.screen or ascreen.focused()) - -- Index is also required - properties.index = properties.index or #raw_tags(properties.screen)+1 - - local newtag = capi.tag{ name = name } - - -- Start with a fresh property table to avoid collisions with unsupported data - newtag.data.awful_tag_properties = {screen=properties.screen, index=properties.index} - - newtag.activated = true - - for k, v in pairs(properties) do - -- `rawget` doesn't work on userdata, `:clients()` is the only relevant - -- entry. - if k == "clients" or tag.object[k] then - newtag[k](newtag, v) - else - newtag[k] = v - end - end - - return newtag -end - ---- Create a set of tags and attach it to a screen. --- @function awful.tag.new --- @param names The tag name, in a table --- @param screen The tag screen, or 1 if not set. --- @param layout The layout or layout table to set for this tags by default. --- @return A table with all created tags. -function tag.new(names, screen, layout) - screen = get_screen(screen or 1) - local tags = {} - for id, name in ipairs(names) do - table.insert(tags, id, tag.add(name, {screen = screen, - layout = (layout and layout[id]) or - layout})) - -- Select the first tag. - if id == 1 then - tags[id].selected = true - end - end - - return tags -end - ---- Find a suitable fallback tag. --- @function awful.tag.find_fallback --- @param screen The screen to look for a tag on. [awful.screen.focused()] --- @param invalids A table of tags we consider unacceptable. [selectedlist(scr)] -function tag.find_fallback(screen, invalids) - local scr = screen or ascreen.focused() - local t = invalids or scr.selected_tags - - for _, v in pairs(scr.tags) do - if not util.table.hasitem(t, v) then return v end - end -end - ---- Delete a tag. --- --- To delete the current tag: --- --- mouse.screen.selected_tag:delete() --- --- @function tag.delete --- @see awful.tag.add --- @see awful.tag.find_fallback --- @tparam[opt=awful.tag.find_fallback()] tag fallback_tag Tag to assign --- stickied tags to. --- @tparam[opt=false] boolean force Move even non-sticky clients to the fallback --- tag. --- @return Returns true if the tag is successfully deleted. --- If there are no clients exclusively on this tag then delete it. Any --- stickied clients are assigned to the optional 'fallback_tag'. --- If after deleting the tag there is no selected tag, try and restore from --- history or select the first tag on the screen. -function tag.object.delete(self, fallback_tag, force) - -- abort if the taf isn't currently activated - if not self.activated then return false end - - local target_scr = get_screen(tag.getproperty(self, "screen")) - local tags = target_scr.tags - local idx = tag.object.get_index(self) - local ntags = #tags - - -- We can't use the target tag as a fallback. - if fallback_tag == self then return false end - - -- No fallback_tag provided, try and get one. - if fallback_tag == nil then - fallback_tag = tag.find_fallback(target_scr, {self}) - end - - -- Abort if we would have un-tagged clients. - local clients = self:clients() - if #clients > 0 and fallback_tag == nil then return false end - - -- Move the clients we can off of this tag. - for _, c in pairs(clients) do - local nb_tags = #c:tags() - - -- If a client has only this tag, or stickied clients with - -- nowhere to go, abort. - if (not c.sticky and nb_tags == 1 and not force) then - return - -- If a client has multiple tags, then do not move it to fallback - elseif nb_tags < 2 then - c:tags({fallback_tag}) - end - end - - -- delete the tag - self.data.awful_tag_properties.screen = nil - self.activated = false - - -- Update all indexes - for i=idx+1, #tags do - tag.setproperty(tags[i], "index", i-1) - end - - -- If no tags are visible (and we did not delete the lasttag), try and - -- view one. The > 1 is because ntags is no longer synchronized with the - -- current count. - if target_scr.selected_tag == nil and ntags > 1 then - tag.history.restore(target_scr, 1) - if target_scr.selected_tag == nil then - local other_tag = tags[tags[1] == self and 2 or 1] - if other_tag then - other_tag.selected = true - end - end - end - - return true -end - ---- Delete a tag. --- @deprecated awful.tag.delete --- @see tag.delete --- @param target_tag Optional tag object to delete. [selected()] --- @param fallback_tag Tag to assign stickied tags to. [~selected()] --- @return Returns true if the tag is successfully deleted, nil otherwise. --- If there are no clients exclusively on this tag then delete it. Any --- stickied clients are assigned to the optional 'fallback_tag'. --- If after deleting the tag there is no selected tag, try and restore from --- history or select the first tag on the screen. -function tag.delete(target_tag, fallback_tag) - util.deprecate("Use t:delete(fallback_tag) instead of awful.tag.delete") - - return tag.object.delete(target_tag, fallback_tag) -end - ---- Update the tag history. --- @function awful.tag.history.update --- @param obj Screen object. -function tag.history.update(obj) - local s = get_screen(obj) - local curtags = s.selected_tags - -- create history table - if not data.history[s] then - data.history[s] = {} - else - if data.history[s].current then - -- Check that the list is not identical - local identical = #data.history[s].current == #curtags - if identical then - for idx, _tag in ipairs(data.history[s].current) do - if curtags[idx] ~= _tag then - identical = false - break - end - end - end - - -- Do not update history the table are identical - if identical then return end - end - - -- Limit history - if #data.history[s] >= tag.history.limit then - for i = tag.history.limit, #data.history[s] do - data.history[s][i] = nil - end - end - end - - -- store previously selected tags in the history table - table.insert(data.history[s], 1, data.history[s].current) - data.history[s].previous = data.history[s][1] - -- store currently selected tags - data.history[s].current = setmetatable(curtags, { __mode = 'v' }) -end - ---- Revert tag history. --- @function awful.tag.history.restore --- @param screen The screen. --- @param idx Index in history. Defaults to "previous" which is a special index --- toggling between last two selected sets of tags. Number (eg 1) will go back --- to the given index in history. -function tag.history.restore(screen, idx) - local s = get_screen(screen or ascreen.focused()) - local i = idx or "previous" - local sel = s.selected_tags - -- do nothing if history empty - if not data.history[s] or not data.history[s][i] then return end - -- if all tags been deleted, try next entry - if #data.history[s][i] == 0 then - if i == "previous" then i = 0 end - tag.history.restore(s, i + 1) - return - end - -- deselect all tags - tag.viewnone(s) - -- select tags from the history entry - for _, t in ipairs(data.history[s][i]) do - if t.activated and t.screen then - t.selected = true - end - end - -- update currently selected tags table - data.history[s].current = data.history[s][i] - -- store previously selected tags - data.history[s].previous = setmetatable(sel, { __mode = 'v' }) - -- remove the reverted history entry - if i ~= "previous" then table.remove(data.history[s], i) end - - s:emit_signal("tag::history::update") -end - ---- Get a list of all tags on a screen --- @deprecated awful.tag.gettags --- @tparam screen s Screen --- @return A table with all available tags --- @see screen.tags -function tag.gettags(s) - util.deprecate("Use s.tags instead of awful.tag.gettags") - - s = get_screen(s) - - return s and s.tags or {} -end - ---- Find a tag by name --- @tparam[opt] screen s The screen of the tag --- @tparam string name The name of the tag --- @return The tag found, or `nil` -function tag.find_by_name(s, name) - local tags = s and s.tags or root.tags() - for _, t in ipairs(tags) do - if name == t.name then - return t - end - end -end - ---- The tag screen. --- --- **Signal:** --- --- * *property::screen* --- --- @property screen --- @param screen --- @see screen - -function tag.object.set_screen(t, s) - - s = get_screen(s or ascreen.focused()) - local sel = tag.selected - local old_screen = get_screen(tag.getproperty(t, "screen")) - - if s == old_screen then return end - - -- Keeping the old index make very little sense when changing screen - tag.setproperty(t, "index", nil) - - -- Change the screen - tag.setproperty(t, "screen", s) - tag.setproperty(t, "index", #s:get_tags(true)) - - -- Make sure the client's screen matches its tags - for _,c in ipairs(t:clients()) do - c.screen = s --Move all clients - c:tags({t}) - end - - -- Update all indexes - for i,t2 in ipairs(old_screen.tags) do - tag.setproperty(t2, "index", i) - end - - -- Restore the old screen history if the tag was selected - if sel then - tag.history.restore(old_screen, 1) - end -end - ---- Set a tag's screen --- @deprecated awful.tag.setscreen --- @see screen --- @param s Screen --- @param t tag object -function tag.setscreen(s, t) - -- For API consistency, the arguments have been swapped for Awesome 3.6 - -- this method is already deprecated, so be silent and swap the args - if type(t) == "number" then - s, t = t, s - end - - util.deprecate("Use t.screen = s instead of awful.tag.setscreen(t, s)") - - tag.object.set_screen(t, s) -end - ---- Get a tag's screen --- @deprecated awful.tag.getscreen --- @see screen --- @param[opt] t tag object --- @return Screen number -function tag.getscreen(t) - util.deprecate("Use t.screen instead of awful.tag.getscreen(t)") - - -- A new getter is not required - - t = t or ascreen.focused().selected_tag - local prop = tag.getproperty(t, "screen") - return prop and prop.index -end - ---- Return a table with all visible tags --- @deprecated awful.tag.selectedlist --- @param s Screen. --- @return A table with all selected tags. --- @see screen.selected_tags -function tag.selectedlist(s) - util.deprecate("Use s.selected_tags instead of awful.tag.selectedlist") - - s = get_screen(s or ascreen.focused()) - - return s.selected_tags -end - ---- Return only the first visible tag. --- @deprecated awful.tag.selected --- @param s Screen. --- @see screen.selected_tag -function tag.selected(s) - util.deprecate("Use s.selected_tag instead of awful.tag.selected") - - s = get_screen(s or ascreen.focused()) - - return s.selected_tag -end - ---- The default master width factor --- --- @beautiful beautiful.master_width_factor --- @param number (default: 0.5) --- @see master_width_factor --- @see gap - ---- The tag master width factor. --- --- The master width factor is one of the 5 main properties used to configure --- the `layout`. Each layout interpret (or ignore) this property differenly. --- --- See the layout suit documentation for information about how the master width --- factor is used. --- --- **Signal:** --- --- * *property::mwfact* (deprecated) --- * *property::master_width_factor* --- --- @property master_width_factor --- @param number Between 0 and 1 --- @see master_count --- @see column_count --- @see master_fill_policy --- @see gap - -function tag.object.set_master_width_factor(t, mwfact) - if mwfact >= 0 and mwfact <= 1 then - tag.setproperty(t, "mwfact", mwfact) - tag.setproperty(t, "master_width_factor", mwfact) - end -end - -function tag.object.get_master_width_factor(t) - return tag.getproperty(t, "master_width_factor") - or beautiful.master_width_factor - or defaults.master_width_factor -end - ---- Set master width factor. --- @deprecated awful.tag.setmwfact --- @see master_fill_policy --- @see master_width_factor --- @param mwfact Master width factor. --- @param t The tag to modify, if null tag.selected() is used. -function tag.setmwfact(mwfact, t) - util.deprecate("Use t.master_width_factor = mwfact instead of awful.tag.setmwfact") - - tag.object.get_master_width_factor(t or ascreen.focused().selected_tag, mwfact) -end - ---- Increase master width factor. --- @function awful.tag.incmwfact --- @see master_width_factor --- @param add Value to add to master width factor. --- @param t The tag to modify, if null tag.selected() is used. -function tag.incmwfact(add, t) - t = t or t or ascreen.focused().selected_tag - tag.object.set_master_width_factor(t, tag.object.get_master_width_factor(t) + add) -end - ---- Get master width factor. --- @deprecated awful.tag.getmwfact --- @see master_width_factor --- @see master_fill_policy --- @param[opt] t The tag. -function tag.getmwfact(t) - util.deprecate("Use t.master_width_factor instead of awful.tag.getmwfact") - - return tag.object.get_master_width_factor(t or ascreen.focused().selected_tag) -end - ---- An ordered list of layouts. --- `awful.tag.layout` Is usually defined in `rc.lua`. It store the list of --- layouts used when selecting the previous and next layouts. This is the --- default: --- --- -- Table of layouts to cover with awful.layout.inc, order matters. --- awful.layout.layouts = { --- awful.layout.suit.floating, --- awful.layout.suit.tile, --- awful.layout.suit.tile.left, --- awful.layout.suit.tile.bottom, --- awful.layout.suit.tile.top, --- awful.layout.suit.fair, --- awful.layout.suit.fair.horizontal, --- awful.layout.suit.spiral, --- awful.layout.suit.spiral.dwindle, --- awful.layout.suit.max, --- awful.layout.suit.max.fullscreen, --- awful.layout.suit.magnifier, --- awful.layout.suit.corner.nw, --- -- awful.layout.suit.corner.ne, --- -- awful.layout.suit.corner.sw, --- -- awful.layout.suit.corner.se, --- } --- --- @field awful.tag.layouts - ---- The tag client layout. --- --- This property hold the layout. A layout can be either stateless or stateful. --- Stateless layouts are used by default by Awesome. They tile clients without --- any other overhead. They take an ordered list of clients and place them on --- the screen. Stateful layouts create an object instance for each tags and --- can store variables and metadata. Because of this, they are able to change --- over time and be serialized (saved). --- --- Both types of layouts have valid usage scenarios. --- --- **Stateless layouts:** --- --- These layouts are stored in `awful.layout.suit`. They expose a table with 2 --- fields: --- --- * **name** (*string*): The layout name. This should be unique. --- * **arrange** (*function*): The function called when the clients need to be --- placed. The only parameter is a table or arguments returned by --- `awful.layout.parameters` --- --- **Stateful layouts:** --- --- The stateful layouts API is the same as stateless, but they are a function --- returining a layout instead of a layout itself. They also should have an --- `is_dynamic = true` property. If they don't, `awful.tag` will create a new --- instance everytime the layout is set. If they do, the instance will be --- cached and re-used. --- --- **Signal:** --- --- * *property::layout* --- --- @property layout --- @see awful.tag.layouts --- @tparam layout|function layout A layout table or a constructor function --- @return The layout - -function tag.object.set_layout(t, layout) - -- Check if the signature match a stateful layout - if type(layout) == "function" or ( - type(layout) == "table" - and getmetatable(layout) - and getmetatable(layout).__call - ) then - if not t.dynamic_layout_cache then - t.dynamic_layout_cache = {} - end - - local instance = t.dynamic_layout_cache[layout] or layout(t) - - -- Always make sure the layout is notified it is enabled - if tag.getproperty(t, "screen").selected_tag == t and instance.wake_up then - instance:wake_up() - end - - -- Avoid creating the same layout twice, use layout:reset() to reset - if instance.is_dynamic then - t.dynamic_layout_cache[layout] = instance - end - - layout = instance - end - - tag.setproperty(t, "layout", layout) - - return layout -end - ---- Set layout. --- @deprecated awful.tag.setlayout --- @see layout --- @param layout a layout table or a constructor function --- @param t The tag to modify --- @return The layout -function tag.setlayout(layout, t) - util.deprecate("Use t.layout = layout instead of awful.tag.setlayout") - - return tag.object.set_layout(t, layout) -end - ---- Define if the tag must be deleted when the last client is untagged. --- --- This is useful to create "throw-away" tags for operation like 50/50 --- side-by-side views. --- --- local t = awful.tag.add("Temporary", { --- screen = client.focus.screen, --- volatile = true, --- clients = { --- client.focus, --- awful.client.focus.history.get(client.focus.screen, 1) --- } --- } --- --- **Signal:** --- --- * *property::volatile* --- --- @property volatile --- @param boolean - --- Volatile accessors are implicit - ---- Set if the tag must be deleted when the last client is untagged --- @deprecated awful.tag.setvolatile --- @see volatile --- @tparam boolean volatile If the tag must be deleted when the last client is untagged --- @param t The tag to modify, if null tag.selected() is used. -function tag.setvolatile(volatile, t) - util.deprecate("Use t.volatile = volatile instead of awful.tag.setvolatile") - - tag.setproperty(t, "volatile", volatile) -end - ---- Get if the tag must be deleted when the last client closes --- @deprecated awful.tag.getvolatile --- @see volatile --- @param t The tag to modify, if null tag.selected() is used. --- @treturn boolean If the tag will be deleted when the last client is untagged -function tag.getvolatile(t) - util.deprecate("Use t.volatile instead of awful.tag.getvolatile") - - return tag.getproperty(t, "volatile") or false -end - ---- The default gap. --- --- @beautiful beautiful.useless_gap --- @param number (default: 0) --- @see gap --- @see gap_single_client - ---- The gap (spacing, also called `useless_gap`) between clients. --- --- This property allow to waste space on the screen in the name of style, --- unicorns and readability. --- --- **Signal:** --- --- * *property::useless_gap* --- --- @property gap --- @param number The value has to be greater than zero. --- @see gap_single_client - -function tag.object.set_gap(t, useless_gap) - if useless_gap >= 0 then - tag.setproperty(t, "useless_gap", useless_gap) - end -end - -function tag.object.get_gap(t) - return tag.getproperty(t, "useless_gap") - or beautiful.useless_gap - or defaults.gap -end - ---- Set the spacing between clients --- @deprecated awful.tag.setgap --- @see gap --- @param useless_gap The spacing between clients --- @param t The tag to modify, if null tag.selected() is used. -function tag.setgap(useless_gap, t) - util.deprecate("Use t.gap = useless_gap instead of awful.tag.setgap") - - tag.object.set_gap(t or ascreen.focused().selected_tag, useless_gap) -end - ---- Increase the spacing between clients --- @function awful.tag.incgap --- @see gap --- @param add Value to add to the spacing between clients --- @param t The tag to modify, if null tag.selected() is used. -function tag.incgap(add, t) - t = t or t or ascreen.focused().selected_tag - tag.object.set_gap(t, tag.object.get_gap(t) + add) -end - ---- Enable gaps for a single client. --- --- @beautiful beautiful.gap_single_client --- @param boolean (default: true) --- @see gap --- @see gap_single_client - ---- Enable gaps for a single client. --- --- **Signal:** --- --- * *property::gap\_single\_client* --- --- @property gap_single_client --- @param boolean Enable gaps for a single client - -function tag.object.set_gap_single_client(t, gap_single_client) - tag.setproperty(t, "gap_single_client", gap_single_client == true) -end - -function tag.object.get_gap_single_client(t) - local val = tag.getproperty(t, "gap_single_client") - if val ~= nil then - return val - end - val = beautiful.gap_single_client - if val ~= nil then - return val - end - return defaults.gap_single_client -end - ---- Get the spacing between clients. --- @deprecated awful.tag.getgap --- @see gap --- @tparam[opt=tag.selected()] tag t The tag. --- @tparam[opt] int numclients Number of (tiled) clients. Passing this will --- return 0 for a single client. You can override this function to change --- this behavior. -function tag.getgap(t, numclients) - util.deprecate("Use t.gap instead of awful.tag.getgap") - - if numclients == 1 then - return 0 - end - - return tag.object.get_gap(t or ascreen.focused().selected_tag) -end - ---- The default fill policy. --- --- ** Possible values**: --- --- * *expand*: Take all the space --- * *master_width_factor*: Only take the ratio defined by the --- `master_width_factor` --- --- @beautiful beautiful.master_fill_policy --- @param string (default: "expand") --- @see master_fill_policy - ---- Set size fill policy for the master client(s). --- --- ** Possible values**: --- --- * *expand*: Take all the space --- * *master_width_factor*: Only take the ratio defined by the --- `master_width_factor` --- --- **Signal:** --- --- * *property::master_fill_policy* --- --- @property master_fill_policy --- @param string "expand" or "master_width_factor" - -function tag.object.get_master_fill_policy(t) - return tag.getproperty(t, "master_fill_policy") - or beautiful.master_fill_policy - or defaults.master_fill_policy -end - ---- Set size fill policy for the master client(s) --- @deprecated awful.tag.setmfpol --- @see master_fill_policy --- @tparam string policy Can be set to --- "expand" (fill all the available workarea) or --- "master_width_factor" (fill only an area inside the master width factor) --- @tparam[opt=tag.selected()] tag t The tag to modify -function tag.setmfpol(policy, t) - util.deprecate("Use t.master_fill_policy = policy instead of awful.tag.setmfpol") - - t = t or ascreen.focused().selected_tag - tag.setproperty(t, "master_fill_policy", policy) -end - ---- Toggle size fill policy for the master client(s) --- between "expand" and "master_width_factor". --- @function awful.tag.togglemfpol --- @see master_fill_policy --- @tparam tag t The tag to modify, if null tag.selected() is used. -function tag.togglemfpol(t) - t = t or ascreen.focused().selected_tag - - if tag.getmfpol(t) == "expand" then - tag.setproperty(t, "master_fill_policy", "master_width_factor") - else - tag.setproperty(t, "master_fill_policy", "expand") - end -end - ---- Get size fill policy for the master client(s) --- @deprecated awful.tag.getmfpol --- @see master_fill_policy --- @tparam[opt=tag.selected()] tag t The tag --- @treturn string Possible values are --- "expand" (fill all the available workarea, default one) or --- "master_width_factor" (fill only an area inside the master width factor) -function tag.getmfpol(t) - util.deprecate("Use t.master_fill_policy instead of awful.tag.getmfpol") - - t = t or ascreen.focused().selected_tag - return tag.getproperty(t, "master_fill_policy") - or beautiful.master_fill_policy - or defaults.master_fill_policy -end - ---- The default number of master windows. --- --- @beautiful beautiful.master_count --- @param integer (default: 1) --- @see master_count - ---- Set the number of master windows. --- --- **Signal:** --- --- * *property::nmaster* (deprecated) --- * *property::master_count* (deprecated) --- --- @property master_count --- @param integer nmaster Only positive values are accepted - -function tag.object.set_master_count(t, nmaster) - if nmaster >= 0 then - tag.setproperty(t, "nmaster", nmaster) - tag.setproperty(t, "master_count", nmaster) - end -end - -function tag.object.get_master_count(t) - return tag.getproperty(t, "master_count") - or beautiful.master_count - or defaults.master_count -end - ---- --- @deprecated awful.tag.setnmaster --- @see master_count --- @param nmaster The number of master windows. --- @param[opt] t The tag. -function tag.setnmaster(nmaster, t) - util.deprecate("Use t.master_count = nmaster instead of awful.tag.setnmaster") - - tag.object.set_master_count(t or ascreen.focused().selected_tag, nmaster) -end - ---- Get the number of master windows. --- @deprecated awful.tag.getnmaster --- @see master_count --- @param[opt] t The tag. -function tag.getnmaster(t) - util.deprecate("Use t.master_count instead of awful.tag.setnmaster") - - t = t or ascreen.focused().selected_tag - return tag.getproperty(t, "master_count") or 1 -end - ---- Increase the number of master windows. --- @function awful.tag.incnmaster --- @see master_count --- @param add Value to add to number of master windows. --- @param[opt] t The tag to modify, if null tag.selected() is used. --- @tparam[opt=false] boolean sensible Limit nmaster based on the number of --- visible tiled windows? -function tag.incnmaster(add, t, sensible) - t = t or ascreen.focused().selected_tag - - if sensible then - local screen = get_screen(tag.getproperty(t, "screen")) - local ntiled = #screen.tiled_clients - - local nmaster = tag.object.get_master_count(t) - if nmaster > ntiled then - nmaster = ntiled - end - - local newnmaster = nmaster + add - if newnmaster > ntiled then - newnmaster = ntiled - end - tag.object.set_master_count(t, newnmaster) - else - tag.object.set_master_count(t, tag.object.get_master_count(t) + add) - end -end - ---- Set the tag icon. --- --- **Signal:** --- --- * *property::icon* --- --- @property icon --- @tparam path|surface icon The icon - --- accessors are implicit. - ---- Set the tag icon --- @deprecated awful.tag.seticon --- @see icon --- @param icon the icon to set, either path or image object --- @param _tag the tag -function tag.seticon(icon, _tag) - util.deprecate("Use t.icon = icon instead of awful.tag.seticon") - - _tag = _tag or ascreen.focused().selected_tag - tag.setproperty(_tag, "icon", icon) -end - ---- Get the tag icon --- @deprecated awful.tag.geticon --- @see icon --- @param _tag the tag -function tag.geticon(_tag) - util.deprecate("Use t.icon instead of awful.tag.geticon") - - _tag = _tag or ascreen.focused().selected_tag - return tag.getproperty(_tag, "icon") -end - ---- The default number of columns. --- --- @beautiful beautiful.column_count --- @param integer (default: 1) --- @see column_count - ---- Set the number of columns. --- --- **Signal:** --- --- * *property::ncol* (deprecated) --- * *property::column_count* --- --- @property column_count --- @tparam integer ncol Has to be greater than 1 - -function tag.object.set_column_count(t, ncol) - if ncol >= 1 then - tag.setproperty(t, "ncol", ncol) - tag.setproperty(t, "column_count", ncol) - end -end - -function tag.object.get_column_count(t) - return tag.getproperty(t, "column_count") - or beautiful.column_count - or defaults.column_count -end - ---- Set number of column windows. --- @deprecated awful.tag.setncol --- @see column_count --- @param ncol The number of column. --- @param t The tag to modify, if null tag.selected() is used. -function tag.setncol(ncol, t) - util.deprecate("Use t.column_count = new_index instead of awful.tag.setncol") - - t = t or ascreen.focused().selected_tag - if ncol >= 1 then - tag.setproperty(t, "ncol", ncol) - tag.setproperty(t, "column_count", ncol) - end -end - ---- Get number of column windows. --- @deprecated awful.tag.getncol --- @see column_count --- @param[opt] t The tag. -function tag.getncol(t) - util.deprecate("Use t.column_count instead of awful.tag.getncol") - - t = t or ascreen.focused().selected_tag - return tag.getproperty(t, "column_count") or 1 -end - ---- Increase number of column windows. --- @function awful.tag.incncol --- @param add Value to add to number of column windows. --- @param[opt] t The tag to modify, if null tag.selected() is used. --- @tparam[opt=false] boolean sensible Limit column_count based on the number --- of visible tiled windows? -function tag.incncol(add, t, sensible) - t = t or ascreen.focused().selected_tag - - if sensible then - local screen = get_screen(tag.getproperty(t, "screen")) - local ntiled = #screen.tiled_clients - local nmaster = tag.object.get_master_count(t) - local nsecondary = ntiled - nmaster - - local ncol = tag.object.get_column_count(t) - if ncol > nsecondary then - ncol = nsecondary - end - - local newncol = ncol + add - if newncol > nsecondary then - newncol = nsecondary - end - - tag.object.set_column_count(t, newncol) - else - tag.object.set_column_count(t, tag.object.get_column_count(t) + add) - end -end - ---- View no tag. --- @function awful.tag.viewnone --- @tparam[opt] int|screen screen The screen. -function tag.viewnone(screen) - screen = screen or ascreen.focused() - local tags = screen.tags - for _, t in pairs(tags) do - t.selected = false - end -end - ---- View a tag by its taglist index. --- --- This is equivalent to `screen.tags[i]:view_only()` --- @function awful.tag.viewidx --- @see screen.tags --- @param i The **relative** index to see. --- @param[opt] screen The screen. -function tag.viewidx(i, screen) - screen = get_screen(screen or ascreen.focused()) - local tags = screen.tags - local showntags = {} - for _, t in ipairs(tags) do - if not tag.getproperty(t, "hide") then - table.insert(showntags, t) - end - end - local sel = screen.selected_tag - tag.viewnone(screen) - for k, t in ipairs(showntags) do - if t == sel then - showntags[util.cycle(#showntags, k + i)].selected = true - end - end - screen:emit_signal("tag::history::update") -end - ---- Get a tag's index in the gettags() table. --- @deprecated awful.tag.getidx --- @see index --- @param query_tag The tag object to find. [selected()] --- @return The index of the tag, nil if the tag is not found. -function tag.getidx(query_tag) - util.deprecate("Use t.index instead of awful.tag.getidx") - - return tag.object.get_index(query_tag or ascreen.focused().selected_tag) -end - ---- View next tag. This is the same as tag.viewidx(1). --- @function awful.tag.viewnext --- @param screen The screen. -function tag.viewnext(screen) - return tag.viewidx(1, screen) -end - ---- View previous tag. This is the same a tag.viewidx(-1). --- @function awful.tag.viewprev --- @param screen The screen. -function tag.viewprev(screen) - return tag.viewidx(-1, screen) -end - ---- View only a tag. --- @function tag.view_only --- @see selected -function tag.object.view_only(self) - local tags = self.screen.tags - -- First, untag everyone except the viewed tag. - for _, _tag in pairs(tags) do - if _tag ~= self then - _tag.selected = false - end - end - -- Then, set this one to selected. - -- We need to do that in 2 operations so we avoid flickering and several tag - -- selected at the same time. - self.selected = true - capi.screen[self.screen]:emit_signal("tag::history::update") -end - ---- View only a tag. --- @deprecated awful.tag.viewonly --- @see tag.view_only --- @param t The tag object. -function tag.viewonly(t) - util.deprecate("Use t:view_only() instead of awful.tag.viewonly") - - tag.object.view_only(t) -end - ---- View only a set of tags. --- @function awful.tag.viewmore --- @param tags A table with tags to view only. --- @param[opt] screen The screen of the tags. -function tag.viewmore(tags, screen) - screen = get_screen(screen or ascreen.focused()) - local screen_tags = screen.tags - for _, _tag in ipairs(screen_tags) do - if not util.table.hasitem(tags, _tag) then - _tag.selected = false - end - end - for _, _tag in ipairs(tags) do - _tag.selected = true - end - screen:emit_signal("tag::history::update") -end - ---- Toggle selection of a tag --- @function awful.tag.viewtoggle --- @see selected --- @tparam tag t Tag to be toggled -function tag.viewtoggle(t) - t.selected = not t.selected - capi.screen[tag.getproperty(t, "screen")]:emit_signal("tag::history::update") -end - ---- Get tag data table. --- --- Do not use. --- --- @deprecated awful.tag.getdata --- @tparam tag _tag The tag. --- @return The data table. -function tag.getdata(_tag) - return _tag.data.awful_tag_properties -end - ---- Get a tag property. --- --- Use `_tag.prop` directly. --- --- @deprecated awful.tag.getproperty --- @tparam tag _tag The tag. --- @tparam string prop The property name. --- @return The property. -function tag.getproperty(_tag, prop) - if not _tag then return end -- FIXME: Turn this into an error? - if _tag.data.awful_tag_properties then - return _tag.data.awful_tag_properties[prop] - end -end - ---- Set a tag property. --- This properties are internal to awful. Some are used to draw taglist, or to --- handle layout, etc. --- --- Use `_tag.prop = value` --- --- @deprecated awful.tag.setproperty --- @param _tag The tag. --- @param prop The property name. --- @param value The value. -function tag.setproperty(_tag, prop, value) - if not _tag.data.awful_tag_properties then - _tag.data.awful_tag_properties = {} - end - - if _tag.data.awful_tag_properties[prop] ~= value then - _tag.data.awful_tag_properties[prop] = value - _tag:emit_signal("property::" .. prop) - end -end - ---- Tag a client with the set of current tags. --- @deprecated awful.tag.withcurrent --- @param c The client to tag. -function tag.withcurrent(c) - util.deprecate("Use c:to_selected_tags() instead of awful.tag.selectedlist") - - -- It can't use c:to_selected_tags() because awful.tag is loaded before - -- awful.client - - local tags = {} - for _, t in ipairs(c:tags()) do - if get_screen(tag.getproperty(t, "screen")) == get_screen(c.screen) then - table.insert(tags, t) - end - end - if #tags == 0 then - tags = c.screen.selected_tags - end - if #tags == 0 then - tags = c.screen.tags - end - if #tags ~= 0 then - c:tags(tags) - end -end - -local function attached_connect_signal_screen(screen, sig, func) - screen = get_screen(screen) - capi.tag.connect_signal(sig, function(_tag) - if get_screen(tag.getproperty(_tag, "screen")) == screen then - func(_tag) - end - end) -end - ---- Add a signal to all attached tags and all tags that will be attached in the --- future. When a tag is detached from the screen, its signal is removed. --- --- @function awful.tag.attached_connect_signal --- @screen The screen concerned, or all if nil. --- @tparam[opt] string Signal --- @tparam[opt] function Callback -function tag.attached_connect_signal(screen, ...) - if screen then - attached_connect_signal_screen(screen, ...) - else - capi.tag.connect_signal(...) - end -end - --- Register standard signals. -capi.client.connect_signal("property::screen", function(c) - -- First, the delayed timer is necessary to avoid a race condition with - -- awful.rules. It is also messing up the tags before the user have a chance - -- to set them manually. - timer.delayed_call(function() - local tags, new_tags = c:tags(), {} - - for _, t in ipairs(tags) do - if t.screen == c.screen then - table.insert(new_tags, t) - end - end - - if #new_tags == 0 then - c:emit_signal("request::tag", nil, {reason="screen"}) - elseif #new_tags < #tags then - c:tags(new_tags) - end - end) -end) - --- Keep track of the number of urgent clients. -local function update_urgent(t, modif) - local count = tag.getproperty(t, "urgent_count") or 0 - count = (count + modif) >= 0 and (count + modif) or 0 - tag.setproperty(t, "urgent" , count > 0) - tag.setproperty(t, "urgent_count", count ) -end - --- Update the urgent counter when a client is tagged. -local function client_tagged(c, t) - if c.urgent then - update_urgent(t, 1) - end -end - --- Update the urgent counter when a client is untagged. -local function client_untagged(c, t) - if c.urgent then - update_urgent(t, -1) - end - - if #t:clients() == 0 and tag.getproperty(t, "volatile") then - tag.object.delete(t) - end -end - --- Count the urgent clients. -local function urgent_callback(c) - for _,t in ipairs(c:tags()) do - update_urgent(t, c.urgent and 1 or -1) - end -end - -capi.client.connect_signal("property::urgent", urgent_callback) -capi.client.connect_signal("untagged", client_untagged) -capi.client.connect_signal("tagged", client_tagged) -capi.tag.connect_signal("request::select", tag.object.view_only) - ---- True when a tagged client is urgent --- @signal property::urgent --- @see client.urgent - ---- The number of urgent tagged clients --- @signal property::urgent_count --- @see client.urgent - -capi.screen.connect_signal("tag::history::update", tag.history.update) - -capi.screen.connect_signal("removed", function(s) - -- First give other code a chance to move the tag to another screen - for _, t in pairs(s.tags) do - t:emit_signal("request::screen") - end - -- Everything that's left: Tell everyone that these tags go away (other code - -- could e.g. save clients) - for _, t in pairs(s.tags) do - t:emit_signal("removal-pending") - end - -- Give other code yet another change to save clients - for _, c in pairs(capi.client.get(s)) do - c:emit_signal("request::tag", nil, { reason = "screen-removed" }) - end - -- Then force all clients left to go somewhere random - local fallback = nil - for other_screen in capi.screen do - if #other_screen.tags > 0 then - fallback = other_screen.tags[1] - break - end - end - for _, t in pairs(s.tags) do - t:delete(fallback, true) - end - -- If any tag survived until now, forcefully get rid of it - for _, t in pairs(s.tags) do - t.activated = false - - if t.data.awful_tag_properties then - t.data.awful_tag_properties.screen = nil - end - end -end) - -function tag.mt:__call(...) - return tag.new(...) -end - --- Extend the luaobject --- `awful.tag.setproperty` currently handle calling the setter method itself --- while `awful.tag.getproperty`. -object.properties(capi.tag, { - getter_class = tag.object, - setter_class = tag.object, - getter_fallback = tag.getproperty, - setter_fallback = tag.setproperty, -}) - -return setmetatable(tag, tag.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/titlebar.lua b/awesome/lib/awful/titlebar.lua deleted file mode 100644 index c055349..0000000 --- a/awesome/lib/awful/titlebar.lua +++ /dev/null @@ -1,509 +0,0 @@ ---------------------------------------------------------------------------- ---- Titlebars for awful. --- --- @author Uli Schlachter --- @copyright 2012 Uli Schlachter --- @module awful.titlebar ---------------------------------------------------------------------------- - -local error = error -local type = type -local util = require("awful.util") -local abutton = require("awful.button") -local aclient = require("awful.client") -local atooltip = require("awful.tooltip") -local beautiful = require("beautiful") -local drawable = require("wibox.drawable") -local imagebox = require("wibox.widget.imagebox") -local textbox = require("wibox.widget.textbox") -local base = require("wibox.widget.base") -local capi = { - client = client -} -local titlebar = { - widget = {} -} - ---- The titlebar foreground (text) color. --- @beautiful beautiful.titlebar_fg_normal --- @param color --- @see gears.color - ---- The titlebar background color. --- @beautiful beautiful.titlebar_bg_normal --- @param color --- @see gears.color - ---- The titlebar background image image. --- @beautiful beautiful.titlebar_bgimage_normal --- @param surface --- @see gears.surface - ---- The titlebar foreground (text) color. --- @beautiful beautiful.titlebar_fg --- @param color --- @see gears.color - ---- The titlebar background color. --- @beautiful beautiful.titlebar_bg --- @param color --- @see gears.color - ---- The titlebar background image image. --- @beautiful beautiful.titlebar_bgimage --- @param surface --- @see gears.surface - ---- The focused titlebar foreground (text) color. --- @beautiful beautiful.titlebar_fg_focus --- @param color --- @see gears.color - ---- The focused titlebar background color. --- @beautiful beautiful.titlebar_bg_focus --- @param color --- @see gears.color - ---- The focused titlebar background image image. --- @beautiful beautiful.titlebar_bgimage_focus --- @param surface --- @see gears.surface - ---- floating_button_normal. --- @beautiful beautiful.titlebar_floating_button_normal --- @param surface --- @see gears.surface - ---- maximized_button_normal. --- @beautiful beautiful.titlebar_maximized_button_normal --- @param surface --- @see gears.surface - ---- minimize_button_normal --- @beautiful beautiful.titlebar_minimize_button_normal --- @param surface --- @see gears.surface - ---- close_button_normal. --- @beautiful beautiful.titlebar_close_button_normal --- @param surface --- @see gears.surface - ---- ontop_button_normal. --- @beautiful beautiful.titlebar_ontop_button_normal --- @param surface --- @see gears.surface - ---- sticky_button_normal. --- @beautiful beautiful.titlebar_sticky_button_normal --- @param surface --- @see gears.surface - ---- floating_button_focus. --- @beautiful beautiful.titlebar_floating_button_focus --- @param surface --- @see gears.surface - ---- maximized_button_focus. --- @beautiful beautiful.titlebar_maximized_button_focus --- @param surface --- @see gears.surface - ---- minimize_button_focus. --- @beautiful beautiful.titlebar_minimize_button_focus --- @param surface --- @see gears.surface - ---- close_button_focus. --- @beautiful beautiful.titlebar_close_button_focus --- @param surface --- @see gears.surface - ---- ontop_button_focus. --- @beautiful beautiful.titlebar_ontop_button_focus --- @param surface --- @see gears.surface - ---- sticky_button_focus. --- @beautiful beautiful.titlebar_sticky_button_focus --- @param surface --- @see gears.surface - ---- floating_button_normal_active. --- @beautiful beautiful.titlebar_floating_button_normal_active --- @param surface --- @see gears.surface - ---- maximized_button_normal_active. --- @beautiful beautiful.titlebar_maximized_button_normal_active --- @param surface --- @see gears.surface - ---- ontop_button_normal_active. --- @beautiful beautiful.titlebar_ontop_button_normal_active --- @param surface --- @see gears.surface - ---- sticky_button_normal_active. --- @beautiful beautiful.titlebar_sticky_button_normal_active --- @param surface --- @see gears.surface - ---- floating_button_focus_active. --- @beautiful beautiful.titlebar_floating_button_focus_active --- @param surface --- @see gears.surface - ---- maximized_button_focus_active. --- @beautiful beautiful.titlebar_maximized_button_focus_active --- @param surface --- @see gears.surface - ---- ontop_button_focus_active. --- @beautiful beautiful.titlebar_ontop_button_focus_active --- @param surface --- @see gears.surface - ---- sticky_button_focus_active. --- @beautiful beautiful.titlebar_sticky_button_focus_active --- @param surface --- @see gears.surface - ---- floating_button_normal_inactive. --- @beautiful beautiful.titlebar_floating_button_normal_inactive --- @param surface --- @see gears.surface - ---- maximized_button_normal_inactive. --- @beautiful beautiful.titlebar_maximized_button_normal_inactive --- @param surface --- @see gears.surface - ---- ontop_button_normal_inactive. --- @beautiful beautiful.titlebar_ontop_button_normal_inactive --- @param surface --- @see gears.surface - ---- sticky_button_normal_inactive. --- @beautiful beautiful.titlebar_sticky_button_normal_inactive --- @param surface --- @see gears.surface - ---- floating_button_focus_inactive. --- @beautiful beautiful.titlebar_floating_button_focus_inactive --- @param surface --- @see gears.surface - ---- maximized_button_focus_inactive. --- @beautiful beautiful.titlebar_maximized_button_focus_inactive --- @param surface --- @see gears.surface - ---- ontop_button_focus_inactive. --- @beautiful beautiful.titlebar_ontop_button_focus_inactive --- @param surface --- @see gears.surface - ---- sticky_button_focus_inactive. --- @beautiful beautiful.titlebar_sticky_button_focus_inactive --- @param surface --- @see gears.surface - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @name setup --- @class function - ---- Show tooltips when hover on titlebar buttons (defaults to 'true') -titlebar.enable_tooltip = true - -local all_titlebars = setmetatable({}, { __mode = 'k' }) - --- Get a color for a titlebar, this tests many values from the array and the theme -local function get_color(name, c, args) - local suffix = "_normal" - if capi.client.focus == c then - suffix = "_focus" - end - local function get(array) - return array["titlebar_"..name..suffix] or array["titlebar_"..name] or array[name..suffix] or array[name] - end - return get(args) or get(beautiful) -end - -local function get_titlebar_function(c, position) - if position == "left" then - return c.titlebar_left - elseif position == "right" then - return c.titlebar_right - elseif position == "top" then - return c.titlebar_top - elseif position == "bottom" then - return c.titlebar_bottom - else - error("Invalid titlebar position '" .. position .. "'") - end -end - ---- Get a client's titlebar --- @class function --- @tparam client c The client for which a titlebar is wanted. --- @tparam[opt={}] table args A table with extra arguments for the titlebar. --- @tparam[opt=font.height*1.5] number args.size The height of the titlebar. --- @tparam[opt=top] string args.position" values are `top`, --- `left`, `right` and `bottom`. --- @tparam[opt=top] string args.bg_normal --- @tparam[opt=top] string args.bg_focus --- @tparam[opt=top] string args.bgimage_normal --- @tparam[opt=top] string args.bgimage_focus --- @tparam[opt=top] string args.fg_normal --- @tparam[opt=top] string args.fg_focus --- @tparam[opt=top] string args.font --- @name titlebar -local function new(c, args) - args = args or {} - local position = args.position or "top" - local size = args.size or util.round(beautiful.get_font_height(args.font) * 1.5) - local d = get_titlebar_function(c, position)(c, size) - - -- Make sure that there is never more than one titlebar for any given client - local bars = all_titlebars[c] - if not bars then - bars = {} - all_titlebars[c] = bars - end - - local ret - if not bars[position] then - local context = { - client = c, - position = position - } - ret = drawable(d, context, "awful.titlebar") - ret:_inform_visible(true) - local function update_colors() - local args_ = bars[position].args - ret:set_bg(get_color("bg", c, args_)) - ret:set_fg(get_color("fg", c, args_)) - ret:set_bgimage(get_color("bgimage", c, args_)) - end - - bars[position] = { - args = args, - drawable = ret, - update_colors = update_colors - } - - -- Update the colors when focus changes - c:connect_signal("focus", update_colors) - c:connect_signal("unfocus", update_colors) - - -- Inform the drawable when it becomes invisible - c:connect_signal("unmanage", function() ret:_inform_visible(false) end) - else - bars[position].args = args - ret = bars[position].drawable - end - - -- Make sure the titlebar has the right colors applied - bars[position].update_colors() - - -- Handle declarative/recursive widget container - ret.setup = base.widget.setup - - return ret -end - ---- Show a client's titlebar. --- @param c The client whose titlebar is modified --- @param[opt] position The position of the titlebar. Must be one of "left", --- "right", "top", "bottom". Default is "top". -function titlebar.show(c, position) - position = position or "top" - local bars = all_titlebars[c] - local data = bars and bars[position] - local args = data and data.args - new(c, args) -end - ---- Hide a client's titlebar. --- @param c The client whose titlebar is modified --- @param[opt] position The position of the titlebar. Must be one of "left", --- "right", "top", "bottom". Default is "top". -function titlebar.hide(c, position) - position = position or "top" - get_titlebar_function(c, position)(c, 0) -end - ---- Toggle a client's titlebar, hiding it if it is visible, otherwise showing it. --- @param c The client whose titlebar is modified --- @param[opt] position The position of the titlebar. Must be one of "left", --- "right", "top", "bottom". Default is "top". -function titlebar.toggle(c, position) - position = position or "top" - local _, size = get_titlebar_function(c, position)(c) - if size == 0 then - titlebar.show(c, position) - else - titlebar.hide(c, position) - end -end - ---- Create a new titlewidget. A title widget displays the name of a client. --- Please note that this returns a textbox and all of textbox' API is available. --- This way, you can e.g. modify the font that is used. --- @param c The client for which a titlewidget should be created. --- @return The title widget. -function titlebar.widget.titlewidget(c) - local ret = textbox() - local function update() - ret:set_text(c.name or "<unknown>") - end - c:connect_signal("property::name", update) - update() - - return ret -end - ---- Create a new icon widget. An icon widget displays the icon of a client. --- Please note that this returns an imagebox and all of the imagebox' API is --- available. This way, you can e.g. disallow resizes. --- @param c The client for which an icon widget should be created. --- @return The icon widget. -function titlebar.widget.iconwidget(c) - local ret = imagebox() - local function update() - ret:set_image(c.icon) - end - c:connect_signal("property::icon", update) - update() - - return ret -end - ---- Create a new button widget. A button widget displays an image and reacts to --- mouse clicks. Please note that the caller has to make sure that this widget --- gets redrawn when needed by calling the returned widget's update() function. --- The selector function should return a value describing a state. If the value --- is a boolean, either "active" or "inactive" are used. The actual image is --- then found in the theme as "titlebar_[name]_button_[normal/focus]_[state]". --- If that value does not exist, the focused state is ignored for the next try. --- @param c The client for which a button is created. --- @tparam string name Name of the button, used for accessing the theme and --- in the tooltip. --- @param selector A function that selects the image that should be displayed. --- @param action Function that is called when the button is clicked. --- @return The widget -function titlebar.widget.button(c, name, selector, action) - local ret = imagebox() - - if titlebar.enable_tooltip then - ret._private.tooltip = atooltip({ objects = {ret}, delay_show = 1 }) - ret._private.tooltip:set_text(name) - end - - local function update() - local img = selector(c) - if type(img) ~= "nil" then - -- Convert booleans automatically - if type(img) == "boolean" then - if img then - img = "active" - else - img = "inactive" - end - end - local prefix = "normal" - if capi.client.focus == c then - prefix = "focus" - end - if img ~= "" then - prefix = prefix .. "_" - end - -- First try with a prefix based on the client's focus state, - -- then try again without that prefix if nothing was found, - -- and finally, try a fallback for compatibility with Awesome 3.5 themes - local theme = beautiful["titlebar_" .. name .. "_button_" .. prefix .. img] - or beautiful["titlebar_" .. name .. "_button_" .. img] - or beautiful["titlebar_" .. name .. "_button_" .. prefix .. "_inactive"] - if theme then - img = theme - end - end - ret:set_image(img) - end - if action then - ret:buttons(abutton({ }, 1, nil, function() action(c, selector(c)) end)) - end - - ret.update = update - update() - - -- We do magic based on whether a client is focused above, so we need to - -- connect to the corresponding signal here. - c:connect_signal("focus", update) - c:connect_signal("unfocus", update) - - return ret -end - ---- Create a new float button for a client. --- @param c The client for which the button is wanted. -function titlebar.widget.floatingbutton(c) - local widget = titlebar.widget.button(c, "floating", aclient.object.get_floating, aclient.floating.toggle) - c:connect_signal("property::floating", widget.update) - return widget -end - ---- Create a new maximize button for a client. --- @param c The client for which the button is wanted. -function titlebar.widget.maximizedbutton(c) - local widget = titlebar.widget.button(c, "maximized", function(cl) - return cl.maximized_horizontal or cl.maximized_vertical - end, function(cl, state) - cl.maximized_horizontal = not state - cl.maximized_vertical = not state - end) - c:connect_signal("property::maximized_vertical", widget.update) - c:connect_signal("property::maximized_horizontal", widget.update) - return widget -end - ---- Create a new minimize button for a client. --- @param c The client for which the button is wanted. -function titlebar.widget.minimizebutton(c) - local widget = titlebar.widget.button(c, "minimize", function() return "" end, function(cl) cl.minimized = not cl.minimized end) - c:connect_signal("property::minimized", widget.update) - return widget -end - ---- Create a new closing button for a client. --- @param c The client for which the button is wanted. -function titlebar.widget.closebutton(c) - return titlebar.widget.button(c, "close", function() return "" end, function(cl) cl:kill() end) -end - ---- Create a new ontop button for a client. --- @param c The client for which the button is wanted. -function titlebar.widget.ontopbutton(c) - local widget = titlebar.widget.button(c, "ontop", function(cl) return cl.ontop end, function(cl, state) cl.ontop = not state end) - c:connect_signal("property::ontop", widget.update) - return widget -end - ---- Create a new sticky button for a client. --- @param c The client for which the button is wanted. -function titlebar.widget.stickybutton(c) - local widget = titlebar.widget.button(c, "sticky", function(cl) return cl.sticky end, function(cl, state) cl.sticky = not state end) - c:connect_signal("property::sticky", widget.update) - return widget -end - -client.connect_signal("unmanage", function(c) - all_titlebars[c] = nil -end) - -return setmetatable(titlebar, { __call = function(_, ...) return new(...) end}) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/tooltip.lua b/awesome/lib/awful/tooltip.lua deleted file mode 100644 index cd151c4..0000000 --- a/awesome/lib/awful/tooltip.lua +++ /dev/null @@ -1,616 +0,0 @@ -------------------------------------------------------------------------- ---- Tooltip module for awesome objects. --- --- A tooltip is a small hint displayed when the mouse cursor --- hovers a specific item. --- In awesome, a tooltip can be linked with almost any --- object having a `:connect_signal()` method and receiving --- `mouse::enter` and `mouse::leave` signals. --- --- 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, --- }) --- --- How to add the same tooltip to multiple objects? --- --- --- --- myclock_t:add_to_object(obj1) --- myclock_t:add_to_object(obj2) --- --- Now the same tooltip is attached to `myclock`, `obj1`, `obj2`. --- --- How to remove a tooltip from several objects? --- --- --- --- myclock_t:remove_from_object(obj1) --- myclock_t:remove_from_object(obj2) --- --- Now the same tooltip is only attached to `myclock`. --- --- @author Sébastien Gross <seb•ɱɩɲʋʃ•awesome•ɑƬ•chezwam•ɖɵʈ•org> --- @copyright 2009 Sébastien Gross --- @classmod awful.tooltip -------------------------------------------------------------------------- - -local mouse = mouse -local timer = require("gears.timer") -local util = require("awful.util") -local object = require("gears.object") -local color = require("gears.color") -local wibox = require("wibox") -local a_placement = require("awful.placement") -local abutton = require("awful.button") -local shape = require("gears.shape") -local beautiful = require("beautiful") -local textbox = require("wibox.widget.textbox") -local dpi = require("beautiful").xresources.apply_dpi -local cairo = require("lgi").cairo -local setmetatable = setmetatable -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local ipairs = ipairs -local capi = {mouse=mouse, awesome=awesome} - -local tooltip = { mt = {} } - --- The mouse point is 1x1, so anything aligned based on it as parent --- geometry will go out of bound. To get the desired placement, it is --- necessary to swap left with right and top with bottom -local align_convert = { - top_left = "bottom_right", - left = "right", - bottom_left = "top_right", - right = "left", - top_right = "bottom_left", - bottom_right = "top_left", - top = "bottom", - bottom = "top", -} - --- If the wibox is under the cursor, it will trigger a mouse::leave -local offset = { - top_left = {x = 0, y = 0 }, - left = {x = 0, y = 0 }, - bottom_left = {x = 0, y = 0 }, - right = {x = 1, y = 0 }, - top_right = {x = 0, y = 0 }, - bottom_right = {x = 1, y = 1 }, - top = {x = 0, y = 0 }, - bottom = {x = 0, y = 1 }, -} - ---- The tooltip border color. --- @beautiful beautiful.tooltip_border_color - ---- The tooltip background color. --- @beautiful beautiful.tooltip_bg - ---- The tooltip foregound (text) color. --- @beautiful beautiful.tooltip_fg - ---- The tooltip font. --- @beautiful beautiful.tooltip_font - ---- The tooltip border width. --- @beautiful beautiful.tooltip_border_width - ---- The tooltip opacity. --- @beautiful beautiful.tooltip_opacity - ---- The default tooltip shape. --- By default, all tooltips are rectangles, however, by setting this variables, --- they can default to rounded rectangle or stretched octogons. --- @beautiful beautiful.tooltip_shape --- @tparam[opt=gears.shape.rectangle] function shape A `gears.shape` compatible function --- @see shape --- @see gears.shape - -local function apply_shape(self) - local s = self._private.shape - - local wb = self.wibox - - if not s then - -- Clear the shape - if wb.shape_bounding then - wb.shape_bounding = nil - wb:set_bgimage(nil) - end - - return - end - - local w, h = wb.width, wb.height - - -- First, create a A1 mask for the shape bounding itself - local img = cairo.ImageSurface(cairo.Format.A1, w, h) - local cr = cairo.Context(img) - - cr:set_source_rgba(1,1,1,1) - - s(cr, w, h, unpack(self._private.shape_args or {})) - cr:fill() - wb.shape_bounding = img._native - - -- The wibox background uses ARGB32 border so tooltip anti-aliasing works - -- when an external compositor is used. This will look better than - -- the capi.drawin's own border support. - img = cairo.ImageSurface(cairo.Format.ARGB32, w, h) - cr = cairo.Context(img) - - -- Draw the border (multiply by 2, then mask the inner part to save a path) - local bw = (self._private.border_width - or beautiful.tooltip_border_width - or beautiful.border_width or 0) * 2 - - -- Fix anti-aliasing - if bw > 2 and awesome.composite_manager_running then - bw = bw - 1 - end - - local bc = self._private.border_color - or beautiful.tooltip_border_color - or beautiful.border_normal - or "#ffcb60" - - cr:translate(bw, bw) - s(cr, w-2*bw, h-2*bw, unpack(self._private.shape_args or {})) - cr:set_line_width(bw) - cr:set_source(color(bc)) - cr:stroke_preserve() - cr:clip() - - local bg = self._private.bg - or beautiful.tooltip_bg - or beautiful.bg_focus or "#ffcb60" - - cr:set_source(color(bg)) - cr:paint() - - wb:set_bgimage(img) -end - -local function apply_mouse_mode(self) - local w = self:get_wibox() - local align = self._private.align - local real_placement = align_convert[align] - - a_placement[real_placement](w, { - parent = capi.mouse, - offset = offset[align] - }) -end - -local function apply_outside_mode(self) - local w = self:get_wibox() - - local _, position = a_placement.next_to(w, { - geometry = self._private.widget_geometry, - preferred_positions = self.preferred_positions, - honor_workarea = true, - }) - - if position ~= self.current_position then - -- Re-apply the shape. - apply_shape(self) - end - - self.current_position = position -end - --- Place the tooltip under the mouse. --- --- @tparam tooltip self A tooltip object. -local function set_geometry(self) - -- calculate width / height - local n_w, n_h = self.textbox:get_preferred_size(mouse.screen) - n_w = n_w + self.marginbox.left + self.marginbox.right - n_h = n_h + self.marginbox.top + self.marginbox.bottom - - local w = self:get_wibox() - w:geometry({ width = n_w, height = n_h }) - - if self._private.shape then - apply_shape(self) - end - - local mode = self.mode - - if mode == "outside" and self._private.widget_geometry then - apply_outside_mode(self) - else - apply_mouse_mode(self) - end - - a_placement.no_offscreen(w) -end - --- Show a tooltip. --- --- @tparam tooltip self The tooltip to show. -local function show(self) - -- do nothing if the tooltip is already shown - if self._private.visible then return end - if self.timer then - if not self.timer.started then - self:timer_function() - self.timer:start() - end - end - set_geometry(self) - self.wibox.visible = true - self._private.visible = true - self:emit_signal("property::visible") -end - --- Hide a tooltip. --- --- @tparam tooltip self The tooltip to hide. -local function hide(self) - -- do nothing if the tooltip is already hidden - if not self._private.visible then return end - if self.timer then - if self.timer.started then - self.timer:stop() - end - end - self.wibox.visible = false - self._private.visible = false - self:emit_signal("property::visible") -end - ---- The wibox. --- @property wibox --- @param `wibox` - -function tooltip:get_wibox() - if self._private.wibox then - return self._private.wibox - end - - local wb = wibox(self.wibox_properties) - wb:set_widget(self.marginbox) - - -- Close the tooltip when clicking it. This gets done on release, to not - -- emit the release event on an underlying object, e.g. the titlebar icon. - wb:buttons(abutton({}, 1, nil, self.hide)) - - self._private.wibox = wb - - return wb -end - ---- Is the tooltip visible? --- @property visible --- @param boolean - -function tooltip:get_visible() - return self._private.visible -end - -function tooltip:set_visible(value) - if self._private.visible == value then return end - - if value then - show(self) - else - hide(self) - end -end - ---- The horizontal alignment. --- --- The following values are valid: --- --- * top_left --- * left --- * bottom_left --- * right --- * top_right --- * bottom_right --- * bottom --- * top --- --- @property align --- @see beautiful.tooltip_align - ---- The default tooltip alignment. --- @beautiful beautiful.tooltip_align --- @param string --- @see align - -function tooltip:get_align() - return self._private.align -end - -function tooltip:set_align(value) - if not align_convert[value] then - return - end - - self._private.align = value - - set_geometry(self) - self:emit_signal("property::align") -end - ---- The shape of the tooltip window. --- If the shape require some parameters, use `set_shape`. --- @property shape --- @see gears.shape --- @see set_shape --- @see beautiful.tooltip_shape - ---- Set the tooltip shape. --- All other arguments will be passed to the shape function. --- @tparam gears.shape s The shape --- @see shape --- @see gears.shape -function tooltip:set_shape(s, ...) - self._private.shape = s - self._private.shape_args = {...} - apply_shape(self) -end - ---- Set the tooltip positioning mode. --- This affects how the tooltip is placed. By default, the tooltip is `align`ed --- close to the mouse cursor. It is also possible to place the tooltip relative --- to the widget geometry. --- --- Valid modes are: --- --- * "mouse": Next to the mouse cursor --- * "outside": Outside of the widget --- --- @property mode --- @param string - -function tooltip:set_mode(mode) - self._private.mode = mode - - set_geometry(self) - self:emit_signal("property::mode") -end - -function tooltip:get_mode() - return self._private.mode or "mouse" -end - ---- The preferred positions when in `outside` mode. --- --- If the tooltip fits on multiple sides of the drawable, then this defines the --- priority --- --- The default is: --- --- {"top", "right", "left", "bottom"} --- --- @property preferred_positions --- @tparam table preferred_positions The position, ordered by priorities - -function tooltip:get_preferred_positions() - return self._private.preferred_positions or - {"top", "right", "left", "bottom"} -end - -function tooltip:set_preferred_positions(value) - self._private.preferred_positions = value - - set_geometry(self) -end - ---- Change displayed text. --- --- @property text --- @tparam tooltip self The tooltip object. --- @tparam string text New tooltip text, passed to --- `wibox.widget.textbox.set_text`. - -function tooltip:set_text(text) - self.textbox:set_text(text) - if self._private.visible then - set_geometry(self) - end -end - ---- Change displayed markup. --- --- @property markup --- @tparam tooltip self The tooltip object. --- @tparam string text New tooltip markup, passed to --- `wibox.widget.textbox.set_markup`. - -function tooltip:set_markup(text) - self.textbox:set_markup(text) - if self._private.visible then - set_geometry(self) - end -end - ---- Change the tooltip's update interval. --- --- @property timeout --- @tparam tooltip self A tooltip object. --- @tparam number timeout The timeout value. - -function tooltip:set_timeout(timeout) - if self.timer then - self.timer.timeout = timeout - end -end - ---- Add tooltip to an object. --- --- @tparam tooltip self The tooltip. --- @tparam gears.object obj An object with `mouse::enter` and --- `mouse::leave` signals. --- @function add_to_object -function tooltip:add_to_object(obj) - if not obj then return end - - obj:connect_signal("mouse::enter", self.show) - obj:connect_signal("mouse::leave", self.hide) -end - ---- Remove tooltip from an object. --- --- @tparam tooltip self The tooltip. --- @tparam gears.object obj An object with `mouse::enter` and --- `mouse::leave` signals. --- @function remove_from_object -function tooltip:remove_from_object(obj) - obj:disconnect_signal("mouse::enter", self.show) - obj:disconnect_signal("mouse::leave", self.hide) -end - --- Tooltip can be applied to both widgets, wibox and client, their geometry --- works differently. -local function get_parent_geometry(arg1, arg2) - if type(arg2) == "table" and arg2.width then - return arg2 - elseif type(arg1) == "table" and arg1.width then - return arg1 - end -end - ---- Create a new tooltip and link it to a widget. --- Tooltips emit `property::visible` when their visibility changes. --- @tparam table args Arguments for tooltip creation. --- @tparam function args.timer_function A function to dynamically set the --- tooltip text. Its return value will be passed to --- `wibox.widget.textbox.set_markup`. --- @tparam[opt=1] number args.timeout The timeout value for --- `timer_function`. --- @tparam[opt] table args.objects A list of objects linked to the tooltip. --- @tparam[opt] number args.delay_show Delay showing the tooltip by this many --- seconds. --- @tparam[opt=apply_dpi(5)] integer args.margin_leftright The left/right margin for the text. --- @tparam[opt=apply_dpi(3)] integer args.margin_topbottom The top/bottom margin for the text. --- @tparam[opt=nil] gears.shape args.shape The shape --- @treturn awful.tooltip The created tooltip. --- @see add_to_object --- @see timeout --- @see text --- @see markup --- @function awful.tooltip -function tooltip.new(args) - local self = object { - enable_properties = true, - } - - rawset(self,"_private", {}) - - self._private.visible = false - self._private.align = args.align or beautiful.tooltip_align or "right" - self._private.shape = args.shape or beautiful.tooltip_shape - or shape.rectangle - - -- private data - if args.delay_show then - local delay_timeout - - delay_timeout = timer { timeout = args.delay_show } - delay_timeout:connect_signal("timeout", function () - show(self) - delay_timeout:stop() - end) - - function self.show(other, geo) - -- Auto detect clients and wiboxes - if other.drawable or other.pid then - geo = other:geometry() - end - - -- Cache the geometry in case it is needed later - self._private.widget_geometry = get_parent_geometry(other, geo) - - if not delay_timeout.started then - delay_timeout:start() - end - end - function self.hide() - if delay_timeout.started then - delay_timeout:stop() - end - hide(self) - end - else - function self.show(other, geo) - -- Auto detect clients and wiboxes - if other.drawable or other.pid then - geo = other:geometry() - end - - -- Cache the geometry in case it is needed later - self._private.widget_geometry = get_parent_geometry(other, geo) - - show(self) - end - function self.hide() - hide(self) - end - end - - -- export functions - util.table.crush(self, tooltip, true) - - -- setup the timer action only if needed - if args.timer_function then - self.timer = timer { timeout = args.timeout and args.timeout or 1 } - self.timer_function = function() - self:set_markup(args.timer_function()) - end - self.timer:connect_signal("timeout", self.timer_function) - end - - local fg = beautiful.tooltip_fg or beautiful.fg_focus or "#000000" - local font = beautiful.tooltip_font or beautiful.font - - -- Set default properties - self.wibox_properties = { - visible = false, - ontop = true, - border_width = 0, - fg = fg, - bg = color.transparent, - opacity = beautiful.tooltip_opacity or 1, - } - - self.textbox = textbox() - self.textbox:set_font(font) - - -- Add margin. - local m_lr = args.margin_leftright or dpi(5) - local m_tb = args.margin_topbottom or dpi(3) - self.marginbox = wibox.container.margin(self.textbox, m_lr, m_lr, m_tb, m_tb) - - -- Add tooltip to objects - if args.objects then - for _, obj in ipairs(args.objects) do - self:add_to_object(obj) - end - end - - -- Apply the properties - for k, v in pairs(args) do - if tooltip["set_"..k] then - self[k] = v - end - end - - return self -end - -function tooltip.mt:__call(...) - return tooltip.new(...) -end - -return setmetatable(tooltip, tooltip.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/util.lua b/awesome/lib/awful/util.lua deleted file mode 100644 index 8dcb955..0000000 --- a/awesome/lib/awful/util.lua +++ /dev/null @@ -1,588 +0,0 @@ ---------------------------------------------------------------------------- ---- Utility module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module awful.util ---------------------------------------------------------------------------- - --- Grab environment we need -local os = os -local assert = assert -local load = loadstring or load -- luacheck: globals loadstring (compatibility with Lua 5.1) -local loadfile = loadfile -local debug = debug -local pairs = pairs -local ipairs = ipairs -local type = type -local rtable = table -local string = string -local lgi = require("lgi") -local grect = require("gears.geometry").rectangle -local Gio = require("lgi").Gio -local Pango = lgi.Pango -local capi = -{ - awesome = awesome, - mouse = mouse -} -local gears_debug = require("gears.debug") -local floor = math.floor - -local util = {} -util.table = {} - ---- The default shell used when spawing processes. -util.shell = os.getenv("SHELL") or "/bin/sh" - -local displayed_deprecations = {} ---- Display a deprecation notice, but only once per traceback. --- @param[opt] see The message to a new method / function to use. --- @tparam table args Extra arguments --- @tparam boolean args.raw Print the message as-is without the automatic context -function util.deprecate(see, args) - args = args or {} - local tb = debug.traceback() - if displayed_deprecations[tb] then - return - end - displayed_deprecations[tb] = true - - -- Get function name/desc from caller. - local info = debug.getinfo(2, "n") - local funcname = info.name or "?" - local msg = "awful: function " .. funcname .. " is deprecated" - if see then - if args.raw then - msg = see - elseif string.sub(see, 1, 3) == 'Use' then - msg = msg .. ". " .. see - else - msg = msg .. ", see " .. see - end - end - gears_debug.print_warning(msg .. ".\n" .. tb) -end - ---- Create a class proxy with deprecation messages. --- This is useful when a class has moved somewhere else. --- @tparam table fallback The new class --- @tparam string old_name The old class name --- @tparam string new_name The new class name --- @treturn table A proxy class. -function util.deprecate_class(fallback, old_name, new_name) - local message = old_name.." has been renamed to "..new_name - - local function call(_,...) - util.deprecate(message) - - return fallback(...) - end - - local function index(_, k) - util.deprecate(message) - - return fallback[k] - end - - local function newindex(_, k, v) - util.deprecate(message, {raw = true}) - - fallback[k] = v - end - - return setmetatable({}, {__call = call, __index = index, __newindex = newindex}) -end - ---- Get a valid color for Pango markup --- @param color The color. --- @tparam string fallback The color to return if the first is invalid. (default: black) --- @treturn string color if it is valid, else fallback. -function util.ensure_pango_color(color, fallback) - color = tostring(color) - return Pango.Color.parse(Pango.Color(), color) and color or fallback or "black" -end - ---- Make i cycle. --- @param t A length. Must be greater than zero. --- @param i An absolute index to fit into #t. --- @return An integer in (1, t) or nil if t is less than or equal to zero. -function util.cycle(t, i) - if t < 1 then return end - i = i % t - if i == 0 then - i = t - end - return i -end - ---- Create a directory --- @param dir The directory. --- @return mkdir return code -function util.mkdir(dir) - return os.execute("mkdir -p " .. dir) -end - ---- Eval Lua code. --- @return The return value of Lua code. -function util.eval(s) - return assert(load(s))() -end - -local xml_entity_names = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; ---- Escape a string from XML char. --- Useful to set raw text in textbox. --- @param text Text to escape. --- @return Escape text. -function util.escape(text) - return text and text:gsub("['&<>\"]", xml_entity_names) or nil -end - -local xml_entity_chars = { lt = "<", gt = ">", nbsp = " ", quot = "\"", apos = "'", ndash = "-", mdash = "-", amp = "&" }; ---- Unescape a string from entities. --- @param text Text to unescape. --- @return Unescaped text. -function util.unescape(text) - return text and text:gsub("&(%a+);", xml_entity_chars) or nil -end - ---- Check if a file is a Lua valid file. --- This is done by loading the content and compiling it with loadfile(). --- @param path The file path. --- @return A function if everything is alright, a string with the error --- otherwise. -function util.checkfile(path) - local f, e = loadfile(path) - -- Return function if function, otherwise return error. - if f then return f end - return e -end - ---- Try to restart awesome. --- It checks if the configuration file is valid, and then restart if it's ok. --- If it's not ok, the error will be returned. --- @return Never return if awesome restart, or return a string error. -function util.restart() - local c = util.checkfile(capi.awesome.conffile) - - if type(c) ~= "function" then - return c - end - - capi.awesome.restart() -end - ---- Get the config home according to the XDG basedir specification. --- @return the config home (XDG_CONFIG_HOME) with a slash at the end. -function util.get_xdg_config_home() - return (os.getenv("XDG_CONFIG_HOME") or os.getenv("HOME") .. "/.config") .. "/" -end - ---- Get the cache home according to the XDG basedir specification. --- @return the cache home (XDG_CACHE_HOME) with a slash at the end. -function util.get_xdg_cache_home() - return (os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache") .. "/" -end - ---- Get the path to the user's config dir. --- This is the directory containing the configuration file ("rc.lua"). --- @return A string with the requested path with a slash at the end. -function util.get_configuration_dir() - return capi.awesome.conffile:match(".*/") or "./" -end - ---- Get the path to a directory that should be used for caching data. --- @return A string with the requested path with a slash at the end. -function util.get_cache_dir() - return util.get_xdg_cache_home() .. "awesome/" -end - ---- Get the path to the directory where themes are installed. --- @return A string with the requested path with a slash at the end. -function util.get_themes_dir() - return "/usr/share/awesome/themes" .. "/" -end - ---- Get the path to the directory where our icons are installed. --- @return A string with the requested path with a slash at the end. -function util.get_awesome_icon_dir() - return "/usr/share/awesome/icons" .. "/" -end - ---- Get the user's config or cache dir. --- It first checks XDG_CONFIG_HOME / XDG_CACHE_HOME, but then goes with the --- default paths. --- @param d The directory to get (either "config" or "cache"). --- @return A string containing the requested path. -function util.getdir(d) - if d == "config" then - -- No idea why this is what is returned, I recommend everyone to use - -- get_configuration_dir() instead - return util.get_xdg_config_home() .. "awesome/" - elseif d == "cache" then - return util.get_cache_dir() - end -end - ---- Search for an icon and return the full path. --- It searches for the icon path under the given directories with respect to the --- given extensions for the icon filename. --- @param iconname The name of the icon to search for. --- @param exts Table of image extensions allowed, otherwise { 'png', gif' } --- @param dirs Table of dirs to search, otherwise { '/usr/share/pixmaps/' } --- @tparam[opt] string size The size. If this is specified, subdirectories `x` --- of the dirs are searched first. -function util.geticonpath(iconname, exts, dirs, size) - exts = exts or { 'png', 'gif' } - dirs = dirs or { '/usr/share/pixmaps/', '/usr/share/icons/hicolor/' } - local icontypes = { 'apps', 'actions', 'categories', 'emblems', - 'mimetypes', 'status', 'devices', 'extras', 'places', 'stock' } - for _, d in pairs(dirs) do - local icon - for _, e in pairs(exts) do - icon = d .. iconname .. '.' .. e - if util.file_readable(icon) then - return icon - end - if size then - for _, t in pairs(icontypes) do - icon = string.format("%s%ux%u/%s/%s.%s", d, size, size, t, iconname, e) - if util.file_readable(icon) then - return icon - end - end - end - end - end -end - ---- Check if a file exists, is not readable and not a directory. --- @param filename The file path. --- @return True if file exists and is readable. -function util.file_readable(filename) - local gfile = Gio.File.new_for_path(filename) - local gfileinfo = gfile:query_info("standard::type,access::can-read", - Gio.FileQueryInfoFlags.NONE) - return gfileinfo and gfileinfo:get_file_type() ~= "DIRECTORY" and - gfileinfo:get_attribute_boolean("access::can-read") -end - ---- Check if a path exists, is readable and is a directory. --- @tparam string path The directory path. --- @treturn boolean True if dir exists and is readable. -function util.dir_readable(path) - local gfile = Gio.File.new_for_path(path) - local gfileinfo = gfile:query_info("standard::type,access::can-read", - Gio.FileQueryInfoFlags.NONE) - return gfileinfo and gfileinfo:get_file_type() == "DIRECTORY" and - gfileinfo:get_attribute_boolean("access::can-read") -end - ---- Check if a path is a directory. --- @tparam string path --- @treturn bool True if path exists and is a directory. -function util.is_dir(path) - return Gio.File.new_for_path(path):query_file_type({}) == "DIRECTORY" -end - -local function subset_mask_apply(mask, set) - local ret = {} - for i = 1, #set do - if mask[i] then - rtable.insert(ret, set[i]) - end - end - return ret -end - -local function subset_next(mask) - local i = 1 - while i <= #mask and mask[i] do - mask[i] = false - i = i + 1 - end - - if i <= #mask then - mask[i] = 1 - return true - end - return false -end - ---- Return all subsets of a specific set. --- This function, giving a set, will return all subset it. --- For example, if we consider a set with value { 10, 15, 34 }, --- it will return a table containing 2^n set: --- { }, { 10 }, { 15 }, { 34 }, { 10, 15 }, { 10, 34 }, etc. --- @param set A set. --- @return A table with all subset. -function util.subsets(set) - local mask = {} - local ret = {} - for i = 1, #set do mask[i] = false end - - -- Insert the empty one - rtable.insert(ret, {}) - - while subset_next(mask) do - rtable.insert(ret, subset_mask_apply(mask, set)) - end - return ret -end - ---- Get the nearest rectangle in the given direction. Every rectangle is specified as a table --- with 'x', 'y', 'width', 'height' keys, the same as client or screen geometries. --- @deprecated awful.util.get_rectangle_in_direction --- @param dir The direction, can be either "up", "down", "left" or "right". --- @param recttbl A table of rectangle specifications. --- @param cur The current rectangle. --- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found. --- @see gears.geometry -function util.get_rectangle_in_direction(dir, recttbl, cur) - util.deprecate("gears.geometry.rectangle.get_in_direction") - - return grect.get_in_direction(dir, recttbl, cur) -end - ---- Join all tables given as parameters. --- This will iterate all tables and insert all their keys into a new table. --- @param args A list of tables to join --- @return A new table containing all keys from the arguments. -function util.table.join(...) - local ret = {} - for _, t in pairs({...}) do - if t then - for k, v in pairs(t) do - if type(k) == "number" then - rtable.insert(ret, v) - else - ret[k] = v - end - end - end - end - return ret -end - ---- Override elements in the first table by the one in the second. --- --- Note that this method doesn't copy entries found in `__index`. --- @tparam table t the table to be overriden --- @tparam table set the table used to override members of `t` --- @tparam[opt=false] boolean raw Use rawset (avoid the metatable) --- @treturn table t (for convenience) -function util.table.crush(t, set, raw) - if raw then - for k, v in pairs(set) do - rawset(t, k, v) - end - else - for k, v in pairs(set) do - t[k] = v - end - end - - return t -end - ---- Pack all elements with an integer key into a new table --- While both lua and luajit implement __len over sparse --- table, the standard define it as an implementation --- detail. --- --- This function remove any non numeric keys from the value set --- --- @tparam table t A potentially sparse table --- @treturn table A packed table with all numeric keys -function util.table.from_sparse(t) - local keys= {} - for k in pairs(t) do - if type(k) == "number" then - keys[#keys+1] = k - end - end - - table.sort(keys) - - local ret = {} - for _,v in ipairs(keys) do - ret[#ret+1] = t[v] - end - - return ret -end - ---- Check if a table has an item and return its key. --- @param t The table. --- @param item The item to look for in values of the table. --- @return The key were the item is found, or nil if not found. -function util.table.hasitem(t, item) - for k, v in pairs(t) do - if v == item then - return k - end - end -end - ---- Split a string into multiple lines --- @param text String to wrap. --- @param width Maximum length of each line. Default: 72. --- @param indent Number of spaces added before each wrapped line. Default: 0. --- @return The string with lines wrapped to width. -function util.linewrap(text, width, indent) - text = text or "" - width = width or 72 - indent = indent or 0 - - local pos = 1 - return text:gsub("(%s+)()(%S+)()", - function(_, st, word, fi) - if fi - pos > width then - pos = st - return "\n" .. string.rep(" ", indent) .. word - end - end) -end - ---- Count number of lines in a string --- @tparam string text Input string. --- @treturn int Number of lines. -function util.linecount(text) - return select(2, text:gsub('\n', '\n')) + 1 -end - ---- Get a sorted table with all integer keys from a table --- @param t the table for which the keys to get --- @return A table with keys -function util.table.keys(t) - local keys = { } - for k, _ in pairs(t) do - rtable.insert(keys, k) - end - rtable.sort(keys, function (a, b) - return type(a) == type(b) and a < b or false - end) - return keys -end - ---- Filter a tables keys for certain content types --- @param t The table to retrieve the keys for --- @param ... the types to look for --- @return A filtered table with keys -function util.table.keys_filter(t, ...) - local keys = util.table.keys(t) - local keys_filtered = { } - for _, k in pairs(keys) do - for _, et in pairs({...}) do - if type(t[k]) == et then - rtable.insert(keys_filtered, k) - break - end - end - end - return keys_filtered -end - ---- Reverse a table --- @param t the table to reverse --- @return the reversed table -function util.table.reverse(t) - local tr = { } - -- reverse all elements with integer keys - for _, v in ipairs(t) do - rtable.insert(tr, 1, v) - end - -- add the remaining elements - for k, v in pairs(t) do - if type(k) ~= "number" then - tr[k] = v - end - end - return tr -end - ---- Clone a table --- @param t the table to clone --- @param deep Create a deep clone? (default: true) --- @return a clone of t -function util.table.clone(t, deep) - deep = deep == nil and true or deep - local c = { } - for k, v in pairs(t) do - if deep and type(v) == "table" then - c[k] = util.table.clone(v) - else - c[k] = v - end - end - return c -end - ---- --- Returns an iterator to cycle through, starting from the first element or the --- given index, all elements of a table that match a given criteria. --- --- @param t the table to iterate --- @param filter a function that returns true to indicate a positive match --- @param start what index to start iterating from. Default is 1 (=> start of --- the table) -function util.table.iterate(t, filter, start) - local count = 0 - local index = start or 1 - local length = #t - - return function () - while count < length do - local item = t[index] - index = util.cycle(#t, index + 1) - count = count + 1 - if filter(item) then return item end - end - end -end - - ---- Merge items from the one table to another one --- @tparam table t the container table --- @tparam table set the mixin table --- @treturn table Return `t` for convenience -function util.table.merge(t, set) - for _, v in ipairs(set) do - table.insert(t, v) - end - return t -end - - --- Escape all special pattern-matching characters so that lua interprets them --- literally instead of as a character class. --- Source: http://stackoverflow.com/a/20778724/15690 -function util.quote_pattern(s) - -- All special characters escaped in a string: %%, %^, %$, ... - local patternchars = '['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..']' - return string.gsub(s, patternchars, "%%%1") -end - --- Generate a pattern matching expression that ignores case. --- @param s Original pattern matching expression. -function util.query_to_pattern(q) - local s = util.quote_pattern(q) - -- Poor man's case-insensitive character matching. - s = string.gsub(s, "%a", - function (c) - return string.format("[%s%s]", string.lower(c), - string.upper(c)) - end) - return s -end - ---- Round a number to an integer. --- @tparam number x --- @treturn integer -function util.round(x) - return floor(x + 0.5) -end - -return util - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/wibar.lua b/awesome/lib/awful/wibar.lua deleted file mode 100644 index bbe7289..0000000 --- a/awesome/lib/awful/wibar.lua +++ /dev/null @@ -1,603 +0,0 @@ ---------------------------------------------------------------------------- ---- Wibox module for awful. --- This module allows you to easily create wibox and attach them to the edge of --- a screen. --- --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2016 Emmanuel Lepage Vallee --- @classmod awful.wibar ---------------------------------------------------------------------------- - --- Grab environment we need -local capi = -{ - screen = screen, - client = client -} -local setmetatable = setmetatable -local tostring = tostring -local ipairs = ipairs -local error = error -local wibox = require("wibox") -local beautiful = require("beautiful") -local util = require("awful.util") -local placement = require("awful.placement") - -local function get_screen(s) - return s and capi.screen[s] -end - -local awfulwibar = { mt = {} } - ---- Array of table with wiboxes inside. --- It's an array so it is ordered. -local wiboxes = setmetatable({}, {__mode = "v"}) - --- Compute the margin on one side -local function get_margin(w, position, auto_stop) - local h_or_w = (position == "top" or position == "bottom") and "height" or "width" - local ret = 0 - - for _, v in ipairs(wiboxes) do - -- Ignore the wibars placed after this one - if auto_stop and v == w then break end - - if v.position == position and v.screen == w.screen and v.visible then - ret = ret + v[h_or_w] - end - end - - return ret -end - --- `honor_workarea` cannot be used as it does modify the workarea itself. --- a manual padding has to be generated. -local function get_margins(w) - local position = w.position - assert(position) - - local margins = {left=0, right=0, top=0, bottom=0} - - margins[position] = get_margin(w, position, true) - - -- Avoid overlapping wibars - if position == "left" or position == "right" then - margins.top = get_margin(w, "top" ) - margins.bottom = get_margin(w, "bottom") - end - - return margins -end - --- Create the placement function -local function gen_placement(position, stretch) - local maximize = (position == "right" or position == "left") and - "maximize_vertically" or "maximize_horizontally" - - return placement[position] + (stretch and placement[maximize] or nil) -end - --- Attach the placement function. -local function attach(wb, align) - gen_placement(align, wb._stretch)(wb, { - attach = true, - update_workarea = true, - margins = get_margins(wb) - }) -end - --- Re-attach all wibars on a given wibar screen -local function reattach(wb) - local s = wb.screen - for _, w in ipairs(wiboxes) do - if w ~= wb and w.screen == s then - if w.detach_callback then - w.detach_callback() - w.detach_callback = nil - end - attach(w, w.position) - end - end -end - ---- The wibox position. --- @property position --- @param string Either "left", right", "top" or "bottom" - -local function get_position(wb) - return wb._position or "top" -end - -local function set_position(wb, position) - -- Detach first to avoid any uneeded callbacks - if wb.detach_callback then - wb.detach_callback() - - -- Avoid disconnecting twice, this produces a lot of warnings - wb.detach_callback = nil - end - - -- Move the wibar to the end of the list to avoid messing up the others in - -- case there is stacked wibars on one side. - if wb._position then - for k, w in ipairs(wiboxes) do - if w == wb then - table.remove(wiboxes, k) - end - end - table.insert(wiboxes, wb) - end - - -- In case the position changed, it may be necessary to reset the size - if (wb._position == "left" or wb._position == "right") - and (position == "top" or position == "bottom") then - wb.height = math.ceil(beautiful.get_font_height(wb.font) * 1.5) - elseif (wb._position == "top" or wb._position == "bottom") - and (position == "left" or position == "right") then - wb.width = math.ceil(beautiful.get_font_height(wb.font) * 1.5) - end - - -- Changing the position will also cause the other margins to be invalidated. - -- For example, adding a wibar to the top will change the margins of any left - -- or right wibars. To solve, this, they need to be re-attached. - reattach(wb) - - -- Set the new position - wb._position = position - - -- Attach to the new position - attach(wb, position) -end - ---- Stretch the wibar. --- --- @property stretch --- @param[opt=true] boolean - -local function get_stretch(w) - return w._stretch -end - -local function set_stretch(w, value) - w._stretch = value - - attach(w, w.position) -end - ---- Remove a wibar. --- @function remove -local function remove(self) - self.visible = false - - if self.detach_callback then - self.detach_callback() - self.detach_callback = nil - end - - for k, w in ipairs(wiboxes) do - if w == self then - table.remove(wiboxes, k) - end - end - - self._screen = nil -end - ---- Get a wibox position if it has been set, or return top. --- @param wb The wibox --- @deprecated awful.wibar.get_position --- @return The wibox position. -function awfulwibar.get_position(wb) - util.deprecate("Use wb:get_position() instead of awful.wibar.get_position") - return get_position(wb) -end - ---- Put a wibox on a screen at this position. --- @param wb The wibox to attach. --- @param position The position: top, bottom left or right. --- @param screen This argument is deprecated, use wb.screen directly. --- @deprecated awful.wibar.set_position -function awfulwibar.set_position(wb, position, screen) --luacheck: no unused args - util.deprecate("Use wb:set_position(position) instead of awful.wibar.set_position") - - set_position(wb, position) -end - ---- Attach a wibox to a screen. --- --- This function has been moved to the `awful.placement` module. Calling this --- no longer does anything. --- --- @param wb The wibox to attach. --- @param position The position of the wibox: top, bottom, left or right. --- @param screen The screen to attach to --- @see awful.placement --- @deprecated awful.wibar.attach -function awfulwibar.attach(wb, position, screen) --luacheck: no unused args - util.deprecate("awful.wibar.attach is deprecated, use the 'attach' property".. - " of awful.placement. This method doesn't do anything anymore" - ) -end - ---- Align a wibox. --- --- Supported alignment are: --- --- * top_left --- * top_right --- * bottom_left --- * bottom_right --- * left --- * right --- * top --- * bottom --- * centered --- * center_vertical --- * center_horizontal --- --- @param wb The wibox. --- @param align The alignment --- @param screen This argument is deprecated. It is not used. Use wb.screen --- directly. --- @deprecated awful.wibar.align --- @see awful.placement.align -function awfulwibar.align(wb, align, screen) --luacheck: no unused args - if align == "center" then - util.deprecate("awful.wibar.align(wb, 'center' is deprecated, use 'centered'") - align = "centered" - end - - if screen then - util.deprecate("awful.wibar.align 'screen' argument is deprecated") - end - - if placement[align] then - return placement[align](wb) - end -end - ---- Stretch a wibox so it takes all screen width or height. --- --- **This function has been removed.** --- --- @deprecated awful.wibox.stretch --- @see awful.placement --- @see awful.wibar.stretch - ---- Create a new wibox and attach it to a screen edge. --- You can add also position key with value top, bottom, left or right. --- You can also use width or height in % and set align to center, right or left. --- You can also set the screen key with a screen number to attach the wibox. --- If not specified, the primary screen is assumed. --- @see wibox --- @tparam[opt=nil] table arg --- @tparam string arg.position The position. --- @tparam string arg.stretch If the wibar need to be stretched to fill the screen. --- @tparam integer arg.border_width Border width. --- @tparam string arg.border_color Border color. --- @tparam boolean arg.ontop On top of other windows. --- @tparam string arg.cursor The mouse cursor. --- @tparam boolean arg.visible Visibility. --- @tparam number arg.opacity The opacity of the wibox, between 0 and 1. --- @tparam string arg.type The window type (desktop, normal, dock, …). --- @tparam integer arg.x The x coordinates. --- @tparam integer arg.y The y coordinates. --- @tparam integer arg.width The width of the wibox. --- @tparam integer arg.height The height of the wibox. --- @tparam screen arg.screen The wibox screen. --- @tparam wibox.widget arg.widget The widget that the wibox displays. --- @param arg.shape_bounding The wibox’s bounding shape as a (native) cairo surface. --- @param arg.shape_clip The wibox’s clip shape as a (native) cairo surface. --- @tparam color arg.bg The background of the wibox. --- @tparam surface arg.bgimage The background image of the drawable. --- @tparam color arg.fg The foreground (text) of the wibox. --- @return The new wibar --- @function awful.wibar -function awfulwibar.new(arg) - arg = arg or {} - local position = arg.position or "top" - local has_to_stretch = true - local screen = get_screen(arg.screen or 1) - - arg.type = arg.type or "dock" - - if position ~= "top" and position ~="bottom" - and position ~= "left" and position ~= "right" then - error("Invalid position in awful.wibar(), you may only use" - .. " 'top', 'bottom', 'left' and 'right'") - end - - -- Set default size - if position == "left" or position == "right" then - arg.width = arg.width or math.ceil(beautiful.get_font_height(arg.font) * 1.5) - if arg.height then - has_to_stretch = false - if arg.screen then - local hp = tostring(arg.height):match("(%d+)%%") - if hp then - arg.height = math.ceil(screen.geometry.height * hp / 100) - end - end - end - else - arg.height = arg.height or math.ceil(beautiful.get_font_height(arg.font) * 1.5) - if arg.width then - has_to_stretch = false - if arg.screen then - local wp = tostring(arg.width):match("(%d+)%%") - if wp then - arg.width = math.ceil(screen.geometry.width * wp / 100) - end - end - end - end - - arg.screen = nil - - local w = wibox(arg) - - w.screen = screen - w._screen = screen --HACK When a screen is removed, then getbycoords wont work - w._stretch = arg.stretch == nil and has_to_stretch or arg.stretch - - w.get_position = get_position - w.set_position = set_position - - w.get_stretch = get_stretch - w.set_stretch = set_stretch - w.remove = remove - - if arg.visible == nil then w.visible = true end - - w:set_position(position) - - table.insert(wiboxes, w) - - w:connect_signal("property::visible", function() reattach(w) end) - - return w -end - -capi.screen.connect_signal("removed", function(s) - for _, wibar in ipairs(wiboxes) do - if wibar._screen == s then - wibar:remove() - end - end -end) - -function awfulwibar.mt:__call(...) - return awfulwibar.new(...) -end - ---Imported documentation - ---- Border width. --- --- **Signal:** --- --- * *property::border_width* --- --- @property border_width --- @param integer - ---- Border color. --- --- Please note that this property only support string based 24 bit or 32 bit --- colors: --- --- Red Blue --- _| _| --- #FF00FF --- T‾ --- Green --- --- --- Red Blue --- _| _| --- #FF00FF00 --- T‾ ‾T --- Green Alpha --- --- **Signal:** --- --- * *property::border_color* --- --- @property border_color --- @param string - ---- On top of other windows. --- --- **Signal:** --- --- * *property::ontop* --- --- @property ontop --- @param boolean - ---- The mouse cursor. --- --- **Signal:** --- --- * *property::cursor* --- --- @property cursor --- @param string --- @see mouse - ---- Visibility. --- --- **Signal:** --- --- * *property::visible* --- --- @property visible --- @param boolean - ---- The opacity of the wibox, between 0 and 1. --- --- **Signal:** --- --- * *property::opacity* --- --- @property opacity --- @tparam number opacity (between 0 and 1) - ---- The window type (desktop, normal, dock, ...). --- --- **Signal:** --- --- * *property::type* --- --- @property type --- @param string --- @see client.type - ---- The x coordinates. --- --- **Signal:** --- --- * *property::x* --- --- @property x --- @param integer - ---- The y coordinates. --- --- **Signal:** --- --- * *property::y* --- --- @property y --- @param integer - ---- The width of the wibox. --- --- **Signal:** --- --- * *property::width* --- --- @property width --- @param width - ---- The height of the wibox. --- --- **Signal:** --- --- * *property::height* --- --- @property height --- @param height - ---- The wibox screen. --- --- @property screen --- @param screen - ---- The wibox's `drawable`. --- --- **Signal:** --- --- * *property::drawable* --- --- @property drawable --- @tparam drawable drawable - ---- The widget that the `wibox` displays. --- @property widget --- @param widget - ---- The X window id. --- --- **Signal:** --- --- * *property::window* --- --- @property window --- @param string --- @see client.window - ---- The wibox's bounding shape as a (native) cairo surface. --- --- **Signal:** --- --- * *property::shape_bounding* --- --- @property shape_bounding --- @param surface._native - ---- The wibox's clip shape as a (native) cairo surface. --- --- **Signal:** --- --- * *property::shape_clip* --- --- @property shape_clip --- @param surface._native - ---- Get or set mouse buttons bindings to a wibox. --- --- @param buttons_table A table of buttons objects, or nothing. --- @function buttons - ---- Get or set wibox geometry. That's the same as accessing or setting the x, --- y, width or height properties of a wibox. --- --- @param A table with coordinates to modify. --- @return A table with wibox coordinates and geometry. --- @function geometry - ---- Get or set wibox struts. --- --- @param strut A table with new strut, or nothing --- @return The wibox strut in a table. --- @function struts --- @see client.struts - ---- The default background color. --- @beautiful beautiful.bg_normal --- @see bg - ---- The default foreground (text) color. --- @beautiful beautiful.fg_normal --- @see fg - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @name setup --- @class function - ---- The background of the wibox. --- @param c The background to use. This must either be a cairo pattern object, --- nil or a string that gears.color() understands. --- @property bg --- @see gears.color - ---- The background image of the drawable. --- If `image` is a function, it will be called with `(context, cr, width, height)` --- as arguments. Any other arguments passed to this method will be appended. --- @param image A background image or a function --- @property bgimage --- @see gears.surface - ---- The foreground (text) of the wibox. --- @param c The foreground to use. This must either be a cairo pattern object, --- nil or a string that gears.color() understands. --- @property fg --- @see gears.color - ---- Find a widget by a point. --- The wibox must have drawn itself at least once for this to work. --- @tparam number x X coordinate of the point --- @tparam number y Y coordinate of the point --- @treturn table A sorted table of widgets positions. The first element is the biggest --- container while the last is the topmost widget. The table contains *x*, *y*, --- *width*, *height* and *widget*. --- @name find_widgets --- @class function - - -return setmetatable(awfulwibar, awfulwibar.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/wibox.lua b/awesome/lib/awful/wibox.lua deleted file mode 100644 index e8c7c7f..0000000 --- a/awesome/lib/awful/wibox.lua +++ /dev/null @@ -1,12 +0,0 @@ ---------------------------------------------------------------------------- ---- This module is deprecated and has been renamed `awful.wibar` --- --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2016 Emmanuel Lepage Vallee --- @module awful.wibox ---------------------------------------------------------------------------- -local util = require("awful.util") - -return util.deprecate_class(require("awful.wibar"), "awful.wibox", "awful.wibar") - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/button.lua b/awesome/lib/awful/widget/button.lua deleted file mode 100644 index 388f9dd..0000000 --- a/awesome/lib/awful/widget/button.lua +++ /dev/null @@ -1,263 +0,0 @@ ---------------------------------------------------------------------------- --- A simple button widget. --- @usage local button = awful.widget.button() --- button:buttons(awful.util.table.join( --- button:buttons(), --- awful.button({}, 1, nil, function () --- print("Mouse was clicked") --- end) --- )) --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget.button ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local abutton = require("awful.button") -local imagebox = require("wibox.widget.imagebox") -local widget = require("wibox.widget.base") -local surface = require("gears.surface") -local cairo = require("lgi").cairo - -local button = { mt = {} } - ---- Create a button widget. When clicked, the image is deplaced to make it like --- a real button. --- --- @param args Widget arguments. "image" is the image to display. --- @return A textbox widget configured as a button. -function button.new(args) - if not args or not args.image then - return widget.empty_widget() - end - - local w = imagebox() - local orig_set_image = w.set_image - local img_release - local img_press - - function w:set_image(image) - img_release = surface.load(image) - img_press = img_release:create_similar(cairo.Content.COLOR_ALPHA, img_release.width, img_release.height) - local cr = cairo.Context(img_press) - cr:set_source_surface(img_release, 2, 2) - cr:paint() - orig_set_image(self, img_release) - end - w:set_image(args.image) - w:buttons(abutton({}, 1, function () orig_set_image(w, img_press) end, function () orig_set_image(w, img_release) end)) - - w:connect_signal("mouse::leave", function(self) orig_set_image(self, img_release) end) - - return w -end - -function button.mt:__call(...) - return button.new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(button, button.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/common.lua b/awesome/lib/awful/widget/common.lua deleted file mode 100644 index e9ae699..0000000 --- a/awesome/lib/awful/widget/common.lua +++ /dev/null @@ -1,119 +0,0 @@ ---------------------------------------------------------------------------- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget.common ---------------------------------------------------------------------------- - --- Grab environment we need -local type = type -local ipairs = ipairs -local capi = { button = button } -local wibox = require("wibox") -local dpi = require("beautiful").xresources.apply_dpi - ---- Common utilities for awful widgets -local common = {} - ---- Common method to create buttons. --- @tab buttons --- @param object --- @treturn table -function common.create_buttons(buttons, object) - if buttons then - local btns = {} - for _, b in ipairs(buttons) do - -- Create a proxy button object: it will receive the real - -- press and release events, and will propagate them to the - -- button object the user provided, but with the object as - -- argument. - local btn = capi.button { modifiers = b.modifiers, button = b.button } - btn:connect_signal("press", function () b:emit_signal("press", object) end) - btn:connect_signal("release", function () b:emit_signal("release", object) end) - btns[#btns + 1] = btn - end - - return btns - end -end - ---- Common update method. --- @param w The widget. --- @tab buttons --- @func label Function to generate label parameters from an object. --- The function gets passed an object from `objects`, and --- has to return `text`, `bg`, `bg_image`, `icon`. --- @tab data Current data/cache, indexed by objects. --- @tab objects Objects to be displayed / updated. -function common.list_update(w, buttons, label, data, objects) - -- update the widgets, creating them if needed - w:reset() - for i, o in ipairs(objects) do - local cache = data[o] - local ib, tb, bgb, tbm, ibm, l - if cache then - ib = cache.ib - tb = cache.tb - bgb = cache.bgb - tbm = cache.tbm - ibm = cache.ibm - else - ib = wibox.widget.imagebox() - tb = wibox.widget.textbox() - bgb = wibox.container.background() - tbm = wibox.container.margin(tb, dpi(4), dpi(4)) - ibm = wibox.container.margin(ib, dpi(4)) - l = wibox.layout.fixed.horizontal() - - -- All of this is added in a fixed widget - l:fill_space(true) - l:add(ibm) - l:add(tbm) - - -- And all of this gets a background - bgb:set_widget(l) - - bgb:buttons(common.create_buttons(buttons, o)) - - data[o] = { - ib = ib, - tb = tb, - bgb = bgb, - tbm = tbm, - ibm = ibm, - } - end - - local text, bg, bg_image, icon, args = label(o, tb) - args = args or {} - - -- The text might be invalid, so use pcall. - if text == nil or text == "" then - tbm:set_margins(0) - else - if not tb:set_markup_silently(text) then - tb:set_markup("<i><Invalid text></i>") - end - end - bgb:set_bg(bg) - if type(bg_image) == "function" then - -- TODO: Why does this pass nil as an argument? - bg_image = bg_image(tb,o,nil,objects,i) - end - bgb:set_bgimage(bg_image) - if icon then - ib:set_image(icon) - else - ibm:set_margins(0) - end - - bgb.shape = args.shape - bgb.shape_border_width = args.shape_border_width - bgb.shape_border_color = args.shape_border_color - - w:add(bgb) - end -end - -return common - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/graph.lua b/awesome/lib/awful/widget/graph.lua deleted file mode 100644 index e231463..0000000 --- a/awesome/lib/awful/widget/graph.lua +++ /dev/null @@ -1,16 +0,0 @@ ---------------------------------------------------------------------------- ---- This module has been moved to `wibox.widget.graph` --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod awful.widget.graph ---------------------------------------------------------------------------- -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.widget.graph"), - "awful.widget.graph", - "wibox.widget.graph" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/init.lua b/awesome/lib/awful/widget/init.lua deleted file mode 100644 index 02400a1..0000000 --- a/awesome/lib/awful/widget/init.lua +++ /dev/null @@ -1,24 +0,0 @@ ---------------------------------------------------------------------------- ---- Widget module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget ---------------------------------------------------------------------------- - -return -{ - taglist = require("awful.widget.taglist"); - tasklist = require("awful.widget.tasklist"); - button = require("awful.widget.button"); - launcher = require("awful.widget.launcher"); - prompt = require("awful.widget.prompt"); - progressbar = require("awful.widget.progressbar"); - graph = require("awful.widget.graph"); - layoutbox = require("awful.widget.layoutbox"); - textclock = require("awful.widget.textclock"); - keyboardlayout = require("awful.widget.keyboardlayout"); - watch = require("awful.widget.watch"); -} - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/keyboardlayout.lua b/awesome/lib/awful/widget/keyboardlayout.lua deleted file mode 100644 index 4f79a81..0000000 --- a/awesome/lib/awful/widget/keyboardlayout.lua +++ /dev/null @@ -1,308 +0,0 @@ ---------------------------------------------------------------------------- --- @author Aleksey Fedotov <lexa@cfotr.com> --- @copyright 2015 Aleksey Fedotov --- @classmod wibox.widget.keyboardlayout ---------------------------------------------------------------------------- - -local capi = {awesome = awesome} -local setmetatable = setmetatable -local textbox = require("wibox.widget.textbox") -local button = require("awful.button") -local util = require("awful.util") -local widget_base = require("wibox.widget.base") -local gdebug = require("gears.debug") - ---- Keyboard Layout widget. --- awful.widget.keyboardlayout -local keyboardlayout = { mt = {} } - --- As to the country-code-like symbols below, refer to the names of XKB's --- data files in /.../xkb/symbols/*. -keyboardlayout.xkeyboard_country_code = { - ["ad"] = true, -- Andorra - ["af"] = true, -- Afganistan - ["al"] = true, -- Albania - ["am"] = true, -- Armenia - ["ara"] = true, -- Arabic - ["at"] = true, -- Austria - ["az"] = true, -- Azerbaijan - ["ba"] = true, -- Bosnia and Herzegovina - ["bd"] = true, -- Bangladesh - ["be"] = true, -- Belgium - ["bg"] = true, -- Bulgaria - ["br"] = true, -- Brazil - ["bt"] = true, -- Bhutan - ["bw"] = true, -- Botswana - ["by"] = true, -- Belarus - ["ca"] = true, -- Canada - ["cd"] = true, -- Congo - ["ch"] = true, -- Switzerland - ["cm"] = true, -- Cameroon - ["cn"] = true, -- China - ["cz"] = true, -- Czechia - ["de"] = true, -- Germany - ["dk"] = true, -- Denmark - ["ee"] = true, -- Estonia - ["epo"] = true, -- Esperanto - ["es"] = true, -- Spain - ["et"] = true, -- Ethiopia - ["fi"] = true, -- Finland - ["fo"] = true, -- Faroe Islands - ["fr"] = true, -- France - ["gb"] = true, -- United Kingdom - ["ge"] = true, -- Georgia - ["gh"] = true, -- Ghana - ["gn"] = true, -- Guinea - ["gr"] = true, -- Greece - ["hr"] = true, -- Croatia - ["hu"] = true, -- Hungary - ["ie"] = true, -- Ireland - ["il"] = true, -- Israel - ["in"] = true, -- India - ["iq"] = true, -- Iraq - ["ir"] = true, -- Iran - ["is"] = true, -- Iceland - ["it"] = true, -- Italy - ["jp"] = true, -- Japan - ["ke"] = true, -- Kenya - ["kg"] = true, -- Kyrgyzstan - ["kh"] = true, -- Cambodia - ["kr"] = true, -- Korea - ["kz"] = true, -- Kazakhstan - ["la"] = true, -- Laos - ["latam"] = true, -- Latin America - ["latin"] = true, -- Latin - ["lk"] = true, -- Sri Lanka - ["lt"] = true, -- Lithuania - ["lv"] = true, -- Latvia - ["ma"] = true, -- Morocco - ["mao"] = true, -- Maori - ["me"] = true, -- Montenegro - ["mk"] = true, -- Macedonia - ["ml"] = true, -- Mali - ["mm"] = true, -- Myanmar - ["mn"] = true, -- Mongolia - ["mt"] = true, -- Malta - ["mv"] = true, -- Maldives - ["ng"] = true, -- Nigeria - ["nl"] = true, -- Netherlands - ["no"] = true, -- Norway - ["np"] = true, -- Nepal - ["ph"] = true, -- Philippines - ["pk"] = true, -- Pakistan - ["pl"] = true, -- Poland - ["pt"] = true, -- Portugal - ["ro"] = true, -- Romania - ["rs"] = true, -- Serbia - ["ru"] = true, -- Russia - ["se"] = true, -- Sweden - ["si"] = true, -- Slovenia - ["sk"] = true, -- Slovakia - ["sn"] = true, -- Senegal - ["sy"] = true, -- Syria - ["th"] = true, -- Thailand - ["tj"] = true, -- Tajikistan - ["tm"] = true, -- Turkmenistan - ["tr"] = true, -- Turkey - ["tw"] = true, -- Taiwan - ["tz"] = true, -- Tanzania - ["ua"] = true, -- Ukraine - ["us"] = true, -- USA - ["uz"] = true, -- Uzbekistan - ["vn"] = true, -- Vietnam - ["za"] = true, -- South Africa -} - --- Callback for updating current layout. -local function update_status (self) - self._current = awesome.xkb_get_layout_group(); - local text = "" - if (#self._layout > 0) then - text = (" " .. self._layout[self._current] .. " ") - end - self.widget:set_text(text) -end - ---- Auxiliary function for the local function update_layout(). --- Create an array whose element is a table consisting of the four fields: --- vendor, file, section and group_idx, which all correspond to the --- xkb_symbols pattern "vendor/file(section):group_idx". --- @tparam string group_names The string awesome.xkb_get_group_names() returns. --- @treturn table An array of tables whose keys are vendor, file, section, and group_idx. -function keyboardlayout.get_groups_from_group_names(group_names) - if group_names == nil then - return nil - end - - -- Pattern elements to be captured. - local word_pat = "([%w_]+)" - local sec_pat = "(%b())" - local idx_pat = ":(%d)" - -- Pairs of a pattern and its callback. In callbacks, set 'group_idx' to 1 - -- and return it if there's no specification on 'group_idx' in the given - -- pattern. - local pattern_and_callback_pairs = { - -- vendor/file(section):group_idx - ["^" .. word_pat .. "/" .. word_pat .. sec_pat .. idx_pat .. "$"] - = function(token, pattern) - local vendor, file, section, group_idx = string.match(token, pattern) - return vendor, file, section, group_idx - end, - -- vendor/file(section) - ["^" .. word_pat .. "/" .. word_pat .. sec_pat .. "$"] - = function(token, pattern) - local vendor, file, section = string.match(token, pattern) - return vendor, file, section, 1 - end, - -- vendor/file:group_idx - ["^" .. word_pat .. "/" .. word_pat .. idx_pat .. "$"] - = function(token, pattern) - local vendor, file, group_idx = string.match(token, pattern) - return vendor, file, nil, group_idx - end, - -- vendor/file - ["^" .. word_pat .. "/" .. word_pat .. "$"] - = function(token, pattern) - local vendor, file = string.match(token, pattern) - return vendor, file, nil, 1 - end, - -- file(section):group_idx - ["^" .. word_pat .. sec_pat .. idx_pat .. "$"] - = function(token, pattern) - local file, section, group_idx = string.match(token, pattern) - return nil, file, section, group_idx - end, - -- file(section) - ["^" .. word_pat .. sec_pat .. "$"] - = function(token, pattern) - local file, section = string.match(token, pattern) - return nil, file, section, 1 - end, - -- file:group_idx - ["^" .. word_pat .. idx_pat .. "$"] - = function(token, pattern) - local file, group_idx = string.match(token, pattern) - return nil, file, nil, group_idx - end, - -- file - ["^" .. word_pat .. "$"] - = function(token, pattern) - local file = string.match(token, pattern) - return nil, file, nil, 1 - end - } - - -- Split 'group_names' into 'tokens'. The separator is "+". - local tokens = {} - string.gsub(group_names, "[^+]+", function(match) - table.insert(tokens, match) - end) - - -- For each token in 'tokens', check if it matches one of the patterns in - -- the array 'pattern_and_callback_pairs', where the patterns are used as - -- key. If a match is found, extract captured strings using the - -- corresponding callback function. Check if those extracted is country - -- specific part of a layout. If so, add it to 'layout_groups'; otherwise, - -- ignore it. - local layout_groups = {} - for i = 1, #tokens do - for pattern, callback in pairs(pattern_and_callback_pairs) do - local vendor, file, section, group_idx = callback(tokens[i], pattern) - if file then - if not keyboardlayout.xkeyboard_country_code[file] then - break - end - - if section then - section = string.gsub(section, "%(([%w-_]+)%)", "%1") - end - - table.insert(layout_groups, { vendor = vendor, - file = file, - section = section, - group_idx = tonumber(group_idx) }) - break - end - end - end - - return layout_groups -end - --- Callback for updating list of layouts -local function update_layout(self) - self._layout = {}; - local layouts = keyboardlayout.get_groups_from_group_names(awesome.xkb_get_group_names()) - if layouts == nil or layouts[1] == nil then - gdebug.print_error("Failed to get list of keyboard groups") - return - end - if #layouts == 1 then - layouts[1].group_idx = 0 - end - for _, v in ipairs(layouts) do - local layout_name = self.layout_name(v) - -- Please note that numbers of groups reported by xkb_get_group_names - -- is greater by one than the real group number. - self._layout[v.group_idx - 1] = layout_name - end - update_status(self) -end - ---- Create a keyboard layout widget. It shows current keyboard layout name in a textbox. --- @return A keyboard layout widget. -function keyboardlayout.new() - local widget = textbox() - local self = widget_base.make_widget(widget) - - self.widget = widget - - self.layout_name = function(v) - local name = v.file - if v.section ~= nil then - name = name .. "(" .. v.section .. ")" - end - return name - end - - self.next_layout = function() - self.set_layout((self._current + 1) % (#self._layout + 1)) - end - - self.set_layout = function(group_number) - if (0 > group_number) or (group_number > #self._layout) then - error("Invalid group number: " .. group_number .. - "expected number from 0 to " .. #self._layout) - return; - end - awesome.xkb_set_layout_group(group_number); - end - - update_layout(self); - - -- callback for processing layout changes - capi.awesome.connect_signal("xkb::map_changed", - function () update_layout(self) end) - capi.awesome.connect_signal("xkb::group_changed", - function () update_status(self) end); - - -- Mouse bindings - self:buttons( - util.table.join(button({ }, 1, self.next_layout)) - ) - - return self -end - -local _instance = nil; - -function keyboardlayout.mt:__call(...) - if _instance == nil then - _instance = keyboardlayout.new(...) - end - return _instance -end - -return setmetatable(keyboardlayout, keyboardlayout.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/launcher.lua b/awesome/lib/awful/widget/launcher.lua deleted file mode 100644 index a944908..0000000 --- a/awesome/lib/awful/widget/launcher.lua +++ /dev/null @@ -1,41 +0,0 @@ ---------------------------------------------------------------------------- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget.launcher ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local util = require("awful.util") -local spawn = require("awful.spawn") -local wbutton = require("awful.widget.button") -local button = require("awful.button") - -local launcher = { mt = {} } - ---- Create a button widget which will launch a command. --- @param args Standard widget table arguments, plus image for the image path --- and command for the command to run on click, or either menu to create menu. --- @return A launcher widget. -function launcher.new(args) - if not args.command and not args.menu then return end - local w = wbutton(args) - if not w then return end - - local b - if args.command then - b = util.table.join(w:buttons(), button({}, 1, nil, function () spawn(args.command) end)) - elseif args.menu then - b = util.table.join(w:buttons(), button({}, 1, nil, function () args.menu:toggle() end)) - end - - w:buttons(b) - return w -end - -function launcher.mt:__call(...) - return launcher.new(...) -end - -return setmetatable(launcher, launcher.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/layoutbox.lua b/awesome/lib/awful/widget/layoutbox.lua deleted file mode 100644 index c5f8ed3..0000000 --- a/awesome/lib/awful/widget/layoutbox.lua +++ /dev/null @@ -1,73 +0,0 @@ ---------------------------------------------------------------------------- ---- Layoutbox widget. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod awful.widget.layoutbox ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local capi = { screen = screen, tag = tag } -local layout = require("awful.layout") -local tooltip = require("awful.tooltip") -local beautiful = require("beautiful") -local imagebox = require("wibox.widget.imagebox") - -local function get_screen(s) - return s and capi.screen[s] -end - -local layoutbox = { mt = {} } - -local boxes = nil - -local function update(w, screen) - screen = get_screen(screen) - local name = layout.getname(layout.get(screen)) - w._layoutbox_tooltip:set_text(name or "[no name]") - w:set_image(name and beautiful["layout_" .. name]) -end - -local function update_from_tag(t) - local screen = get_screen(t.screen) - local w = boxes[screen] - if w then - update(w, screen) - end -end - ---- Create a layoutbox widget. It draws a picture with the current layout --- symbol of the current tag. --- @param screen The screen number that the layout will be represented for. --- @return An imagebox widget configured as a layoutbox. -function layoutbox.new(screen) - screen = get_screen(screen or 1) - - -- Do we already have the update callbacks registered? - if boxes == nil then - boxes = setmetatable({}, { __mode = "kv" }) - capi.tag.connect_signal("property::selected", update_from_tag) - capi.tag.connect_signal("property::layout", update_from_tag) - layoutbox.boxes = boxes - end - - -- Do we already have a layoutbox for this screen? - local w = boxes[screen] - if not w then - w = imagebox() - w._layoutbox_tooltip = tooltip {objects = {w}, delay_show = 1} - - update(w, screen) - boxes[screen] = w - end - - return w -end - -function layoutbox.mt:__call(...) - return layoutbox.new(...) -end - -return setmetatable(layoutbox, layoutbox.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/progressbar.lua b/awesome/lib/awful/widget/progressbar.lua deleted file mode 100644 index 11147f4..0000000 --- a/awesome/lib/awful/widget/progressbar.lua +++ /dev/null @@ -1,16 +0,0 @@ ---------------------------------------------------------------------------- ---- This module has been moved to `wibox.widget.progressbar` --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod awful.widget.progressbar ---------------------------------------------------------------------------- -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.widget.progressbar"), - "awful.widget.progressbar", - "wibox.widget.progressbar" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/prompt.lua b/awesome/lib/awful/widget/prompt.lua deleted file mode 100644 index ff9d904..0000000 --- a/awesome/lib/awful/widget/prompt.lua +++ /dev/null @@ -1,64 +0,0 @@ ---------------------------------------------------------------------------- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod awful.widget.prompt ---------------------------------------------------------------------------- - -local setmetatable = setmetatable - -local completion = require("awful.completion") -local util = require("awful.util") -local spawn = require("awful.spawn") -local prompt = require("awful.prompt") -local widget_base = require("wibox.widget.base") -local textbox = require("wibox.widget.textbox") -local type = type - -local widgetprompt = { mt = {} } - ---- Run method for promptbox. --- --- @param promptbox The promptbox to run. -local function run(promptbox) - return prompt.run { - prompt = promptbox.prompt, - textbox = promptbox.widget, - completion_callback = completion.shell, - history_path = util.get_cache_dir() .. "/history", - exe_callback = function (...) - promptbox:spawn_and_handle_error(...) - end, - } -end - -local function spawn_and_handle_error(self, ...) - local result = spawn(...) - if type(result) == "string" then - self.widget:set_text(result) - end -end - ---- Create a prompt widget which will launch a command. --- --- @param args Arguments table. "prompt" is the prompt to use. --- @return A launcher widget. -function widgetprompt.new(args) - args = args or {} - local widget = textbox() - local promptbox = widget_base.make_widget(widget) - - promptbox.widget = widget - promptbox.widget:set_ellipsize("start") - promptbox.run = run - promptbox.spawn_and_handle_error = spawn_and_handle_error - promptbox.prompt = args.prompt or "Run: " - return promptbox -end - -function widgetprompt.mt:__call(...) - return widgetprompt.new(...) -end - -return setmetatable(widgetprompt, widgetprompt.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/taglist.lua b/awesome/lib/awful/widget/taglist.lua deleted file mode 100644 index d8cf475..0000000 --- a/awesome/lib/awful/widget/taglist.lua +++ /dev/null @@ -1,452 +0,0 @@ ---------------------------------------------------------------------------- ---- Taglist widget module for awful --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget.taglist ---------------------------------------------------------------------------- - --- Grab environment we need -local capi = { screen = screen, - awesome = awesome, - client = client } -local setmetatable = setmetatable -local pairs = pairs -local ipairs = ipairs -local table = table -local common = require("awful.widget.common") -local util = require("awful.util") -local tag = require("awful.tag") -local beautiful = require("beautiful") -local fixed = require("wibox.layout.fixed") -local surface = require("gears.surface") -local timer = require("gears.timer") - -local function get_screen(s) - return s and capi.screen[s] -end - -local taglist = { mt = {} } -taglist.filter = {} - ---- The tag list main foreground (text) color. --- @beautiful beautiful.taglist_fg_focus --- @param[opt=fg_focus] color --- @see gears.color - ---- The tag list main background color. --- @beautiful beautiful.taglist_bg_focus --- @param[opt=bg_focus] color --- @see gears.color - ---- The tag list urgent elements foreground (text) color. --- @beautiful beautiful.taglist_fg_urgent --- @param[opt=fg_urgent] color --- @see gears.color - ---- The tag list urgent elements background color. --- @beautiful beautiful.taglist_bg_urgent --- @param[opt=bg_urgent] color --- @see gears.color - ---- The tag list occupied elements background color. --- @beautiful beautiful.taglist_bg_occupied --- @param color --- @see gears.color - ---- The tag list occupied elements foreground (text) color. --- @beautiful beautiful.taglist_fg_occupied --- @param color --- @see gears.color - ---- The tag list empty elements background color. --- @beautiful beautiful.taglist_bg_empty --- @param color --- @see gears.color - ---- The tag list empty elements foreground (text) color. --- @beautiful beautiful.taglist_fg_empty --- @param color --- @see gears.color - ---- The selected elements background image. --- @beautiful beautiful.taglist_squares_sel --- @param surface --- @see gears.surface - ---- The unselected elements background image. --- @beautiful beautiful.taglist_squares_unsel --- @param surface --- @see gears.surface - ---- The selected empty elements background image. --- @beautiful beautiful.taglist_squares_sel_empty --- @param surface --- @see gears.surface - ---- The unselected empty elements background image. --- @beautiful beautiful.taglist_squares_unsel_empty --- @param surface --- @see gears.surface - ---- If the background images can be resized. --- @beautiful beautiful.taglist_squares_resize --- @param boolean - ---- Do not display the tag icons, even if they are set. --- @beautiful beautiful.taglist_disable_icon --- @param boolean - ---- The taglist font. --- @beautiful beautiful.taglist_font --- @param string - ---- The main shape used for the elements. --- This will be the fallback for state specific shapes. --- To get a shape for the whole taglist, use `wibox.container.background`. --- @beautiful beautiful.taglist_shape --- @param[opt=rectangle] gears.shape --- @see gears.shape --- @see beautiful.taglist_shape_empty --- @see beautiful.taglist_shape_focus --- @see beautiful.taglist_shape_urgent - ---- The shape elements border width. --- @beautiful beautiful.taglist_shape_border_width --- @param[opt=0] number --- @see wibox.container.background - ---- The elements shape border color. --- @beautiful beautiful.taglist_shape_border_color --- @param color --- @see gears.color - ---- The shape used for the empty elements. --- @beautiful beautiful.taglist_shape_empty --- @param[opt=rectangle] gears.shape --- @see gears.shape - ---- The shape used for the empty elements border width. --- @beautiful beautiful.taglist_shape_border_width_empty --- @param[opt=0] number --- @see wibox.container.background - ---- The empty elements shape border color. --- @beautiful beautiful.taglist_shape_border_color_empty --- @param color --- @see gears.color - ---- The shape used for the selected elements. --- @beautiful beautiful.taglist_shape_focus --- @param[opt=rectangle] gears.shape --- @see gears.shape - ---- The shape used for the selected elements border width. --- @beautiful beautiful.taglist_shape_border_width_focus --- @param[opt=0] number --- @see wibox.container.background - ---- The selected elements shape border color. --- @beautiful beautiful.taglist_shape_border_color_focus --- @param color --- @see gears.color - ---- The shape used for the urgent elements. --- @beautiful beautiful.taglist_shape_urgent --- @param[opt=rectangle] gears.shape --- @see gears.shape - ---- The shape used for the urgent elements border width. --- @beautiful beautiful.taglist_shape_border_width_urgent --- @param[opt=0] number --- @see wibox.container.background - ---- The urgents elements shape border color. --- @beautiful beautiful.taglist_shape_border_color_urgent --- @param color --- @see gears.color - -local instances = nil - -function taglist.taglist_label(t, args) - if not args then args = {} end - local theme = beautiful.get() - local fg_focus = args.fg_focus or theme.taglist_fg_focus or theme.fg_focus - local bg_focus = args.bg_focus or theme.taglist_bg_focus or theme.bg_focus - local fg_urgent = args.fg_urgent or theme.taglist_fg_urgent or theme.fg_urgent - local bg_urgent = args.bg_urgent or theme.taglist_bg_urgent or theme.bg_urgent - local bg_occupied = args.bg_occupied or theme.taglist_bg_occupied - local fg_occupied = args.fg_occupied or theme.taglist_fg_occupied - local bg_empty = args.bg_empty or theme.taglist_bg_empty - local fg_empty = args.fg_empty or theme.taglist_fg_empty - local taglist_squares_sel = args.squares_sel or theme.taglist_squares_sel - local taglist_squares_unsel = args.squares_unsel or theme.taglist_squares_unsel - local taglist_squares_sel_empty = args.squares_sel_empty or theme.taglist_squares_sel_empty - local taglist_squares_unsel_empty = args.squares_unsel_empty or theme.taglist_squares_unsel_empty - local taglist_squares_resize = theme.taglist_squares_resize or args.squares_resize or "true" - local taglist_disable_icon = args.taglist_disable_icon or theme.taglist_disable_icon or false - local font = args.font or theme.taglist_font or theme.font or "" - local text = nil - local sel = capi.client.focus - local bg_color = nil - local fg_color = nil - local bg_image - local icon - local shape = args.shape or theme.taglist_shape - local shape_border_width = args.shape_border_width or theme.taglist_shape_border_width - local shape_border_color = args.shape_border_color or theme.taglist_shape_border_color - -- TODO: Re-implement bg_resize - local bg_resize = false -- luacheck: ignore - local is_selected = false - local cls = t:clients() - - if sel and taglist_squares_sel then - -- Check that the selected client is tagged with 't'. - local seltags = sel:tags() - for _, v in ipairs(seltags) do - if v == t then - bg_image = taglist_squares_sel - bg_resize = taglist_squares_resize == "true" - is_selected = true - break - end - end - end - if #cls == 0 and t.selected and taglist_squares_sel_empty then - bg_image = taglist_squares_sel_empty - bg_resize = taglist_squares_resize == "true" - elseif not is_selected then - if #cls > 0 then - if taglist_squares_unsel then - bg_image = taglist_squares_unsel - bg_resize = taglist_squares_resize == "true" - end - if bg_occupied then bg_color = bg_occupied end - if fg_occupied then fg_color = fg_occupied end - else - if taglist_squares_unsel_empty then - bg_image = taglist_squares_unsel_empty - bg_resize = taglist_squares_resize == "true" - end - if bg_empty then bg_color = bg_empty end - if fg_empty then fg_color = fg_empty end - - if args.shape_empty or theme.taglist_shape_empty then - shape = args.shape_empty or theme.taglist_shape_empty - end - - if args.shape_border_width_empty or theme.taglist_shape_border_width_empty then - shape_border_width = args.shape_border_width_empty or theme.taglist_shape_border_width_empty - end - - if args.shape_border_color_empty or theme.taglist_shape_border_color_empty then - shape_border_color = args.shape_border_color_empty or theme.taglist_shape_border_color_empty - end - end - end - if t.selected then - bg_color = bg_focus - fg_color = fg_focus - - if args.shape_focus or theme.taglist_shape_focus then - shape = args.shape_focus or theme.taglist_shape_focus - end - - if args.shape_border_width_focus or theme.taglist_shape_border_width_focus then - shape = args.shape_border_width_focus or theme.taglist_shape_border_width_focus - end - - if args.shape_border_color_focus or theme.taglist_shape_border_color_focus then - shape = args.shape_border_color_focus or theme.taglist_shape_border_color_focus - end - - elseif tag.getproperty(t, "urgent") then - if bg_urgent then bg_color = bg_urgent end - if fg_urgent then fg_color = fg_urgent end - - if args.shape_urgent or theme.taglist_shape_urgent then - shape = args.shape_urgent or theme.taglist_shape_urgent - end - - if args.shape_border_width_urgent or theme.taglist_shape_border_width_urgent then - shape_border_width = args.shape_border_width_urgent or theme.taglist_shape_border_width_urgent - end - - if args.shape_border_color_urgent or theme.taglist_shape_border_color_urgent then - shape_border_color = args.shape_border_color_urgent or theme.taglist_shape_border_color_urgent - end - end - - if not tag.getproperty(t, "icon_only") then - text = "<span font_desc='"..font.."'>" - if fg_color then - text = text .. "<span color='" .. util.ensure_pango_color(fg_color) .. - "'>" .. (util.escape(t.name) or "") .. "</span>" - else - text = text .. (util.escape(t.name) or "") - end - text = text .. "</span>" - end - if not taglist_disable_icon then - if t.icon then - icon = surface.load(t.icon) - end - end - - local other_args = { - shape = shape, - shape_border_width = shape_border_width, - shape_border_color = shape_border_color, - } - - return text, bg_color, bg_image, not taglist_disable_icon and icon or nil, other_args -end - -local function taglist_update(s, w, buttons, filter, data, style, update_function) - local tags = {} - for _, t in ipairs(s.tags) do - if not tag.getproperty(t, "hide") and filter(t) then - table.insert(tags, t) - end - end - - local function label(c) return taglist.taglist_label(c, style) end - - update_function(w, buttons, label, data, tags) -end - ---- Create a new taglist widget. The last two arguments (update_function --- and base_widget) serve to customize the layout of the taglist (eg. to --- make it vertical). For that, you will need to copy the --- awful.widget.common.list_update function, make your changes to it --- and pass it as update_function here. Also change the base_widget if the --- default is not what you want. --- @param screen The screen to draw taglist for. --- @param filter Filter function to define what clients will be listed. --- @param buttons A table with buttons binding to set. --- @tparam[opt={}] table style The style overrides default theme. --- @tparam[opt=nil] string|pattern style.fg_focus --- @tparam[opt=nil] string|pattern style.bg_focus --- @tparam[opt=nil] string|pattern style.fg_urgent --- @tparam[opt=nil] string|pattern style.bg_urgent --- @tparam[opt=nil] string|pattern style.bg_occupied --- @tparam[opt=nil] string|pattern style.fg_occupied --- @tparam[opt=nil] string|pattern style.bg_empty --- @tparam[opt=nil] string|pattern style.fg_empty --- @tparam[opt=nil] string style.taglist_squares_sel --- @tparam[opt=nil] string style.taglist_squares_unsel --- @tparam[opt=nil] string style.taglist_squares_sel_empty --- @tparam[opt=nil] string style.taglist_squares_unsel_empty --- @tparam[opt=nil] string style.taglist_squares_resize --- @tparam[opt=nil] string style.taglist_disable_icon --- @tparam[opt=nil] string style.font --- @tparam[opt=nil] number style.spacing The spacing between tags. --- @param[opt] update_function Function to create a tag widget on each --- update. See `awful.widget.common`. --- @param[opt] base_widget Optional container widget for tag widgets. Default --- is wibox.layout.fixed.horizontal(). --- @param base_widget.bg_focus The background color for focused client. --- @param base_widget.fg_focus The foreground color for focused client. --- @param base_widget.bg_urgent The background color for urgent clients. --- @param base_widget.fg_urgent The foreground color for urgent clients. --- @param[opt] base_widget.squares_sel A user provided image for selected squares. --- @param[opt] base_widget.squares_unsel A user provided image for unselected squares. --- @param[opt] base_widget.squares_sel_empty A user provided image for selected squares for empty tags. --- @param[opt] base_widget.squares_unsel_empty A user provided image for unselected squares for empty tags. --- @param[opt] base_widget.squares_resize True or false to resize squares. --- @param base_widget.font The font. --- @function awful.taglist -function taglist.new(screen, filter, buttons, style, update_function, base_widget) - screen = get_screen(screen) - local uf = update_function or common.list_update - local w = base_widget or fixed.horizontal() - - if w.set_spacing and (style and style.spacing or beautiful.taglist_spacing) then - w:set_spacing(style and style.spacing or beautiful.taglist_spacing) - end - - local data = setmetatable({}, { __mode = 'k' }) - - local queued_update = {} - function w._do_taglist_update() - -- Add a delayed callback for the first update. - if not queued_update[screen] then - timer.delayed_call(function() - if screen.valid then - taglist_update(screen, w, buttons, filter, data, style, uf) - end - queued_update[screen] = false - end) - queued_update[screen] = true - end - end - if instances == nil then - instances = setmetatable({}, { __mode = "k" }) - local function u(s) - local i = instances[get_screen(s)] - if i then - for _, tlist in pairs(i) do - tlist._do_taglist_update() - end - end - end - local uc = function (c) return u(c.screen) end - local ut = function (t) return u(t.screen) end - capi.client.connect_signal("focus", uc) - capi.client.connect_signal("unfocus", uc) - tag.attached_connect_signal(nil, "property::selected", ut) - tag.attached_connect_signal(nil, "property::icon", ut) - tag.attached_connect_signal(nil, "property::hide", ut) - tag.attached_connect_signal(nil, "property::name", ut) - tag.attached_connect_signal(nil, "property::activated", ut) - tag.attached_connect_signal(nil, "property::screen", ut) - tag.attached_connect_signal(nil, "property::index", ut) - tag.attached_connect_signal(nil, "property::urgent", ut) - capi.client.connect_signal("property::screen", function(c, old_screen) - u(c.screen) - u(old_screen) - end) - capi.client.connect_signal("tagged", uc) - capi.client.connect_signal("untagged", uc) - capi.client.connect_signal("unmanage", uc) - capi.screen.connect_signal("removed", function(s) - instances[get_screen(s)] = nil - end) - end - w._do_taglist_update() - local list = instances[screen] - if not list then - list = setmetatable({}, { __mode = "v" }) - instances[screen] = list - end - table.insert(list, w) - return w -end - ---- Filtering function to include all nonempty tags on the screen. --- @param t The tag. --- @return true if t is not empty, else false -function taglist.filter.noempty(t) - return #t:clients() > 0 or t.selected -end - ---- Filtering function to include selected tags on the screen. --- @param t The tag. --- @return true if t is not empty, else false -function taglist.filter.selected(t) - return t.selected -end - ---- Filtering function to include all tags on the screen. --- @return true -function taglist.filter.all() - return true -end - -function taglist.mt:__call(...) - return taglist.new(...) -end - -return setmetatable(taglist, taglist.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/tasklist.lua b/awesome/lib/awful/widget/tasklist.lua deleted file mode 100644 index d5580c1..0000000 --- a/awesome/lib/awful/widget/tasklist.lua +++ /dev/null @@ -1,573 +0,0 @@ ---------------------------------------------------------------------------- ---- Tasklist widget module for awful. --- --- <a name="status_icons"></a> --- **Status icons:** --- --- By default, the tasklist prepends some symbols in front of the client name. --- This is used to notify that the client has some specific properties that are --- currently enabled. This can be disabled using --- `beautiful.tasklist_plain_task_name`=true in the theme. --- --- <table class='widget_list' border=1> --- <tr style='font-weight: bold;'> --- <th align='center'>Icon</th> --- <th align='center'>Client property</th> --- </tr> --- <tr><td>▪</td><td><a href="./client.html#client.sticky">sticky</a></td></tr> --- <tr><td>⌃</td><td><a href="./client.html#client.ontop">ontop</a></td></tr> --- <tr><td>▴</td><td><a href="./client.html#client.above">above</a></td></tr> --- <tr><td>▾</td><td><a href="./client.html#client.below">below</a></td></tr> --- <tr><td>✈</td><td><a href="./client.html#client.floating">floating</a></td></tr> --- <tr><td>+</td><td><a href="./client.html#client.maximized">maximized</a></td></tr> --- <tr><td>⬌</td><td><a href="./client.html#client.maximized_horizontal">maximized_horizontal</a></td></tr> --- <tr><td>⬍</td><td><a href="./client.html#client.maximized_vertical">maximized_vertical</a></td></tr> --- </table> --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget.tasklist ---------------------------------------------------------------------------- - --- Grab environment we need -local capi = { screen = screen, - client = client } -local ipairs = ipairs -local setmetatable = setmetatable -local table = table -local common = require("awful.widget.common") -local beautiful = require("beautiful") -local util = require("awful.util") -local tag = require("awful.tag") -local flex = require("wibox.layout.flex") -local timer = require("gears.timer") - -local function get_screen(s) - return s and screen[s] -end - -local tasklist = { mt = {} } - -local instances - ---- The default foreground (text) color. --- @beautiful beautiful.tasklist_fg_normal --- @tparam[opt=nil] string|pattern fg_normal --- @see gears.color - ---- The default background color. --- @beautiful beautiful.tasklist_bg_normal --- @tparam[opt=nil] string|pattern bg_normal --- @see gears.color - ---- The focused client foreground (text) color. --- @beautiful beautiful.tasklist_fg_focus --- @tparam[opt=nil] string|pattern fg_focus --- @see gears.color - ---- The focused client background color. --- @beautiful beautiful.tasklist_bg_focus --- @tparam[opt=nil] string|pattern bg_focus --- @see gears.color - ---- The urgent clients foreground (text) color. --- @beautiful beautiful.tasklist_fg_urgent --- @tparam[opt=nil] string|pattern fg_urgent --- @see gears.color - ---- The urgent clients background color. --- @beautiful beautiful.tasklist_bg_urgent --- @tparam[opt=nil] string|pattern bg_urgent --- @see gears.color - ---- The minimized clients foreground (text) color. --- @beautiful beautiful.tasklist_fg_minimize --- @tparam[opt=nil] string|pattern fg_minimize --- @see gears.color - ---- The minimized clients background color. --- @beautiful beautiful.tasklist_bg_minimize --- @tparam[opt=nil] string|pattern bg_minimize --- @see gears.color - ---- The elements default background image. --- @beautiful beautiful.tasklist_bg_image_normal --- @tparam[opt=nil] string bg_image_normal - ---- The focused client background image. --- @beautiful beautiful.tasklist_bg_image_focus --- @tparam[opt=nil] string bg_image_focus - ---- The urgent clients background image. --- @beautiful beautiful.tasklist_bg_image_urgent --- @tparam[opt=nil] string bg_image_urgent - ---- The minimized clients background image. --- @beautiful beautiful.tasklist_bg_image_minimize --- @tparam[opt=nil] string bg_image_minimize - ---- Disable the tasklist client icons. --- @beautiful beautiful.tasklist_tasklist_disable_icon --- @tparam[opt=false] boolean tasklist_disable_icon - ---- Disable the extra tasklist client property notification icons. --- --- See the <a href="status_icons">Status icons</a> section for more details. --- --- @beautiful beautiful.tasklist_plain_task_name --- @tparam[opt=false] boolean tasklist_plain_task_name - ---- The tasklist font. --- @beautiful beautiful.tasklist_font --- @tparam[opt=nil] string font - ---- The focused client alignment. --- @beautiful beautiful.tasklist_align --- @tparam[opt=left] string align *left*, *right* or *center* - ---- The focused client title alignment. --- @beautiful beautiful.tasklist_font_focus --- @tparam[opt=nil] string font_focus - ---- The minimized clients font. --- @beautiful beautiful.tasklist_font_minimized --- @tparam[opt=nil] string font_minimized - ---- The urgent clients font. --- @beautiful beautiful.tasklist_font_urgent --- @tparam[opt=nil] string font_urgent - ---- The space between the tasklist elements. --- @beautiful beautiful.tasklist_spacing --- @tparam[opt=0] number spacing The spacing between tags. - ---- The default tasklist elements shape. --- @beautiful beautiful.tasklist_shape --- @tparam[opt=nil] gears.shape shape - ---- The default tasklist elements border width. --- @beautiful beautiful.tasklist_shape_border_width --- @tparam[opt=0] number shape_border_width - ---- The default tasklist elements border color. --- @beautiful beautiful.tasklist_shape_border_color --- @tparam[opt=nil] string|color shape_border_color --- @see gears.color - ---- The focused client shape. --- @beautiful beautiful.tasklist_shape_focus --- @tparam[opt=nil] gears.shape shape_focus - ---- The focused client border width. --- @beautiful beautiful.tasklist_shape_border_width_focus --- @tparam[opt=0] number shape_border_width_focus - ---- The focused client border color. --- @beautiful beautiful.tasklist_shape_border_color_focus --- @tparam[opt=nil] string|color shape_border_color_focus --- @see gears.color - ---- The minimized clients shape. --- @beautiful beautiful.tasklist_shape_minimized --- @tparam[opt=nil] gears.shape shape_minimized - ---- The minimized clients border width. --- @beautiful beautiful.tasklist_shape_border_width_minimized --- @tparam[opt=0] number shape_border_width_minimized - ---- The minimized clients border color. --- @beautiful beautiful.tasklist_shape_border_color_minimized --- @tparam[opt=nil] string|color shape_border_color_minimized --- @see gears.color - ---- The urgent clients shape. --- @beautiful beautiful.tasklist_shape_urgent --- @tparam[opt=nil] gears.shape shape_urgent - ---- The urgent clients border width. --- @beautiful beautiful.tasklist_shape_border_width_urgent --- @tparam[opt=0] number shape_border_width_urgent - ---- The urgent clients border color. --- @beautiful beautiful.tasklist_shape_border_color_urgent --- @tparam[opt=nil] string|color shape_border_color_urgent --- @see gears.color - --- Public structures -tasklist.filter = {} - -local function tasklist_label(c, args, tb) - if not args then args = {} end - local theme = beautiful.get() - local align = args.align or theme.tasklist_align or "left" - local fg_normal = util.ensure_pango_color(args.fg_normal or theme.tasklist_fg_normal or theme.fg_normal, "white") - local bg_normal = args.bg_normal or theme.tasklist_bg_normal or theme.bg_normal or "#000000" - local fg_focus = util.ensure_pango_color(args.fg_focus or theme.tasklist_fg_focus or theme.fg_focus, fg_normal) - local bg_focus = args.bg_focus or theme.tasklist_bg_focus or theme.bg_focus or bg_normal - local fg_urgent = util.ensure_pango_color(args.fg_urgent or theme.tasklist_fg_urgent or theme.fg_urgent, fg_normal) - local bg_urgent = args.bg_urgent or theme.tasklist_bg_urgent or theme.bg_urgent or bg_normal - local fg_minimize = util.ensure_pango_color(args.fg_minimize or theme.tasklist_fg_minimize or theme.fg_minimize, fg_normal) - local bg_minimize = args.bg_minimize or theme.tasklist_bg_minimize or theme.bg_minimize or bg_normal - local bg_image_normal = args.bg_image_normal or theme.bg_image_normal - local bg_image_focus = args.bg_image_focus or theme.bg_image_focus - local bg_image_urgent = args.bg_image_urgent or theme.bg_image_urgent - local bg_image_minimize = args.bg_image_minimize or theme.bg_image_minimize - local tasklist_disable_icon = args.tasklist_disable_icon or theme.tasklist_disable_icon or false - local font = args.font or theme.tasklist_font or theme.font or "" - local font_focus = args.font_focus or theme.tasklist_font_focus or theme.font_focus or font or "" - local font_minimized = args.font_minimized or theme.tasklist_font_minimized or theme.font_minimized or font or "" - local font_urgent = args.font_urgent or theme.tasklist_font_urgent or theme.font_urgent or font or "" - local text = "" - local name = "" - local bg - local bg_image - local shape = args.shape or theme.tasklist_shape - local shape_border_width = args.shape_border_width or theme.tasklist_shape_border_width - local shape_border_color = args.shape_border_color or theme.tasklist_shape_border_color - - -- symbol to use to indicate certain client properties - local sticky = args.sticky or theme.tasklist_sticky or "▪" - local ontop = args.ontop or theme.tasklist_ontop or '⌃' - local above = args.above or theme.tasklist_above or '▴' - local below = args.below or theme.tasklist_below or '▾' - local floating = args.floating or theme.tasklist_floating or '✈' - local maximized = args.maximized or theme.tasklist_maximized or '<b>+</b>' - local maximized_horizontal = args.maximized_horizontal or theme.tasklist_maximized_horizontal or '⬌' - local maximized_vertical = args.maximized_vertical or theme.tasklist_maximized_vertical or '⬍' - - tb:set_align(align) - - if not theme.tasklist_plain_task_name then - if c.sticky then name = name .. sticky end - - if c.ontop then name = name .. ontop - elseif c.above then name = name .. above - elseif c.below then name = name .. below end - - if c.maximized then - name = name .. maximized - else - if c.maximized_horizontal then name = name .. maximized_horizontal end - if c.maximized_vertical then name = name .. maximized_vertical end - if c.floating then name = name .. floating end - end - end - - if c.minimized then - name = name .. (util.escape(c.icon_name) or util.escape(c.name) or util.escape("<untitled>")) - else - name = name .. (util.escape(c.name) or util.escape("<untitled>")) - end - - local focused = capi.client.focus == c - -- Handle transient_for: the first parent that does not skip the taskbar - -- is considered to be focused, if the real client has skip_taskbar. - if not focused and capi.client.focus and capi.client.focus.skip_taskbar - and capi.client.focus:get_transient_for_matching(function(cl) - return not cl.skip_taskbar - end) == c then - focused = true - end - - if focused then - bg = bg_focus - text = text .. "<span color='"..fg_focus.."'>"..name.."</span>" - bg_image = bg_image_focus - font = font_focus - - if args.shape_focus or theme.tasklist_shape_focus then - shape = args.shape_focus or theme.tasklist_shape_focus - end - - if args.shape_border_width_focus or theme.tasklist_shape_border_width_focus then - shape_border_width = args.shape_border_width_focus or theme.tasklist_shape_border_width_focus - end - - if args.shape_border_color_focus or theme.tasklist_shape_border_color_focus then - shape_border_color = args.shape_border_color_focus or theme.tasklist_shape_border_color_focus - end - elseif c.urgent then - bg = bg_urgent - text = text .. "<span color='"..fg_urgent.."'>"..name.."</span>" - bg_image = bg_image_urgent - font = font_urgent - - if args.shape_urgent or theme.tasklist_shape_urgent then - shape = args.shape_urgent or theme.tasklist_shape_urgent - end - - if args.shape_border_width_urgent or theme.tasklist_shape_border_width_urgent then - shape_border_width = args.shape_border_width_urgent or theme.tasklist_shape_border_width_urgent - end - - if args.shape_border_color_urgent or theme.tasklist_shape_border_color_urgent then - shape_border_color = args.shape_border_color_urgent or theme.tasklist_shape_border_color_urgent - end - elseif c.minimized then - bg = bg_minimize - text = text .. "<span color='"..fg_minimize.."'>"..name.."</span>" - bg_image = bg_image_minimize - font = font_minimized - - if args.shape_minimized or theme.tasklist_shape_minimized then - shape = args.shape_minimized or theme.tasklist_shape_minimized - end - - if args.shape_border_width_minimized or theme.tasklist_shape_border_width_minimized then - shape_border_width = args.shape_border_width_minimized or theme.tasklist_shape_border_width_minimized - end - - if args.shape_border_color_minimized or theme.tasklist_shape_border_color_minimized then - shape_border_color = args.shape_border_color_minimized or theme.tasklist_shape_border_color_minimized - end - else - bg = bg_normal - text = text .. "<span color='"..fg_normal.."'>"..name.."</span>" - bg_image = bg_image_normal - end - tb:set_font(font) - - local other_args = { - shape = shape, - shape_border_width = shape_border_width, - shape_border_color = shape_border_color, - } - - return text, bg, bg_image, not tasklist_disable_icon and c.icon or nil, other_args -end - -local function tasklist_update(s, w, buttons, filter, data, style, update_function) - local clients = {} - for _, c in ipairs(capi.client.get()) do - if not (c.skip_taskbar or c.hidden - or c.type == "splash" or c.type == "dock" or c.type == "desktop") - and filter(c, s) then - table.insert(clients, c) - end - end - - local function label(c, tb) return tasklist_label(c, style, tb) end - - update_function(w, buttons, label, data, clients) -end - ---- Create a new tasklist widget. The last two arguments (update_function --- and base_widget) serve to customize the layout of the tasklist (eg. to --- make it vertical). For that, you will need to copy the --- awful.widget.common.list_update function, make your changes to it --- and pass it as update_function here. Also change the base_widget if the --- default is not what you want. --- @param screen The screen to draw tasklist for. --- @param filter Filter function to define what clients will be listed. --- @param buttons A table with buttons binding to set. --- @tparam[opt={}] table style The style overrides default theme. --- @tparam[opt=nil] string|pattern style.fg_normal --- @tparam[opt=nil] string|pattern style.bg_normal --- @tparam[opt=nil] string|pattern style.fg_focus --- @tparam[opt=nil] string|pattern style.bg_focus --- @tparam[opt=nil] string|pattern style.fg_urgent --- @tparam[opt=nil] string|pattern style.bg_urgent --- @tparam[opt=nil] string|pattern style.fg_minimize --- @tparam[opt=nil] string|pattern style.bg_minimize --- @tparam[opt=nil] string style.bg_image_normal --- @tparam[opt=nil] string style.bg_image_focus --- @tparam[opt=nil] string style.bg_image_urgent --- @tparam[opt=nil] string style.bg_image_minimize --- @tparam[opt=nil] boolean style.tasklist_disable_icon --- @tparam[opt=nil] string style.font --- @tparam[opt=left] string style.align *left*, *right* or *center* --- @tparam[opt=nil] string style.font_focus --- @tparam[opt=nil] string style.font_minimized --- @tparam[opt=nil] string style.font_urgent --- @tparam[opt=nil] number style.spacing The spacing between tags. --- @tparam[opt=nil] gears.shape style.shape --- @tparam[opt=nil] number style.shape_border_width --- @tparam[opt=nil] string|color style.shape_border_color --- @tparam[opt=nil] gears.shape style.shape_focus --- @tparam[opt=nil] number style.shape_border_width_focus --- @tparam[opt=nil] string|color style.shape_border_color_focus --- @tparam[opt=nil] gears.shape style.shape_minimized --- @tparam[opt=nil] number style.shape_border_width_minimized --- @tparam[opt=nil] string|color style.shape_border_color_minimized --- @tparam[opt=nil] gears.shape style.shape_urgent --- @tparam[opt=nil] number style.shape_border_width_urgent --- @tparam[opt=nil] string|color style.shape_border_color_urgent --- @param[opt] update_function Function to create a tag widget on each --- update. See `awful.widget.common.list_update`. --- @tparam[opt] table base_widget Container widget for tag widgets. Default --- is `wibox.layout.flex.horizontal`. --- @function awful.tasklist -function tasklist.new(screen, filter, buttons, style, update_function, base_widget) - screen = get_screen(screen) - local uf = update_function or common.list_update - local w = base_widget or flex.horizontal() - - local data = setmetatable({}, { __mode = 'k' }) - - if w.set_spacing and (style and style.spacing or beautiful.taglist_spacing) then - w:set_spacing(style and style.spacing or beautiful.taglist_spacing) - end - - local queued_update = false - function w._do_tasklist_update() - -- Add a delayed callback for the first update. - if not queued_update then - timer.delayed_call(function() - queued_update = false - if screen.valid then - tasklist_update(screen, w, buttons, filter, data, style, uf) - end - end) - queued_update = true - end - end - function w._unmanage(c) - data[c] = nil - end - if instances == nil then - instances = setmetatable({}, { __mode = "k" }) - local function us(s) - local i = instances[get_screen(s)] - if i then - for _, tlist in pairs(i) do - tlist._do_tasklist_update() - end - end - end - local function u() - for s in pairs(instances) do - if s.valid then - us(s) - end - end - end - - tag.attached_connect_signal(nil, "property::selected", u) - tag.attached_connect_signal(nil, "property::activated", u) - capi.client.connect_signal("property::urgent", u) - capi.client.connect_signal("property::sticky", u) - capi.client.connect_signal("property::ontop", u) - capi.client.connect_signal("property::above", u) - capi.client.connect_signal("property::below", u) - capi.client.connect_signal("property::floating", u) - capi.client.connect_signal("property::maximized_horizontal", u) - capi.client.connect_signal("property::maximized_vertical", u) - capi.client.connect_signal("property::minimized", u) - capi.client.connect_signal("property::name", u) - capi.client.connect_signal("property::icon_name", u) - capi.client.connect_signal("property::icon", u) - capi.client.connect_signal("property::skip_taskbar", u) - capi.client.connect_signal("property::screen", function(c, old_screen) - us(c.screen) - us(old_screen) - end) - capi.client.connect_signal("property::hidden", u) - capi.client.connect_signal("tagged", u) - capi.client.connect_signal("untagged", u) - capi.client.connect_signal("unmanage", function(c) - u(c) - for _, i in pairs(instances) do - for _, tlist in pairs(i) do - tlist._unmanage(c) - end - end - end) - capi.client.connect_signal("list", u) - capi.client.connect_signal("focus", u) - capi.client.connect_signal("unfocus", u) - capi.screen.connect_signal("removed", function(s) - instances[get_screen(s)] = nil - end) - end - w._do_tasklist_update() - local list = instances[screen] - if not list then - list = setmetatable({}, { __mode = "v" }) - instances[screen] = list - end - table.insert(list, w) - return w -end - ---- Filtering function to include all clients. --- @return true -function tasklist.filter.allscreen() - return true -end - ---- Filtering function to include the clients from all tags on the screen. --- @param c The client. --- @param screen The screen we are drawing on. --- @return true if c is on screen, false otherwise -function tasklist.filter.alltags(c, screen) - -- Only print client on the same screen as this widget - return get_screen(c.screen) == get_screen(screen) -end - ---- Filtering function to include only the clients from currently selected tags. --- @param c The client. --- @param screen The screen we are drawing on. --- @return true if c is in a selected tag on screen, false otherwise -function tasklist.filter.currenttags(c, screen) - screen = get_screen(screen) - -- Only print client on the same screen as this widget - if get_screen(c.screen) ~= screen then return false end - -- Include sticky client too - if c.sticky then return true end - local tags = screen.tags - for _, t in ipairs(tags) do - if t.selected then - local ctags = c:tags() - for _, v in ipairs(ctags) do - if v == t then - return true - end - end - end - end - return false -end - ---- Filtering function to include only the minimized clients from currently selected tags. --- @param c The client. --- @param screen The screen we are drawing on. --- @return true if c is in a selected tag on screen and is minimized, false otherwise -function tasklist.filter.minimizedcurrenttags(c, screen) - screen = get_screen(screen) - -- Only print client on the same screen as this widget - if get_screen(c.screen) ~= screen then return false end - -- Check client is minimized - if not c.minimized then return false end - -- Include sticky client - if c.sticky then return true end - local tags = screen.tags - for _, t in ipairs(tags) do - -- Select only minimized clients - if t.selected then - local ctags = c:tags() - for _, v in ipairs(ctags) do - if v == t then - return true - end - end - end - end - return false -end - ---- Filtering function to include only the currently focused client. --- @param c The client. --- @param screen The screen we are drawing on. --- @return true if c is focused on screen, false otherwise -function tasklist.filter.focused(c, screen) - -- Only print client on the same screen as this widget - return get_screen(c.screen) == get_screen(screen) and capi.client.focus == c -end - -function tasklist.mt:__call(...) - return tasklist.new(...) -end - -return setmetatable(tasklist, tasklist.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/textclock.lua b/awesome/lib/awful/widget/textclock.lua deleted file mode 100644 index 002aa0e..0000000 --- a/awesome/lib/awful/widget/textclock.lua +++ /dev/null @@ -1,16 +0,0 @@ ---------------------------------------------------------------------------- --- This widget has moved to `wibox.widget.textclock` --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Julien Danjou --- @classmod awful.widget.textclock ---------------------------------------------------------------------------- -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.widget.textclock"), - "awful.widget.textclock", - "wibox.widget.textclock" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/awful/widget/watch.lua b/awesome/lib/awful/widget/watch.lua deleted file mode 100644 index bc4c9af..0000000 --- a/awesome/lib/awful/widget/watch.lua +++ /dev/null @@ -1,91 +0,0 @@ ---------------------------------------------------------------------------- ---- Watch widget. --- Here is an example of simple temperature widget which will update each 15 --- seconds implemented in two different ways. --- The first, simpler one, will just display the return command output --- (so output is stripped by shell commands). --- In the other example `sensors` returns to the widget its full output --- and it's trimmed in the widget callback function: --- --- 211 mytextclock, --- 212 wibox.widget.textbox(' | '), --- 213 -- one way to do that: --- 214 awful.widget.watch('bash -c "sensors | grep temp1"', 15), --- 215 -- another way: --- 216 awful.widget.watch('sensors', 15, function(widget, stdout) --- 217 for line in stdout:gmatch("[^\r\n]+") do --- 218 if line:match("temp1") then --- 219 widget:set_text(line) --- 220 return --- 221 end --- 222 end --- 223 end), --- 224 s.mylayoutbox, --- --- ![Example screenshot](../images/awful_widget_watch.png) --- --- @author Benjamin Petrenko --- @author Yauheni Kirylau --- @copyright 2015, 2016 Benjamin Petrenko, Yauheni Kirylau --- @classmod awful.widget.watch ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local textbox = require("wibox.widget.textbox") -local timer = require("gears.timer") -local spawn = require("awful.spawn") - -local watch = { mt = {} } - ---- Create a textbox that shows the output of a command --- and updates it at a given time interval. --- --- @tparam string|table command The command. --- --- @tparam[opt=5] integer timeout The time interval at which the textbox --- will be updated. --- --- @tparam[opt] function callback The function that will be called after --- the command output will be received. it is shown in the textbox. --- Defaults to: --- function(widget, stdout, stderr, exitreason, exitcode) --- widget:set_text(stdout) --- end --- @param callback.widget Base widget instance. --- @tparam string callback.stdout Output on stdout. --- @tparam string callback.stderr Output on stderr. --- @tparam string callback.exitreason Exit Reason. --- The reason can be "exit" or "signal". --- @tparam integer callback.exitcode Exit code. --- For "exit" reason it's the exit code. --- For "signal" reason — the signal causing process termination. --- --- @param[opt=wibox.widget.textbox()] base_widget Base widget. --- --- @return The widget used by this watch -function watch.new(command, timeout, callback, base_widget) - timeout = timeout or 5 - base_widget = base_widget or textbox() - callback = callback or function(widget, stdout, stderr, exitreason, exitcode) -- luacheck: no unused args - widget:set_text(stdout) - end - local t = timer { timeout = timeout } - t:connect_signal("timeout", function() - t:stop() - spawn.easy_async(command, function(stdout, stderr, exitreason, exitcode) - callback(base_widget, stdout, stderr, exitreason, exitcode) - t:again() - end) - end) - t:start() - t:emit_signal("timeout") - return base_widget -end - -function watch.mt.__call(_, ...) - return watch.new(...) -end - -return setmetatable(watch, watch.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/beautiful.lua b/awesome/lib/beautiful.lua deleted file mode 100644 index f6f0106..0000000 --- a/awesome/lib/beautiful.lua +++ /dev/null @@ -1,7 +0,0 @@ --- Work-around for broken systems which are updated by overwriting the awesome --- installation. This would not remove beautiful.lua from older awesome versions --- and thus breakage follows. --- The work-around is to use a pointless beautiful.lua file. -return require("beautiful.init") - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/beautiful/init.lua b/awesome/lib/beautiful/init.lua deleted file mode 100644 index 0e72cbc..0000000 --- a/awesome/lib/beautiful/init.lua +++ /dev/null @@ -1,217 +0,0 @@ ----------------------------------------------------------------------------- ---- Theme library. --- --- @author Damien Leone <damien.leone@gmail.com> --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008-2009 Damien Leone, Julien Danjou --- @module beautiful ----------------------------------------------------------------------------- - --- Grab environment -local os = os -local pairs = pairs -local type = type -local dofile = dofile -local setmetatable = setmetatable -local lgi = require("lgi") -local Pango = lgi.Pango -local PangoCairo = lgi.PangoCairo -local gears_debug = require("gears.debug") -local protected_call = require("gears.protected_call") - -local xresources = require("beautiful.xresources") - -local beautiful = { xresources = xresources, mt = {} } - --- Local data -local theme = {} -local descs = setmetatable({}, { __mode = 'k' }) -local fonts = setmetatable({}, { __mode = 'v' }) -local active_font - ---- The default font. --- @beautiful beautiful.font - --- The default background color. --- @beautiful beautiful.bg_normal - --- The default focused element background color. --- @beautiful beautiful.bg_focus - --- The default urgent element background color. --- @beautiful beautiful.bg_urgent - --- The default minimized element background color. --- @beautiful beautiful.bg_minimize - --- The system tray background color. --- Please note that only solid colors are currently supported. --- @beautiful beautiful.bg_systray - --- The default focused element foreground (text) color. --- @beautiful beautiful.fg_normal - --- The default focused element foreground (text) color. --- @beautiful beautiful.fg_focus - --- The default urgent element foreground (text) color. --- @beautiful beautiful.fg_urgent - --- The default minimized element foreground (text) color. --- @beautiful beautiful.fg_minimize - ---- The gap between clients. --- @beautiful beautiful.useless_gap --- @param[opt=0] number - ---- The client border width. --- @beautiful beautiful.border_width - ---- The default clients border width. --- Note that only solid colors are supported. --- @beautiful beautiful.border_normal - ---- The focused client border width. --- Note that only solid colors are supported. --- @beautiful beautiful.border_focus - ---- The marked clients border width. --- Note that only solid colors are supported. --- @beautiful beautiful.border_marked - ---- The wallpaper path. --- @beautiful beautiful.wallpaper - --- The icon theme name. --- It has to be a directory in `/usr/share/icons` or an XDG icon folder. --- @beautiful beautiful.icon_theme - ---- The Awesome icon path. --- @beautiful beautiful.awesome_icon - ---- Load a font from a string or a font description. --- --- @see https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string --- @tparam string|lgi.Pango.FontDescription name Font, which can be a --- string or a lgi.Pango.FontDescription. --- @treturn table A table with `name`, `description` and `height`. -local function load_font(name) - name = name or active_font - if name and type(name) ~= "string" then - if descs[name] then - name = descs[name] - else - name = name:to_string() - end - end - if fonts[name] then - return fonts[name] - end - - -- Load new font - local desc = Pango.FontDescription.from_string(name) - local ctx = PangoCairo.font_map_get_default():create_context() - ctx:set_resolution(beautiful.xresources.get_dpi()) - - -- Apply default values from the context (e.g. a default font size) - desc:merge(ctx:get_font_description(), false) - - -- Calculate font height. - local metrics = ctx:get_metrics(desc, nil) - local height = math.ceil((metrics:get_ascent() + metrics:get_descent()) / Pango.SCALE) - - local font = { name = name, description = desc, height = height } - fonts[name] = font - descs[desc] = name - return font -end - ---- Set an active font --- --- @param name The font -local function set_font(name) - active_font = load_font(name).name -end - ---- Get a font description. --- --- See https://developer.gnome.org/pango/stable/pango-Fonts.html#PangoFontDescription. --- @tparam string|lgi.Pango.FontDescription name The name of the font. --- @treturn lgi.Pango.FontDescription -function beautiful.get_font(name) - return load_font(name).description -end - ---- Get a new font with merged attributes, based on another one. --- --- See https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string. --- @tparam string|Pango.FontDescription name The base font. --- @tparam string merge Attributes that should be merged, e.g. "bold". --- @treturn lgi.Pango.FontDescription -function beautiful.get_merged_font(name, merge) - local font = beautiful.get_font(name) - merge = Pango.FontDescription.from_string(merge) - local merged = font:copy_static() - merged:merge(merge, true) - return beautiful.get_font(merged:to_string()) -end - ---- Get the height of a font. --- --- @param name Name of the font -function beautiful.get_font_height(name) - return load_font(name).height -end - ---- Init function, should be runned at the beginning of configuration file. --- @tparam string|table config The theme to load. It can be either the path to --- the theme file (returning a table) or directly the table --- containing all the theme values. -function beautiful.init(config) - if config then - local homedir = os.getenv("HOME") - - -- If `config` is the path to a theme file, run this file, - -- otherwise if it is a theme table, save it. - if type(config) == 'string' then - -- Expand the '~' $HOME shortcut - config = config:gsub("^~/", homedir .. "/") - theme = protected_call(dofile, config) - elseif type(config) == 'table' then - theme = config - end - - if theme then - -- expand '~' - if homedir then - for k, v in pairs(theme) do - if type(v) == "string" then theme[k] = v:gsub("^~/", homedir .. "/") end - end - end - - if theme.font then set_font(theme.font) end - else - return gears_debug.print_error("beautiful: error loading theme file " .. config) - end - else - return gears_debug.print_error("beautiful: error loading theme: no theme specified") - end -end - ---- Get the current theme. --- --- @treturn table The current theme table. -function beautiful.get() - return theme -end - -function beautiful.mt:__index(k) - return theme[k] -end - --- Set the default font -set_font("sans 8") - -return setmetatable(beautiful, beautiful.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/beautiful/xresources.lua b/awesome/lib/beautiful/xresources.lua deleted file mode 100644 index f0f5d78..0000000 --- a/awesome/lib/beautiful/xresources.lua +++ /dev/null @@ -1,117 +0,0 @@ ----------------------------------------------------------------------------- ---- Library for getting xrdb data. --- --- @author Yauhen Kirylau <yawghen@gmail.com> --- @copyright 2015 Yauhen Kirylau --- @module beautiful.xresources ----------------------------------------------------------------------------- - --- Grab environment -local awesome = awesome -local screen = screen -local round = require("awful.util").round -local gears_debug = require("gears.debug") - -local xresources = {} - -local fallback = { - --black - color0 = '#000000', - color8 = '#465457', - --red - color1 = '#cb1578', - color9 = '#dc5e86', - --green - color2 = '#8ecb15', - color10 = '#9edc60', - --yellow - color3 = '#cb9a15', - color11 = '#dcb65e', - --blue - color4 = '#6f15cb', - color12 = '#7e5edc', - --purple - color5 = '#cb15c9', - color13 = '#b75edc', - --cyan - color6 = '#15b4cb', - color14 = '#5edcb4', - --white - color7 = '#888a85', - color15 = '#ffffff', - -- - background = '#0e0021', - foreground = '#bcbcbc', -} - ---- Get current base colorscheme from xrdb. --- @treturn table Color table with keys 'background', 'foreground' and 'color0'..'color15' -function xresources.get_current_theme() - local keys = { 'background', 'foreground' } - for i=0,15 do table.insert(keys, "color"..i) end - local colors = {} - for _, key in ipairs(keys) do - colors[key] = awesome.xrdb_get_value("", key) - if not colors[key] then - gears_debug.print_warning("beautiful: can't get colorscheme from xrdb (using fallback).") - return fallback - end - if colors[key]:find("rgb:") then - colors[key] = "#"..colors[key]:gsub("[a]?rgb:", ""):gsub("/", "") - end - end - return colors -end - - -local dpi_per_screen = {} - -local function get_screen(s) - return s and screen[s] -end - ---- Get global or per-screen DPI value falling back to xrdb. --- @tparam[opt] integer|screen s The screen. --- @treturn number DPI value. -function xresources.get_dpi(s) - s = get_screen(s) - if dpi_per_screen[s] then - return dpi_per_screen[s] - end - if not xresources.dpi then - -- Might not be present when run under unit tests - if awesome and awesome.xrdb_get_value then - xresources.dpi = tonumber(awesome.xrdb_get_value("", "Xft.dpi")) - end - if not xresources.dpi then - xresources.dpi = 96 - end - end - return xresources.dpi -end - - ---- Set DPI for a given screen (defaults to global). --- @tparam number dpi DPI value. --- @tparam[opt] integer s Screen. -function xresources.set_dpi(dpi, s) - s = get_screen(s) - if not s then - xresources.dpi = dpi - else - dpi_per_screen[s] = dpi - end -end - - ---- Compute resulting size applying current DPI value (optionally per screen). --- @tparam number size Size --- @tparam[opt] integer|screen s The screen. --- @treturn integer Resulting size (rounded to integer). -function xresources.apply_dpi(size, s) - return round(size / 96 * xresources.get_dpi(s)) -end - -return xresources - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/cache.lua b/awesome/lib/gears/cache.lua deleted file mode 100644 index dc5add5..0000000 --- a/awesome/lib/gears/cache.lua +++ /dev/null @@ -1,51 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2015 Uli Schlachter --- @classmod gears.cache ---------------------------------------------------------------------------- - -local select = select -local setmetatable = setmetatable -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) - -local cache = {} - ---- Get an entry from the cache, creating it if it's missing. --- @param ... Arguments for the creation callback. These are checked against the --- cache contents for equality. --- @return The entry from the cache -function cache:get(...) - local result = self._cache - for i = 1, select("#", ...) do - local arg = select(i, ...) - local next = result[arg] - if not next then - next = {} - result[arg] = next - end - result = next - end - local ret = result._entry - if not ret then - ret = { self._creation_cb(...) } - result._entry = ret - end - return unpack(ret) -end - ---- Create a new cache object. A cache keeps some data that can be --- garbage-collected at any time, but might be useful to keep. --- @param creation_cb Callback that is used for creating missing cache entries. --- @return A new cache object. -function cache.new(creation_cb) - return setmetatable({ - _cache = setmetatable({}, { __mode = "v" }), - _creation_cb = creation_cb - }, { - __index = cache - }) -end - -return setmetatable(cache, { __call = function(_, ...) return cache.new(...) end }) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/color.lua b/awesome/lib/gears/color.lua deleted file mode 100644 index f0197c1..0000000 --- a/awesome/lib/gears/color.lua +++ /dev/null @@ -1,346 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @module gears.color ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local string = string -local table = table -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local tonumber = tonumber -local ipairs = ipairs -local pairs = pairs -local type = type -local lgi = require("lgi") -local cairo = lgi.cairo -local Pango = lgi.Pango -local surface = require("gears.surface") - -local color = { mt = {} } -local pattern_cache - ---- Create a pattern from a given string. --- This function can create solid, linear, radial and png patterns. In general, --- patterns are specified as strings formatted as "type:arguments". "arguments" --- is specific to the pattern being used. For example, one can use --- "radial:50,50,10:55,55,30:0,#ff0000:0.5,#00ff00:1,#0000ff". --- Alternatively, patterns can be specified via tables. In this case, the --- table's 'type' member specifies the type. For example: --- { --- type = "radial", --- from = { 50, 50, 10 }, --- to = { 55, 55, 30 }, --- stops = { { 0, "#ff0000" }, { 0.5, "#00ff00" }, { 1, "#0000ff" } } --- } --- Any argument that cannot be understood is passed to @{create_solid_pattern}. --- --- Please note that you MUST NOT modify the returned pattern, for example by --- calling :set_matrix() on it, because this function uses a cache and your --- changes could thus have unintended side effects. Use @{create_pattern_uncached} --- if you need to modify the returned pattern. --- @see create_pattern_uncached, create_solid_pattern, create_png_pattern, --- create_linear_pattern, create_radial_pattern --- @tparam string col The string describing the pattern. --- @return a cairo pattern object --- @function gears.color - ---- Parse a HTML-color. --- This function can parse colors like `#rrggbb` and `#rrggbbaa` and also `red`. --- Max 4 chars per channel. --- --- @param col The color to parse --- @treturn table 4 values representing color in RGBA format (each of them in --- [0, 1] range) or nil if input is incorrect. --- @usage -- This will return 0, 1, 0, 1 --- gears.color.parse_color("#00ff00ff") -function color.parse_color(col) - local rgb = {} - if string.match(col, "^#%x+$") then - local hex_str = col:sub(2, #col) - local channels - if #hex_str % 3 == 0 then - channels = 3 - elseif #hex_str % 4 == 0 then - channels = 4 - else - return nil - end - local chars_per_channel = #hex_str / channels - if chars_per_channel > 4 then - return nil - end - local dividor = (0x10 ^ chars_per_channel) - 1 - for idx=1,#hex_str,chars_per_channel do - local channel_val = tonumber(hex_str:sub(idx,idx+chars_per_channel-1), 16) - table.insert(rgb, channel_val / dividor) - end - if channels == 3 then - table.insert(rgb, 1) - end - else - local c = Pango.Color() - if not c:parse(col) then - return nil - end - rgb = { - c.red / 0xffff, - c.green / 0xffff, - c.blue / 0xffff, - 1.0 - } - end - assert(#rgb == 4, col) - return unpack(rgb) -end - ---- Find all numbers in a string --- --- @tparam string s The string to parse --- @return Each number found as a separate value -local function parse_numbers(s) - local res = {} - for k in string.gmatch(s, "-?[0-9]+[.]?[0-9]*") do - table.insert(res, tonumber(k)) - end - return unpack(res) -end - ---- Create a solid pattern --- --- @param col The color for the pattern --- @return A cairo pattern object -function color.create_solid_pattern(col) - if col == nil then - col = "#000000" - elseif type(col) == "table" then - col = col.color - end - return cairo.Pattern.create_rgba(color.parse_color(col)) -end - ---- Create an image pattern from a png file --- --- @param file The filename of the file --- @return a cairo pattern object -function color.create_png_pattern(file) - if type(file) == "table" then - file = file.file - end - local image = surface.load(file) - local pattern = cairo.Pattern.create_for_surface(image) - pattern:set_extend(cairo.Extend.REPEAT) - return pattern -end - ---- Add stops to the given pattern. --- @param p The cairo pattern to add stops to --- @param iterator An iterator that returns strings. Each of those strings --- should be in the form place,color where place is in [0, 1]. -local function add_iterator_stops(p, iterator) - for k in iterator do - local sub = string.gmatch(k, "[^,]+") - local point, clr = sub(), sub() - p:add_color_stop_rgba(point, color.parse_color(clr)) - end -end - ---- Add a list of stops to a given pattern -local function add_stops_table(pat, arg) - for _, stop in ipairs(arg) do - pat:add_color_stop_rgba(stop[1], color.parse_color(stop[2])) - end -end - ---- Create a pattern from a string -local function string_pattern(creator, arg) - local iterator = string.gmatch(arg, "[^:]+") - -- Create a table where each entry is a number from the original string - local args = { parse_numbers(iterator()) } - local to = { parse_numbers(iterator()) } - -- Now merge those two tables - for _, v in pairs(to) do - table.insert(args, v) - end - -- And call our creator function with the values - local p = creator(unpack(args)) - - add_iterator_stops(p, iterator) - return p -end - ---- Create a linear pattern object. --- The pattern is created from a string. This string should have the following --- form: `"x0, y0:x1, y1:<stops>"` --- Alternatively, the pattern can be specified as a table: --- { type = "linear", from = { x0, y0 }, to = { x1, y1 }, --- stops = { <stops> } } --- `x0,y0` and `x1,y1` are the start and stop point of the pattern. --- For the explanation of `<stops>`, see `color.create_pattern`. --- @tparam string|table arg The argument describing the pattern. --- @return a cairo pattern object -function color.create_linear_pattern(arg) - local pat - - if type(arg) == "string" then - return string_pattern(cairo.Pattern.create_linear, arg) - elseif type(arg) ~= "table" then - error("Wrong argument type: " .. type(arg)) - end - - pat = cairo.Pattern.create_linear(arg.from[1], arg.from[2], arg.to[1], arg.to[2]) - add_stops_table(pat, arg.stops) - return pat -end - ---- Create a radial pattern object. --- The pattern is created from a string. This string should have the following --- form: `"x0, y0, r0:x1, y1, r1:<stops>"` --- Alternatively, the pattern can be specified as a table: --- { type = "radial", from = { x0, y0, r0 }, to = { x1, y1, r1 }, --- stops = { <stops> } } --- `x0,y0` and `x1,y1` are the start and stop point of the pattern. --- `r0` and `r1` are the radii of the start / stop circle. --- For the explanation of `<stops>`, see `color.create_pattern`. --- @tparam string|table arg The argument describing the pattern --- @return a cairo pattern object -function color.create_radial_pattern(arg) - local pat - - if type(arg) == "string" then - return string_pattern(cairo.Pattern.create_radial, arg) - elseif type(arg) ~= "table" then - error("Wrong argument type: " .. type(arg)) - end - - pat = cairo.Pattern.create_radial(arg.from[1], arg.from[2], arg.from[3], - arg.to[1], arg.to[2], arg.to[3]) - add_stops_table(pat, arg.stops) - return pat -end - ---- Mapping of all supported color types. New entries can be added. -color.types = { - solid = color.create_solid_pattern, - png = color.create_png_pattern, - linear = color.create_linear_pattern, - radial = color.create_radial_pattern -} - ---- Create a pattern from a given string. --- For full documentation of this function, please refer to --- `color.create_pattern`. The difference between `color.create_pattern` --- and this function is that this function does not insert the generated --- objects into the pattern cache. Thus, you are allowed to modify the --- returned object. --- @see create_pattern --- @param col The string describing the pattern. --- @return a cairo pattern object -function color.create_pattern_uncached(col) - -- If it already is a cairo pattern, just leave it as that - if cairo.Pattern:is_type_of(col) then - return col - end - col = col or "#000000" - if type(col) == "string" then - local t = string.match(col, "[^:]+") - if color.types[t] then - local pos = string.len(t) - local arg = string.sub(col, pos + 2) - return color.types[t](arg) - end - elseif type(col) == "table" then - local t = col.type - if color.types[t] then - return color.types[t](col) - end - end - return color.create_solid_pattern(col) -end - ---- Create a pattern from a given string, same as `gears.color`. --- @see gears.color -function color.create_pattern(col) - if cairo.Pattern:is_type_of(col) then - return col - end - return pattern_cache:get(col or "#000000") -end - ---- Check if a pattern is opaque. --- A pattern is transparent if the background on which it gets drawn (with --- operator OVER) doesn't influence the visual result. --- @param col An argument that `create_pattern` accepts. --- @return The pattern if it is surely opaque, else nil -function color.create_opaque_pattern(col) - local pattern = color.create_pattern(col) - local kind = pattern:get_type() - - if kind == "SOLID" then - local _, _, _, _, alpha = pattern:get_rgba() - if alpha ~= 1 then - return - end - return pattern - elseif kind == "SURFACE" then - local status, surf = pattern:get_surface() - if status ~= "SUCCESS" or surf.content ~= "COLOR" then - -- The surface has an alpha channel which *might* be non-opaque - return - end - - -- Only the "NONE" extend mode is forbidden, everything else doesn't - -- introduce transparent parts - if pattern:get_extend() == "NONE" then - return - end - - return pattern - elseif kind == "LINEAR" then - local _, stops = pattern:get_color_stop_count() - - -- No color stops or extend NONE -> pattern *might* contain transparency - if stops == 0 or pattern:get_extend() == "NONE" then - return - end - - -- Now check if any of the color stops contain transparency - for i = 0, stops - 1 do - local _, _, _, _, _, alpha = pattern:get_color_stop_rgba(i) - if alpha ~= 1 then - return - end - end - return pattern - end - - -- Unknown type, e.g. mesh or raster source or unsupported type (radial - -- gradients can do weird self-intersections) -end - ---- Fill non-transparent area of an image with a given color. --- @param image Image or path to it. --- @param new_color New color. --- @return Recolored image. -function color.recolor_image(image, new_color) - if type(image) == 'string' then - image = surface.duplicate_surface(image) - end - local cr = cairo.Context.create(image) - cr:set_source(color.create_pattern(new_color)) - cr:mask(cairo.Pattern.create_for_surface(image), 0, 0) - return image -end - -function color.mt.__call(_, ...) - return color.create_pattern(...) -end - -pattern_cache = require("gears.cache").new(color.create_pattern_uncached) - ---- No color -color.transparent = color.create_pattern("#00000000") - -return setmetatable(color, color.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/debug.lua b/awesome/lib/gears/debug.lua deleted file mode 100644 index 55f72f5..0000000 --- a/awesome/lib/gears/debug.lua +++ /dev/null @@ -1,78 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @module gears.debug ---------------------------------------------------------------------------- - -local tostring = tostring -local print = print -local type = type -local pairs = pairs - -local debug = {} - ---- Given a table (or any other data) return a string that contains its --- tag, value and type. If data is a table then recursively call `dump_raw` --- on each of its values. --- @param data Value to inspect. --- @param shift Spaces to indent lines with. --- @param tag The name of the value. --- @tparam[opt=10] int depth Depth of recursion. --- @return a string which contains tag, value, value type and table key/value --- pairs if data is a table. -local function dump_raw(data, shift, tag, depth) - depth = depth == nil and 10 or depth or 0 - local result = "" - - if tag then - result = result .. tostring(tag) .. " : " - end - - if type(data) == "table" and depth > 0 then - shift = (shift or "") .. " " - result = result .. tostring(data) - for k, v in pairs(data) do - result = result .. "\n" .. shift .. dump_raw(v, shift, k, depth - 1) - end - else - result = result .. tostring(data) .. " (" .. type(data) .. ")" - if depth == 0 and type(data) == "table" then - result = result .. " […]" - end - end - - return result -end - ---- Inspect the value in data. --- @param data Value to inspect. --- @param tag The name of the value. --- @tparam[opt] int depth Depth of recursion. --- @return string A string that contains the expanded value of data. -function debug.dump_return(data, tag, depth) - return dump_raw(data, nil, tag, depth) -end - ---- Print the table (or any other value) to the console. --- @param data Table to print. --- @param tag The name of the table. --- @tparam[opt] int depth Depth of recursion. -function debug.dump(data, tag, depth) - print(debug.dump_return(data, tag, depth)) -end - ---- Print an warning message --- @tparam string message The warning message to print -function debug.print_warning(message) - io.stderr:write(os.date("%Y-%m-%d %T W: ") .. tostring(message) .. "\n") -end - ---- Print an error message --- @tparam string message The error message to print -function debug.print_error(message) - io.stderr:write(os.date("%Y-%m-%d %T E: ") .. tostring(message) .. "\n") -end - -return debug - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/geometry.lua b/awesome/lib/gears/geometry.lua deleted file mode 100644 index a429abd..0000000 --- a/awesome/lib/gears/geometry.lua +++ /dev/null @@ -1,240 +0,0 @@ ---------------------------------------------------------------------------- --- --- Helper functions used to compute geometries. --- --- When this module refer to a geometry table, this assume a table with at least --- an *x*, *y*, *width* and *height* keys and numeric values. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2008 Julien Danjou --- @module gears.geometry ---------------------------------------------------------------------------- -local math = math - -local gears = {geometry = {rectangle = {} } } - ---- Get the square distance between a rectangle and a point. --- @tparam table geom A rectangle --- @tparam number geom.x The horizontal coordinate --- @tparam number geom.y The vertical coordinate --- @tparam number geom.width The rectangle width --- @tparam number geom.height The rectangle height --- @tparam number x X coordinate of point --- @tparam number y Y coordinate of point --- @treturn number The squared distance of the rectangle to the provided point -function gears.geometry.rectangle.get_square_distance(geom, x, y) - local dist_x, dist_y = 0, 0 - if x < geom.x then - dist_x = geom.x - x - elseif x >= geom.x + geom.width then - dist_x = x - geom.x - geom.width + 1 - end - if y < geom.y then - dist_y = geom.y - y - elseif y >= geom.y + geom.height then - dist_y = y - geom.y - geom.height + 1 - end - return dist_x * dist_x + dist_y * dist_y -end - ---- Return the closest rectangle from `list` for a given point. --- @tparam table list A list of geometry tables. --- @tparam number x The x coordinate --- @tparam number y The y coordinate --- @return The key from the closest geometry. -function gears.geometry.rectangle.get_closest_by_coord(list, x, y) - local dist = math.huge - local ret = nil - - for k, v in pairs(list) do - local d = gears.geometry.rectangle.get_square_distance(v, x, y) - if d < dist then - ret, dist = k, d - end - end - - return ret -end - ---- Return the rectangle containing the [x, y] point. --- --- Note that if multiple element from the geometry list contains the point, the --- returned result is nondeterministic. --- --- @tparam table list A list of geometry tables. --- @tparam number x The x coordinate --- @tparam number y The y coordinate --- @return The key from the closest geometry. In case no result is found, *nil* --- is returned. -function gears.geometry.rectangle.get_by_coord(list, x, y) - for k, geometry in pairs(list) do - if x >= geometry.x and x < geometry.x + geometry.width - and y >= geometry.y and y < geometry.y + geometry.height then - return k - end - end -end - ---- Return true whether rectangle B is in the right direction --- compared to rectangle A. --- @param dir The direction. --- @param gA The geometric specification for rectangle A. --- @param gB The geometric specification for rectangle B. --- @return True if B is in the direction of A. -local function is_in_direction(dir, gA, gB) - if dir == "up" then - return gA.y > gB.y - elseif dir == "down" then - return gA.y < gB.y - elseif dir == "left" then - return gA.x > gB.x - elseif dir == "right" then - return gA.x < gB.x - end - return false -end - ---- Calculate distance between two points. --- i.e: if we want to move to the right, we will take the right border --- of the currently focused screen and the left side of the checked screen. --- @param dir The direction. --- @param _gA The first rectangle. --- @param _gB The second rectangle. --- @return The distance between the screens. -local function calculate_distance(dir, _gA, _gB) - local gAx = _gA.x - local gAy = _gA.y - local gBx = _gB.x - local gBy = _gB.y - - if dir == "up" then - gBy = _gB.y + _gB.height - elseif dir == "down" then - gAy = _gA.y + _gA.height - elseif dir == "left" then - gBx = _gB.x + _gB.width - elseif dir == "right" then - gAx = _gA.x + _gA.width - end - - return math.sqrt(math.pow(gBx - gAx, 2) + math.pow(gBy - gAy, 2)) -end - ---- Get the nearest rectangle in the given direction. Every rectangle is specified as a table --- with *x*, *y*, *width*, *height* keys, the same as client or screen geometries. --- @tparam string dir The direction, can be either *up*, *down*, *left* or *right*. --- @tparam table recttbl A table of rectangle specifications. --- @tparam table cur The current rectangle. --- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found. -function gears.geometry.rectangle.get_in_direction(dir, recttbl, cur) - local dist, dist_min - local target = nil - - -- We check each object - for i, rect in pairs(recttbl) do - -- Check geometry to see if object is located in the right direction. - if is_in_direction(dir, cur, rect) then - -- Calculate distance between current and checked object. - dist = calculate_distance(dir, cur, rect) - - -- If distance is shorter then keep the object. - if not target or dist < dist_min then - target = i - dist_min = dist - end - end - end - return target -end - ---- Check if an area intersect another area. --- @param a The area. --- @param b The other area. --- @return True if they intersect, false otherwise. -local function area_intersect_area(a, b) - return (b.x < a.x + a.width - and b.x + b.width > a.x - and b.y < a.y + a.height - and b.y + b.height > a.y) -end - ---- Get the intersect area between a and b. --- @tparam table a The area. --- @tparam number a.x The horizontal coordinate --- @tparam number a.y The vertical coordinate --- @tparam number a.width The rectangle width --- @tparam number a.height The rectangle height --- @tparam table b The other area. --- @tparam number b.x The horizontal coordinate --- @tparam number b.y The vertical coordinate --- @tparam number b.width The rectangle width --- @tparam number b.height The rectangle height --- @treturn table The intersect area. -function gears.geometry.rectangle.get_intersection(a, b) - local g = {} - g.x = math.max(a.x, b.x) - g.y = math.max(a.y, b.y) - g.width = math.min(a.x + a.width, b.x + b.width) - g.x - g.height = math.min(a.y + a.height, b.y + b.height) - g.y - return g -end - ---- Remove an area from a list, splitting the space between several area that --- can overlap. --- @tparam table areas Table of areas. --- @tparam table elem Area to remove. --- @tparam number elem.x The horizontal coordinate --- @tparam number elem.y The vertical coordinate --- @tparam number elem.width The rectangle width --- @tparam number elem.height The rectangle height --- @return The new area list. -function gears.geometry.rectangle.area_remove(areas, elem) - for i = #areas, 1, -1 do - -- Check if the 'elem' intersect - if area_intersect_area(areas[i], elem) then - -- It does? remove it - local r = table.remove(areas, i) - local inter = gears.geometry.rectangle.get_intersection(r, elem) - - if inter.x > r.x then - table.insert(areas, { - x = r.x, - y = r.y, - width = inter.x - r.x, - height = r.height - }) - end - - if inter.y > r.y then - table.insert(areas, { - x = r.x, - y = r.y, - width = r.width, - height = inter.y - r.y - }) - end - - if inter.x + inter.width < r.x + r.width then - table.insert(areas, { - x = inter.x + inter.width, - y = r.y, - width = (r.x + r.width) - (inter.x + inter.width), - height = r.height - }) - end - - if inter.y + inter.height < r.y + r.height then - table.insert(areas, { - x = r.x, - y = inter.y + inter.height, - width = r.width, - height = (r.y + r.height) - (inter.y + inter.height) - }) - end - end - end - - return areas -end - -return gears.geometry diff --git a/awesome/lib/gears/init.lua b/awesome/lib/gears/init.lua deleted file mode 100644 index eae92ee..0000000 --- a/awesome/lib/gears/init.lua +++ /dev/null @@ -1,23 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @module gears ---------------------------------------------------------------------------- - - -return -{ - color = require("gears.color"); - debug = require("gears.debug"); - object = require("gears.object"); - surface = require("gears.surface"); - wallpaper = require("gears.wallpaper"); - timer = require("gears.timer"); - cache = require("gears.cache"); - matrix = require("gears.matrix"); - shape = require("gears.shape"); - protected_call = require("gears.protected_call"); - geometry = require("gears.geometry"); -} - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/matrix.lua b/awesome/lib/gears/matrix.lua deleted file mode 100644 index a6bc975..0000000 --- a/awesome/lib/gears/matrix.lua +++ /dev/null @@ -1,219 +0,0 @@ ---------------------------------------------------------------------------- --- An implementation of matrices for describing and working with affine --- transformations. --- @author Uli Schlachter --- @copyright 2015 Uli Schlachter --- @classmod gears.matrix ---------------------------------------------------------------------------- - -local cairo = require("lgi").cairo -local matrix = {} - --- Metatable for matrix instances. This is set up near the end of the file. -local matrix_mt = {} - ---- Create a new matrix instance --- @tparam number xx The xx transformation part. --- @tparam number yx The yx transformation part. --- @tparam number xy The xy transformation part. --- @tparam number yy The yy transformation part. --- @tparam number x0 The x0 transformation part. --- @tparam number y0 The y0 transformation part. --- @return A new matrix describing the given transformation. -function matrix.create(xx, yx, xy, yy, x0, y0) - return setmetatable({ - xx = xx, xy = xy, x0 = x0, - yx = yx, yy = yy, y0 = y0 - }, matrix_mt) -end - ---- Create a new translation matrix --- @tparam number x The translation in x direction. --- @tparam number y The translation in y direction. --- @return A new matrix describing the given transformation. -function matrix.create_translate(x, y) - return matrix.create(1, 0, 0, 1, x, y) -end - ---- Create a new scaling matrix --- @tparam number sx The scaling in x direction. --- @tparam number sy The scaling in y direction. --- @return A new matrix describing the given transformation. -function matrix.create_scale(sx, sy) - return matrix.create(sx, 0, 0, sy, 0, 0) -end - ---- Create a new rotation matrix --- @tparam number angle The angle of the rotation in radians. --- @return A new matrix describing the given transformation. -function matrix.create_rotate(angle) - local c, s = math.cos(angle), math.sin(angle) - return matrix.create(c, s, -s, c, 0, 0) -end - ---- Create a new rotation matrix rotating around a custom point --- @tparam number x The horizontal rotation point --- @tparam number y The vertical rotation point --- @tparam number angle The angle of the rotation in radians. --- @return A new matrix describing the given transformation. -function matrix.create_rotate_at(x, y, angle) - return matrix.create_translate( -x, -y ) - * matrix.create_rotate ( angle ) - * matrix.create_translate( x, y ) -end - ---- Translate this matrix --- @tparam number x The translation in x direction. --- @tparam number y The translation in y direction. --- @return A new matrix describing the new transformation. -function matrix:translate(x, y) - return matrix.create_translate(x, y):multiply(self) -end - ---- Scale this matrix --- @tparam number sx The scaling in x direction. --- @tparam number sy The scaling in y direction. --- @return A new matrix describing the new transformation. -function matrix:scale(sx, sy) - return matrix.create_scale(sx, sy):multiply(self) -end - ---- Rotate this matrix --- @tparam number angle The angle of the rotation in radians. --- @return A new matrix describing the new transformation. -function matrix:rotate(angle) - return matrix.create_rotate(angle):multiply(self) -end - ---- Rotate a shape from a custom point --- @tparam number x The horizontal rotation point --- @tparam number y The vertical rotation point --- @tparam number angle The angle (in radiant: -2*math.pi to 2*math.pi) --- @return A transformation object -function matrix:rotate_at(x, y, angle) - return self * matrix.create_rotate_at(x, y, angle) -end - ---- Invert this matrix --- @return A new matrix describing the inverse transformation. -function matrix:invert() - -- Beware of math! (I just copied the algorithm from cairo's source code) - local a, b, c, d, x0, y0 = self.xx, self.yx, self.xy, self.yy, self.x0, self.y0 - local inv_det = 1/(a*d - b*c) - return matrix.create(inv_det * d, inv_det * -b, - inv_det * -c, inv_det * a, - inv_det * (c * y0 - d * x0), inv_det * (b * x0 - a * y0)) -end - ---- Multiply this matrix with another matrix. --- The resulting matrix describes a transformation that is equivalent to first --- applying this transformation and then the transformation from `other`. --- Note that this function can also be called by directly multiplicating two --- matrix instances: `a * b == a:multiply(b)`. --- @tparam gears.matrix|cairo.Matrix other The other matrix to multiply with. --- @return The multiplication result. -function matrix:multiply(other) - local ret = matrix.create(self.xx * other.xx + self.yx * other.xy, - self.xx * other.yx + self.yx * other.yy, - self.xy * other.xx + self.yy * other.xy, - self.xy * other.yx + self.yy * other.yy, - self.x0 * other.xx + self.y0 * other.xy + other.x0, - self.x0 * other.yx + self.y0 * other.yy + other.y0) - - return ret -end - ---- Check if two matrices are equal. --- Note that this function cal also be called by directly comparing two matrix --- instances: `a == b`. --- @tparam gears.matrix|cairo.Matrix other The matrix to compare with. --- @return True if this and the other matrix are equal. -function matrix:equals(other) - for _, k in pairs{ "xx", "xy", "yx", "yy", "x0", "y0" } do - if self[k] ~= other[k] then - return false - end - end - return true -end - ---- Get a string representation of this matrix --- @return A string showing this matrix in column form. -function matrix:tostring() - return string.format("[[%g, %g], [%g, %g], [%g, %g]]", - self.xx, self.yx, self.xy, - self.yy, self.x0, self.y0) -end - ---- Transform a distance by this matrix. --- The difference to @{matrix:transform_point} is that the translation part of --- this matrix is ignored. --- @tparam number x The x coordinate of the point. --- @tparam number y The y coordinate of the point. --- @treturn number The x coordinate of the transformed point. --- @treturn number The x coordinate of the transformed point. -function matrix:transform_distance(x, y) - return self.xx * x + self.xy * y, self.yx * x + self.yy * y -end - ---- Transform a point by this matrix. --- @tparam number x The x coordinate of the point. --- @tparam number y The y coordinate of the point. --- @treturn number The x coordinate of the transformed point. --- @treturn number The y coordinate of the transformed point. -function matrix:transform_point(x, y) - x, y = self:transform_distance(x, y) - return self.x0 + x, self.y0 + y -end - ---- Calculate a bounding rectangle for transforming a rectangle by a matrix. --- @tparam number x The x coordinate of the rectangle. --- @tparam number y The y coordinate of the rectangle. --- @tparam number width The width of the rectangle. --- @tparam number height The height of the rectangle. --- @treturn number X coordinate of the bounding rectangle. --- @treturn number Y coordinate of the bounding rectangle. --- @treturn number Width of the bounding rectangle. --- @treturn number Height of the bounding rectangle. -function matrix:transform_rectangle(x, y, width, height) - -- Transform all four corners of the rectangle - local x1, y1 = self:transform_point(x, y) - local x2, y2 = self:transform_point(x, y + height) - local x3, y3 = self:transform_point(x + width, y + height) - local x4, y4 = self:transform_point(x + width, y) - -- Find the extremal points of the result - x = math.min(x1, x2, x3, x4) - y = math.min(y1, y2, y3, y4) - width = math.max(x1, x2, x3, x4) - x - height = math.max(y1, y2, y3, y4) - y - - return x, y, width, height -end - ---- Convert to a cairo matrix --- @treturn cairo.Matrix A cairo matrix describing the same transformation. -function matrix:to_cairo_matrix() - local ret = cairo.Matrix() - ret:init(self.xx, self.yx, self.xy, self.yy, self.x0, self.y0) - return ret -end - ---- Convert to a cairo matrix --- @tparam cairo.Matrix mat A cairo matrix describing the sought transformation --- @treturn gears.matrix A matrix instance describing the same transformation. -function matrix.from_cairo_matrix(mat) - return matrix.create(mat.xx, mat.yx, mat.xy, mat.yy, mat.x0, mat.y0) -end - -matrix_mt.__index = matrix -matrix_mt.__newindex = error -matrix_mt.__eq = matrix.equals -matrix_mt.__mul = matrix.multiply -matrix_mt.__tostring = matrix.tostring - ---- A constant for the identity matrix. -matrix.identity = matrix.create(1, 0, 0, 1, 0, 0) - -return matrix - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/object.lua b/awesome/lib/gears/object.lua deleted file mode 100644 index e6436e3..0000000 --- a/awesome/lib/gears/object.lua +++ /dev/null @@ -1,285 +0,0 @@ ---------------------------------------------------------------------------- --- The object oriented programming base class used by various Awesome --- widgets and components. --- --- It provide basic observer pattern, signaling and dynamic properties. --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod gears.object ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local pairs = pairs -local type = type -local error = error -local properties = require("gears.object.properties") - -local object = { properties = properties, mt = {} } - ---- Verify that obj is indeed a valid object as returned by new() -local function check(obj) - if type(obj) ~= "table" or type(obj._signals) ~= "table" then - error("called on non-object") - end -end - ---- Find a given signal --- @tparam table obj The object to search in --- @tparam string name The signal to find --- @treturn table The signal table -local function find_signal(obj, name) - check(obj) - if not obj._signals[name] then - assert(type(name) == "string", "name must be a string, got: " .. type(name)) - obj._signals[name] = { - strong = {}, - weak = setmetatable({}, { __mode = "kv" }) - } - end - return obj._signals[name] -end - -function object.add_signal() - require("awful.util").deprecate("Use signals without explicitly adding them. This is now done implicitly.") -end - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted -function object:connect_signal(name, func) - assert(type(func) == "function", "callback must be a function, got: " .. type(func)) - local sig = find_signal(self, name) - assert(sig.weak[func] == nil, "Trying to connect a strong callback which is already connected weakly") - sig.strong[func] = true -end - -local function make_the_gc_obey(func) - if _VERSION <= "Lua 5.1" then - -- Lua 5.1 only has the behaviour we want if a userdata is used as the - -- value in a weak table. Thus, do some magic so that we get a userdata. - - -- luacheck: globals newproxy getfenv setfenv - local userdata = newproxy(true) - getmetatable(userdata).__gc = function() end - -- Now bind the lifetime of userdata to the lifetime of func. For this, - -- we mess with the function's environment and add a table for all the - -- various userdata that it should keep alive. - local key = "_secret_key_used_by_gears_object_in_Lua51" - local old_env = getfenv(func) - if old_env[key] then - -- Assume the code in the else branch added this and the function - -- already has its own, private environment - table.insert(old_env[key], userdata) - else - -- No table yet, add it - local new_env = { [key] = { userdata } } - setmetatable(new_env, { __index = old_env, __newindex = old_env }) - setfenv(func, new_env) - end - assert(_G[key] == nil, "Something broke, things escaped to _G") - return userdata - end - -- Lua 5.2+ already behaves the way we want with functions directly, no magic - return func -end - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted -function object:weak_connect_signal(name, func) - assert(type(func) == "function", "callback must be a function, got: " .. type(func)) - local sig = find_signal(self, name) - assert(sig.strong[func] == nil, "Trying to connect a weak callback which is already connected strongly") - sig.weak[func] = make_the_gc_obey(func) -end - ---- Disonnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected -function object:disconnect_signal(name, func) - local sig = find_signal(self, name) - sig.weak[func] = nil - sig.strong[func] = nil -end - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() -function object:emit_signal(name, ...) - local sig = find_signal(self, name) - for func in pairs(sig.strong) do - func(self, ...) - end - for func in pairs(sig.weak) do - func(self, ...) - end -end - -local function get_miss(self, key) - local class = rawget(self, "_class") - - if rawget(self, "get_"..key) then - return rawget(self, "get_"..key)(self) - elseif class and class["get_"..key] then - return class["get_"..key](self) - elseif class then - return class[key] - end - -end - -local function set_miss(self, key, value) - local class = rawget(self, "_class") - - if rawget(self, "set_"..key) then - return rawget(self, "set_"..key)(self, value) - elseif class and class["set_"..key] then - return class["set_"..key](self, value) - elseif rawget(self, "_enable_auto_signals") then - local changed = class[key] ~= value - class[key] = value - - if changed then - self:emit_signal("property::"..key, value) - end - elseif (not rawget(self, "get_"..key)) - and not (class and class["get_"..key]) then - return rawset(self, key, value) - else - error("Cannot set '" .. tostring(key) .. "' on " .. tostring(self) - .. " because it is read-only") - end -end - ---- Returns a new object. You can call `:emit_signal()`, `:disconnect_signal()` --- and `:connect_signal()` on the resulting object. --- --- Note that `args.enable_auto_signals` is only supported when --- `args.enable_properties` is true. --- --- --- --- ---**Usage example output**: --- --- In get foo bar --- bar --- In set foo 42 --- In get foo 42 --- 42 --- In a mathod 1 2 3 --- nil --- In the connection handler! a cow --- a cow --- --- --- @usage --- -- Create a class for this object. It will be used as a backup source for --- -- methods and accessors. It is also possible to set them directly on the --- -- object. ---local class = {} ---function class:get_foo() --- print('In get foo', self._foo or 'bar') --- return self._foo or 'bar' ---end ---function class:set_foo(value) --- print('In set foo', value) --- -- In case it is necessary to bypass the object property system, use --- -- `rawset` --- rawset(self, '_foo', value) --- -- When using custom accessors, the signals need to be handled manually --- self:emit_signal('property::foo', value) ---end ---function class:method(a, b, c) --- print('In a mathod', a, b, c) ---end ---local o = gears.object { --- class = class, --- enable_properties = true, --- enable_auto_signals = true, ---} ---print(o.foo) ---o.foo = 42 ---print(o.foo) ---o:method(1, 2, 3) --- -- Random properties can also be added, the signal will be emitted automatically. ---o:connect_signal('property::something', function(obj, value) --- assert(obj == o) --- print('In the connection handler!', value) ---end) ---print(o.something) ---o.something = 'a cow' ---print(o.something) --- @tparam[opt={}] table args The arguments --- @tparam[opt=false] boolean args.enable_properties Automatically call getters and setters --- @tparam[opt=false] boolean args.enable_auto_signals Generate "property::xxxx" signals --- when an unknown property is set. --- @tparam[opt=nil] table args.class --- @treturn table A new object --- @function gears.object -local function new(args) - args = args or {} - local ret = {} - - -- Automatic signals cannot work without both miss handlers. - assert(not (args.enable_auto_signals and args.enable_properties ~= true)) - - -- Copy all our global functions to our new object - for k, v in pairs(object) do - if type(v) == "function" then - ret[k] = v - end - end - - ret._signals = {} - - local mt = {} - - -- Look for methods in another table - ret._class = args.class - ret._enable_auto_signals = args.enable_auto_signals - - -- To catch all changes, a proxy is required - if args.enable_auto_signals then - ret._class = ret._class and setmetatable({}, {__index = args.class}) or {} - end - - if args.enable_properties then - -- Check got existing get_xxxx and set_xxxx - mt.__index = get_miss - mt.__newindex = set_miss - elseif args.class then - -- Use the class table a miss handler - mt.__index = ret._class - end - - return setmetatable(ret, mt) -end - -function object.mt.__call(_, ...) - return new(...) -end - ---- Helper function to get the module name out of `debug.getinfo`. --- @usage --- local mt = {} --- mt.__tostring = function(o) --- return require("gears.object").modulename(2) --- end --- return setmetatable(ret, mt) --- --- @tparam[opt=2] integer level Level for `debug.getinfo(level, "S")`. --- Typically 2 or 3. --- @treturn string The module name, e.g. "wibox.container.background". -function object.modulename(level) - return debug.getinfo(level, "S").source:gsub(".*/lib/", ""):gsub("/", "."):gsub("%.lua", "") -end - -return setmetatable(object, object.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/object/properties.lua b/awesome/lib/gears/object/properties.lua deleted file mode 100644 index 36b8fcb..0000000 --- a/awesome/lib/gears/object/properties.lua +++ /dev/null @@ -1,88 +0,0 @@ ---------------------------------------------------------------------------- ---- An helper module to map userdata __index and __newindex entries to --- lua classes. --- --- @author Emmanuel Lepage-Vallee <elv1313@gmail.com> --- @copyright 2016 Emmanuel Lepage-Vallee --- @module gears.object.properties ---------------------------------------------------------------------------- - -local object = {} - - ---- Add the missing properties handler to a CAPI object such as client/tag/screen. --- Valid args: --- --- * **getter**: A smart getter (handle property getter itself) --- * **getter_fallback**: A dumb getter method (don't handle individual property getter) --- * **getter_class**: A module with individual property getter/setter --- * **getter_prefix**: A special getter prefix (like "get" or "get_" (default)) --- * **setter**: A smart setter (handle property setter itself) --- * **setter_fallback**: A dumb setter method (don't handle individual property setter) --- * **setter_class**: A module with individual property getter/setter --- * **setter_prefix**: A special setter prefix (like "set" or "set_" (default)) --- * **auto_emit**: Emit "property::___" automatically (default: false). This is --- ignored when setter_fallback is set or a setter is found --- --- @param class A standard luaobject derived object --- @tparam[opt={}] table args A set of accessors configuration parameters -function object.capi_index_fallback(class, args) - args = args or {} - - local getter_prefix = args.getter_prefix or "get_" - local setter_prefix = args.setter_prefix or "set_" - - local getter = args.getter or function(cobj, prop) - -- Look for a getter method - if args.getter_class and args.getter_class[getter_prefix..prop] then - return args.getter_class[getter_prefix..prop](cobj) - elseif args.getter_class and args.getter_class["is_"..prop] then - return args.getter_class["is_"..prop](cobj) - end - - -- Make sure something like c:a_mutator() works - if args.getter_class and args.getter_class[prop] then - return args.getter_class[prop] - end - -- In case there is already a "dumb" getter like `awful.tag.getproperty' - if args.getter_fallback then - return args.getter_fallback(cobj, prop) - end - - -- Use the fallback property table - return cobj.data[prop] - end - - local setter = args.setter or function(cobj, prop, value) - -- Look for a setter method - if args.setter_class and args.setter_class[setter_prefix..prop] then - return args.setter_class[setter_prefix..prop](cobj, value) - end - - -- In case there is already a "dumb" setter like `awful.client.property.set' - if args.setter_fallback then - return args.setter_fallback(cobj, prop, value) - end - - -- If a getter exists but not a setter, then the property is read-only - if args.getter_class and args.getter_class[getter_prefix..prop] then - return - end - - -- Use the fallback property table - cobj.data[prop] = value - - -- Emit the signal - if args.auto_emit then - cobj:emit_signal("property::"..prop, value) - end - end - - -- Attach the accessor methods - class.set_index_miss_handler(getter) - class.set_newindex_miss_handler(setter) -end - -return setmetatable( object, {__call = function(_,...) object.capi_index_fallback(...) end}) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/protected_call.lua b/awesome/lib/gears/protected_call.lua deleted file mode 100644 index c182e14..0000000 --- a/awesome/lib/gears/protected_call.lua +++ /dev/null @@ -1,57 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2016 Uli Schlachter --- @module gears.protected_call ---------------------------------------------------------------------------- - -local gdebug = require("gears.debug") -local tostring = tostring -local traceback = debug.traceback -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local xpcall = xpcall - -local protected_call = {} - -local function error_handler(err) - gdebug.print_error(traceback("Error during a protected call: " .. tostring(err), 2)) -end - -local function handle_result(success, ...) - if success then - return ... - end -end - -local do_pcall -if _VERSION <= "Lua 5.1" then - -- Lua 5.1 doesn't support arguments in xpcall :-( - do_pcall = function(func, ...) - local args = { ... } - return handle_result(xpcall(function() - return func(unpack(args)) - end, error_handler)) - end -else - do_pcall = function(func, ...) - return handle_result(xpcall(func, error_handler, ...)) - end -end - ---- Call a function in protected mode and handle error-reporting. --- If the function call succeeds, all results of the function are returned. --- Otherwise, an error message is printed and nothing is returned. --- @tparam function func The function to call --- @param ... Arguments to the function --- @return The result of the given function, or nothing if an error occurred. -function protected_call.call(func, ...) - return do_pcall(func, ...) -end - -local pcall_mt = {} -function pcall_mt:__call(...) - return do_pcall(...) -end - -return setmetatable(protected_call, pcall_mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/shape.lua b/awesome/lib/gears/shape.lua deleted file mode 100644 index 4962d78..0000000 --- a/awesome/lib/gears/shape.lua +++ /dev/null @@ -1,785 +0,0 @@ ---------------------------------------------------------------------------- ---- Module dedicated to gather common shape painters. --- --- It add the concept of "shape" to Awesome. A shape can be applied to a --- background, a margin, a mask or a drawable shape bounding. --- --- The functions exposed by this module always take a context as first --- parameter followed by the widget and height and additional parameters. --- --- The functions provided by this module only create a path in the content. --- to actually draw the content, use `cr:fill()`, `cr:mask()`, `cr:clip()` or --- `cr:stroke()` --- --- In many case, it is necessary to apply the shape using a transformation --- such as a rotation. The preferred way to do this is to wrap the function --- in another function calling `cr:rotate()` (or any other transformation --- matrix). --- --- To specialize a shape where the API doesn't allows extra arguments to be --- passed, it is possible to wrap the shape function like: --- --- local new_shape = function(cr, width, height) --- gears.shape.rounded_rect(cr, width, height, 2) --- end --- --- Many elements can be shaped. This include: --- --- * `client`s (see `gears.surface.apply_shape_bounding`) --- * `wibox`es (see `wibox.shape`) --- * All widgets (see `wibox.container.background`) --- * The progressbar (see `wibox.widget.progressbar.bar_shape`) --- * The graph (see `wibox.widget.graph.step_shape`) --- * The checkboxes (see `wibox.widget.checkbox.check_shape`) --- * Images (see `wibox.widget.imagebox.clip_shape`) --- * The taglist tags (see `awful.widget.taglist`) --- * The tasklist clients (see `awful.widget.tasklist`) --- * The tooltips (see `awful.tooltip`) --- --- @author Emmanuel Lepage Vallee --- @copyright 2011-2016 Emmanuel Lepage Vallee --- @module gears.shape ---------------------------------------------------------------------------- -local g_matrix = require( "gears.matrix" ) -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local atan2 = math.atan2 or math.atan -- lua 5.3 compat - -local module = {} - ---- Add a rounded rectangle to the current path. --- Note: If the radius is bigger than either half side, it will be reduced. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_rounded_rect.svg) --- --- @usage ---shape.rounded_rect(cr, 70, 70, 10) ---shape.rounded_rect(cr,20,70, 5) ---shape.transform(shape.rounded_rect) : translate(0,25) (cr,70,20, 5) --- --- @param cr A cairo content --- @tparam number width The rectangle width --- @tparam number height The rectangle height --- @tparam number radius the corner radius -function module.rounded_rect(cr, width, height, radius) - - radius = radius or 10 - - if width / 2 < radius then - radius = width / 2 - end - - if height / 2 < radius then - radius = height / 2 - end - - cr:move_to(0, radius) - - cr:arc( radius , radius , radius, math.pi , 3*(math.pi/2) ) - cr:arc( width-radius, radius , radius, 3*(math.pi/2), math.pi*2 ) - cr:arc( width-radius, height-radius, radius, math.pi*2 , math.pi/2 ) - cr:arc( radius , height-radius, radius, math.pi/2 , math.pi ) - - cr:close_path() -end - ---- Add a rectangle delimited by 2 180 degree arcs to the path. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_rounded_bar.svg) --- --- @usage ---shape.rounded_bar(cr, 70, 70) ---shape.rounded_bar(cr, 20, 70) ---shape.rounded_bar(cr, 70, 20) --- --- @param cr A cairo content --- @param width The rectangle width --- @param height The rectangle height -function module.rounded_bar(cr, width, height) - module.rounded_rect(cr, width, height, height / 2) -end - ---- A rounded rect with only some of the corners rounded. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_partially_rounded_rect.svg) --- --- @usage ---shape.partially_rounded_rect(cr, 70, 70) ---shape.partially_rounded_rect(cr, 70, 70, true) ---shape.partially_rounded_rect(cr, 70, 70, true, true, false, true, 30) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam boolean tl If the top left corner is rounded --- @tparam boolean tr If the top right corner is rounded --- @tparam boolean br If the bottom right corner is rounded --- @tparam boolean bl If the bottom left corner is rounded --- @tparam number rad The corner radius -function module.partially_rounded_rect(cr, width, height, tl, tr, br, bl, rad) - rad = rad or 10 - if width / 2 < rad then - rad = width / 2 - end - - if height / 2 < rad then - rad = height / 2 - end - - -- Top left - if tl then - cr:arc( rad, rad, rad, math.pi, 3*(math.pi/2)) - else - cr:move_to(0,0) - end - - -- Top right - if tr then - cr:arc( width-rad, rad, rad, 3*(math.pi/2), math.pi*2) - else - cr:line_to(width, 0) - end - - -- Bottom right - if br then - cr:arc( width-rad, height-rad, rad, math.pi*2 , math.pi/2) - else - cr:line_to(width, height) - end - - -- Bottom left - if bl then - cr:arc( rad, height-rad, rad, math.pi/2, math.pi) - else - cr:line_to(0, height) - end - - cr:close_path() -end - ---- A rounded rectangle with a triangle at the top. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_infobubble.svg) --- --- @usage ---shape.infobubble(cr, 70, 70) ---shape.transform(shape.infobubble) : translate(0, 20) --- : rotate_at(35,35,math.pi) (cr,70,20,10, 5, 35 - 5) ---shape.transform(shape.infobubble) --- : rotate_at(35,35,3*math.pi/2) (cr,70,70, nil, nil, 40) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=5] number corner_radius The corner radius --- @tparam[opt=10] number arrow_size The width and height of the arrow --- @tparam[opt=width/2 - arrow_size/2] number arrow_position The position of the arrow -function module.infobubble(cr, width, height, corner_radius, arrow_size, arrow_position) - arrow_size = arrow_size or 10 - corner_radius = math.min((height-arrow_size)/2, corner_radius or 5) - arrow_position = arrow_position or width/2 - arrow_size/2 - - - cr:move_to(0 ,corner_radius+arrow_size) - - -- Top left corner - cr:arc(corner_radius, corner_radius+arrow_size, (corner_radius), math.pi, 3*(math.pi/2)) - - -- The arrow triangle (still at the top) - cr:line_to(arrow_position , arrow_size ) - cr:line_to(arrow_position + arrow_size , 0 ) - cr:line_to(arrow_position + 2*arrow_size , arrow_size ) - - -- Complete the rounded rounded rectangle - cr:arc(width-corner_radius, corner_radius+arrow_size , (corner_radius) , 3*(math.pi/2) , math.pi*2 ) - cr:arc(width-corner_radius, height-(corner_radius) , (corner_radius) , math.pi*2 , math.pi/2 ) - cr:arc(corner_radius , height-(corner_radius) , (corner_radius) , math.pi/2 , math.pi ) - - -- Close path - cr:close_path() -end - ---- A rectangle terminated by an arrow. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_rectangular_tag.svg) --- --- @usage ---shape.rectangular_tag(cr, 70, 70) ---shape.transform(shape.rectangular_tag) : translate(0, 30) (cr, 70, 10, 10) ---shape.transform(shape.rectangular_tag) : translate(0, 30) (cr, 70, 10, -10) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=height/2] number arrow_length The length of the arrow part -function module.rectangular_tag(cr, width, height, arrow_length) - arrow_length = arrow_length or height/2 - if arrow_length > 0 then - cr:move_to(0 , height/2 ) - cr:line_to(arrow_length , 0 ) - cr:line_to(width , 0 ) - cr:line_to(width , height ) - cr:line_to(arrow_length , height ) - else - cr:move_to(0 , 0 ) - cr:line_to(-arrow_length, height/2 ) - cr:line_to(0 , height ) - cr:line_to(width , height ) - cr:line_to(width , 0 ) - end - - cr:close_path() -end - ---- A simple arrow shape. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_arrow.svg) --- --- @usage ---shape.arrow(cr, 70, 70) ---shape.arrow(cr,70,70, 30, 10, 60) ---shape.transform(shape.arrow) : rotate_at(35,35,math.pi/2)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=head_width] number head_width The width of the head (/\) of the arrow --- @tparam[opt=width /2] number shaft_width The width of the shaft of the arrow --- @tparam[opt=height/2] number shaft_length The head_length of the shaft (the rest is the head) -function module.arrow(cr, width, height, head_width, shaft_width, shaft_length) - shaft_length = shaft_length or height / 2 - shaft_width = shaft_width or width / 2 - head_width = head_width or width - local head_length = height - shaft_length - - cr:move_to ( width/2 , 0 ) - cr:rel_line_to( head_width/2 , head_length ) - cr:rel_line_to( -(head_width-shaft_width)/2 , 0 ) - cr:rel_line_to( 0 , shaft_length ) - cr:rel_line_to( -shaft_width , 0 ) - cr:rel_line_to( 0 , -shaft_length ) - cr:rel_line_to( -(head_width-shaft_width)/2 , 0 ) - - cr:close_path() -end - ---- A squeezed hexagon filling the rectangle. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_hexagon.svg) --- --- @usage ---shape.hexagon(cr, 70, 70) ---shape.transform(shape.hexagon) : translate(0,15)(cr,70,20) ---shape.transform(shape.hexagon) : rotate_at(35,35,math.pi/2)(cr,70,40) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height -function module.hexagon(cr, width, height) - cr:move_to(height/2,0) - cr:line_to(width-height/2,0) - cr:line_to(width,height/2) - cr:line_to(width-height/2,height) - cr:line_to(height/2,height) - cr:line_to(0,height/2) - cr:line_to(height/2,0) - cr:close_path() -end - ---- Double arrow popularized by the vim-powerline module. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_powerline.svg) --- --- @usage ---shape.powerline(cr, 70, 70) ---shape.transform(shape.powerline) : translate(0, 25) (cr,70,20) ---shape.transform(shape.powerline) : translate(0, 25) (cr,70,20, -20) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=height/2] number arrow_depth The width of the arrow part of the shape -function module.powerline(cr, width, height, arrow_depth) - arrow_depth = arrow_depth or height/2 - local offset = 0 - - -- Avoid going out of the (potential) clip area - if arrow_depth < 0 then - width = width + 2*arrow_depth - offset = -arrow_depth - end - - cr:move_to(offset , 0 ) - cr:line_to(offset + width - arrow_depth , 0 ) - cr:line_to(offset + width , height/2 ) - cr:line_to(offset + width - arrow_depth , height ) - cr:line_to(offset , height ) - cr:line_to(offset + arrow_depth , height/2 ) - - cr:close_path() -end - ---- An isosceles triangle. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_isosceles_triangle.svg) --- --- @usage ---shape.isosceles_triangle(cr, 70, 70) ---shape.isosceles_triangle(cr,20,70) ---shape.transform(shape.isosceles_triangle) : rotate_at(35, 35, math.pi/2)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height -function module.isosceles_triangle(cr, width, height) - cr:move_to( width/2, 0 ) - cr:line_to( width , height ) - cr:line_to( 0 , height ) - cr:close_path() -end - ---- A cross (**+**) symbol. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_cross.svg) --- --- @usage ---shape.cross(cr, 70, 70) ---shape.cross(cr,20,70) ---shape.transform(shape.cross) : scale(0.5, 1)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=width/3] number thickness The cross section thickness -function module.cross(cr, width, height, thickness) - thickness = thickness or width/3 - local xpadding = (width - thickness) / 2 - local ypadding = (height - thickness) / 2 - cr:move_to(xpadding, 0) - cr:line_to(width - xpadding, 0) - cr:line_to(width - xpadding, ypadding) - cr:line_to(width , ypadding) - cr:line_to(width , height-ypadding) - cr:line_to(width - xpadding, height-ypadding) - cr:line_to(width - xpadding, height ) - cr:line_to(xpadding , height ) - cr:line_to(xpadding , height-ypadding) - cr:line_to(0 , height-ypadding) - cr:line_to(0 , ypadding ) - cr:line_to(xpadding , ypadding ) - cr:close_path() -end - ---- A similar shape to the `rounded_rect`, but with sharp corners. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_octogon.svg) --- --- @usage ---shape.octogon(cr, 70, 70) ---shape.octogon(cr,70,70,70/2.5) ---shape.transform(shape.octogon) : translate(0, 25) (cr,70,20) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam number corner_radius -function module.octogon(cr, width, height, corner_radius) - corner_radius = corner_radius or math.min(10, math.min(width, height)/4) - local offset = math.sqrt( (corner_radius*corner_radius) / 2 ) - - cr:move_to(offset, 0) - cr:line_to(width-offset, 0) - cr:line_to(width, offset) - cr:line_to(width, height-offset) - cr:line_to(width-offset, height) - cr:line_to(offset, height) - cr:line_to(0, height-offset) - cr:line_to(0, offset) - cr:close_path() -end - ---- A circle shape. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_circle.svg) --- --- @usage ---shape.circle(cr, 70, 70) ---shape.circle(cr,20,70) ---shape.transform(shape.circle) : scale(0.5, 1)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=math.min(width height) / 2)] number radius The radius -function module.circle(cr, width, height, radius) - radius = radius or math.min(width, height) / 2 - cr:move_to(width/2+radius, height/2) - cr:arc(width / 2, height / 2, radius, 0, 2*math.pi) - cr:close_path() -end - ---- A simple rectangle. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_rectangle.svg) --- --- @usage ---shape.rectangle(cr, 70, 70) ---shape.rectangle(cr,20,70) ---shape.transform(shape.rectangle) : scale(0.5, 1)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height -function module.rectangle(cr, width, height) - cr:rectangle(0, 0, width, height) -end - ---- A diagonal parallelogram with the bottom left corner at x=0 and top right --- at x=width. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_parallelogram.svg) --- --- @usage ---shape.parallelogram(cr, 70, 70) ---shape.parallelogram(cr,70,20) ---shape.transform(shape.parallelogram) : scale(0.5, 1)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=width/3] number base_width The parallelogram base width -function module.parallelogram(cr, width, height, base_width) - base_width = base_width or width/3 - cr:move_to(width-base_width, 0 ) - cr:line_to(width , 0 ) - cr:line_to(base_width , height ) - cr:line_to(0 , height ) - cr:close_path() -end - ---- A losange. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_losange.svg) --- --- @usage ---shape.losange(cr, 70, 70) ---shape.losange(cr,20,70) ---shape.transform(shape.losange) : scale(0.5, 1)(cr,70,70) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height -function module.losange(cr, width, height) - cr:move_to(width/2 , 0 ) - cr:line_to(width , height/2 ) - cr:line_to(width/2 , height ) - cr:line_to(0 , height/2 ) - cr:close_path() -end - ---- A pie. --- --- The pie center is the center of the area. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_pie.svg) --- --- @usage ---shape.pie(cr, 70, 70) ---shape.pie(cr,70,70, 1.0471975511966, 4.1887902047864) ---shape.pie(cr,70,70, 0, 2*math.pi, 10) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=0] number start_angle The start angle (in radian) --- @tparam[opt=math.pi/2] number end_angle The end angle (in radian) --- @tparam[opt=math.min(width height)/2] number radius The shape height -function module.pie(cr, width, height, start_angle, end_angle, radius) - radius = radius or math.floor(math.min(width, height)/2) - start_angle, end_angle = start_angle or 0, end_angle or math.pi/2 - - -- If the shape is a circle, then avoid the lines - if math.abs(start_angle + end_angle - 2*math.pi) <= 0.01 then - cr:arc(width/2, height/2, radius, 0, 2*math.pi) - else - cr:move_to(width/2, height/2) - cr:line_to( - width/2 + math.cos(start_angle)*radius, - height/2 + math.sin(start_angle)*radius - ) - cr:arc(width/2, height/2, radius, start_angle, end_angle) - end - - cr:close_path() -end - ---- A rounded arc. --- --- The pie center is the center of the area. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_arc.svg) --- --- @usage ---shape.arc(cr,70,70, 10) ---shape.arc(cr,70,70, 10, nil, nil, true, true) ---shape.arc(cr,70,70, nil, 0, 2*math.pi) --- --- @param cr A cairo context --- @tparam number width The shape width --- @tparam number height The shape height --- @tparam[opt=math.min(width height)/2] number thickness The arc thickness --- @tparam[opt=0] number start_angle The start angle (in radian) --- @tparam[opt=math.pi/2] number end_angle The end angle (in radian) --- @tparam[opt=false] boolean start_rounded if the arc start rounded --- @tparam[opt=false] boolean end_rounded if the arc end rounded -function module.arc(cr, width, height, thickness, start_angle, end_angle, start_rounded, end_rounded) - start_angle = start_angle or 0 - end_angle = end_angle or math.pi/2 - - -- This shape is a partial circle - local radius = math.min(width, height)/2 - - thickness = thickness or radius/2 - - local inner_radius = radius - thickness - - -- As the edge of the small arc need to touch the [start_p1, start_p2] - -- line, a small subset of the arc circumference has to be substracted - -- that's (less or more) equal to the thickness/2 (a little longer given - -- it is an arc and not a line, but it wont show) - local arc_percent = math.abs(end_angle-start_angle)/(2*math.pi) - local arc_length = ((radius-thickness/2)*2*math.pi)*arc_percent - - if start_rounded then - arc_length = arc_length - thickness/2 - - -- And back to angles - start_angle = end_angle - (arc_length/(radius - thickness/2)) - end - - if end_rounded then - arc_length = arc_length - thickness/2 - - -- And back to angles - end_angle = start_angle + (arc_length/(radius - thickness/2)) - end - - -- The path is a curcular arc joining 4 points - - -- Outer first corner - local start_p1 = { - width /2 + math.cos(start_angle)*radius, - height/2 + math.sin(start_angle)*radius - } - - if start_rounded then - - -- Inner first corner - local start_p2 = { - width /2 + math.cos(start_angle)*inner_radius, - height/2 + math.sin(start_angle)*inner_radius - } - - local median_angle = atan2( - start_p2[1] - start_p1[1], - -(start_p2[2] - start_p1[2]) - ) - - local arc_center = { - (start_p1[1] + start_p2[1])/2, - (start_p1[2] + start_p2[2])/2, - } - - cr:arc(arc_center[1], arc_center[2], thickness/2, - median_angle-math.pi/2, median_angle+math.pi/2 - ) - - else - cr:move_to(unpack(start_p1)) - end - - cr:arc(width/2, height/2, radius, start_angle, end_angle) - - if end_rounded then - - -- Outer second corner - local end_p1 = { - width /2 + math.cos(end_angle)*radius, - height/2 + math.sin(end_angle)*radius - } - - -- Inner first corner - local end_p2 = { - width /2 + math.cos(end_angle)*inner_radius, - height/2 + math.sin(end_angle)*inner_radius - } - local median_angle = atan2( - end_p2[1] - end_p1[1], - -(end_p2[2] - end_p1[2]) - ) - math.pi - - local arc_center = { - (end_p1[1] + end_p2[1])/2, - (end_p1[2] + end_p2[2])/2, - } - - cr:arc(arc_center[1], arc_center[2], thickness/2, - median_angle-math.pi/2, median_angle+math.pi/2 - ) - - end - - cr:arc_negative(width/2, height/2, inner_radius, end_angle, start_angle) - - cr:close_path() -end - ---- A partial rounded bar. How much of the rounded bar is visible depends on --- the given percentage value. --- --- Note that this shape is not closed and thus filling it doesn't make much --- sense. --- --- --- ---![Usage example](../images/AUTOGEN_gears_shape_radial_progress.svg) --- --- @usage ---shape.radial_progress(cr, 70, 20, .3) ---shape.radial_progress(cr, 70, 20, .6) ---shape.radial_progress(cr, 70, 20, .9) --- --- @param cr A cairo context --- @tparam number w The shape width --- @tparam number h The shape height --- @tparam number percent The progressbar percent --- @tparam boolean hide_left Do not draw the left side of the shape -function module.radial_progress(cr, w, h, percent, hide_left) - percent = percent or 1 - local total_length = (2*(w-h))+2*((h/2)*math.pi) - local bar_percent = (w-h)/total_length - local arc_percent = ((h/2)*math.pi)/total_length - - -- Bottom line - if percent > bar_percent then - cr:move_to(h/2,h) - cr:line_to((h/2) + (w-h),h) - cr:stroke() - elseif percent < bar_percent then - cr:move_to(h/2,h) - cr:line_to(h/2+(total_length*percent),h) - cr:stroke() - end - - -- Right arc - if percent >= bar_percent+arc_percent then - cr:arc(w-h/2 , h/2, h/2,3*(math.pi/2),math.pi/2) - cr:stroke() - elseif percent > bar_percent and percent < bar_percent+(arc_percent/2) then - cr:arc(w-h/2 , h/2, h/2,(math.pi/2)-((math.pi/2)*((percent-bar_percent)/(arc_percent/2))),math.pi/2) - cr:stroke() - elseif percent >= bar_percent+arc_percent/2 and percent < bar_percent+arc_percent then - cr:arc(w-h/2 , h/2, h/2,0,math.pi/2) - cr:stroke() - local add = (math.pi/2)*((percent-bar_percent-arc_percent/2)/(arc_percent/2)) - cr:arc(w-h/2 , h/2, h/2,2*math.pi-add,0) - cr:stroke() - end - - -- Top line - if percent > 2*bar_percent+arc_percent then - cr:move_to((h/2) + (w-h),0) - cr:line_to(h/2,0) - cr:stroke() - elseif percent > bar_percent+arc_percent and percent < 2*bar_percent+arc_percent then - cr:move_to((h/2) + (w-h),0) - cr:line_to(((h/2) + (w-h))-total_length*(percent-bar_percent-arc_percent),0) - cr:stroke() - end - - -- Left arc - if not hide_left then - if percent > 0.985 then - cr:arc(h/2, h/2, h/2,math.pi/2,3*(math.pi/2)) - cr:stroke() - elseif percent > 2*bar_percent+arc_percent then - local relpercent = (percent - 2*bar_percent - arc_percent)/arc_percent - cr:arc(h/2, h/2, h/2,3*(math.pi/2)-(math.pi)*relpercent,3*(math.pi/2)) - cr:stroke() - end - end -end - ---- Adjust the shape using a transformation object --- --- Apply various transformations to the shape --- --- @usage gears.shape.transform(gears.shape.rounded_bar) --- : rotate(math.pi/2) --- : translate(10, 10) --- --- @param shape A shape function --- @return A transformation handle, also act as a shape function -function module.transform(shape) - - -- Apply the transformation matrix and apply the shape, then restore - local function apply(self, cr, width, height, ...) - cr:save() - cr:transform(self.matrix:to_cairo_matrix()) - shape(cr, width, height, ...) - cr:restore() - end - -- Redirect function calls like :rotate() to the underlying matrix - local function index(_, key) - return function(self, ...) - self.matrix = self.matrix[key](self.matrix, ...) - return self - end - end - - local result = setmetatable({ - matrix = g_matrix.identity - }, { - __call = apply, - __index = index - }) - - return result -end - -return module - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/surface.lua b/awesome/lib/gears/surface.lua deleted file mode 100644 index 78f2216..0000000 --- a/awesome/lib/gears/surface.lua +++ /dev/null @@ -1,252 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2012 Uli Schlachter --- @module gears.surface ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local type = type -local capi = { awesome = awesome } -local cairo = require("lgi").cairo -local color = nil -local gdebug = require("gears.debug") -local hierarchy = require("wibox.hierarchy") - --- Keep this in sync with build-utils/lgi-check.sh! -local ver_major, ver_minor, ver_patch = string.match(require('lgi.version'), '(%d)%.(%d)%.(%d)') -if tonumber(ver_major) <= 0 and (tonumber(ver_minor) < 7 or (tonumber(ver_minor) == 7 and tonumber(ver_patch) < 1)) then - error("lgi too old, need at least version 0.7.1") -end - -local surface = { mt = {} } -local surface_cache = setmetatable({}, { __mode = 'v' }) - -local function get_default(arg) - if type(arg) == 'nil' then - return cairo.ImageSurface(cairo.Format.ARGB32, 0, 0) - end - return arg -end - ---- Try to convert the argument into an lgi cairo surface. --- This is usually needed for loading images by file name. --- @param _surface The surface to load or nil --- @param default The default value to return on error; when nil, then a surface --- in an error state is returned. --- @return The loaded surface, or the replacement default --- @return An error message, or nil on success -function surface.load_uncached_silently(_surface, default) - local file - -- On nil, return some sane default - if not _surface then - return get_default(default) - end - -- lgi cairo surfaces don't get changed either - if cairo.Surface:is_type_of(_surface) then - return _surface - end - -- Strings are assumed to be file names and get loaded - if type(_surface) == "string" then - local err - file = _surface - _surface, err = capi.awesome.load_image(file) - if not _surface then - return get_default(default), err - end - end - -- Everything else gets forced into a surface - return cairo.Surface(_surface, true) -end - ---- Try to convert the argument into an lgi cairo surface. --- This is usually needed for loading images by file name and uses a cache. --- In contrast to `load()`, errors are returned to the caller. --- @param _surface The surface to load or nil --- @param default The default value to return on error; when nil, then a surface --- in an error state is returned. --- @return The loaded surface, or the replacement default, or nil if called with --- nil. --- @return An error message, or nil on success -function surface.load_silently(_surface, default) - if type(_surface) == "string" then - local cache = surface_cache[_surface] - if cache then - return cache - end - local result, err = surface.load_uncached_silently(_surface, default) - if not err then - -- Cache the file - surface_cache[_surface] = result - end - return result, err - end - return surface.load_uncached_silently(_surface, default) -end - -local function do_load_and_handle_errors(_surface, func) - if type(_surface) == 'nil' then - return get_default() - end - local result, err = func(_surface, false) - if result then - return result - end - gdebug.print_error(debug.traceback( - "Failed to load '" .. tostring(_surface) .. "': " .. tostring(err))) - return get_default() -end - ---- Try to convert the argument into an lgi cairo surface. --- This is usually needed for loading images by file name. Errors are handled --- via `gears.debug.print_error`. --- @param _surface The surface to load or nil --- @return The loaded surface, or nil -function surface.load_uncached(_surface) - return do_load_and_handle_errors(_surface, surface.load_uncached_silently) -end - ---- Try to convert the argument into an lgi cairo surface. --- This is usually needed for loading images by file name. Errors are handled --- via `gears.debug.print_error`. --- @param _surface The surface to load or nil --- @return The loaded surface, or nil -function surface.load(_surface) - return do_load_and_handle_errors(_surface, surface.load_silently) -end - -function surface.mt.__call(_, ...) - return surface.load(...) -end - ---- Get the size of a cairo surface --- @param surf The surface you are interested in --- @return The surface's width and height -function surface.get_size(surf) - local cr = cairo.Context(surf) - local x, y, w, h = cr:clip_extents() - return w - x, h - y -end - ---- Create a copy of a cairo surface. --- The surfaces returned by `surface.load` are cached and must not be --- modified to avoid unintended side-effects. This function allows to create --- a copy of a cairo surface. This copy can then be freely modified. --- The surface returned will be as compatible as possible to the input --- surface. For example, it will likely be of the same surface type as the --- input. The details are explained in the `create_similar` function on a cairo --- surface. --- @param s Source surface. --- @return The surface's duplicate. -function surface.duplicate_surface(s) - s = surface.load(s) - - -- Figure out surface size (this does NOT work for unbounded recording surfaces) - local cr = cairo.Context(s) - local x, y, w, h = cr:clip_extents() - - -- Create a copy - local result = s:create_similar(s.content, w - x, h - y) - cr = cairo.Context(result) - cr:set_source_surface(s, 0, 0) - cr.operator = cairo.Operator.SOURCE - cr:paint() - return result -end - ---- Create a surface from a `gears.shape` --- Any additional parameters will be passed to the shape function --- @tparam number width The surface width --- @tparam number height The surface height --- @param shape A `gears.shape` compatible function --- @param[opt=white] shape_color The shape color or pattern --- @param[opt=transparent] bg_color The surface background color --- @treturn cairo.surface the new surface -function surface.load_from_shape(width, height, shape, shape_color, bg_color, ...) - color = color or require("gears.color") - - local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height) - local cr = cairo.Context(img) - - cr:set_source(color(bg_color or "#00000000")) - cr:paint() - - cr:set_source(color(shape_color or "#000000")) - - shape(cr, width, height, ...) - - cr:fill() - - return img -end - ---- Apply a shape to a client or a wibox. --- --- If the wibox or client size change, this function need to be called --- again. --- @param draw A wibox or a client --- @param shape or gears.shape function or a custom function with a context, --- width and height as parameter. --- @param[opt] Any additional parameters will be passed to the shape function -function surface.apply_shape_bounding(draw, shape, ...) - local geo = draw:geometry() - - local img = cairo.ImageSurface(cairo.Format.A1, geo.width, geo.height) - local cr = cairo.Context(img) - - cr:set_operator(cairo.Operator.CLEAR) - cr:set_source_rgba(0,0,0,1) - cr:paint() - cr:set_operator(cairo.Operator.SOURCE) - cr:set_source_rgba(1,1,1,1) - - shape(cr, geo.width, geo.height, ...) - - cr:fill() - - draw.shape_bounding = img._native -end - -local function no_op() end - -local function run_in_hierarchy(self, cr, width, height) - local context = {dpi=96} - local h = hierarchy.new(context, self, width, height, no_op, no_op, {}) - h:draw(context, cr) - return h -end - ---- Create an SVG file with this widget content. --- This is dynamic, so the SVG will be updated along with the widget content. --- because of this, the painting may happen hover multiple event loop cycles. --- @tparam widget widget A widget --- @tparam string path The output file path --- @tparam number width The surface width --- @tparam number height The surface height --- @return The cairo surface --- @return The hierarchy -function surface.widget_to_svg(widget, path, width, height) - local img = cairo.SvgSurface.create(path, width, height) - local cr = cairo.Context(img) - - return img, run_in_hierarchy(widget, cr, width, height) -end - ---- Create a cairo surface with this widget content. --- This is dynamic, so the SVG will be updated along with the widget content. --- because of this, the painting may happen hover multiple event loop cycles. --- @tparam widget widget A widget --- @tparam number width The surface width --- @tparam number height The surface height --- @param[opt=cairo.Format.ARGB32] format The surface format --- @return The cairo surface --- @return The hierarchy -function surface.widget_to_surface(widget, width, height, format) - local img = cairo.ImageSurface(format or cairo.Format.ARGB32, width, height) - local cr = cairo.Context(img) - - return img, run_in_hierarchy(widget, cr, width, height) -end - -return setmetatable(surface, surface.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/timer.lua b/awesome/lib/gears/timer.lua deleted file mode 100644 index 110c39a..0000000 --- a/awesome/lib/gears/timer.lua +++ /dev/null @@ -1,187 +0,0 @@ ---------------------------------------------------------------------------- ---- Timer objects and functions. --- --- @author Uli Schlachter --- @copyright 2014 Uli Schlachter --- @classmod gears.timer ---------------------------------------------------------------------------- - -local capi = { awesome = awesome } -local ipairs = ipairs -local pairs = pairs -local setmetatable = setmetatable -local table = table -local tonumber = tonumber -local traceback = debug.traceback -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local glib = require("lgi").GLib -local object = require("gears.object") -local protected_call = require("gears.protected_call") - ---- Timer objects. This type of object is useful when triggering events repeatedly. --- The timer will emit the "timeout" signal every N seconds, N being the timeout --- value. Note that a started timer will not be garbage collected. Call `:stop` --- to enable garbage collection. --- @tfield number timeout Interval in seconds to emit the timeout signal. --- Can be any value, including floating point ones (e.g. 1.5 seconds). --- @tfield boolean started Read-only boolean field indicating if the timer has been --- started. --- @table timer - ---- When the timer is started. --- @signal .start - ---- When the timer is stopped. --- @signal .stop - ---- When the timer had a timeout event. --- @signal .timeout - -local timer = { mt = {} } - ---- Start the timer. -function timer:start() - if self.data.source_id ~= nil then - print(traceback("timer already started")) - return - end - self.data.source_id = glib.timeout_add(glib.PRIORITY_DEFAULT, self.data.timeout * 1000, function() - protected_call(self.emit_signal, self, "timeout") - return true - end) - self:emit_signal("start") -end - ---- Stop the timer. -function timer:stop() - if self.data.source_id == nil then - print(traceback("timer not started")) - return - end - glib.source_remove(self.data.source_id) - self.data.source_id = nil - self:emit_signal("stop") -end - ---- Restart the timer. --- This is equivalent to stopping the timer if it is running and then starting --- it. -function timer:again() - if self.data.source_id ~= nil then - self:stop() - end - self:start() -end - ---- The timer is started. --- @property started --- @param boolean - ---- The timer timeout value. --- **Signal:** property::timeout --- @property timeout --- @param number - -local timer_instance_mt = { - __index = function(self, property) - if property == "timeout" then - return self.data.timeout - elseif property == "started" then - return self.data.source_id ~= nil - end - - return timer[property] - end, - - __newindex = function(self, property, value) - if property == "timeout" then - self.data.timeout = tonumber(value) - self:emit_signal("property::timeout") - end - end -} - ---- Create a new timer object. --- @tparam table args Arguments. --- @tparam number args.timeout Timeout in seconds (e.g. 1.5). --- @treturn timer --- @function gears.timer -timer.new = function(args) - local ret = object() - - ret.data = { timeout = 0 } - setmetatable(ret, timer_instance_mt) - - for k, v in pairs(args) do - ret[k] = v - end - - return ret -end - ---- Create a timeout for calling some callback function. --- When the callback function returns true, it will be called again after the --- same timeout. If false is returned, no more calls will be done. If the --- callback function causes an error, no more calls are done. --- @tparam number timeout Timeout in seconds (e.g. 1.5). --- @tparam function callback Function to run. --- @treturn timer The timer object that was set up. --- @see timer.weak_start_new --- @function gears.timer.start_new -function timer.start_new(timeout, callback) - local t = timer.new({ timeout = timeout }) - t:connect_signal("timeout", function() - local cont = protected_call(callback) - if not cont then - t:stop() - end - end) - t:start() - return t -end - ---- Create a timeout for calling some callback function. --- This function is almost identical to `timer.start_new`. The only difference --- is that this does not prevent the callback function from being garbage --- collected. After the callback function was collected, the timer returned --- will automatically be stopped. --- @tparam number timeout Timeout in seconds (e.g. 1.5). --- @tparam function callback Function to start. --- @treturn timer The timer object that was set up. --- @see timer.start_new --- @function gears.timer.weak_start_new -function timer.weak_start_new(timeout, callback) - local indirection = setmetatable({}, { __mode = "v" }) - indirection.callback = callback - return timer.start_new(timeout, function() - local cb = indirection.callback - if cb then - return cb() - end - end) -end - -local delayed_calls = {} -capi.awesome.connect_signal("refresh", function() - for _, callback in ipairs(delayed_calls) do - protected_call(unpack(callback)) - end - delayed_calls = {} -end) - ---- Call the given function at the end of the current main loop iteration --- @tparam function callback The function that should be called --- @param ... Arguments to the callback function --- @function gears.timer.delayed_call -function timer.delayed_call(callback, ...) - assert(type(callback) == "function", "callback must be a function, got: " .. type(callback)) - table.insert(delayed_calls, { callback, ... }) -end - -function timer.mt.__call(_, ...) - return timer.new(...) -end - -return setmetatable(timer, timer.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/gears/wallpaper.lua b/awesome/lib/gears/wallpaper.lua deleted file mode 100644 index 70ecf48..0000000 --- a/awesome/lib/gears/wallpaper.lua +++ /dev/null @@ -1,221 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2012 Uli Schlachter --- @module gears.wallpaper ---------------------------------------------------------------------------- - -local cairo = require("lgi").cairo -local color = require("gears.color") -local surface = require("gears.surface") -local timer = require("gears.timer") -local root = root - -local wallpaper = { mt = {} } - -local function root_geometry() - local width, height = root.size() - return { x = 0, y = 0, width = width, height = height } -end - --- Information about a pending wallpaper change, see prepare_context() -local pending_wallpaper = nil - -local function get_screen(s) - return s and screen[s] -end - ---- Prepare the needed state for setting a wallpaper. --- This function returns a cairo context through which a wallpaper can be drawn. --- The context is only valid for a short time and should not be saved in a --- global variable. --- @param s The screen to set the wallpaper on or nil for all screens --- @return[1] The available geometry (table with entries width and height) --- @return[1] A cairo context that the wallpaper should be drawn to -function wallpaper.prepare_context(s) - s = get_screen(s) - - local root_width, root_height = root.size() - local geom = s and s.geometry or root_geometry() - local source, target, cr - - if not pending_wallpaper then - -- Prepare a pending wallpaper - source = surface(root.wallpaper()) - target = source:create_similar(cairo.Content.COLOR, root_width, root_height) - - -- Set the wallpaper (delayed) - timer.delayed_call(function() - local paper = pending_wallpaper - pending_wallpaper = nil - wallpaper.set(paper.surface) - paper.surface:finish() - end) - elseif root_width > pending_wallpaper.width or root_height > pending_wallpaper.height then - -- The root window was resized while a wallpaper is pending - source = pending_wallpaper.surface - target = source:create_similar(cairo.Content.COLOR, root_width, root_height) - else - -- Draw to the already-pending wallpaper - source = nil - target = pending_wallpaper.surface - end - - cr = cairo.Context(target) - - if source then - -- Copy the old wallpaper to the new one - cr:save() - cr.operator = cairo.Operator.SOURCE - cr:set_source_surface(source, 0, 0) - cr:paint() - cr:restore() - end - - pending_wallpaper = { - surface = target, - width = root_width, - height = root_height - } - - -- Only draw to the selected area - cr:translate(geom.x, geom.y) - cr:rectangle(0, 0, geom.width, geom.height) - cr:clip() - - return geom, cr -end - ---- Set the current wallpaper. --- @param pattern The wallpaper that should be set. This can be a cairo surface, --- a description for gears.color or a cairo pattern. --- @see gears.color -function wallpaper.set(pattern) - if cairo.Surface:is_type_of(pattern) then - pattern = cairo.Pattern.create_for_surface(pattern) - end - if type(pattern) == "string" or type(pattern) == "table" then - pattern = color(pattern) - end - if not cairo.Pattern:is_type_of(pattern) then - error("wallpaper.set() called with an invalid argument") - end - root.wallpaper(pattern._native) -end - ---- Set a centered wallpaper. --- @param surf The wallpaper to center. Either a cairo surface or a file name. --- @param s The screen whose wallpaper should be set. Can be nil, in which case --- all screens are set. --- @param background The background color that should be used. Gets handled via --- gears.color. The default is black. --- @see gears.color -function wallpaper.centered(surf, s, background) - local geom, cr = wallpaper.prepare_context(s) - surf = surface.load_uncached(surf) - background = color(background) - - -- Fill the area with the background - cr.operator = cairo.Operator.SOURCE - cr.source = background - cr:paint() - - -- Now center the surface - local w, h = surface.get_size(surf) - cr:translate((geom.width - w) / 2, (geom.height - h) / 2) - cr:rectangle(0, 0, w, h) - cr:clip() - cr:set_source_surface(surf, 0, 0) - cr:paint() - surf:finish() -end - ---- Set a tiled wallpaper. --- @param surf The wallpaper to tile. Either a cairo surface or a file name. --- @param s The screen whose wallpaper should be set. Can be nil, in which case --- all screens are set. --- @param offset This can be set to a table with entries x and y. -function wallpaper.tiled(surf, s, offset) - local _, cr = wallpaper.prepare_context(s) - - if offset then - cr:translate(offset.x, offset.y) - end - - surf = surface.load_uncached(surf) - local pattern = cairo.Pattern.create_for_surface(surf) - pattern.extend = cairo.Extend.REPEAT - cr.source = pattern - cr.operator = cairo.Operator.SOURCE - cr:paint() - surf:finish() -end - ---- Set a maximized wallpaper. --- @param surf The wallpaper to set. Either a cairo surface or a file name. --- @param s The screen whose wallpaper should be set. Can be nil, in which case --- all screens are set. --- @param ignore_aspect If this is true, the image's aspect ratio is ignored. --- The default is to honor the aspect ratio. --- @param offset This can be set to a table with entries x and y. -function wallpaper.maximized(surf, s, ignore_aspect, offset) - local geom, cr = wallpaper.prepare_context(s) - surf = surface.load_uncached(surf) - local w, h = surface.get_size(surf) - local aspect_w = geom.width / w - local aspect_h = geom.height / h - - if not ignore_aspect then - aspect_h = math.max(aspect_w, aspect_h) - aspect_w = math.max(aspect_w, aspect_h) - end - cr:scale(aspect_w, aspect_h) - - if offset then - cr:translate(offset.x, offset.y) - elseif not ignore_aspect then - local scaled_width = geom.width / aspect_w - local scaled_height = geom.height / aspect_h - cr:translate((scaled_width - w) / 2, (scaled_height - h) / 2) - end - - cr:set_source_surface(surf, 0, 0) - cr.operator = cairo.Operator.SOURCE - cr:paint() - surf:finish() -end - ---- Set a fitting wallpaper. --- @param surf The wallpaper to set. Either a cairo surface or a file name. --- @param s The screen whose wallpaper should be set. Can be nil, in which case --- all screens are set. --- @param background The background color that should be used. Gets handled via --- gears.color. The default is black. --- @see gears.color -function wallpaper.fit(surf, s, background) - local geom, cr = wallpaper.prepare_context(s) - surf = surface.load_uncached(surf) - background = color(background) - - -- Fill the area with the background - cr.operator = cairo.Operator.SOURCE - cr.source = background - cr:paint() - - -- Now fit the surface - local w, h = surface.get_size(surf) - local scale = geom.width / w - if h * scale > geom.height then - scale = geom.height / h - end - cr:translate((geom.width - (w * scale)) / 2, (geom.height - (h * scale)) / 2) - cr:rectangle(0, 0, w * scale, h * scale) - cr:clip() - cr:scale(scale, scale) - cr:set_source_surface(surf, 0, 0) - cr:paint() - surf:finish() -end - -return wallpaper - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/menubar/icon_theme.lua b/awesome/lib/menubar/icon_theme.lua deleted file mode 100644 index f76252f..0000000 --- a/awesome/lib/menubar/icon_theme.lua +++ /dev/null @@ -1,251 +0,0 @@ ---------------------------------------------------------------------------- ---- Class module for icon lookup for menubar --- --- @author Kazunobu Kuriyama --- @copyright 2015 Kazunobu Kuriyama --- @classmod menubar.icon_theme ---------------------------------------------------------------------------- - --- This implementation is based on the specifications: --- Icon Theme Specification 0.12 --- http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.12.html - -local beautiful = require("beautiful") -local awful_util = require("awful.util") -local GLib = require("lgi").GLib -local index_theme = require("menubar.index_theme") - -local ipairs = ipairs -local setmetatable = setmetatable -local string = string -local table = table -local math = math - -local get_pragmatic_base_directories = function() - local dirs = {} - - local dir = GLib.build_filenamev({GLib.get_home_dir(), ".icons"}) - if awful_util.dir_readable(dir) then - table.insert(dirs, dir) - end - - dir = GLib.build_filenamev({GLib.get_user_data_dir(), "icons"}) - if awful_util.dir_readable(dir) then - table.insert(dirs, dir) - end - - for _, v in ipairs(GLib.get_system_data_dirs()) do - dir = GLib.build_filenamev({v, "icons"}) - if awful_util.dir_readable(dir) then - table.insert(dirs, dir) - end - end - - local need_usr_share_pixmaps = true - for _, v in ipairs(GLib.get_system_data_dirs()) do - dir = GLib.build_filenamev({v, "pixmaps"}) - if awful_util.dir_readable(dir) then - table.insert(dirs, dir) - end - if dir == "/usr/share/pixmaps" then - need_usr_share_pixmaps = false - end - end - - dir = "/usr/share/pixmaps" - if need_usr_share_pixmaps and awful_util.dir_readable(dir) then - table.insert(dirs, dir) - end - - return dirs -end - -local get_default_icon_theme_name = function() - local icon_theme_names = { "Adwaita", "gnome", "hicolor" } - for _, dir in ipairs(get_pragmatic_base_directories()) do - for _, icon_theme_name in ipairs(icon_theme_names) do - local filename = string.format("%s/%s/index.theme", dir, icon_theme_name) - if awful_util.file_readable(filename) then - return icon_theme_name - end - end - end - return nil -end - -local icon_theme = { mt = {} } - -local index_theme_cache = {} - ---- Class constructor of `icon_theme` --- @tparam string icon_theme_name Internal name of icon theme --- @tparam table base_directories Paths used for lookup --- @treturn table An instance of the class `icon_theme` -icon_theme.new = function(icon_theme_name, base_directories) - icon_theme_name = icon_theme_name or beautiful.icon_theme or get_default_icon_theme_name() - base_directories = base_directories or get_pragmatic_base_directories() - - local self = {} - self.icon_theme_name = icon_theme_name - self.base_directories = base_directories - self.extensions = { "png", "svg", "xpm" } - - -- Instantiate index_theme (cached). - if not index_theme_cache[self.icon_theme_name] then - index_theme_cache[self.icon_theme_name] = {} - end - local cache_key = table.concat(self.base_directories, ':') - if not index_theme_cache[self.icon_theme_name][cache_key] then - index_theme_cache[self.icon_theme_name][cache_key] = index_theme( - self.icon_theme_name, - self.base_directories) - end - self.index_theme = index_theme_cache[self.icon_theme_name][cache_key] - - return setmetatable(self, { __index = icon_theme }) -end - -local directory_matches_size = function(self, subdirectory, icon_size) - local kind, size, min_size, max_size, threshold = self.index_theme:get_per_directory_keys(subdirectory) - - if kind == "Fixed" then - return icon_size == size - elseif kind == "Scalable" then - return icon_size >= min_size and icon_size <= max_size - elseif kind == "Threshold" then - return icon_size >= size - threshold and icon_size <= size + threshold - end - - return false -end - -local directory_size_distance = function(self, subdirectory, icon_size) - local kind, size, min_size, max_size, threshold = self.index_theme:get_per_directory_keys(subdirectory) - - if kind == "Fixed" then - return math.abs(icon_size - size) - elseif kind == "Scalable" then - if icon_size < min_size then - return min_size - icon_size - elseif icon_size > max_size then - return icon_size - max_size - end - return 0 - elseif kind == "Threshold" then - if icon_size < size - threshold then - return min_size - icon_size - elseif icon_size > size + threshold then - return icon_size - max_size - end - return 0 - end - - return 0xffffffff -- Any large number will do. -end - -local lookup_icon = function(self, icon_name, icon_size) - local checked_already = {} - for _, subdir in ipairs(self.index_theme:get_subdirectories()) do - for _, basedir in ipairs(self.base_directories) do - for _, ext in ipairs(self.extensions) do - if directory_matches_size(self, subdir, icon_size) then - local filename = string.format("%s/%s/%s/%s.%s", - basedir, self.icon_theme_name, subdir, - icon_name, ext) - if awful_util.file_readable(filename) then - return filename - else - checked_already[filename] = true - end - end - end - end - end - - local minimal_size = 0xffffffff -- Any large number will do. - local closest_filename = nil - for _, subdir in ipairs(self.index_theme:get_subdirectories()) do - local dist = directory_size_distance(self, subdir, icon_size) - if dist < minimal_size then - for _, basedir in ipairs(self.base_directories) do - for _, ext in ipairs(self.extensions) do - local filename = string.format("%s/%s/%s/%s.%s", - basedir, self.icon_theme_name, subdir, - icon_name, ext) - if not checked_already[filename] then - if awful_util.file_readable(filename) then - closest_filename = filename - minimal_size = dist - end - end - end - end - end - end - return closest_filename -end - -local find_icon_path_helper -- Gets called recursively. -find_icon_path_helper = function(self, icon_name, icon_size) - local filename = lookup_icon(self, icon_name, icon_size) - if filename then - return filename - end - - for _, parent in ipairs(self.index_theme:get_inherits()) do - local parent_icon_theme = icon_theme(parent, self.base_directories) - filename = find_icon_path_helper(parent_icon_theme, icon_name, icon_size) - if filename then - return filename - end - end - - return nil -end - -local lookup_fallback_icon = function(self, icon_name) - for _, dir in ipairs(self.base_directories) do - for _, ext in ipairs(self.extensions) do - local filename = string.format("%s/%s.%s", - dir, - icon_name, ext) - if awful_util.file_readable(filename) then - return filename - end - end - end - return nil -end - ---- Look up an image file based on a given icon name and/or a preferable size. --- @tparam string icon_name Icon name to be looked up --- @tparam number icon_size Prefereable icon size --- @treturn string Absolute path to the icon file, or nil if not found -function icon_theme:find_icon_path(icon_name, icon_size) - icon_size = icon_size or 16 - if not icon_name or icon_name == "" then - return nil - end - - local filename = find_icon_path_helper(self, icon_name, icon_size) - if filename then - return filename - end - - if self.icon_theme_name ~= "hicolor" then - filename = find_icon_path_helper(icon_theme("hicolor", self.base_directories), icon_name, icon_size) - if filename then - return filename - end - end - - return lookup_fallback_icon(self, icon_name) -end - -icon_theme.mt.__call = function(_, ...) - return icon_theme.new(...) -end - -return setmetatable(icon_theme, icon_theme.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/menubar/index_theme.lua b/awesome/lib/menubar/index_theme.lua deleted file mode 100644 index 633964a..0000000 --- a/awesome/lib/menubar/index_theme.lua +++ /dev/null @@ -1,164 +0,0 @@ ---------------------------------------------------------------------------- ---- Class module for parsing an index.theme file --- --- @author Kazunobu Kuriyama --- @copyright 2015 Kazunobu Kuriyama --- @classmod menubar.index_theme ---------------------------------------------------------------------------- - --- This implementation is based on the specifications: --- Icon Theme Specification 0.12 --- http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.12.html - -local ipairs = ipairs -local setmetatable = setmetatable -local string = string -local table = table -local io = io - --- index.theme groups -local ICON_THEME = "Icon Theme" --- index.theme keys -local DIRECTORIES = "Directories" -local INHERITS = "Inherits" --- per-directory subkeys -local TYPE = "Type" -local SIZE = "Size" -local MINSIZE = "MinSize" -local MAXSIZE = "MaxSize" -local THRESHOLD = "Threshold" - -local index_theme = { mt = {} } - ---- Class constructor of `index_theme` --- @tparam table cls Metatable that will be used. Should always be `index_theme.mt`. --- @tparam string icon_theme_name Internal name of icon theme --- @tparam table base_directories Paths used for lookup --- @treturn table An instance of the class `index_theme` -index_theme.new = function(cls, icon_theme_name, base_directories) - local self = {} - setmetatable(self, { __index = cls }) - - -- Initialize the fields - self.icon_theme_name = icon_theme_name - self.base_directory = nil - self[DIRECTORIES] = {} - self[INHERITS] = {} - self.per_directory_keys = {} - - -- base_directory - local basedir = nil - local handler = nil - for _, dir in ipairs(base_directories) do - basedir = dir .. "/" .. self.icon_theme_name - handler = io.open(basedir .. "/index.theme", "r") - if handler then - -- Use the index.theme which is found first. - break - end - end - if not handler then - return self - end - self.base_directory = basedir - - -- Parse index.theme. - while true do - local line = handler:read() - if not line then - break - end - - local group_header = "^%[(.+)%]$" - local group = line:match(group_header) - if group then - if group == ICON_THEME then - while true do - local item = handler:read() - if not item then - break - end - if item:match(group_header) then - handler:seek("cur", -string.len(item) - 1) - break - end - - local k, v = item:match("^(%w+)=(.*)$") - if k == DIRECTORIES or k == INHERITS then - string.gsub(v, "([^,]+),?", function(match) - table.insert(self[k], match) - end) - end - end - else - -- This must be a 'per-directory keys' group - local keys = {} - - while true do - local item = handler:read() - if not item then - break - end - if item:match(group_header) then - handler:seek("cur", -string.len(item) - 1) - break - end - - local k, v = item:match("^(%w+)=(%w+)$") - if k == SIZE or k == MINSIZE or k == MAXSIZE or k == THRESHOLD then - keys[k] = tonumber(v) - elseif k == TYPE then - keys[k] = v - end - end - - -- Size is a must. Other keys are optional. - if keys[SIZE] then - -- Set unset keys to the default values. - if not keys[TYPE] then keys[TYPE] = THRESHOLD end - if not keys[MINSIZE] then keys[MINSIZE] = keys[SIZE] end - if not keys[MAXSIZE] then keys[MAXSIZE] = keys[SIZE] end - if not keys[THRESHOLD] then keys[THRESHOLD] = 2 end - - self.per_directory_keys[group] = keys - end - end - end - end - - handler:close() - - return self -end - ---- Table of the values of the `Directories` key --- @treturn table Values of the `Directories` key -index_theme.get_subdirectories = function(self) - return self[DIRECTORIES] -end - ---- Table of the values of the `Inherits` key --- @treturn table Values of the `Inherits` key -index_theme.get_inherits = function(self) - return self[INHERITS] -end - ---- Query (part of) per-directory keys of a given subdirectory name. --- @tparam table subdirectory Icon theme's subdirectory --- @treturn[1] string Value of the `Type` key --- @treturn[2] number Value of the `Size` key --- @treturn[3] number VAlue of the `MinSize` key --- @treturn[4] number Value of the `MaxSize` key --- @treturn[5] number Value of the `Threshold` key -function index_theme:get_per_directory_keys(subdirectory) - local keys = self.per_directory_keys[subdirectory] - return keys[TYPE], keys[SIZE], keys[MINSIZE], keys[MAXSIZE], keys[THRESHOLD] -end - -index_theme.mt.__call = function(cls, icon_theme_name, base_directories) - return index_theme.new(cls, icon_theme_name, base_directories) -end - -return setmetatable(index_theme, index_theme.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/menubar/init.lua b/awesome/lib/menubar/init.lua deleted file mode 100644 index 10ad65c..0000000 --- a/awesome/lib/menubar/init.lua +++ /dev/null @@ -1,480 +0,0 @@ ---------------------------------------------------------------------------- ---- Menubar module, which aims to provide a freedesktop menu alternative --- --- List of menubar keybindings: --- --- --- --- * "Left" | "C-j" select an item on the left --- * "Right" | "C-k" select an item on the right --- * "Backspace" exit the current category if we are in any --- * "Escape" exit the current directory or exit menubar --- * "Home" select the first item --- * "End" select the last --- * "Return" execute the entry --- * "C-Return" execute the command with awful.spawn --- * "C-M-Return" execute the command in a terminal --- --- @author Alexander Yakushev <yakushev.alex@gmail.com> --- @copyright 2011-2012 Alexander Yakushev --- @module menubar ---------------------------------------------------------------------------- - --- Grab environment we need -local capi = { - client = client, - mouse = mouse, - screen = screen -} -local awful = require("awful") -local common = require("awful.widget.common") -local theme = require("beautiful") -local wibox = require("wibox") - -local function get_screen(s) - return s and capi.screen[s] -end - --- menubar -local menubar = { mt = {}, menu_entries = {} } -menubar.menu_gen = require("menubar.menu_gen") -menubar.utils = require("menubar.utils") -local compute_text_width = menubar.utils.compute_text_width - --- Options section - ---- When true the .desktop files will be reparsed only when the --- extension is initialized. Use this if menubar takes much time to --- open. --- @tfield[opt=true] boolean cache_entries -menubar.cache_entries = true - ---- When true the categories will be shown alongside application --- entries. --- @tfield[opt=true] boolean show_categories -menubar.show_categories = true - ---- Specifies the geometry of the menubar. This is a table with the keys --- x, y, width and height. Missing values are replaced via the screen's --- geometry. However, missing height is replaced by the font size. --- @table geometry --- @tfield number geometry.x A forced horizontal position --- @tfield number geometry.y A forced vertical position --- @tfield number geometry.width A forced width --- @tfield number geometry.height A forced height -menubar.geometry = { width = nil, - height = nil, - x = nil, - y = nil } - ---- Width of blank space left in the right side. --- @tfield number right_margin -menubar.right_margin = theme.xresources.apply_dpi(8) - ---- Label used for "Next page", default "▶▶". --- @tfield[opt="▶▶"] string right_label -menubar.right_label = "▶▶" - ---- Label used for "Previous page", default "◀◀". --- @tfield[opt="◀◀"] string left_label -menubar.left_label = "◀◀" - --- awful.widget.common.list_update adds three times a margin of dpi(4) --- for each item: --- @tfield number list_interspace -local list_interspace = theme.xresources.apply_dpi(4) * 3 - ---- Allows user to specify custom parameters for prompt.run function --- (like colors). --- @see awful.prompt -menubar.prompt_args = {} - --- Private section -local current_item = 1 -local previous_item = nil -local current_category = nil -local shownitems = nil -local instance = { prompt = nil, - widget = nil, - wibox = nil } - -local common_args = { w = wibox.layout.fixed.horizontal(), - data = setmetatable({}, { __mode = 'kv' }) } - ---- Wrap the text with the color span tag. --- @param s The text. --- @param c The desired text color. --- @return the text wrapped in a span tag. -local function colortext(s, c) - return "<span color='" .. awful.util.ensure_pango_color(c) .. "'>" .. s .. "</span>" -end - ---- Get how the menu item should be displayed. --- @param o The menu item. --- @return item name, item background color, background image, item icon. -local function label(o) - if o.focused then - return colortext(o.name, (theme.menu_fg_focus or theme.fg_focus)), (theme.menu_bg_focus or theme.bg_focus), nil, o.icon - else - return o.name, (theme.menu_bg_normal or theme.bg_normal), nil, o.icon - end -end - -local function load_count_table() - local count_file_name = awful.util.getdir("cache") .. "/menu_count_file" - - local count_file = io.open (count_file_name, "r") - local count_table = {} - - -- read weight file - if count_file then - io.input (count_file) - for line in io.lines() do - local name, count = string.match(line, "([^;]+);([^;]+)") - if name ~= nil and count ~= nil then - count_table[name] = count - end - end - end - - return count_table -end - -local function write_count_table(count_table) - local count_file_name = awful.util.getdir("cache") .. "/menu_count_file" - - local count_file = io.open (count_file_name, "w") - - if count_file then - io.output (count_file) - - for name, count in pairs(count_table) do - local str = string.format("%s;%d\n", name, count) - io.write(str) - end - io.flush() - end -end - ---- Perform an action for the given menu item. --- @param o The menu item. --- @return if the function processed the callback, new awful.prompt command, new awful.prompt prompt text. -local function perform_action(o) - if not o then return end - if o.key then - current_category = o.key - local new_prompt = shownitems[current_item].name .. ": " - previous_item = current_item - current_item = 1 - return true, "", new_prompt - elseif shownitems[current_item].cmdline then - awful.spawn(shownitems[current_item].cmdline) - - -- load count_table from cache file - local count_table = load_count_table() - - -- increase count - local curname = shownitems[current_item].name - if count_table[curname] ~= nil then - count_table[curname] = count_table[curname] + 1 - else - count_table[curname] = 1 - end - - -- write updated count table to cache file - write_count_table(count_table) - - -- Let awful.prompt execute dummy exec_callback and - -- done_callback to stop the keygrabber properly. - return false - end -end - --- Cut item list to return only current page. --- @tparam table all_items All items list. --- @tparam str query Search query. --- @tparam number|screen scr Screen --- @return table List of items for current page. -local function get_current_page(all_items, query, scr) - scr = get_screen(scr) - if not instance.prompt.width then - instance.prompt.width = compute_text_width(instance.prompt.prompt, scr) - end - if not menubar.left_label_width then - menubar.left_label_width = compute_text_width(menubar.left_label, scr) - end - if not menubar.right_label_width then - menubar.right_label_width = compute_text_width(menubar.right_label, scr) - end - local available_space = instance.geometry.width - menubar.right_margin - - menubar.right_label_width - menubar.left_label_width - - compute_text_width(query, scr) - instance.prompt.width - - local width_sum = 0 - local current_page = {} - for i, item in ipairs(all_items) do - item.width = item.width or - compute_text_width(item.name, scr) + - (item.icon and instance.geometry.height or 0) + list_interspace - if width_sum + item.width > available_space then - if current_item < i then - table.insert(current_page, { name = menubar.right_label, icon = nil }) - break - end - current_page = { { name = menubar.left_label, icon = nil }, item, } - width_sum = item.width - else - table.insert(current_page, item) - width_sum = width_sum + item.width - end - end - return current_page -end - ---- Update the menubar according to the command entered by user. --- @tparam str query Search query. --- @tparam number|screen scr Screen -local function menulist_update(query, scr) - query = query or "" - shownitems = {} - local pattern = awful.util.query_to_pattern(query) - - -- All entries are added to a list that will be sorted - -- according to the priority (first) and weight (second) of its - -- entries. - -- If categories are used in the menu, we add the entries matching - -- the current query with high priority as to ensure they are - -- displayed first. Afterwards the non-category entries are added. - -- All entries are weighted according to the number of times they - -- have been executed previously (stored in count_table). - - local count_table = load_count_table() - local command_list = {} - - local PRIO_NONE = 0 - local PRIO_CATEGORY_MATCH = 2 - - -- Add the categories - if menubar.show_categories then - for _, v in pairs(menubar.menu_gen.all_categories) do - v.focused = false - if not current_category and v.use then - - -- check if current query matches a category - if string.match(v.name, pattern) then - - v.weight = 0 - v.prio = PRIO_CATEGORY_MATCH - - -- get use count from count_table if present - -- and use it as weight - if string.len(pattern) > 0 and count_table[v.name] ~= nil then - v.weight = tonumber(count_table[v.name]) - end - - -- check for prefix match - if string.match(v.name, "^" .. pattern) then - -- increase default priority - v.prio = PRIO_CATEGORY_MATCH + 1 - else - v.prio = PRIO_CATEGORY_MATCH - end - - table.insert (command_list, v) - end - end - end - end - - -- Add the applications according to their name and cmdline - for _, v in ipairs(menubar.menu_entries) do - v.focused = false - if not current_category or v.category == current_category then - - -- check if the query matches either the name or the commandline - -- of some entry - if string.match(v.name, pattern) - or string.match(v.cmdline, pattern) then - - v.weight = 0 - v.prio = PRIO_NONE - - -- get use count from count_table if present - -- and use it as weight - if string.len(pattern) > 0 and count_table[v.name] ~= nil then - v.weight = tonumber(count_table[v.name]) - end - - -- check for prefix match - if string.match(v.name, "^" .. pattern) - or string.match(v.cmdline, "^" .. pattern) then - -- increase default priority - v.prio = PRIO_NONE + 1 - else - v.prio = PRIO_NONE - end - - table.insert (command_list, v) - end - end - end - - local function compare_counts(a, b) - if a.prio == b.prio then - return a.weight > b.weight - end - return a.prio > b.prio - end - - -- sort command_list by weight (highest first) - table.sort(command_list, compare_counts) - -- copy into showitems - shownitems = command_list - - if #shownitems > 0 then - -- Insert a run item value as the last choice - table.insert(shownitems, { name = "Exec: " .. query, cmdline = query, icon = nil }) - - if current_item > #shownitems then - current_item = #shownitems - end - shownitems[current_item].focused = true - else - table.insert(shownitems, { name = "", cmdline = query, icon = nil }) - end - - common.list_update(common_args.w, nil, label, - common_args.data, - get_current_page(shownitems, query, scr)) -end - ---- Create the menubar wibox and widgets. --- @tparam[opt] screen scr Screen. -local function initialize(scr) - instance.wibox = wibox({}) - instance.widget = menubar.get(scr) - instance.wibox.ontop = true - instance.prompt = awful.widget.prompt() - local layout = wibox.layout.fixed.horizontal() - layout:add(instance.prompt) - layout:add(instance.widget) - instance.wibox:set_widget(layout) -end - ---- Refresh menubar's cache by reloading .desktop files. --- @tparam[opt] screen scr Screen. -function menubar.refresh(scr) - menubar.menu_gen.generate(function(entries) - menubar.menu_entries = entries - menulist_update(nil, scr) - end) -end - ---- Awful.prompt keypressed callback to be used when the user presses a key. --- @param mod Table of key combination modifiers (Control, Shift). --- @param key The key that was pressed. --- @param comm The current command in the prompt. --- @return if the function processed the callback, new awful.prompt command, new awful.prompt prompt text. -local function prompt_keypressed_callback(mod, key, comm) - if key == "Left" or (mod.Control and key == "j") then - current_item = math.max(current_item - 1, 1) - return true - elseif key == "Right" or (mod.Control and key == "k") then - current_item = current_item + 1 - return true - elseif key == "BackSpace" then - if comm == "" and current_category then - current_category = nil - current_item = previous_item - return true, nil, "Run: " - end - elseif key == "Escape" then - if current_category then - current_category = nil - current_item = previous_item - return true, nil, "Run: " - end - elseif key == "Home" then - current_item = 1 - return true - elseif key == "End" then - current_item = #shownitems - return true - elseif key == "Return" or key == "KP_Enter" then - if mod.Control then - current_item = #shownitems - if mod.Mod1 then - -- add a terminal to the cmdline - shownitems[current_item].cmdline = menubar.utils.terminal - .. " -e " .. shownitems[current_item].cmdline - end - end - return perform_action(shownitems[current_item]) - end - return false -end - ---- Show the menubar on the given screen. --- @param scr Screen. -function menubar.show(scr) - if not instance.wibox then - initialize(scr) - elseif instance.wibox.visible then -- Menu already shown, exit - return - elseif not menubar.cache_entries then - menubar.refresh(scr) - end - - -- Set position and size - scr = scr or awful.screen.focused() or 1 - scr = get_screen(scr) - local scrgeom = scr.workarea - local geometry = menubar.geometry - instance.geometry = {x = geometry.x or scrgeom.x, - y = geometry.y or scrgeom.y, - height = geometry.height or awful.util.round(theme.get_font_height() * 1.5), - width = geometry.width or scrgeom.width} - instance.wibox:geometry(instance.geometry) - - current_item = 1 - current_category = nil - menulist_update(nil, scr) - - local prompt_args = menubar.prompt_args or {} - - awful.prompt.run(setmetatable({ - prompt = "Run: ", - textbox = instance.prompt.widget, - completion_callback = awful.completion.shell, - history_path = awful.util.get_cache_dir() .. "/history_menu", - done_callback = menubar.hide, - changed_callback = function(query) menulist_update(query, scr) end, - keypressed_callback = prompt_keypressed_callback - }, {__index=prompt_args})) - - instance.wibox.visible = true -end - ---- Hide the menubar. -function menubar.hide() - instance.wibox.visible = false -end - ---- Get a menubar wibox. --- @tparam[opt] screen scr Screen. --- @return menubar wibox. -function menubar.get(scr) - menubar.refresh(scr) - -- Add to each category the name of its key in all_categories - for k, v in pairs(menubar.menu_gen.all_categories) do - v.key = k - end - return common_args.w -end - -function menubar.mt.__call(_, ...) - return menubar.get(...) -end - -return setmetatable(menubar, menubar.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/menubar/menu_gen.lua b/awesome/lib/menubar/menu_gen.lua deleted file mode 100644 index ed2aa14..0000000 --- a/awesome/lib/menubar/menu_gen.lua +++ /dev/null @@ -1,141 +0,0 @@ ---------------------------------------------------------------------------- ---- Menu generation module for menubar --- --- @author Antonio Terceiro --- @copyright 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev --- @module menubar.menu_gen ---------------------------------------------------------------------------- - --- Grab environment -local utils = require("menubar.utils") -local icon_theme = require("menubar.icon_theme") -local pairs = pairs -local ipairs = ipairs -local string = string -local table = table - -local menu_gen = {} - --- Options section - -local data_dir = os.getenv("XDG_DATA_HOME") -if not data_dir then - data_dir = os.getenv("HOME") .. '/.local/share/' -end - ---- Specifies all directories where menubar should look for .desktop --- files. The search is recursive. -menu_gen.all_menu_dirs = { data_dir .. 'applications/', '/usr/share/applications/', '/usr/local/share/applications/' } - ---- Specify the mapping of .desktop Categories section to the --- categories in the menubar. If "use" flag is set to false then any of --- the applications that fall only to this category will not be shown. -menu_gen.all_categories = { - multimedia = { app_type = "AudioVideo", name = "Multimedia", - icon_name = "applications-multimedia", use = true }, - development = { app_type = "Development", name = "Development", - icon_name = "applications-development", use = true }, - education = { app_type = "Education", name = "Education", - icon_name = "applications-science", use = true }, - games = { app_type = "Game", name = "Games", - icon_name = "applications-games", use = true }, - graphics = { app_type = "Graphics", name = "Graphics", - icon_name = "applications-graphics", use = true }, - office = { app_type = "Office", name = "Office", - icon_name = "applications-office", use = true }, - internet = { app_type = "Network", name = "Internet", - icon_name = "applications-internet", use = true }, - settings = { app_type = "Settings", name = "Settings", - icon_name = "applications-utilities", use = true }, - tools = { app_type = "System", name = "System Tools", - icon_name = "applications-system", use = true }, - utility = { app_type = "Utility", name = "Accessories", - icon_name = "applications-accessories", use = true } -} - ---- Find icons for category entries. -function menu_gen.lookup_category_icons() - for _, v in pairs(menu_gen.all_categories) do - v.icon = icon_theme():find_icon_path(v.icon_name) - end -end - ---- Get category key name and whether it is used by its app_type. --- @param app_type Application category as written in .desktop file. --- @return category key name in all_categories, whether the category is used -local function get_category_name_and_usage_by_type(app_type) - for k, v in pairs(menu_gen.all_categories) do - if app_type == v.app_type then - return k, v.use - end - end -end - ---- Remove CR\LF newline from the end of the string. --- @param s string to trim -local function trim(s) - if not s then return end - if string.byte(s, #s) == 13 then - return string.sub(s, 1, #s - 1) - end - return s -end - ---- Generate an array of all visible menu entries. --- @tparam function callback Will be fired when all menu entries were parsed --- with the resulting list of menu entries as argument. --- @tparam table callback.entries All menu entries. -function menu_gen.generate(callback) - -- Update icons for category entries - menu_gen.lookup_category_icons() - - local result = {} - local unique_entries = {} - local dirs_parsed = 0 - - for _, dir in ipairs(menu_gen.all_menu_dirs) do - utils.parse_dir(dir, function(entries) - entries = entries or {} - for _, entry in ipairs(entries) do - -- Check whether to include program in the menu - if entry.show and entry.Name and entry.cmdline then - local unique_key = entry.Name .. '\0' .. entry.cmdline - if not unique_entries[unique_key] then - local target_category = nil - -- Check if the program falls into at least one of the - -- usable categories. Set target_category to be the id - -- of the first category it finds. - if entry.categories then - for _, category in pairs(entry.categories) do - local cat_key, cat_use = - get_category_name_and_usage_by_type(category) - if cat_key and cat_use then - target_category = cat_key - break - end - end - end - if target_category then - local name = trim(entry.Name) or "" - local cmdline = trim(entry.cmdline) or "" - local icon = entry.icon_path or nil - table.insert(result, { name = name, - cmdline = cmdline, - icon = icon, - category = target_category }) - unique_entries[unique_key] = true - end - end - end - end - dirs_parsed = dirs_parsed + 1 - if dirs_parsed == #menu_gen.all_menu_dirs then - callback(result) - end - end) - end -end - -return menu_gen - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/menubar/utils.lua b/awesome/lib/menubar/utils.lua deleted file mode 100644 index 6f80e86..0000000 --- a/awesome/lib/menubar/utils.lua +++ /dev/null @@ -1,316 +0,0 @@ ---------------------------------------------------------------------------- ---- Utility module for menubar --- --- @author Antonio Terceiro --- @copyright 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev --- @module menubar.utils ---------------------------------------------------------------------------- - --- Grab environment -local io = io -local table = table -local ipairs = ipairs -local string = string -local screen = screen -local awful_util = require("awful.util") -local theme = require("beautiful") -local lgi = require("lgi") -local gio = lgi.Gio -local glib = lgi.GLib -local wibox = require("wibox") -local debug = require("gears.debug") -local protected_call = require("gears.protected_call") - -local utils = {} - --- NOTE: This icons/desktop files module was written according to the --- following freedesktop.org specifications: --- Icons: http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.11.html --- Desktop files: http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - --- Options section - ---- Terminal which applications that need terminal would open in. -utils.terminal = 'xterm' - ---- The default icon for applications that don't provide any icon in --- their .desktop files. -local default_icon = nil - ---- Name of the WM for the OnlyShownIn entry in the .desktop file. -utils.wm_name = "awesome" - --- Private section - -local all_icon_sizes = { - '128x128' , - '96x96', - '72x72', - '64x64', - '48x48', - '36x36', - '32x32', - '24x24', - '22x22', - '16x16' -} - ---- List of supported icon formats. -local icon_formats = { "png", "xpm", "svg" } - ---- Check whether the icon format is supported. --- @param icon_file Filename of the icon. --- @return true if format is supported, false otherwise. -local function is_format_supported(icon_file) - for _, f in ipairs(icon_formats) do - if icon_file:match('%.' .. f) then - return true - end - end - return false -end - -local icon_lookup_path = nil ---- Get a list of icon lookup paths. --- @treturn table A list of directories, without trailing slash. -local function get_icon_lookup_path() - if not icon_lookup_path then - local add_if_readable = function(t, path) - if awful_util.dir_readable(path) then - table.insert(t, path) - end - end - icon_lookup_path = {} - local icon_theme_paths = {} - local icon_theme = theme.icon_theme - local paths = glib.get_system_data_dirs() - table.insert(paths, 1, glib.get_user_data_dir()) - table.insert(paths, 1, glib.build_filenamev({glib.get_home_dir(), - '.icons'})) - for _,dir in ipairs(paths) do - local icons_dir = glib.build_filenamev({dir, 'icons'}) - if awful_util.dir_readable(icons_dir) then - if icon_theme then - add_if_readable(icon_theme_paths, - glib.build_filenamev({icons_dir, - icon_theme})) - end - -- Fallback theme. - add_if_readable(icon_theme_paths, - glib.build_filenamev({icons_dir, 'hicolor'})) - end - end - for _, icon_theme_directory in ipairs(icon_theme_paths) do - for _, size in ipairs(all_icon_sizes) do - add_if_readable(icon_lookup_path, - glib.build_filenamev({icon_theme_directory, - size, 'apps'})) - end - end - for _,dir in ipairs(paths)do - -- lowest priority fallbacks - add_if_readable(icon_lookup_path, - glib.build_filenamev({dir, 'pixmaps'})) - add_if_readable(icon_lookup_path, - glib.build_filenamev({dir, 'icons'})) - end - end - return icon_lookup_path -end - ---- Lookup an icon in different folders of the filesystem. --- @tparam string icon_file Short or full name of the icon. --- @treturn string|boolean Full name of the icon, or false on failure. -function utils.lookup_icon_uncached(icon_file) - if not icon_file or icon_file == "" then - return false - end - - if icon_file:sub(1, 1) == '/' and is_format_supported(icon_file) then - -- If the path to the icon is absolute and its format is - -- supported, do not perform a lookup. - return awful_util.file_readable(icon_file) and icon_file or nil - else - for _, directory in ipairs(get_icon_lookup_path()) do - if is_format_supported(icon_file) and - awful_util.file_readable(directory .. "/" .. icon_file) then - return directory .. "/" .. icon_file - else - -- Icon is probably specified without path and format, - -- like 'firefox'. Try to add supported extensions to - -- it and see if such file exists. - for _, format in ipairs(icon_formats) do - local possible_file = directory .. "/" .. icon_file .. "." .. format - if awful_util.file_readable(possible_file) then - return possible_file - end - end - end - end - return false - end -end - -local lookup_icon_cache = {} ---- Lookup an icon in different folders of the filesystem (cached). --- @param icon Short or full name of the icon. --- @return full name of the icon. -function utils.lookup_icon(icon) - if not lookup_icon_cache[icon] and lookup_icon_cache[icon] ~= false then - lookup_icon_cache[icon] = utils.lookup_icon_uncached(icon) - end - return lookup_icon_cache[icon] or default_icon -end - ---- Parse a .desktop file. --- @param file The .desktop file. --- @return A table with file entries. -function utils.parse_desktop_file(file) - local program = { show = true, file = file } - local desktop_entry = false - - -- Parse the .desktop file. - -- We are interested in [Desktop Entry] group only. - for line in io.lines(file) do - if line:find("^%s*#") then - -- Skip comments. - (function() end)() -- I haven't found a nice way to silence luacheck here - elseif not desktop_entry and line == "[Desktop Entry]" then - desktop_entry = true - else - if line:sub(1, 1) == "[" and line:sub(-1) == "]" then - -- A declaration of new group - stop parsing - break - end - - -- Grab the values - for key, value in line:gmatch("(%w+)%s*=%s*(.+)") do - program[key] = value - end - end - end - - -- In case [Desktop Entry] was not found - if not desktop_entry then return nil end - - -- In case the (required) 'Name' entry was not found - if not program.Name or program.Name == '' then return nil end - - -- Don't show program if NoDisplay attribute is false - if program.NoDisplay and string.lower(program.NoDisplay) == "true" then - program.show = false - end - - -- Only show the program if there is no OnlyShowIn attribute - -- or if it's equal to utils.wm_name - if program.OnlyShowIn ~= nil and not program.OnlyShowIn:match(utils.wm_name) then - program.show = false - end - - -- Look up for a icon. - if program.Icon then - program.icon_path = utils.lookup_icon(program.Icon) - end - - -- Split categories into a table. Categories are written in one - -- line separated by semicolon. - if program.Categories then - program.categories = {} - for category in program.Categories:gmatch('[^;]+') do - table.insert(program.categories, category) - end - end - - if program.Exec then - -- Substitute Exec special codes as specified in - -- http://standards.freedesktop.org/desktop-entry-spec/1.1/ar01s06.html - if program.Name == nil then - program.Name = '['.. file:match("([^/]+)%.desktop$") ..']' - end - local cmdline = program.Exec:gsub('%%c', program.Name) - cmdline = cmdline:gsub('%%[fuFU]', '') - cmdline = cmdline:gsub('%%k', program.file) - if program.icon_path then - cmdline = cmdline:gsub('%%i', '--icon ' .. program.icon_path) - else - cmdline = cmdline:gsub('%%i', '') - end - if program.Terminal == "true" then - cmdline = utils.terminal .. ' -e ' .. cmdline - end - program.cmdline = cmdline - end - - return program -end - ---- Parse a directory with .desktop files recursively. --- @tparam string dir_path The directory path. --- @tparam function callback Will be fired when all the files were parsed --- with the resulting list of menu entries as argument. --- @tparam table callback.programs Paths of found .desktop files. -function utils.parse_dir(dir_path, callback) - - local function parser(dir, programs) - local f = gio.File.new_for_path(dir) - -- Except for "NONE" there is also NOFOLLOW_SYMLINKS - local query = gio.FILE_ATTRIBUTE_STANDARD_NAME .. "," .. gio.FILE_ATTRIBUTE_STANDARD_TYPE - local enum, err = f:async_enumerate_children(query, gio.FileQueryInfoFlags.NONE) - if not enum then - debug.print_error(err) - return - end - local files_per_call = 100 -- Actual value is not that important - while true do - local list, enum_err = enum:async_next_files(files_per_call) - if enum_err then - debug.print_error(enum_err) - return - end - for _, info in ipairs(list) do - local file_type = info:get_file_type() - local file_path = enum:get_child(info):get_path() - if file_type == 'REGULAR' then - local program = utils.parse_desktop_file(file_path) - if program then - table.insert(programs, program) - end - elseif file_type == 'DIRECTORY' then - parser(file_path, programs) - end - end - if #list == 0 then - break - end - end - enum:async_close() - end - - gio.Async.start(function() - local result = {} - parser(dir_path, result) - protected_call.call(callback, result) - end)() -end - ---- Compute textbox width. --- @tparam wibox.widget.textbox textbox Textbox instance. --- @tparam number|screen s Screen --- @treturn int Text width. -function utils.compute_textbox_width(textbox, s) - s = screen[s or mouse.screen] - local w, _ = textbox:get_preferred_size(s) - return w -end - ---- Compute text width. --- @tparam str text Text. --- @tparam number|screen s Screen --- @treturn int Text width. -function utils.compute_text_width(text, s) - return utils.compute_textbox_width(wibox.widget.textbox(awful_util.escape(text)), s) -end - -return utils - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/naughty.lua b/awesome/lib/naughty.lua deleted file mode 100644 index 89eac7c..0000000 --- a/awesome/lib/naughty.lua +++ /dev/null @@ -1,7 +0,0 @@ --- Work-around for broken systems which are updated by overwriting the awesome --- installation. This would not remove naughty.lua from older awesome versions --- and thus breakage follows. --- The work-around is to use a pointless naughty.lua file. -return require("naughty.init") - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/naughty/core.lua b/awesome/lib/naughty/core.lua deleted file mode 100644 index 764afe2..0000000 --- a/awesome/lib/naughty/core.lua +++ /dev/null @@ -1,688 +0,0 @@ ----------------------------------------------------------------------------- ---- Notification library --- --- @author koniu <gkusnierz@gmail.com> --- @copyright 2008 koniu --- @module naughty ----------------------------------------------------------------------------- - --- Package environment -local pairs = pairs -local table = table -local type = type -local string = string -local pcall = pcall -local capi = { screen = screen, - awesome = awesome } -local timer = require("gears.timer") -local button = require("awful.button") -local screen = require("awful.screen") -local util = require("awful.util") -local bt = require("beautiful") -local wibox = require("wibox") -local surface = require("gears.surface") -local cairo = require("lgi").cairo -local dpi = require("beautiful").xresources.apply_dpi - -local function get_screen(s) - return s and capi.screen[s] -end - -local naughty = {} - ---[[-- -Naughty configuration - a table containing common popup settings. - -@table naughty.config -@tfield[opt=apply_dpi(4)] int padding Space between popups and edge of the - workarea. -@tfield[opt=apply_dpi(1)] int spacing Spacing between popups. -@tfield[opt={"/usr/share/pixmaps/"}] table icon_dirs List of directories - that will be checked by `getIcon()`. -@tfield[opt={ "png", "gif" }] table icon_formats List of formats that will be - checked by `getIcon()`. -@tfield[opt] function notify_callback Callback used to modify or reject -notifications, e.g. - naughty.config.notify_callback = function(args) - args.text = 'prefix: ' .. args.text - return args - end - -@tfield table presets Notification presets. See `config.presets`. - -@tfield table defaults Default values for the params to `notify()`. These can - optionally be overridden by specifying a preset. See `config.defaults`. - ---]] --- -naughty.config = { - padding = dpi(4), - spacing = dpi(1), - icon_dirs = { "/usr/share/pixmaps/", }, - icon_formats = { "png", "gif" }, - notify_callback = nil, -} - ---- Notification presets for `naughty.notify`. --- This holds presets for different purposes. A preset is a table of any --- parameters for `notify()`, overriding the default values --- (`naughty.config.defaults`). --- --- You have to pass a reference of a preset in your `notify()` as the `preset` --- argument. --- --- The presets `"low"`, `"normal"` and `"critical"` are used for notifications --- over DBUS. --- --- @table config.presets --- @tfield table low The preset for notifications with low urgency level. --- @tfield[opt=5] int low.timeout --- @tfield[opt=empty] table normal The default preset for every notification without a --- preset that will also be used for normal urgency level. --- @tfield table critical The preset for notifications with a critical urgency --- level. --- @tfield[opt="#ff0000"] string critical.bg --- @tfield[opt="#ffffff"] string critical.fg --- @tfield[opt=0] string critical.timeout -naughty.config.presets = { - low = { - timeout = 5 - }, - normal = {}, - critical = { - bg = "#ff0000", - fg = "#ffffff", - timeout = 0, - } -} - ---- Defaults for `naughty.notify`. --- --- @table config.defaults --- @tfield[opt=5] int timeout --- @tfield[opt=""] string text --- @tfield[opt] int screen Defaults to `awful.screen.focused`. --- @tfield[opt=true] boolean ontop --- @tfield[opt=apply_dpi(5)] int margin --- @tfield[opt=apply_dpi(1)] int border_width --- @tfield[opt="top_right"] string position -naughty.config.defaults = { - timeout = 5, - text = "", - screen = nil, - ontop = true, - margin = dpi(5), - border_width = dpi(1), - position = "top_right" -} - -naughty.notificationClosedReason = { - silent = -1, - expired = 1, - dismissedByUser = 2, - dismissedByCommand = 3, - undefined = 4 -} - --- Counter for the notifications --- Required for later access via DBUS -local counter = 1 - --- True if notifying is suspended -local suspended = false - ---- Index of notifications per screen and position. --- See config table for valid 'position' values. --- Each element is a table consisting of: --- --- @field box Wibox object containing the popup --- @field height Popup height --- @field width Popup width --- @field die Function to be executed on timeout --- @field id Unique notification id based on a counter --- @table notifications -naughty.notifications = { suspended = { } } -screen.connect_for_each_screen(function(s) - naughty.notifications[s] = { - top_left = {}, - top_middle = {}, - top_right = {}, - bottom_left = {}, - bottom_middle = {}, - bottom_right = {}, - } -end) - -capi.screen.connect_signal("removed", function(scr) - -- Destroy all notifications on this screen - for _, list in pairs(naughty.notifications[scr]) do - while #list > 0 do - naughty.destroy(list[1]) - end - end - naughty.notifications[scr] = nil -end) - ---- Notification state -function naughty.is_suspended() - return suspended -end - ---- Suspend notifications -function naughty.suspend() - suspended = true -end - ---- Resume notifications -function naughty.resume() - suspended = false - for _, v in pairs(naughty.notifications.suspended) do - v.box.visible = true - if v.timer then v.timer:start() end - end - naughty.notifications.suspended = { } -end - ---- Toggle notification state -function naughty.toggle() - if suspended then - naughty.resume() - else - naughty.suspend() - end -end - ---- Evaluate desired position of the notification by index - internal --- --- @param s Screen to use --- @param position top_right | top_left | bottom_right | bottom_left --- | top_middle | bottom_middle --- @param idx Index of the notification --- @param[opt] width Popup width. --- @param height Popup height --- @return Absolute position and index in { x = X, y = Y, idx = I } table -local function get_offset(s, position, idx, width, height) - s = get_screen(s) - local ws = s.workarea - local v = {} - idx = idx or #naughty.notifications[s][position] + 1 - width = width or naughty.notifications[s][position][idx].width - - -- calculate x - if position:match("left") then - v.x = ws.x + naughty.config.padding - elseif position:match("middle") then - v.x = (ws.width / 2) - (width / 2) - else - v.x = ws.x + ws.width - (width + naughty.config.padding) - end - - -- calculate existing popups' height - local existing = 0 - for i = 1, idx-1, 1 do - existing = existing + naughty.notifications[s][position][i].height + naughty.config.spacing - end - - -- calculate y - if position:match("top") then - v.y = ws.y + naughty.config.padding + existing - else - v.y = ws.y + ws.height - (naughty.config.padding + height + existing) - end - - -- Find old notification to replace in case there is not enough room. - -- This tries to skip permanent notifications (without a timeout), - -- e.g. critical ones. - local find_old_to_replace = function() - for i = 1, idx-1 do - local n = naughty.notifications[s][position][i] - if n.timeout > 0 then - return n - end - end - -- Fallback to first one. - return naughty.notifications[s][position][1] - end - - -- if positioned outside workarea, destroy oldest popup and recalculate - if v.y + height > ws.y + ws.height or v.y < ws.y then - naughty.destroy(find_old_to_replace()) - idx = idx - 1 - v = get_offset(s, position, idx, width, height) - end - if not v.idx then v.idx = idx end - - return v -end - ---- Re-arrange notifications according to their position and index - internal --- --- @return None -local function arrange(s) - for p in pairs(naughty.notifications[s]) do - for i,notification in pairs(naughty.notifications[s][p]) do - local offset = get_offset(s, p, i, notification.width, notification.height) - notification.box:geometry({ x = offset.x, y = offset.y }) - notification.idx = offset.idx - end - end -end - ---- Destroy notification by notification object --- --- @param notification Notification object to be destroyed --- @param reason One of the reasons from notificationClosedReason --- @return True if the popup was successfully destroyed, nil otherwise -function naughty.destroy(notification, reason) - if notification and notification.box.visible then - if suspended then - for k, v in pairs(naughty.notifications.suspended) do - if v.box == notification.box then - table.remove(naughty.notifications.suspended, k) - break - end - end - end - local scr = notification.screen - table.remove(naughty.notifications[scr][notification.position], notification.idx) - if notification.timer then - notification.timer:stop() - end - notification.box.visible = false - arrange(scr) - if notification.destroy_cb and reason ~= naughty.notificationClosedReason.silent then - notification.destroy_cb(reason or naughty.notificationClosedReason.undefined) - end - return true - end -end - ---- Get notification by ID --- --- @param id ID of the notification --- @return notification object if it was found, nil otherwise -function naughty.getById(id) - -- iterate the notifications to get the notfications with the correct ID - for s in pairs(naughty.notifications) do - for p in pairs(naughty.notifications[s]) do - for _, notification in pairs(naughty.notifications[s][p]) do - if notification.id == id then - return notification - end - end - end - end -end - ---- Install expiration timer for notification object. --- @tparam notification notification Notification object. --- @tparam number timeout Time in seconds to be set as expiration timeout. -local function set_timeout(notification, timeout) - local die = function (reason) - naughty.destroy(notification, reason) - end - if timeout > 0 then - local timer_die = timer { timeout = timeout } - timer_die:connect_signal("timeout", function() die(naughty.notificationClosedReason.expired) end) - if not suspended then - timer_die:start() - end - notification.timer = timer_die - end - notification.die = die -end - ---- Set new notification timeout. --- @tparam notification notification Notification object, which timer is to be reset. --- @tparam number new_timeout Time in seconds after which notification disappears. --- @return None. -function naughty.reset_timeout(notification, new_timeout) - if notification.timer then notification.timer:stop() end - - local timeout = new_timeout or notification.timeout - set_timeout(notification, timeout) - notification.timeout = timeout - - notification.timer:start() -end - ---- Escape and set title and text for notification object. --- @tparam notification notification Notification object. --- @tparam string title Title of notification. --- @tparam string text Main text of notification. --- @return None. -local function set_text(notification, title, text) - local escape_pattern = "[<>&]" - local escape_subs = { ['<'] = "<", ['>'] = ">", ['&'] = "&" } - - local textbox = notification.textbox - - local function setMarkup(pattern, replacements) - return textbox:set_markup_silently(string.format('<b>%s</b>%s', title, text:gsub(pattern, replacements))) - end - local function setText() - textbox:set_text(string.format('%s %s', title, text)) - end - - -- Since the title cannot contain markup, it must be escaped first so that - -- it is not interpreted by Pango later. - title = title:gsub(escape_pattern, escape_subs) - -- Try to set the text while only interpreting <br>. - if not setMarkup("<br.->", "\n") then - -- That failed, escape everything which might cause an error from pango - if not setMarkup(escape_pattern, escape_subs) then - -- Ok, just ignore all pango markup. If this fails, we got some invalid utf8 - if not pcall(setText) then - textbox:set_markup("<i><Invalid markup or UTF8, cannot display message></i>") - end - end - end -end - ---- Replace title and text of an existing notification. --- @tparam notification notification Notification object, which contents are to be replaced. --- @tparam string new_title New title of notification. If not specified, old title remains unchanged. --- @tparam string new_text New text of notification. If not specified, old text remains unchanged. --- @return None. -function naughty.replace_text(notification, new_title, new_text) - local title = new_title - - if title then title = title .. "\n" else title = "" end - - set_text(notification, title, new_text) -end - ---- Create a notification. --- --- @tab args The argument table containing any of the arguments below. --- @string[opt=""] args.text Text of the notification. --- @string[opt] args.title Title of the notification. --- @int[opt=5] args.timeout Time in seconds after which popup expires. --- Set 0 for no timeout. --- @int[opt] args.hover_timeout Delay in seconds after which hovered popup disappears. --- @tparam[opt=focused] integer|screen args.screen Target screen for the notification. --- @string[opt="top_right"] args.position Corner of the workarea displaying the popups. --- Values: `"top_right"`, `"top_left"`, `"bottom_left"`, --- `"bottom_right"`, `"top_middle"`, `"bottom_middle"`. --- @bool[opt=true] args.ontop Boolean forcing popups to display on top. --- @int[opt=auto] args.height Popup height. --- @int[opt=auto] args.width Popup width. --- @string[opt=beautiful.font or awesome.font] args.font Notification font. --- @string[opt] args.icon Path to icon. --- @int[opt] args.icon_size Desired icon size in px. --- @string[opt=`beautiful.fg_focus` or `'#ffffff'`] args.fg Foreground color. --- @string[opt=`beautiful.bg_focus` or `'#535d6c'`] args.bg Background color. --- @int[opt=1] args.border_width Border width. --- @string[opt=`beautiful.border_focus` or `'#535d6c'`] args.border_color Border color. --- @tparam[opt] func args.run Function to run on left click. The notification --- object will be passed to it as an argument. --- You need to call e.g. --- `notification.die(naughty.notificationClosedReason.dismissedByUser)` from --- there to dismiss the notification yourself. --- @tparam[opt] func args.destroy Function to run when notification is destroyed. --- @tparam[opt] table args.preset Table with any of the above parameters. --- Note: Any parameters specified directly in args will override ones defined --- in the preset. --- @tparam[opt] int args.replaces_id Replace the notification with the given ID. --- @tparam[opt] func args.callback Function that will be called with all arguments. --- The notification will only be displayed if the function returns true. --- Note: this function is only relevant to notifications sent via dbus. --- @tparam[opt] table args.actions Mapping that maps a string to a callback when this --- action is selected. --- @usage naughty.notify({ title = "Achtung!", text = "You're idling", timeout = 0 }) --- @treturn ?table The notification object, or nil in case a notification was --- not displayed. -function naughty.notify(args) - if naughty.config.notify_callback then - args = naughty.config.notify_callback(args) - if not args then return end - end - - -- gather variables together - local preset = util.table.join(naughty.config.defaults or {}, - args.preset or naughty.config.presets.normal or {}) - local timeout = args.timeout or preset.timeout - local icon = args.icon or preset.icon - local icon_size = args.icon_size or preset.icon_size - local text = args.text or preset.text - local title = args.title or preset.title - local s = get_screen(args.screen or preset.screen or screen.focused()) - if not s then - local err = "naughty.notify: there is no screen available to display the following notification:" - err = string.format("%s title='%s' text='%s'", err, tostring(title or ""), tostring(text or "")) - require("gears.debug").print_warning(err) - return - end - local ontop = args.ontop or preset.ontop - local width = args.width or preset.width - local height = args.height or preset.height - local hover_timeout = args.hover_timeout or preset.hover_timeout - local opacity = args.opacity or preset.opacity - local margin = args.margin or preset.margin - local border_width = args.border_width or preset.border_width - local position = args.position or preset.position - local actions = args.actions - local destroy_cb = args.destroy - - -- beautiful - local beautiful = bt.get() - local font = args.font or preset.font or beautiful.font or capi.awesome.font - local fg = args.fg or preset.fg or beautiful.fg_normal or '#ffffff' - local bg = args.bg or preset.bg or beautiful.bg_normal or '#535d6c' - local border_color = args.border_color or preset.border_color or beautiful.bg_focus or '#535d6c' - local notification = { screen = s, destroy_cb = destroy_cb, timeout = timeout } - - -- replace notification if needed - if args.replaces_id then - local obj = naughty.getById(args.replaces_id) - if obj then - -- destroy this and ... - naughty.destroy(obj, naughty.notificationClosedReason.silent) - end - -- ... may use its ID - if args.replaces_id <= counter then - notification.id = args.replaces_id - else - counter = counter + 1 - notification.id = counter - end - else - -- get a brand new ID - counter = counter + 1 - notification.id = counter - end - - notification.position = position - - if title then title = title .. "\n" else title = "" end - - -- hook destroy - set_timeout(notification, timeout) - local die = notification.die - - local run = function () - if args.run then - args.run(notification) - else - die(naughty.notificationClosedReason.dismissedByUser) - end - end - - local hover_destroy = function () - if hover_timeout == 0 then - die(naughty.notificationClosedReason.expired) - else - if notification.timer then notification.timer:stop() end - notification.timer = timer { timeout = hover_timeout } - notification.timer:connect_signal("timeout", function() die(naughty.notificationClosedReason.expired) end) - notification.timer:start() - end - end - - -- create textbox - local textbox = wibox.widget.textbox() - local marginbox = wibox.container.margin() - marginbox:set_margins(margin) - marginbox:set_widget(textbox) - textbox:set_valign("middle") - textbox:set_font(font) - - notification.textbox = textbox - - set_text(notification, title, text) - - local actionslayout = wibox.layout.fixed.vertical() - local actions_max_width = 0 - local actions_total_height = 0 - if actions then - for action, callback in pairs(actions) do - local actiontextbox = wibox.widget.textbox() - local actionmarginbox = wibox.container.margin() - actionmarginbox:set_margins(margin) - actionmarginbox:set_widget(actiontextbox) - actiontextbox:set_valign("middle") - actiontextbox:set_font(font) - actiontextbox:set_markup(string.format('☛ <u>%s</u>', action)) - -- calculate the height and width - local w, h = actiontextbox:get_preferred_size(s) - local action_height = h + 2 * margin - local action_width = w + 2 * margin - - actionmarginbox:buttons(util.table.join( - button({ }, 1, callback), - button({ }, 3, callback) - )) - actionslayout:add(actionmarginbox) - - actions_total_height = actions_total_height + action_height - if actions_max_width < action_width then - actions_max_width = action_width - end - end - end - - -- create iconbox - local iconbox = nil - local iconmargin = nil - local icon_w, icon_h = 0, 0 - if icon then - -- Is this really an URI instead of a path? - if type(icon) == "string" and string.sub(icon, 1, 7) == "file://" then - icon = string.sub(icon, 8) - end - -- try to guess icon if the provided one is non-existent/readable - if type(icon) == "string" and not util.file_readable(icon) then - icon = util.geticonpath(icon, naughty.config.icon_formats, naughty.config.icon_dirs, icon_size) or icon - end - - -- is the icon file readable? - icon = surface.load_uncached(icon) - - -- if we have an icon, use it - if icon then - iconbox = wibox.widget.imagebox() - iconmargin = wibox.container.margin(iconbox, margin, margin, margin, margin) - if icon_size then - local scaled = cairo.ImageSurface(cairo.Format.ARGB32, icon_size, icon_size) - local cr = cairo.Context(scaled) - cr:scale(icon_size / icon:get_height(), icon_size / icon:get_width()) - cr:set_source_surface(icon, 0, 0) - cr:paint() - icon = scaled - end - iconbox:set_resize(false) - iconbox:set_image(icon) - icon_w = icon:get_width() - icon_h = icon:get_height() - end - end - - -- create container wibox - notification.box = wibox({ fg = fg, - bg = bg, - border_color = border_color, - border_width = border_width, - type = "notification" }) - - if hover_timeout then notification.box:connect_signal("mouse::enter", hover_destroy) end - - -- calculate the width - if not width then - local w, _ = textbox:get_preferred_size(s) - width = w + (iconbox and icon_w + 2 * margin or 0) + 2 * margin - end - - if width < actions_max_width then - width = actions_max_width - end - - -- calculate the height - if not height then - local w = width - (iconbox and icon_w + 2 * margin or 0) - 2 * margin - local h = textbox:get_height_for_width(w, s) - if iconbox and icon_h + 2 * margin > h + 2 * margin then - height = icon_h + 2 * margin - else - height = h + 2 * margin - end - end - - height = height + actions_total_height - - -- crop to workarea size if too big - local workarea = s.workarea - if width > workarea.width - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0) then - width = workarea.width - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0) - end - if height > workarea.height - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0) then - height = workarea.height - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0) - end - - -- set size in notification object - notification.height = height + 2 * (border_width or 0) - notification.width = width + 2 * (border_width or 0) - - -- position the wibox - local offset = get_offset(s, notification.position, nil, notification.width, notification.height) - notification.box.ontop = ontop - notification.box:geometry({ width = width, - height = height, - x = offset.x, - y = offset.y }) - notification.box.opacity = opacity - notification.box.visible = true - notification.idx = offset.idx - - -- populate widgets - local layout = wibox.layout.fixed.horizontal() - if iconmargin then - layout:add(iconmargin) - end - layout:add(marginbox) - - local completelayout = wibox.layout.fixed.vertical() - completelayout:add(layout) - completelayout:add(actionslayout) - notification.box:set_widget(completelayout) - - -- Setup the mouse events - layout:buttons(util.table.join(button({ }, 1, run), - button({ }, 3, function() - die(naughty.notificationClosedReason.dismissedByUser) - end))) - - -- insert the notification to the table - table.insert(naughty.notifications[s][notification.position], notification) - - if suspended then - notification.box.visible = false - table.insert(naughty.notifications.suspended, notification) - end - - -- return the notification - return notification -end - -return naughty - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/naughty/dbus.lua b/awesome/lib/naughty/dbus.lua deleted file mode 100644 index c49dc7e..0000000 --- a/awesome/lib/naughty/dbus.lua +++ /dev/null @@ -1,261 +0,0 @@ ---------------------------------------------------------------------------- --- DBUS/Notification support --- Notify --- --- @author koniu <gkusnierz@gmail.com> --- @copyright 2008 koniu --- @module naughty.dbus ---------------------------------------------------------------------------- - -assert(dbus) - --- Package environment -local pairs = pairs -local type = type -local string = string -local capi = { awesome = awesome, - dbus = dbus } -local util = require("awful.util") -local cairo = require("lgi").cairo - -local schar = string.char -local sbyte = string.byte -local tcat = table.concat -local tins = table.insert -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local naughty = require("naughty.core") - ---- Notification library, dbus bindings -local dbus = { config = {} } - --- DBUS Notification constants -local urgency = { - low = "\0", - normal = "\1", - critical = "\2" -} - ---- DBUS notification to preset mapping. --- The first element is an object containing the filter. --- If the rules in the filter match, the associated preset will be applied. --- The rules object can contain the following keys: urgency, category, appname. --- The second element is the preset. --- @tfield table 1 low urgency --- @tfield table 2 normal urgency --- @tfield table 3 critical urgency --- @table config.mapping -dbus.config.mapping = { - {{urgency = urgency.low}, naughty.config.presets.low}, - {{urgency = urgency.normal}, naughty.config.presets.normal}, - {{urgency = urgency.critical}, naughty.config.presets.critical} -} - -local function sendActionInvoked(notificationId, action) - if capi.dbus then - capi.dbus.emit_signal("session", "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", "ActionInvoked", - "u", notificationId, - "s", action) - end -end - -local function sendNotificationClosed(notificationId, reason) - if capi.dbus then - capi.dbus.emit_signal("session", "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", "NotificationClosed", - "u", notificationId, - "u", reason) - end -end - -local function convert_icon(w, h, rowstride, channels, data) - -- Do the arguments look sane? (e.g. we have enough data) - local expected_length = rowstride * (h - 1) + w * channels - if w < 0 or h < 0 or rowstride < 0 or (channels ~= 3 and channels ~= 4) or - string.len(data) < expected_length then - w = 0 - h = 0 - end - - local format = cairo.Format[channels == 4 and 'ARGB32' or 'RGB24'] - - -- Figure out some stride magic (cairo dictates rowstride) - local stride = cairo.Format.stride_for_width(format, w) - local append = schar(0):rep(stride - 4 * w) - local offset = 0 - - -- Now convert each row on its own - local rows = {} - - for _ = 1, h do - local this_row = {} - - for i = 1 + offset, w * channels + offset, channels do - local R, G, B, A = sbyte(data, i, i + channels - 1) - tins(this_row, schar(B, G, R, A or 255)) - end - - -- Handle rowstride, offset is stride for the input, append for output - tins(this_row, append) - tins(rows, tcat(this_row)) - - offset = offset + rowstride - end - - return cairo.ImageSurface.create_for_data(tcat(rows), format, w, h, stride) -end - -capi.dbus.connect_signal("org.freedesktop.Notifications", function (data, appname, replaces_id, icon, title, text, actions, hints, expire) - local args = { } - if data.member == "Notify" then - if text ~= "" then - args.text = text - if title ~= "" then - args.title = title - end - else - if title ~= "" then - args.text = title - else - return - end - end - if appname ~= "" then - args.appname = appname - end - for _, obj in pairs(dbus.config.mapping) do - local filter, preset = obj[1], obj[2] - if (not filter.urgency or filter.urgency == hints.urgency) and - (not filter.category or filter.category == hints.category) and - (not filter.appname or filter.appname == appname) then - args.preset = util.table.join(args.preset, preset) - end - end - local preset = args.preset or naughty.config.defaults - local notification - if actions then - args.actions = {} - - for i = 1,#actions,2 do - local action_id = actions[i] - local action_text = actions[i + 1] - - if action_id == "default" then - args.run = function() - sendActionInvoked(notification.id, "default") - naughty.destroy(notification, naughty.notificationClosedReason.dismissedByUser) - end - elseif action_id ~= nil and action_text ~= nil then - args.actions[action_text] = function() - sendActionInvoked(notification.id, action_id) - naughty.destroy(notification, naughty.notificationClosedReason.dismissedByUser) - end - end - end - end - args.destroy = function(reason) - sendNotificationClosed(notification.id, reason) - end - if not preset.callback or (type(preset.callback) == "function" and - preset.callback(data, appname, replaces_id, icon, title, text, actions, hints, expire)) then - if icon ~= "" then - args.icon = icon - elseif hints.icon_data or hints.image_data then - if hints.icon_data == nil then hints.icon_data = hints.image_data end - - -- icon_data is an array: - -- 1 -> width - -- 2 -> height - -- 3 -> rowstride - -- 4 -> has alpha - -- 5 -> bits per sample - -- 6 -> channels - -- 7 -> data - local w, h, rowstride, _, _, channels, icon_data = unpack(hints.icon_data) - args.icon = convert_icon(w, h, rowstride, channels, icon_data) - end - if replaces_id and replaces_id ~= "" and replaces_id ~= 0 then - args.replaces_id = replaces_id - end - if expire and expire > -1 then - args.timeout = expire / 1000 - end - notification = naughty.notify(args) - return "u", notification.id - end - return "u", "0" - elseif data.member == "CloseNotification" then - local obj = naughty.getById(appname) - if obj then - naughty.destroy(obj, naughty.notificationClosedReason.dismissedByCommand) - end - elseif data.member == "GetServerInfo" or data.member == "GetServerInformation" then - -- name of notification app, name of vender, version, specification version - return "s", "naughty", "s", "awesome", "s", capi.awesome.version, "s", "1.0" - elseif data.member == "GetCapabilities" then - -- We actually do display the body of the message, we support <b>, <i> - -- and <u> in the body and we handle static (non-animated) icons. - return "as", { "s", "body", "s", "body-markup", "s", "icon-static", "s", "actions" } - end -end) - -capi.dbus.connect_signal("org.freedesktop.DBus.Introspectable", function (data) - if data.member == "Introspect" then - local xml = [=[<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object - Introspection 1.0//EN" - "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> - <node> - <interface name="org.freedesktop.DBus.Introspectable"> - <method name="Introspect"> - <arg name="data" direction="out" type="s"/> - </method> - </interface> - <interface name="org.freedesktop.Notifications"> - <method name="GetCapabilities"> - <arg name="caps" type="as" direction="out"/> - </method> - <method name="CloseNotification"> - <arg name="id" type="u" direction="in"/> - </method> - <method name="Notify"> - <arg name="app_name" type="s" direction="in"/> - <arg name="id" type="u" direction="in"/> - <arg name="icon" type="s" direction="in"/> - <arg name="summary" type="s" direction="in"/> - <arg name="body" type="s" direction="in"/> - <arg name="actions" type="as" direction="in"/> - <arg name="hints" type="a{sv}" direction="in"/> - <arg name="timeout" type="i" direction="in"/> - <arg name="return_id" type="u" direction="out"/> - </method> - <method name="GetServerInformation"> - <arg name="return_name" type="s" direction="out"/> - <arg name="return_vendor" type="s" direction="out"/> - <arg name="return_version" type="s" direction="out"/> - <arg name="return_spec_version" type="s" direction="out"/> - </method> - <method name="GetServerInfo"> - <arg name="return_name" type="s" direction="out"/> - <arg name="return_vendor" type="s" direction="out"/> - <arg name="return_version" type="s" direction="out"/> - </method> - <signal name="NotificationClosed"> - <arg name="id" type="u" direction="out"/> - <arg name="reason" type="u" direction="out"/> - </signal> - <signal name="ActionInvoked"> - <arg name="id" type="u" direction="out"/> - <arg name="action_key" type="s" direction="out"/> - </signal> - </interface> - </node>]=] - return "s", xml - end -end) - --- listen for dbus notification requests -capi.dbus.request_name("session", "org.freedesktop.Notifications") - -return dbus - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/naughty/init.lua b/awesome/lib/naughty/init.lua deleted file mode 100644 index 71dee9f..0000000 --- a/awesome/lib/naughty/init.lua +++ /dev/null @@ -1,14 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter <psychon@znc.in> --- @copyright 2014 Uli Schlachter --- @module naughty ---------------------------------------------------------------------------- - -local naughty = require("naughty.core") -if dbus then - naughty.dbus = require("naughty.dbus") -end - -return naughty - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/shifty.lua b/awesome/lib/shifty.lua deleted file mode 100644 index 9320295..0000000 --- a/awesome/lib/shifty.lua +++ /dev/null @@ -1,1138 +0,0 @@ ---- Shifty: Dynamic tagging library, version for awesome v3.5 --- @author koniu <gkusnierz@gmail.com> --- @author resixian (aka bioe007) <resixian@gmail.com> --- @author cdump <andreevmaxim@gmail.com> --- --- https://github.com/cdump/awesome-shifty --- http://awesome.naquadah.org/wiki/index.php?title=Shifty - --- environment -local type = type -local ipairs = ipairs -local table = table -local string = string -local beautiful = require("beautiful") -local awful = require("awful") -local wibox = require("wibox") -local pairs = pairs -local io = io -local math = math -local tonumber = tonumber -local dbg= dbg -local capi = { - client = client, - tag = tag, - screen = screen, - button = button, - mouse = mouse, - root = root, - timer = timer -} - -local shifty = {} - --- variables -shifty.config = {} -shifty.config.tags = {} -shifty.config.apps = {} -shifty.config.defaults = {} -shifty.config.float_bars = false -shifty.config.guess_name = true -shifty.config.guess_position = true -shifty.config.remember_index = true -shifty.config.sloppy = true -shifty.config.default_name = "new" -shifty.config.clientkeys = {} -shifty.config.globalkeys = nil -shifty.config.layouts = {} -shifty.config.prompt_sources = { - "config_tags", - "config_apps", - "existing", - "history" -} -shifty.config.prompt_matchers = { - "^", - ":", - "" -} -shifty.config.delete_deserted = true - -local matchp = "" -local index_cache = {} -for i = 1, capi.screen.count() do index_cache[i] = {} end - ---name2tags: matches string 'name' to tag objects --- @param name : tag name to find --- @param scr : screen to look for tags on --- @return table of tag objects or nil -function name2tags(name, scr) - local ret = {} - local a, b = scr or 1, scr or capi.screen.count() - for s = a, b do - for i, t in ipairs(awful.tag.gettags(s)) do - if name == t.name then - table.insert(ret, t) - end - end - end - if #ret > 0 then return ret end -end - -function name2tag(name, scr, idx) - local ts = name2tags(name, scr) - if ts then return ts[idx or 1] end -end - ---tag2index: finds index of a tag object --- @param scr : screen number to look for tag on --- @param tag : the tag object to find --- @return the index [or zero] or end of the list -function tag2index(scr, tag) - for i, t in ipairs(awful.tag.gettags(scr)) do - if t == tag then return i end - end -end - ---rename ---@param tag: tag object to be renamed ---@param prefix: if any prefix is to be added ---@param no_selectall: -function shifty.rename(tag, prefix, no_selectall) - local theme = beautiful.get() - local t = tag or awful.tag.selected(capi.mouse.screen) - - if t == nil then return end - - local scr = awful.tag.getscreen(t) - local bg = nil - local fg = nil - local text = prefix or t.name - local before = t.name - - if t == awful.tag.selected(scr) then - bg = theme.bg_focus or '#535d6c' - fg = theme.fg_urgent or '#ffffff' - else - bg = theme.bg_normal or '#222222' - fg = theme.fg_urgent or '#ffffff' - end - - local tag_index = tag2index(scr, t) - -- Access to textbox widget in taglist - local tb_widget = shifty.taglist[scr].widgets[tag_index].widget.widgets[2].widget - awful.prompt.run({ - fg_cursor = fg, bg_cursor = bg, ul_cursor = "single", - text = text, selectall = not no_selectall}, - tb_widget, - function (name) if name:len() > 0 then t.name = name; end end, - completion, - awful.util.getdir("cache") .. "/history_tags", - nil, - function () - if t.name == before then - if awful.tag.getproperty(t, "initial") then shifty.del(t) end - else - awful.tag.setproperty(t, "initial", true) - set(t) - end - tagkeys(capi.screen[scr]) - t:emit_signal("property::name") - end - ) -end - ---send: moves client to tag[idx] --- maybe this isn't needed here in shifty? --- @param idx the tag number to send a client to -function send(idx) - local scr = capi.client.focus.screen or capi.mouse.screen - local sel = awful.tag.selected(scr) - local sel_idx = tag2index(scr, sel) - local tags = awful.tag.gettags(scr) - local target = awful.util.cycle(#tags, sel_idx + idx) - awful.client.movetotag(tags[target], capi.client.focus) - awful.tag.viewonly(tags[target]) -end - -function shifty.send_next() send(1) end -function shifty.send_prev() send(-1) end - ---pos2idx: translate shifty position to tag index ---@param pos: position (an integer) ---@param scr: screen number -function pos2idx(pos, scr) - local v = 1 - if pos and scr then - local tags = awful.tag.gettags(scr) - for i = #tags , 1, -1 do - local t = tags[i] - if awful.tag.getproperty(t, "position") and - awful.tag.getproperty(t, "position") <= pos then - v = i + 1 - break - end - end - end - return v -end - ---select : helper function chooses the first non-nil argument ---@param args - table of arguments -local function select(args) - for i, a in pairs(args) do - if a ~= nil then - return a - end - end -end - ---tagtoscr : move an entire tag to another screen --- ---@param scr : the screen to move tag to ---@param t : the tag to be moved [awful.tag.selected()] ---@return the tag -function shifty.tagtoscr(scr, t) - -- break if called with an invalid screen number - if not scr or scr < 1 or scr > capi.screen.count() then return end - -- tag to move - local otag = t or awful.tag.selected() - - awful.tag.setscreen(otag, scr) - -- set screen and then reset tag to order properly - if #otag:clients() > 0 then - for _ , c in ipairs(otag:clients()) do - if not c.sticky then - c.screen = scr - c:tags({otag}) - else - awful.client.toggletag(otag, c) - end - end - end - return otag -end - ---set : set a tags properties ---@param t: the tag ---@param args : a table of optional (?) tag properties ---@return t - the tag object -function set(t, args) - if not t then return end - if not args then args = {} end - - -- set the name - t.name = args.name or t.name - - -- attempt to load preset on initial run - local preset = (awful.tag.getproperty(t, "initial") and - shifty.config.tags[t.name]) or {} - - -- pick screen and get its tag table - local scr = args.screen or - (not awful.tag.getscreen(t) and awful.tag.getscreen(preset)) or - awful.tag.getscreen(t) or - capi.mouse.screen - - local clientstomove = nil - if scr > capi.screen.count() then scr = capi.screen.count() end - if awful.tag.getscreen(t) and scr ~= awful.tag.getscreen(t) then - shifty.tagtoscr(scr, t) - awful.tag.setscreen(t, nil) - end - local tags = awful.tag.gettags(scr) - - -- try to guess position from the name - local guessed_position = nil - if not (args.position or preset.position) and shifty.config.guess_position then - local num = t.name:find('^[1-9]') - if num then guessed_position = tonumber(t.name:sub(1, 1)) end - end - - -- allow preset.layout to be a table to provide a different layout per - -- screen for a given tag - local preset_layout = preset.layout - if preset_layout and preset_layout[scr] then - preset_layout = preset.layout[scr] - end - - -- select from args, preset, getproperty, - -- config.defaults.configs or defaults - local props = { - layout = select{args.layout, preset_layout, - awful.tag.getproperty(t, "layout"), - shifty.config.defaults.layout, awful.layout.suit.tile}, - mwfact = select{args.mwfact, preset.mwfact, - awful.tag.getproperty(t, "mwfact"), - shifty.config.defaults.mwfact, 0.55}, - nmaster = select{args.nmaster, preset.nmaster, - awful.tag.getproperty(t, "nmaster"), - shifty.config.defaults.nmaster, 1}, - ncol = select{args.ncol, preset.ncol, - awful.tag.getproperty(t, "ncol"), - shifty.config.defaults.ncol, 1}, - matched = select{args.matched, awful.tag.getproperty(t, "matched")}, - exclusive = select{args.exclusive, preset.exclusive, - awful.tag.getproperty(t, "exclusive"), - shifty.config.defaults.exclusive}, - persist = select{args.persist, preset.persist, - awful.tag.getproperty(t, "persist"), - shifty.config.defaults.persist}, - nopopup = select{args.nopopup, preset.nopopup, - awful.tag.getproperty(t, "nopopup"), - shifty.config.defaults.nopopup}, - leave_kills = select{args.leave_kills, preset.leave_kills, - awful.tag.getproperty(t, "leave_kills"), - shifty.config.defaults.leave_kills}, - max_clients = select{args.max_clients, preset.max_clients, - awful.tag.getproperty(t, "max_clients"), - shifty.config.defaults.max_clients}, - position = select{args.position, preset.position, guessed_position, - awful.tag.getproperty(t, "position")}, - icon = select{args.icon and args.icon, - preset.icon and preset.icon, - awful.tag.getproperty(t, "icon"), - shifty.config.defaults.icon and shifty.config.defaults.icon}, - icon_only = select{args.icon_only, preset.icon_only, - awful.tag.getproperty(t, "icon_only"), - shifty.config.defaults.icon_only}, - sweep_delay = select{args.sweep_delay, preset.sweep_delay, - awful.tag.getproperty(t, "sweep_delay"), - shifty.config.defaults.sweep_delay}, - overload_keys = select{args.overload_keys, preset.overload_keys, - awful.tag.getproperty(t, "overload_keys"), - shifty.config.defaults.overload_keys}, - } - - -- get layout by name if given as string - if type(props.layout) == "string" then - props.layout = getlayout(props.layout) - end - - -- set keys - if args.keys or preset.keys then - local keys = awful.util.table.join(shifty.config.globalkeys, - args.keys or preset.keys) - if props.overload_keys then - props.keys = keys - else - props.keys = squash_keys(keys) - end - end - - -- calculate desired taglist index - local index = args.index or preset.index or shifty.config.defaults.index - local rel_index = args.rel_index or - preset.rel_index or - shifty.config.defaults.rel_index - local sel = awful.tag.selected(scr) - --TODO: what happens with rel_idx if no tags selected - local sel_idx = (sel and tag2index(scr, sel)) or 0 - local t_idx = tag2index(scr, t) - local limit = (not t_idx and #tags + 1) or #tags - local idx = nil - - if rel_index then - idx = awful.util.cycle(limit, (t_idx or sel_idx) + rel_index) - elseif index then - idx = awful.util.cycle(limit, index) - elseif props.position then - idx = pos2idx(props.position, scr) - if t_idx and t_idx < idx then idx = idx - 1 end - elseif shifty.config.remember_index and index_cache[scr][t.name] then - idx = math.min(index_cache[scr][t.name], #tags+1) - elseif not t_idx then - idx = #tags + 1 - end - - -- if we have a new index, remove from old index and insert - if idx then - if t_idx then table.remove(tags, t_idx) end - table.insert(tags, idx, t) - index_cache[scr][t.name] = idx - end - - -- set tag properties and push the new tag table - for i, tmp_tag in ipairs(tags) do - awful.tag.setscreen(tmp_tag, scr) - awful.tag.setproperty(tmp_tag, "index", i) - end - for prop, val in pairs(props) do awful.tag.setproperty(t, prop, val) end - - -- execute run/spawn - if awful.tag.getproperty(t, "initial") then - local spawn = args.spawn or preset.spawn or shifty.config.defaults.spawn - local run = args.run or preset.run or shifty.config.defaults.run - if spawn and args.matched ~= true then - awful.util.spawn_with_shell(spawn, scr) - end - if run then run(t) end - awful.tag.setproperty(t, "initial", nil) - end - - - return t -end - -function shift_next() set(awful.tag.selected(), {rel_index = 1}) end -function shift_prev() set(awful.tag.selected(), {rel_index = -1}) end - ---add : adds a tag ---@param args: table of optional arguments -function shifty.add(args) - if not args then args = {} end - local name = args.name or " " - - -- initialize a new tag object and its data structure - local t = awful.tag.add(name, { initial = true }) - - - -- apply tag settings - set(t, args) - - -- unless forbidden or if first tag on the screen, show the tag - if not (awful.tag.getproperty(t, "nopopup") or args.noswitch) or - #awful.tag.gettags(awful.tag.getscreen(t)) == 1 then - awful.tag.viewonly(t) - end - - -- get the name or rename - if args.name then - t.name = args.name - else - -- FIXME: hack to delay rename for un-named tags for - -- tackling taglist refresh which disabled prompt - -- from being rendered until input - awful.tag.setproperty(t, "initial", true) - local f - local tmr - if args.position then - f = function() shifty.rename(t, args.rename, true); tmr:stop() end - else - f = function() shifty.rename(t); tmr:stop() end - end - tmr = capi.timer({timeout = 0.01}) - tmr:connect_signal("timeout", f) - tmr:start() - end - - return t -end - ---del : delete a tag ---@param tag : the tag to be deleted [current tag] -function shifty.del(tag) - local scr = (tag and awful.tag.getscreen(tag)) or capi.mouse.screen or 1 - local tags = awful.tag.gettags(scr) - local sel = awful.tag.selected(scr) - local t = tag or sel - local idx = tag2index(scr, t) - - -- return if tag not empty (except sticky) - local clients = t:clients() - local sticky = 0 - for i, c in ipairs(clients) do - if c.sticky then sticky = sticky + 1 end - end - if #clients > sticky then return end - - -- store index for later - index_cache[scr][t.name] = idx - - -- remove tag - awful.tag.delete(t) - - -- if the current tag is being deleted, restore from history - if t == sel and #tags > 1 then - awful.tag.history.restore(scr, 1) - -- this is supposed to cycle if history is invalid? - -- e.g. if many tags are deleted in a row - if not awful.tag.selected(scr) then - awful.tag.viewonly(tags[awful.util.cycle(#tags, idx - 1)]) - end - end - - -- FIXME: what is this for?? - if capi.client.focus then capi.client.focus:raise() end -end - ---is_client_tagged : replicate behavior in tag.c - returns true if the ---given client is tagged with the given tag -function is_client_tagged(tag, client) - for i, c in ipairs(tag:clients()) do - if c == client then - return true - end - end - return false -end - ---match : handles app->tag matching, a replacement for the manage hook in --- rc.lua ---@param c : client to be matched -function match(c, startup) - local nopopup, intrusive, nofocus, run, slave - local wfact, struts, geom, float - local target_tag_names, target_tags = {}, {} - local typ = c.type - local cls = c.class - local inst = c.instance - local role = c.role - local name = c.name - local keys = shifty.config.clientkeys or c:keys() or {} - local target_screen = capi.mouse.screen - - c.border_color = beautiful.border_normal - c.border_width = beautiful.border_width - - -- try matching client to config.apps - for i, a in ipairs(shifty.config.apps) do - if a.match then - local matched = false - -- match only class - if not matched and cls and a.match.class then - for k, w in ipairs(a.match.class) do - matched = cls:find(w) - if matched then - break - end - end - end - -- match only instance - if not matched and inst and a.match.instance then - for k, w in ipairs(a.match.instance) do - matched = inst:find(w) - if matched then - break - end - end - end - -- match only name - if not matched and name and a.match.name then - for k, w in ipairs(a.match.name) do - matched = name:find(w) - if matched then - break - end - end - end - -- match only role - if not matched and role and a.match.role then - for k, w in ipairs(a.match.role) do - matched = role:find(w) - if matched then - break - end - end - end - -- match only type - if not matched and typ and a.match.type then - for k, w in ipairs(a.match.type) do - matched = typ:find(w) - if matched then - break - end - end - end - -- check everything else against all attributes - if not matched then - for k, w in ipairs(a.match) do - matched = (cls and cls:find(w)) or - (inst and inst:find(w)) or - (name and name:find(w)) or - (role and role:find(w)) or - (typ and typ:find(w)) - if matched then - break - end - end - end - -- set attributes - if matched then - if a.screen then target_screen = a.screen end - if a.tag then - if type(a.tag) == "string" then - target_tag_names = {a.tag} - else - target_tag_names = a.tag - end - end - if a.startup and startup then - a = awful.util.table.join(a, a.startup) - end - if a.geometry ~=nil then - geom = {x = a.geometry[1], - y = a.geometry[2], - width = a.geometry[3], - height = a.geometry[4]} - end - if a.float ~= nil then float = a.float end - if a.slave ~=nil then slave = a.slave end - if a.border_width ~= nil then - c.border_width = a.border_width - end - if a.nopopup ~=nil then nopopup = a.nopopup end - if a.intrusive ~=nil then - intrusive = a.intrusive - end - if a.fullscreen ~=nil then - c.fullscreen = a.fullscreen - end - if a.honorsizehints ~=nil then - c.size_hints_honor = a.honorsizehints - end - if a.kill ~=nil then c:kill(); return end - if a.ontop ~= nil then c.ontop = a.ontop end - if a.above ~= nil then c.above = a.above end - if a.below ~= nil then c.below = a.below end - if a.buttons ~= nil then - c:buttons(a.buttons) - end - if a.nofocus ~= nil then nofocus = a.nofocus end - if a.keys ~= nil then - keys = awful.util.table.join(keys, a.keys) - end - if a.hidden ~= nil then c.hidden = a.hidden end - if a.minimized ~= nil then - c.minimized = a.minimized - end - if a.dockable ~= nil then - awful.client.dockable.set(c, a.dockable) - end - if a.urgent ~= nil then - c.urgent = a.urgent - end - if a.opacity ~= nil then - c.opacity = a.opacity - end - if a.run ~= nil then run = a.run end - if a.sticky ~= nil then c.sticky = a.sticky end - if a.wfact ~= nil then wfact = a.wfact end - if a.struts then struts = a.struts end - if a.skip_taskbar ~= nil then - c.skip_taskbar = a.skip_taskbar - end - if a.props then - for kk, vv in pairs(a.props) do - awful.client.property.set(c, kk, vv) - end - end - end - end - end - - -- set key bindings - c:keys(keys) - - -- Add titlebars to all clients when the float, remove when they are - -- tiled. - if shifty.config.float_bars then - shifty.create_titlebar(c) - - c:connect_signal("property::floating", function(c) - if awful.client.floating.get(c) then - awful.titlebar(c) - else - awful.titlebar(c, { size = 0 }) - end - awful.placement.no_offscreen(c) - end) - end - - -- set properties of floating clients - if float ~= nil then - awful.client.floating.set(c, float) - awful.placement.no_offscreen(c) - end - - local sel = awful.tag.selectedlist(target_screen) - if not target_tag_names or #target_tag_names == 0 then - -- if not matched to some names try putting - -- client in c.transient_for or current tags - if c.transient_for then - target_tags = c.transient_for:tags() - elseif #sel > 0 then - for i, t in ipairs(sel) do - local mc = awful.tag.getproperty(t, "max_clients") - if intrusive or - not (awful.tag.getproperty(t, "exclusive") or - (mc and mc >= #t:clients())) then - table.insert(target_tags, t) - end - end - end - end - - if (not target_tag_names or #target_tag_names == 0) and - (not target_tags or #target_tags == 0) then - -- if we still don't know any target names/tags guess - -- name from class or use default - if shifty.config.guess_name and cls then - target_tag_names = {cls:lower()} - else - target_tag_names = {shifty.config.default_name} - end - end - - if #target_tag_names > 0 and #target_tags == 0 then - -- translate target names to tag objects, creating - -- missing ones - for i, tn in ipairs(target_tag_names) do - local res = {} - for j, t in ipairs(name2tags(tn, target_screen) or - name2tags(tn) or {}) do - local mc = awful.tag.getproperty(t, "max_clients") - local tagged = is_client_tagged(t, c) - if intrusive or - not (mc and (((#t:clients() >= mc) and not - tagged) or - (#t:clients() > mc))) or - intrusive then - if awful.tag.getscreen(t) == mouse.screen then - table.insert(res, t) - end - end - end - if #res == 0 then - table.insert(target_tags, - shifty.add({name = tn, - noswitch = true, - matched = true})) - else - target_tags = awful.util.table.join(target_tags, res) - end - end - end - - -- set client's screen/tag if needed - target_screen = awful.tag.getscreen(target_tags[1]) or target_screen - if c.screen ~= target_screen then c.screen = target_screen end - if slave then awful.client.setslave(c) end - c:tags(target_tags) - - if wfact then awful.client.setwfact(wfact, c) end - if geom then c:geometry(geom) end - if struts then c:struts(struts) end - - local showtags = {} - local u = nil - if #target_tags > 0 and not startup then - -- switch or highlight - for i, t in ipairs(target_tags) do - if not (nopopup or awful.tag.getproperty(t, "nopopup")) then - table.insert(showtags, t) - elseif not startup then - c.urgent = true - end - end - if #showtags > 0 then - local ident = false - -- iterate selected tags and and see if any targets - -- currently selected - for kk, vv in pairs(showtags) do - for _, tag in pairs(sel) do - if tag == vv then - ident = true - end - end - end - if not ident then - awful.tag.viewmore(showtags, c.screen) - end - end - end - - if not (nofocus or c.hidden or c.minimized) then - --focus and raise accordingly or lower if supressed - if (target and target ~= sel) and - (awful.tag.getproperty(target, "nopopup") or nopopup) then - awful.client.focus.history.add(c) - else - capi.client.focus = c - end - c:raise() - else - c:lower() - end - - if shifty.config.sloppy then - -- Enable sloppy focus - c:connect_signal("mouse::enter", function(c) - if awful.client.focus.filter(c) and - awful.layout.get(c.screen) ~= awful.layout.suit.magnifier then - capi.client.focus = c - end - end) - end - - -- execute run function if specified - if run then run(c, target) end - -end - ---sweep : hook function that marks tags as used, visited, ---deserted also handles deleting used and empty tags -function sweep() - for s = 1, capi.screen.count() do - for i, t in ipairs(awful.tag.gettags(s)) do - local clients = t:clients() - local sticky = 0 - for i, c in ipairs(clients) do - if c.sticky then sticky = sticky + 1 end - end - if #clients == sticky then - if awful.tag.getproperty(t, "used") and - not awful.tag.getproperty(t, "persist") then - if awful.tag.getproperty(t, "deserted") or - not awful.tag.getproperty(t, "leave_kills") then - local delay = awful.tag.getproperty(t, "sweep_delay") - if delay then - local tmr - local f = function() - shifty.del(t); tmr:stop() - end - tmr = capi.timer({timeout = delay}) - tmr:connect_signal("timeout", f) - tmr:start() - else - if shifty.config.delete_deserted then - shifty.del(t) - end - end - else - if awful.tag.getproperty(t, "visited") and - not t.selected then - awful.tag.setproperty(t, "deserted", true) - end - end - end - else - awful.tag.setproperty(t, "used", true) - end - if t.selected then - awful.tag.setproperty(t, "visited", true) - end - end - end -end - ---getpos : returns a tag to match position --- @param pos : the index to find --- @return v : the tag (found or created) at position == 'pos' -function shifty.getpos(pos, scr_arg) - local v = nil - local existing = {} - local selected = nil - local scr = scr_arg or capi.mouse.screen or 1 - - -- search for existing tag assigned to pos - for i = 1, capi.screen.count() do - for j, t in ipairs(awful.tag.gettags(i)) do - if awful.tag.getproperty(t, "position") == pos then - table.insert(existing, t) - if t.selected and i == scr then - selected = #existing - end - end - end - end - - if #existing > 0 then - -- if there is no selected tag on current screen, look for the first one - if not selected then - for _, tag in pairs(existing) do - if awful.tag.getscreen(tag) == scr then return tag end - end - - -- no tag found, loop through the other tags - selected = #existing - end - - -- look for the next unselected tag - i = selected - repeat - i = awful.util.cycle(#existing, i + 1) - tag = existing[i] - - if (scr_arg == nil or awful.tag.getscreen(tag) == scr_arg) and not tag.selected then return tag end - until i == selected - - -- if the screen is not specified or - -- if a selected tag exists on the specified screen - -- return the selected tag - if scr_arg == nil or awful.tag.getscreen(existing[selected]) == scr then return existing[selected] end - - -- if scr_arg ~= nil and no tag exists on this screen, continue - end - - local screens = {} - for s = 1, capi.screen.count() do table.insert(screens, s) end - - -- search for preconf with 'pos' on current screen and create it - for i, j in pairs(shifty.config.tags) do - local tag_scr = j.screen or screens - if type(tag_scr) ~= 'table' then tag_scr = {tag_scr} end - - if j.position == pos and awful.util.table.hasitem(tag_scr, scr) then - return shifty.add({name = i, - position = pos, - noswitch = not switch}) - end - end - - -- not existing, not preconfigured - return shifty.add({position = pos, - rename = pos .. ':', - no_selectall = true, - noswitch = not switch}) -end - ---init : search config.tags for initial set of ---tags to open -function shifty.init() - local numscr = capi.screen.count() - - local screens = {} - for s = 1, capi.screen.count() do table.insert(screens, s) end - - for i, j in pairs(shifty.config.tags) do - local scr = j.screen or screens - if type(scr) ~= 'table' then - scr = {scr} - end - for _, s in pairs(scr) do - if j.init and (s <= numscr) then - shifty.add({name = i, - persist = true, - screen = s, - layout = j.layout, - mwfact = j.mwfact}) - end - end - end -end - --- Create a titlebar for the given client --- By default, make it invisible (size = 0) - -function shifty.create_titlebar(c) - -- Widgets that are aligned to the left - local left_layout = wibox.layout.fixed.horizontal() - left_layout:add(awful.titlebar.widget.iconwidget(c)) - - -- Widgets that are aligned to the right - local right_layout = wibox.layout.fixed.horizontal() - right_layout:add(awful.titlebar.widget.floatingbutton(c)) - right_layout:add(awful.titlebar.widget.maximizedbutton(c)) - right_layout:add(awful.titlebar.widget.stickybutton(c)) - right_layout:add(awful.titlebar.widget.ontopbutton(c)) - right_layout:add(awful.titlebar.widget.closebutton(c)) - - -- The title goes in the middle - local title = awful.titlebar.widget.titlewidget(c) - title:buttons(awful.util.table.join( - awful.button({ }, 1, function() - client.focus = c - c:raise() - awful.mouse.client.move(c) - end), - awful.button({ }, 3, function() - client.focus = c - c:raise() - awful.mouse.client.resize(c) - end) - )) - - -- Now bring it all together - local layout = wibox.layout.align.horizontal() - layout:set_left(left_layout) - layout:set_right(right_layout) - layout:set_middle(title) - - awful.titlebar(c, { size = 0 }):set_widget(layout) -end - ---count : utility function returns the index of a table element ---FIXME: this is currently used only in remove_dup, so is it really ---necessary? -function count(table, element) - local v = 0 - for i, e in pairs(table) do - if element == e then v = v + 1 end - end - return v -end - ---remove_dup : used by shifty.completion when more than one ---tag at a position exists -function remove_dup(table) - local v = {} - for i, entry in ipairs(table) do - if count(v, entry) == 0 then v[#v+ 1] = entry end - end - return v -end - ---completion : prompt completion --- -function completion(cmd, cur_pos, ncomp, sources, matchers) - - -- get sources and matches tables - sources = sources or shifty.config.prompt_sources - matchers = matchers or shifty.config.prompt_matchers - - local get_source = { - -- gather names from config.tags - config_tags = function() - local ret = {} - for n, p in pairs(shifty.config.tags) do - table.insert(ret, n) - end - return ret - end, - -- gather names from config.apps - config_apps = function() - local ret = {} - for i, p in pairs(shifty.config.apps) do - if p.tag then - if type(p.tag) == "string" then - table.insert(ret, p.tag) - else - ret = awful.util.table.join(ret, p.tag) - end - end - end - return ret - end, - -- gather names from existing tags, starting with the - -- current screen - existing = function() - local ret = {} - for i = 1, capi.screen.count() do - local s = awful.util.cycle(capi.screen.count(), - capi.mouse.screen + i - 1) - local tags = awful.tag.gettags(s) - for j, t in pairs(tags) do - table.insert(ret, t.name) - end - end - return ret - end, - -- gather names from history - history = function() - local ret = {} - local f = io.open(awful.util.getdir("cache") .. - "/history_tags") - for name in f:lines() do table.insert(ret, name) end - f:close() - return ret - end, - } - - -- if empty, match all - if #cmd == 0 or cmd == " " then cmd = "" end - - -- match all up to the cursor if moved or no matchphrase - if matchp == "" or - cmd:sub(cur_pos, cur_pos+#matchp) ~= matchp then - matchp = cmd:sub(1, cur_pos) - end - - -- find matching commands - local matches = {} - for i, src in ipairs(sources) do - local source = get_source[src]() - for j, matcher in ipairs(matchers) do - for k, name in ipairs(source) do - if name:find(matcher .. matchp) then - table.insert(matches, name) - end - end - end - end - - -- no matches - if #matches == 0 then return cmd, cur_pos end - - -- remove duplicates - matches = remove_dup(matches) - - -- cycle - while ncomp > #matches do ncomp = ncomp - #matches end - - -- put cursor at the end of the matched phrase - if #matches == 1 then - cur_pos = #matches[ncomp] + 1 - else - cur_pos = matches[ncomp]:find(matchp) + #matchp - end - - -- return match and position - return matches[ncomp], cur_pos -end - --- tagkeys : hook function that sets keybindings per tag -function tagkeys(s) - local sel = awful.tag.selected(s.index) - local keys = awful.tag.getproperty(sel, "keys") or - shifty.config.globalkeys - if keys and sel.selected then capi.root.keys(keys) end -end - --- squash_keys: helper function which removes duplicate --- keybindings by picking only the last one to be listed in keys --- table arg -function squash_keys(keys) - local squashed = {} - local ret = {} - for i, k in ipairs(keys) do - squashed[table.concat(k.modifiers) .. k.key] = k - end - for i, k in pairs(squashed) do - table.insert(ret, k) - end - return ret -end - --- getlayout: returns a layout by name -function getlayout(name) - for _, layout in ipairs(shifty.config.layouts) do - if awful.layout.getname(layout) == name then - return layout - end - end -end - --- add signals before using them --- Note: these signals are emitted when tag properties --- are accessed through awful.tag.setproperty -capi.tag.add_signal("property::initial") -capi.tag.add_signal("property::used") -capi.tag.add_signal("property::visited") -capi.tag.add_signal("property::deserted") -capi.tag.add_signal("property::matched") -capi.tag.add_signal("property::selected") -capi.tag.add_signal("property::position") -capi.tag.add_signal("property::exclusive") -capi.tag.add_signal("property::persist") -capi.tag.add_signal("property::index") -capi.tag.add_signal("property::nopopup") -capi.tag.add_signal("property::leave_kills") -capi.tag.add_signal("property::max_clients") -capi.tag.add_signal("property::icon_only") -capi.tag.add_signal("property::sweep_delay") -capi.tag.add_signal("property::overload_keys") - --- replace awful's default hook -capi.client.connect_signal("manage", match) -capi.client.connect_signal("unmanage", sweep) -capi.client.disconnect_signal("manage", awful.tag.withcurrent) - -for s = 1, capi.screen.count() do - awful.tag.attached_connect_signal(s, "property::selected", sweep) - awful.tag.attached_connect_signal(s, "tagged", sweep) - capi.screen[s]:connect_signal("tag::history::update", tagkeys) -end - -return shifty - diff --git a/awesome/lib/wibox/container/arcchart.lua b/awesome/lib/wibox/container/arcchart.lua deleted file mode 100644 index 3794630..0000000 --- a/awesome/lib/wibox/container/arcchart.lua +++ /dev/null @@ -1,566 +0,0 @@ ---------------------------------------------------------------------------- --- --- A circular chart (arc chart). --- --- It can contain a central widget (or not) and display multiple values. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_arcchart.svg) --- --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2013 Emmanuel Lepage Vallee --- @classmod wibox.container.arcchart ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local base = require("wibox.widget.base") -local shape = require("gears.shape" ) -local util = require( "awful.util" ) -local color = require( "gears.color" ) -local beautiful = require("beautiful" ) - - -local arcchart = { mt = {} } - ---- The progressbar border background color. --- @beautiful beautiful.arcchart_border_color - ---- The progressbar foreground color. --- @beautiful beautiful.arcchart_color - ---- The progressbar border width. --- @beautiful beautiful.arcchart_border_width - ---- The padding between the outline and the progressbar. --- @beautiful beautiful.arcchart_paddings --- @tparam[opt=0] table|number paddings A number or a table --- @tparam[opt=0] number paddings.top --- @tparam[opt=0] number paddings.bottom --- @tparam[opt=0] number paddings.left --- @tparam[opt=0] number paddings.right - ---- The arc thickness. --- @beautiful beautiful.thickness --- @param number - -local function outline_workarea(width, height) - local x, y = 0, 0 - local size = math.min(width, height) - - return {x=x+(width-size)/2, y=y+(height-size)/2, width=size, height=size} -end - --- The child widget area -local function content_workarea(self, width, height) - local padding = self._private.paddings or {} - local border_width = self:get_border_width() or 0 - local wa = outline_workarea(width, height) - local thickness = math.max(border_width, self:get_thickness() or 5) - - wa.x = wa.x + (padding.left or 0) + thickness + 2*border_width - wa.y = wa.y + (padding.top or 0) + thickness + 2*border_width - wa.width = wa.width - (padding.left or 0) - (padding.right or 0) - - 2*thickness - 4*border_width - wa.height = wa.height - (padding.top or 0) - (padding.bottom or 0) - - 2*thickness - 4*border_width - - return wa -end - --- Draw the radial outline and progress -function arcchart:after_draw_children(_, cr, width, height) - cr:restore() - - local values = self:get_values() or {} - local border_width = self:get_border_width() or 0 - local thickness = math.max(border_width, self:get_thickness() or 5) - - local offset = thickness + 2*border_width - - -- Draw a circular background - local bg = self:get_bg() - if bg then - cr:save() - cr:translate(offset/2, offset/2) - shape.circle( - cr, - width-offset, - height-offset - ) - cr:set_line_width(thickness+2*border_width) - cr:set_source(color(bg)) - cr:stroke() - cr:restore() - end - - if #values == 0 then - return - end - - local wa = outline_workarea(width, height) - cr:translate(wa.x+border_width/2, wa.y+border_width/2) - - - -- Get the min and max value - --local min_val = self:get_min_value() or 0 --TODO support min_values - local max_val = self:get_max_value() - local sum = 0 - - if not max_val then - for _, v in ipairs(values) do - sum = sum + v - end - max_val = sum - end - - max_val = math.max(max_val, sum) - - local use_rounded_edges = sum ~= max_val and self:get_rounded_edge() - - -- Fallback to the current foreground color - local colors = self:get_colors() or {} - - -- Draw the outline - local offset_angle = self:get_start_angle() or math.pi - local start_angle, end_angle = offset_angle, offset_angle - - for k, v in ipairs(values) do - end_angle = start_angle + (v*2*math.pi) / max_val - - if colors[k] then - cr:set_source(color(colors[k])) - end - - shape.arc(cr, wa.width-border_width, wa.height-border_width, - thickness+border_width, math.pi-end_angle, math.pi-start_angle, - (use_rounded_edges and k == 1), (use_rounded_edges and k == #values) - ) - - cr:fill() - start_angle = end_angle - end - - if border_width > 0 then - local border_color = self:get_border_color() - - cr:set_source(color(border_color)) - cr:set_line_width(border_width) - - shape.arc(cr, wa.width-border_width, wa.height-border_width, - thickness+border_width, math.pi-end_angle, math.pi-offset_angle, - use_rounded_edges, use_rounded_edges - ) - cr:stroke() - end - -end - --- Set the clip -function arcchart:before_draw_children(_, cr, width, height) - cr:save() - local wa = content_workarea(self, width, height) - cr:translate(wa.x, wa.y) - shape.circle( - cr, - wa.width, - wa.height - ) - cr:clip() - cr:translate(-wa.x, -wa.y) -end - --- Layout this layout -function arcchart:layout(_, width, height) - if self._private.widget then - local wa = content_workarea(self, width, height) - - return { base.place_widget_at( - self._private.widget, wa.x, wa.y, wa.width, wa.height - ) } - end -end - --- Fit this layout into the given area -function arcchart:fit(_, width, height) - local size = math.min(width, height) - return size, size -end - ---- The widget to wrap in a radial proggressbar. --- @property widget --- @tparam widget widget The widget - -function arcchart:set_widget(widget) - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - ---- Get the children elements. --- @treturn table The children -function arcchart:get_children() - return {self._private.widget} -end - ---- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function arcchart:set_children(children) - self._private.widget = children and children[1] - self:emit_signal("widget::layout_changed") -end - ---- Reset this layout. The widget will be removed and the rotation reset. -function arcchart:reset() - self:set_widget(nil) -end - -for _,v in ipairs {"left", "right", "top", "bottom"} do - arcchart["set_"..v.."_padding"] = function(self, val) - self._private.paddings = self._private.paddings or {} - self._private.paddings[v] = val - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - end -end - ---- The padding between the outline and the progressbar. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_paddings.svg) --- --- @property paddings --- @tparam[opt=0] table|number paddings A number or a table --- @tparam[opt=0] number paddings.top --- @tparam[opt=0] number paddings.bottom --- @tparam[opt=0] number paddings.left --- @tparam[opt=0] number paddings.right - ---- The border background color. --- --- @property border_color - ---- The border foreground color. --- --- @property color - ---- The border width. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_border_width.svg) --- --- @property border_width --- @tparam[opt=3] number border_width - ---- The minimum value. --- @property min_value - ---- The maximum value. --- @property max_value - ---- The radial background. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_bg.svg) --- --- @property bg --- @param color --- @see gears.color - ---- The value. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_value.svg) --- --- @property value --- @tparam number value Between min_value and max_value --- @see values - ---- The values. --- The arcchart is designed to display multiple values at once. Each will be --- shown in table order. --- --- @property values --- @tparam table values An ordered set if values. --- @see value - ---- If the chart has rounded edges. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_rounded_edge.svg) --- --- @property rounded_edge --- @param[opt=false] boolean - ---- The arc thickness. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_thickness.svg) --- --- @property thickness --- @param number - ---- The (radiant) angle where the first value start. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_arcchart_start_angle.svg) --- --- @property start_angle --- @param[opt=math.pi] number A number between 0 and 2*math.pi - -for _, prop in ipairs {"border_width", "border_color", "paddings", "colors", - "rounded_edge", "bg", "thickness", "values", "min_value", "max_value", - "start_angle" } do - arcchart["set_"..prop] = function(self, value) - self._private[prop] = value - self:emit_signal("property::"..prop) - self:emit_signal("widget::redraw_needed") - end - arcchart["get_"..prop] = function(self) - return self._private[prop] or beautiful["arcchart_"..prop] - end -end - -function arcchart:set_paddings(val) - self._private.paddings = type(val) == "number" and { - left = val, - right = val, - top = val, - bottom = val, - } or val or {} - self:emit_signal("property::paddings") - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") -end - -function arcchart:set_value(value) - self:set_values {value} -end - ---- Returns a new arcchart layout. --- @param[opt] widget The widget to display. --- @function wibox.container.arcchart -local function new(widget) - local ret = base.make_widget(nil, nil, { - enable_properties = true, - }) - - util.table.crush(ret, arcchart) - - ret:set_widget(widget) - - return ret -end - -function arcchart.mt:__call(...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(arcchart, arcchart.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/background.lua b/awesome/lib/wibox/container/background.lua deleted file mode 100644 index 2fb88c3..0000000 --- a/awesome/lib/wibox/container/background.lua +++ /dev/null @@ -1,626 +0,0 @@ ---------------------------------------------------------------------------- --- A container capable of changing the background color, foreground color --- widget shape. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_background.svg) --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.container.background ---------------------------------------------------------------------------- - -local base = require("wibox.widget.base") -local color = require("gears.color") -local surface = require("gears.surface") -local beautiful = require("beautiful") -local cairo = require("lgi").cairo -local util = require("awful.util") -local setmetatable = setmetatable -local type = type -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) - -local background = { mt = {} } - --- Draw this widget -function background:draw(context, cr, width, height) - if not self._private.widget or not self._private.widget:get_visible() then - return - end - - -- Keep the shape path in case there is a border - self._private.path = nil - - if self._private.shape then - -- Only add the offset if there is something to draw - local offset = ((self._private.shape_border_width and self._private.shape_border_color) - and self._private.shape_border_width or 0) / 2 - - cr:translate(offset, offset) - self._private.shape(cr, width - 2*offset, height - 2*offset, unpack(self._private.shape_args or {})) - cr:translate(-offset, -offset) - self._private.path = cr:copy_path() - cr:clip() - end - - if self._private.background then - cr:set_source(self._private.background) - cr:paint() - end - if self._private.bgimage then - if type(self._private.bgimage) == "function" then - self._private.bgimage(context, cr, width, height,unpack(self._private.bgimage_args)) - else - local pattern = cairo.Pattern.create_for_surface(self._private.bgimage) - cr:set_source(pattern) - cr:paint() - end - end - -end - --- Draw the border -function background:after_draw_children(_, cr) - -- Draw the border - if self._private.path and self._private.shape_border_width and self._private.shape_border_width > 0 then - cr:append_path(self._private.path) - cr:set_source(color(self._private.shape_border_color or self._private.foreground or beautiful.fg_normal)) - - cr:set_line_width(self._private.shape_border_width) - cr:stroke() - self._private.path = nil - end -end - --- Prepare drawing the children of this widget -function background:before_draw_children(_, cr) - if self._private.foreground then - cr:set_source(self._private.foreground) - end - - -- Clip the shape - if self._private.path and self._private.shape_clip then - cr:append_path(self._private.path) - cr:clip() - end -end - --- Layout this widget -function background:layout(_, width, height) - if self._private.widget then - return { base.place_widget_at(self._private.widget, 0, 0, width, height) } - end -end - --- Fit this widget into the given area -function background:fit(context, width, height) - if not self._private.widget then - return 0, 0 - end - - return base.fit_widget(self, context, self._private.widget, width, height) -end - ---- The widget displayed in the background widget. --- @property widget --- @tparam widget widget The widget to be disaplayed inside of the background --- area - -function background:set_widget(widget) - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - -function background:get_widget() - return self._private.widget -end - --- Get children element --- @treturn table The children -function background:get_children() - return {self._private.widget} -end - --- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function background:set_children(children) - self:set_widget(children[1]) -end - ---- The background color/pattern/gradient to use. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_background_bg.svg) --- --- @usage ---local text_widget = { --- text = 'Hello world!', --- widget = wibox.widget.textbox ---} ---parent : setup { --- { --- text_widget, --- bg = '#ff0000', --- widget = wibox.container.background --- }, --- { --- text_widget, --- bg = '#00ff00', --- widget = wibox.container.background --- }, --- { --- text_widget, --- bg = '#0000ff', --- widget = wibox.container.background --- }, --- spacing = 10, --- layout = wibox.layout.fixed.vertical ---} --- @property bg --- @param bg A color string, pattern or gradient --- @see gears.color - -function background:set_bg(bg) - if bg then - self._private.background = color(bg) - else - self._private.background = nil - end - self:emit_signal("widget::redraw_needed") -end - -function background:get_bg() - return self._private.background -end - ---- The foreground (text) color/pattern/gradient to use. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_background_fg.svg) --- --- @usage ---local text_widget = { --- text = 'Hello world!', --- widget = wibox.widget.textbox ---} ---parent : setup { --- { --- text_widget, --- fg = '#ff0000', --- widget = wibox.container.background --- }, --- { --- text_widget, --- fg = '#00ff00', --- widget = wibox.container.background --- }, --- { --- text_widget, --- fg = '#0000ff', --- widget = wibox.container.background --- }, --- spacing = 10, --- layout = wibox.layout.fixed.vertical ---} --- @property fg --- @param fg A color string, pattern or gradient --- @see gears.color - -function background:set_fg(fg) - if fg then - self._private.foreground = color(fg) - else - self._private.foreground = nil - end - self:emit_signal("widget::redraw_needed") -end - -function background:get_fg() - return self._private.foreground -end - ---- The background shap e. --- --- Use `set_shape` to set additional shape paramaters. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_background_shape.svg) --- --- @usage ---parent : setup { --- { --- -- Adding a shape without margin may result in cropped output --- { --- text = 'Hello world!', --- widget = wibox.widget.textbox --- }, --- shape = gears.shape.hexagon, --- bg = beautiful.bg_normal, --- shape_border_color = beautiful.border_color, --- shape_border_width = beautiful.border_width, --- widget = wibox.container.background --- }, --- { --- -- To solve this, use a margin --- { --- { --- text = 'Hello world!', --- widget = wibox.widget.textbox --- }, --- left = 10, --- right = 10, --- top = 3, --- bottom = 3, --- widget = wibox.container.margin --- }, --- shape = gears.shape.hexagon, --- bg = beautiful.bg_normal, --- shape_border_color = beautiful.border_color, --- shape_border_width = beautiful.border_width, --- widget = wibox.container.background --- }, --- spacing = 10, --- layout = wibox.layout.fixed.vertical ---} --- @property shape --- @param shape A function taking a context, width and height as arguments --- @see gears.shape --- @see set_shape - ---- Set the background shape. --- --- Any other arguments will be passed to the shape function --- @param shape A function taking a context, width and height as arguments --- @see gears.shape --- @see shape -function background:set_shape(shape, ...) - local args = {...} - - if shape == self._private.shape and #args == 0 then return end - - self._private.shape = shape - self._private.shape_args = {...} - self:emit_signal("widget::redraw_needed") -end - -function background:get_shape() - return self._private.shape -end - ---- When a `shape` is set, also draw a border. --- --- See `wibox.container.background.shape` for an usage example. --- @property shape_border_width --- @tparam number width The border width - -function background:set_shape_border_width(width) - if self._private.shape_border_width == width then return end - - self._private.shape_border_width = width - self:emit_signal("widget::redraw_needed") -end - -function background:get_shape_border_width() - return self._private.shape_border_width -end - ---- When a `shape` is set, also draw a border. --- --- See `wibox.container.background.shape` for an usage example. --- @property shape_border_color --- @param[opt=self._private.foreground] fg The border color, pattern or gradient --- @see gears.color - -function background:set_shape_border_color(fg) - if self._private.shape_border_color == fg then return end - - self._private.shape_border_color = fg - self:emit_signal("widget::redraw_needed") -end - -function background:get_shape_border_color() - return self._private.shape_border_color -end - ---- When a `shape` is set, make sure nothing is drawn outside of it. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_background_clip.svg) --- --- @usage ---parent : setup { --- { --- -- Some content may be outside of the shape --- { --- text = 'Hello\nworld!', --- widget = wibox.widget.textbox --- }, --- shape = gears.shape.circle, --- bg = beautiful.bg_normal, --- shape_border_color = beautiful.border_color, --- widget = wibox.container.background --- }, --- { --- -- To solve this, clip the content --- { --- text = 'Hello\nworld!', --- widget = wibox.widget.textbox --- }, --- shape_clip = true, --- shape = gears.shape.circle, --- bg = beautiful.bg_normal, --- shape_border_color = beautiful.border_color, --- widget = wibox.container.background --- }, --- spacing = 10, --- layout = wibox.layout.fixed.vertical ---} --- @property shape_clip --- @tparam boolean value If the shape clip is enable - -function background:set_shape_clip(value) - if self._private.shape_clip == value then return end - - self._private.shape_clip = value - self:emit_signal("widget::redraw_needed") -end - -function background:get_shape_clip() - return self._private.shape_clip or false -end - ---- The background image to use --- If `image` is a function, it will be called with `(context, cr, width, height)` --- as arguments. Any other arguments passed to this method will be appended. --- @property bgimage --- @param image A background image or a function --- @see gears.surface - -function background:set_bgimage(image, ...) - self._private.bgimage = type(image) == "function" and image or surface.load(image) - self._private.bgimage_args = {...} - self:emit_signal("widget::redraw_needed") -end - -function background:get_bgimage() - return self._private.bgimage -end - ---- Returns a new background container. --- --- A background container applies a background and foreground color --- to another widget. --- @param[opt] widget The widget to display. --- @param[opt] bg The background to use for that widget. --- @param[opt] shape A `gears.shape` compatible shape function --- @function wibox.container.background -local function new(widget, bg, shape) - local ret = base.make_widget(nil, nil, { - enable_properties = true, - }) - - util.table.crush(ret, background, true) - - ret._private.shape = shape - - ret:set_widget(widget) - ret:set_bg(bg) - - return ret -end - -function background.mt:__call(...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(background, background.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/constraint.lua b/awesome/lib/wibox/container/constraint.lua deleted file mode 100644 index a210387..0000000 --- a/awesome/lib/wibox/container/constraint.lua +++ /dev/null @@ -1,371 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_constraint.svg) --- --- @author Lukáš Hrázký --- @copyright 2012 Lukáš Hrázký --- @classmod wibox.container.constraint ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local base = require("wibox.widget.base") -local util = require("awful.util") -local math = math - -local constraint = { mt = {} } - --- Layout a constraint layout -function constraint:layout(_, width, height) - if self._private.widget then - return { base.place_widget_at(self._private.widget, 0, 0, width, height) } - end -end - --- Fit a constraint layout into the given space -function constraint:fit(context, width, height) - local w, h - if self._private.widget then - w = self._private.strategy(width, self._private.width) - h = self._private.strategy(height, self._private.height) - - w, h = base.fit_widget(self, context, self._private.widget, w, h) - else - w, h = 0, 0 - end - - w = self._private.strategy(w, self._private.width) - h = self._private.strategy(h, self._private.height) - - return w, h -end - ---- The widget to be constrained. --- @property widget --- @tparam widget widget The widget - -function constraint:set_widget(widget) - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - -function constraint:get_widget() - return self._private.widget -end - ---- Get the number of children element --- @treturn table The children -function constraint:get_children() - return {self._private.widget} -end - ---- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function constraint:set_children(children) - self:set_widget(children[1]) -end - ---- Set the strategy to use for the constraining. Valid values are 'max', --- 'min' or 'exact'. Throws an error on invalid values. --- @property strategy - -function constraint:set_strategy(val) - local func = { - min = function(real_size, limit) - return limit and math.max(limit, real_size) or real_size - end, - max = function(real_size, limit) - return limit and math.min(limit, real_size) or real_size - end, - exact = function(real_size, limit) - return limit or real_size - end - } - - if not func[val] then - error("Invalid strategy for constraint layout: " .. tostring(val)) - end - - self._private.strategy = func[val] - self:emit_signal("widget::layout_changed") -end - -function constraint:get_strategy() - return self._private.strategy -end - ---- Set the maximum width to val. nil for no width limit. --- @property height --- @param number - -function constraint:set_width(val) - self._private.width = val - self:emit_signal("widget::layout_changed") -end - -function constraint:get_width() - return self._private.width -end - ---- Set the maximum height to val. nil for no height limit. --- @property width --- @param number - -function constraint:set_height(val) - self._private.height = val - self:emit_signal("widget::layout_changed") -end - -function constraint:get_height() - return self._private.height -end - ---- Reset this layout. The widget will be unreferenced, strategy set to "max" --- and the constraints set to nil. -function constraint:reset() - self._private.width = nil - self._private.height = nil - self:set_strategy("max") - self:set_widget(nil) -end - ---- Returns a new constraint container. --- This container will constraint the size of a --- widget according to the strategy. Note that this will only work for layouts --- that respect the widget's size, eg. fixed layout. In layouts that don't --- (fully) respect widget's requested size, the inner widget still might get --- drawn with a size that does not fit the constraint, eg. in flex layout. --- @param[opt] widget A widget to use. --- @param[opt] strategy How to constraint the size. 'max' (default), 'min' or --- 'exact'. --- @param[opt] width The maximum width of the widget. nil for no limit. --- @param[opt] height The maximum height of the widget. nil for no limit. --- @treturn table A new constraint container --- @function wibox.container.constraint -local function new(widget, strategy, width, height) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - util.table.crush(ret, constraint, true) - - ret:set_strategy(strategy or "max") - ret:set_width(width) - ret:set_height(height) - - if widget then - ret:set_widget(widget) - end - - return ret -end - -function constraint.mt:__call(...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(constraint, constraint.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/init.lua b/awesome/lib/wibox/container/init.lua deleted file mode 100644 index 93158ab..0000000 --- a/awesome/lib/wibox/container/init.lua +++ /dev/null @@ -1,21 +0,0 @@ ---------------------------------------------------------------------------- ---- Collection of containers that can be used in widget boxes --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.container ---------------------------------------------------------------------------- -local base = require("wibox.widget.base") - -return setmetatable({ - rotate = require("wibox.container.rotate"); - margin = require("wibox.container.margin"); - mirror = require("wibox.container.mirror"); - constraint = require("wibox.container.constraint"); - scroll = require("wibox.container.scroll"); - background = require("wibox.container.background"); - radialprogressbar = require("wibox.container.radialprogressbar"); - arcchart = require("wibox.container.arcchart"); -}, {__call = function(_, args) return base.make_widget_declarative(args) end}) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/margin.lua b/awesome/lib/wibox/container/margin.lua deleted file mode 100644 index edf9673..0000000 --- a/awesome/lib/wibox/container/margin.lua +++ /dev/null @@ -1,419 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_margin.svg) --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.container.margin ---------------------------------------------------------------------------- - -local pairs = pairs -local setmetatable = setmetatable -local base = require("wibox.widget.base") -local gcolor = require("gears.color") -local cairo = require("lgi").cairo -local util = require("awful.util") - -local margin = { mt = {} } - --- Draw a margin layout -function margin:draw(_, cr, width, height) - local x = self._private.left - local y = self._private.top - local w = self._private.right - local h = self._private.bottom - local color = self._private.color - - if not self._private.widget or width <= x + w or height <= y + h then - return - end - - if color then - cr:set_source(color) - cr:rectangle(0, 0, width, height) - cr:rectangle(x, y, width - x - w, height - y - h) - cr:set_fill_rule(cairo.FillRule.EVEN_ODD) - cr:fill() - end -end - --- Layout a margin layout -function margin:layout(_, width, height) - if self._private.widget then - local x = self._private.left - local y = self._private.top - local w = self._private.right - local h = self._private.bottom - - return { base.place_widget_at(self._private.widget, x, y, width - x - w, height - y - h) } - end -end - --- Fit a margin layout into the given space -function margin:fit(context, width, height) - local extra_w = self._private.left + self._private.right - local extra_h = self._private.top + self._private.bottom - local w, h = 0, 0 - if self._private.widget then - w, h = base.fit_widget(self, context, self._private.widget, width - extra_w, height - extra_h) - end - - if self._private.draw_empty == false and (w == 0 or h == 0) then - return 0, 0 - end - - return w + extra_w, h + extra_h -end - ---- The widget to be wrapped the the margins. --- @property widget --- @tparam widget widget The widget - -function margin:set_widget(widget) - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - -function margin:get_widget() - return self._private.widget -end - --- Get the number of children element --- @treturn table The children -function margin:get_children() - return {self._private.widget} -end - --- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function margin:set_children(children) - self:set_widget(children[1]) -end - ---- Set all the margins to val. --- @property margins --- @tparam number val The margin value - -function margin:set_margins(val) - if self._private.left == val and - self._private.right == val and - self._private.top == val and - self._private.bottom == val then - return - end - - self._private.left = val - self._private.right = val - self._private.top = val - self._private.bottom = val - self:emit_signal("widget::layout_changed") -end - ---- Set the margins color to create a border. --- @property color --- @param color A color used to fill the margin. - -function margin:set_color(color) - self._private.color = color and gcolor(color) - self:emit_signal("widget::redraw_needed") -end - -function margin:get_color() - return self._private.color -end - ---- Draw the margin even if the content size is 0x0 (default: true) --- @function draw_empty --- @tparam boolean draw_empty Draw nothing is content is 0x0 or draw the margin anyway - -function margin:set_draw_empty(draw_empty) - self._private.draw_empty = draw_empty - self:emit_signal("widget::layout_changed") -end - -function margin:get_draw_empty() - return self._private.draw_empty -end - ---- Reset this layout. The widget will be unreferenced, the margins set to 0 --- and the color erased -function margin:reset() - self:set_widget(nil) - self:set_margins(0) - self:set_color(nil) -end - ---- Set the left margin that this layout adds to its widget. --- @param margin The new margin to use. --- @property left - ---- Set the right margin that this layout adds to its widget. --- @param margin The new margin to use. --- @property right - ---- Set the top margin that this layout adds to its widget. --- @param margin The new margin to use. --- @property top - ---- Set the bottom margin that this layout adds to its widget. --- @param margin The new margin to use. --- @property bottom - --- Create setters for each direction -for _, v in pairs({ "left", "right", "top", "bottom" }) do - margin["set_" .. v] = function(layout, val) - if layout._private[v] == val then return end - layout._private[v] = val - layout:emit_signal("widget::layout_changed") - end - - margin["get_" .. v] = function(layout) - return layout._private[v] - end -end - ---- Returns a new margin container. --- @param[opt] widget A widget to use. --- @param[opt] left A margin to use on the left side of the widget. --- @param[opt] right A margin to use on the right side of the widget. --- @param[opt] top A margin to use on the top side of the widget. --- @param[opt] bottom A margin to use on the bottom side of the widget. --- @param[opt] color A color for the margins. --- @param[opt] draw_empty whether or not to draw the margin when the content is empty --- @treturn table A new margin container --- @function wibox.container.margin -local function new(widget, left, right, top, bottom, color, draw_empty) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - util.table.crush(ret, margin, true) - - ret:set_left(left or 0) - ret:set_right(right or 0) - ret:set_top(top or 0) - ret:set_bottom(bottom or 0) - ret:set_draw_empty(draw_empty) - - ret:set_color(color) - - if widget then - ret:set_widget(widget) - end - - return ret -end - -function margin.mt:__call(...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(margin, margin.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/mirror.lua b/awesome/lib/wibox/container/mirror.lua deleted file mode 100644 index fc275cf..0000000 --- a/awesome/lib/wibox/container/mirror.lua +++ /dev/null @@ -1,340 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_mirror.svg) --- --- @author dodo --- @copyright 2012 dodo --- @classmod wibox.container.mirror ---------------------------------------------------------------------------- - -local type = type -local error = error -local ipairs = ipairs -local setmetatable = setmetatable -local base = require("wibox.widget.base") -local matrix = require("gears.matrix") -local util = require("awful.util") - -local mirror = { mt = {} } - --- Layout this layout -function mirror:layout(_, width, height) - if not self._private.widget then return end - - local m = matrix.identity - local t = { x = 0, y = 0 } -- translation - local s = { x = 1, y = 1 } -- scale - if self._private.horizontal then - t.x = width - s.x = -1 - end - if self._private.vertical then - t.y = height - s.y = -1 - end - m = m:translate(t.x, t.y) - m = m:scale(s.x, s.y) - - return { base.place_widget_via_matrix(self._private.widget, m, width, height) } -end - --- Fit this layout into the given area -function mirror:fit(context, ...) - if not self._private.widget then - return 0, 0 - end - return base.fit_widget(self, context, self._private.widget, ...) -end - ---- The widget to be reflected. --- @property widget --- @tparam widget widget The widget - -function mirror:set_widget(widget) - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - -function mirror:get_widget() - return self._private.widget -end - ---- Get the number of children element --- @treturn table The children -function mirror:get_children() - return {self._private.widget} -end - ---- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function mirror:set_children(children) - self:set_widget(children[1]) -end - ---- Reset this layout. The widget will be removed and the axes reset. -function mirror:reset() - self._private.horizontal = false - self._private.vertical = false - self:set_widget(nil) -end - -function mirror:set_reflection(reflection) - if type(reflection) ~= 'table' then - error("Invalid type of reflection for mirror layout: " .. - type(reflection) .. " (should be a table)") - end - for _, ref in ipairs({"horizontal", "vertical"}) do - if reflection[ref] ~= nil then - self._private[ref] = reflection[ref] - end - end - self:emit_signal("widget::layout_changed") -end - ---- Get the reflection of this mirror layout. --- @property reflection --- @param table reflection A table of booleans with the keys "horizontal", "vertical". --- @param boolean reflection.horizontal --- @param boolean reflection.vertical - -function mirror:get_reflection() - return { horizontal = self._private.horizontal, vertical = self._private.vertical } -end - ---- Returns a new mirror container. --- A mirror container mirrors a given widget. Use --- `:set_widget()` to set the widget and --- `:set_horizontal()` and `:set_vertical()` for the direction. --- horizontal and vertical are by default false which doesn't change anything. --- @param[opt] widget The widget to display. --- @param[opt] reflection A table describing the reflection to apply. --- @treturn table A new mirror container --- @function wibox.container.mirror -local function new(widget, reflection) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - ret._private.horizontal = false - ret._private.vertical = false - - util.table.crush(ret, mirror, true) - - ret:set_widget(widget) - ret:set_reflection(reflection or {}) - - return ret -end - -function mirror.mt:__call(...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(mirror, mirror.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/radialprogressbar.lua b/awesome/lib/wibox/container/radialprogressbar.lua deleted file mode 100644 index 7c67906..0000000 --- a/awesome/lib/wibox/container/radialprogressbar.lua +++ /dev/null @@ -1,481 +0,0 @@ ---------------------------------------------------------------------------- --- --- A circular progressbar wrapper. --- --- If no child `widget` is set, then the radialprogressbar will take all the --- available size. Use a `wibox.container.constraint` to prevent this. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_radialprogressbar.svg) --- --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2013 Emmanuel Lepage Vallee --- @classmod wibox.container.radialprogressbar ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local base = require("wibox.widget.base") -local shape = require("gears.shape" ) -local util = require( "awful.util" ) -local color = require( "gears.color" ) -local beautiful = require("beautiful" ) - -local default_outline_width = 2 - -local radialprogressbar = { mt = {} } - ---- The progressbar border background color. --- @beautiful beautiful.radialprogressbar_border_color - ---- The progressbar foreground color. --- @beautiful beautiful.radialprogressbar_color - ---- The progressbar border width. --- @beautiful beautiful.radialprogressbar_border_width - ---- The padding between the outline and the progressbar. --- @beautiful beautiful.radialprogressbar_paddings --- @tparam[opt=0] table|number paddings A number or a table --- @tparam[opt=0] number paddings.top --- @tparam[opt=0] number paddings.bottom --- @tparam[opt=0] number paddings.left --- @tparam[opt=0] number paddings.right - -local function outline_workarea(self, width, height) - local border_width = self._private.border_width or - beautiful.radialprogressbar_border_width or default_outline_width - - local x, y = 0, 0 - - -- Make sure the border fit in the clip area - local offset = border_width/2 - x, y = x + offset, y+offset - width, height = width-2*offset, height-2*offset - - return {x=x, y=y, width=width, height=height}, offset -end - --- The child widget area -local function content_workarea(self, width, height) - local padding = self._private.paddings or {} - local wa = outline_workarea(self, width, height) - - wa.x = wa.x + (padding.left or 0) - wa.y = wa.y + (padding.top or 0) - wa.width = wa.width - (padding.left or 0) - (padding.right or 0) - wa.height = wa.height - (padding.top or 0) - (padding.bottom or 0) - - return wa -end - --- Draw the radial outline and progress -function radialprogressbar:after_draw_children(_, cr, width, height) - cr:restore() - - local border_width = self._private.border_width or - beautiful.radialprogressbar_border_width or default_outline_width - - local wa = outline_workarea(self, width, height) - cr:translate(wa.x, wa.y) - - -- Draw the outline - shape.rounded_bar(cr, wa.width, wa.height) - cr:set_source(color(self:get_border_color() or "#0000ff")) - cr:set_line_width(border_width) - cr:stroke() - - -- Draw the progress - cr:set_source(color(self:get_color() or "#ff00ff")) - shape.radial_progress(cr, wa.width, wa.height, self._percent or 0) - cr:set_line_width(border_width) - cr:stroke() - -end - --- Set the clip -function radialprogressbar:before_draw_children(_, cr, width, height) - cr:save() - local wa = content_workarea(self, width, height) - cr:translate(wa.x, wa.y) - shape.rounded_bar(cr, wa.width, wa.height) - cr:clip() - cr:translate(-wa.x, -wa.y) -end - --- Layout this layout -function radialprogressbar:layout(_, width, height) - if self._private.widget then - local wa = content_workarea(self, width, height) - - return { base.place_widget_at( - self._private.widget, wa.x, wa.y, wa.width, wa.height - ) } - end -end - --- Fit this layout into the given area -function radialprogressbar:fit(context, width, height) - if self._private.widget then - local wa = content_workarea(self, width, height) - local w, h = base.fit_widget(self, context, self._private.widget, wa.width, wa.height) - return wa.x + w, wa.y + h - end - - return width, height -end - ---- The widget to wrap in a radial proggressbar. --- @property widget --- @tparam widget widget The widget - -function radialprogressbar:set_widget(widget) - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - ---- Get the children elements --- @treturn table The children -function radialprogressbar:get_children() - return {self._private.widget} -end - ---- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function radialprogressbar:set_children(children) - self._private.widget = children and children[1] - self:emit_signal("widget::layout_changed") -end - ---- Reset this container. -function radialprogressbar:reset() - self:set_widget(nil) -end - -for _,v in ipairs {"left", "right", "top", "bottom"} do - radialprogressbar["set_"..v.."_padding"] = function(self, val) - self._private.paddings = self._private.paddings or {} - self._private.paddings[v] = val - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - end -end - ---- The padding between the outline and the progressbar. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_padding.svg) --- --- @property paddings --- @tparam[opt=0] table|number paddings A number or a table --- @tparam[opt=0] number paddings.top --- @tparam[opt=0] number paddings.bottom --- @tparam[opt=0] number paddings.left --- @tparam[opt=0] number paddings.right - ---- The progressbar value. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_value.svg) --- --- @property value --- @tparam number value Between min_value and max_value - -function radialprogressbar:set_value(val) - if not val then self._percent = 0; return end - - if val > self._private.max_value then - self:set_max_value(val) - elseif val < self._private.min_value then - self:set_min_value(val) - end - - local delta = self._private.max_value - self._private.min_value - - self._percent = val/delta - self:emit_signal("widget::redraw_needed") -end - ---- The border background color. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_border_color.svg) --- --- @property border_color - ---- The border foreground color. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_color.svg) --- --- @property color - ---- The border width. --- --- ---![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_border_width.svg) --- --- @property border_width --- @tparam[opt=3] number border_width - ---- The minimum value. --- @property min_value - ---- The maximum value. --- @property max_value - -for _, prop in ipairs {"max_value", "min_value", "border_color", "color", - "border_width", "paddings"} do - radialprogressbar["set_"..prop] = function(self, value) - self._private[prop] = value - self:emit_signal("property::"..prop) - self:emit_signal("widget::redraw_needed") - end - radialprogressbar["get_"..prop] = function(self) - return self._private[prop] or beautiful["radialprogressbar_"..prop] - end -end - -function radialprogressbar:set_paddings(val) - self._private.paddings = type(val) == "number" and { - left = val, - right = val, - top = val, - bottom = val, - } or val or {} - self:emit_signal("property::paddings") - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") -end - ---- Returns a new radialprogressbar layout. A radialprogressbar layout --- radialprogressbars a given widget. Use `.widget` to set the widget. --- @param[opt] widget The widget to display. --- @function wibox.container.radialprogressbar -local function new(widget) - local ret = base.make_widget(nil, nil, { - enable_properties = true, - }) - - util.table.crush(ret, radialprogressbar) - ret._private.max_value = 1 - ret._private.min_value = 0 - - ret:set_widget(widget) - - return ret -end - -function radialprogressbar.mt:__call(_, ...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(radialprogressbar, radialprogressbar.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/rotate.lua b/awesome/lib/wibox/container/rotate.lua deleted file mode 100644 index 5fe4a8e..0000000 --- a/awesome/lib/wibox/container/rotate.lua +++ /dev/null @@ -1,384 +0,0 @@ ---------------------------------------------------------------------------- --- A container rotating the conained widget by 90 degrees. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_defaults_rotate.svg) --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.container.rotate ---------------------------------------------------------------------------- - -local error = error -local pi = math.pi -local setmetatable = setmetatable -local tostring = tostring -local base = require("wibox.widget.base") -local matrix = require("gears.matrix") -local util = require("awful.util") - -local rotate = { mt = {} } - -local function transform(layout, width, height) - local dir = layout:get_direction() - if dir == "east" or dir == "west" then - return height, width - end - return width, height -end - --- Layout this layout -function rotate:layout(_, width, height) - if not self._private.widget or not self._private.widget._private.visible then - return - end - - local dir = self:get_direction() - - local m = matrix.identity - if dir == "west" then - m = m:rotate(pi / 2) - m = m:translate(0, -width) - elseif dir == "south" then - m = m:rotate(pi) - m = m:translate(-width, -height) - elseif dir == "east" then - m = m:rotate(3 * pi / 2) - m = m:translate(-height, 0) - end - - -- Since we rotated, we might have to swap width and height. - -- transform() does that for us. - return { base.place_widget_via_matrix(self._private.widget, m, transform(self, width, height)) } -end - --- Fit this layout into the given area -function rotate:fit(context, width, height) - if not self._private.widget then - return 0, 0 - end - return transform(self, base.fit_widget(self, context, self._private.widget, transform(self, width, height))) -end - ---- The widget to be rotated. --- @property widget --- @tparam widget widget The widget - -function rotate:set_widget(widget) - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") -end - -function rotate:get_widget() - return self._private.widget -end - ---- Get the number of children element --- @treturn table The children -function rotate:get_children() - return {self._private.widget} -end - ---- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function rotate:set_children(children) - self:set_widget(children[1]) -end - ---- Reset this layout. The widget will be removed and the rotation reset. -function rotate:reset() - self._private.direction = nil - self:set_widget(nil) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - ---- The direction of this rotating container. --- Valid values are: --- --- * *north* --- * *east* --- * *south* --- * *north* --- --- --- ---![Usage example](../images/AUTOGEN_wibox_container_rotate_angle.svg) --- --- @usage ---local normal = create_arrow('Normal') ---local north = wibox.container { --- create_arrow('North'), --- direction = 'north', --- widget = wibox.container.rotate ---} ---local south = wibox.container { --- create_arrow('South'), --- direction = 'south', --- widget = wibox.container.rotate ---} ---local east = wibox.container { --- create_arrow('East'), --- direction = 'east', --- widget = wibox.container.rotate ---} ---local west = wibox.container { --- create_arrow('West'), --- direction = 'west', --- widget = wibox.container.rotate ---} --- @property direction --- @tparam string dir The direction - -function rotate:set_direction(dir) - local allowed = { - north = true, - east = true, - south = true, - west = true - } - - if not allowed[dir] then - error("Invalid direction for rotate layout: " .. tostring(dir)) - end - - self._private.direction = dir - self:emit_signal("widget::layout_changed") -end - ---- Get the direction of this rotating layout -function rotate:get_direction() - return self._private.direction or "north" -end - ---- Returns a new rotate container. --- A rotate container rotates a given widget. Use --- :set_widget() to set the widget and :set_direction() for the direction. --- The default direction is "north" which doesn't change anything. --- @param[opt] widget The widget to display. --- @param[opt] dir The direction to rotate to. --- @treturn table A new rotate container. --- @function wibox.container.rotate -local function new(widget, dir) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - util.table.crush(ret, rotate, true) - - ret:set_widget(widget) - ret:set_direction(dir or "north") - - return ret -end - -function rotate.mt:__call(...) - return new(...) -end - -return setmetatable(rotate, rotate.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/container/scroll.lua b/awesome/lib/wibox/container/scroll.lua deleted file mode 100644 index 0fb2ad5..0000000 --- a/awesome/lib/wibox/container/scroll.lua +++ /dev/null @@ -1,716 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter (based on ideas from Saleur Geoffrey) --- @copyright 2015 Uli Schlachter --- @classmod wibox.container.scroll ---------------------------------------------------------------------------- - -local cache = require("gears.cache") -local timer = require("gears.timer") -local hierarchy = require("wibox.hierarchy") -local base = require("wibox.widget.base") -local lgi = require("lgi") -local GLib = lgi.GLib - -local scroll = {} -local scroll_mt = { __index = scroll } -local _need_scroll_redraw - --- "Strip" a context so that we can use it for our own drawing -local function cleanup_context(context) - local skip = { wibox = true, drawable = true, client = true, position = true } - local res = {} - for k, v in pairs(context) do - if not skip[k] then - res[k] = v - end - end - return res -end - --- Create a hierarchy (and some more stuff) for drawing the given widget. This --- allows "some stuff" to be re-used instead of re-created all the time. -local hierarchy_cache = cache.new(function(context, widget, width, height) - context = cleanup_context(context) - local layouts = setmetatable({}, { __mode = "k" }) - - -- Create a widget hierarchy and update when needed - local hier - local function do_pending_updates(layout) - layouts[layout] = true - hier:update(context, widget, width, height, nil) - end - local function emit(signal) - -- Make the scroll layouts redraw - for w in pairs(layouts) do - w:emit_signal(signal) - end - end - local function redraw_callback() - emit("widget::redraw_needed") - end - local function layout_callback() - emit("widget::redraw_needed") - emit("widget::layout_changed") - end - hier = hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, nil) - - return hier, do_pending_updates, context -end) - ---- Calculate all the information needed for scrolling. --- @param self The instance of the scrolling layout. --- @param context A widget context under which we are fit/drawn. --- @param width The available width --- @param height The available height --- @return A table with the following entries --- @field fit_width The width that should be returned from :fit --- @field fit_height The height that should be returned from :fit --- @field surface_width The width for showing the child widget --- @field surface_height The height for showing the child widget --- @field first_x The x offset for drawing the child the first time --- @field first_y The y offset for drawing the child the first time --- @field[opt] second_x The x offset for drawing the child the second time --- @field[opt] second_y The y offset for drawing the child the second time --- @field hierarchy The wibox.hierarchy instance representing "everything" --- @field context The widget context for drawing the hierarchy -local function calculate_info(self, context, width, height) - local result = {} - assert(self._private.widget) - - -- First, get the size of the widget (and the size of extra space) - local surface_width, surface_height = width, height - local extra_width, extra_height, extra = 0, 0, self._private.expand and self._private.extra_space or 0 - local w, h - if self._private.dir == "h" then - w, h = base.fit_widget(self, context, self._private.widget, self._private.space_for_scrolling, height) - surface_width = w - extra_width = extra - else - w, h = base.fit_widget(self, context, self._private.widget, width, self._private.space_for_scrolling) - surface_height = h - extra_height = extra - end - result.fit_width, result.fit_height = w, h - if self._private.dir == "h" then - if self._private.max_size then - result.fit_width = math.min(w, self._private.max_size) - end - else - if self._private.max_size then - result.fit_height = math.min(h, self._private.max_size) - end - end - if w > width or h > height then - -- There is less space available than we need, we have to scroll - _need_scroll_redraw(self) - - surface_width, surface_height = surface_width + extra_width, surface_height + extra_height - - local x, y = 0, 0 - local function get_scroll_offset(size, visible_size) - return self._private.step_function(self._private.timer:elapsed(), size, visible_size, self._private.speed, self._private.extra_space) - end - if self._private.dir == "h" then - x = -get_scroll_offset(surface_width - extra, width) - else - y = -get_scroll_offset(surface_height - extra, height) - end - result.first_x, result.first_y = x, y - -- Was the extra space already included elsewhere? - local extra_spacer = self._private.expand and 0 or self._private.extra_space - if self._private.dir == "h" then - x = x + surface_width + extra_spacer - else - y = y + surface_height + extra_spacer - end - result.second_x, result.second_y = x, y - else - result.first_x, result.first_y = 0, 0 - end - result.surface_width, result.surface_height = surface_width, surface_height - - -- Get the hierarchy and subscribe ourselves to updates - local hier, do_pending_updates, ctx = hierarchy_cache:get(context, - self._private.widget, surface_width, surface_height) - result.hierarchy = hier - result.context = ctx - do_pending_updates(self) - - return result -end - --- Draw this scrolling layout. --- @param context The context in which we are drawn. --- @param cr The cairo context to draw to. --- @param width The available width. --- @param height The available height. -function scroll:draw(context, cr, width, height) - if not self._private.widget then - return - end - - local info = calculate_info(self, context, width, height) - - -- Draw the first instance of the child - cr:save() - cr:translate(info.first_x, info.first_y) - cr:rectangle(0, 0, info.surface_width, info.surface_height) - cr:clip() - info.hierarchy:draw(info.context, cr) - cr:restore() - - -- If there is one, draw the second instance (same code as above, minus the - -- clip) - if info.second_x and info.second_y then - cr:translate(info.second_x, info.second_y) - cr:rectangle(0, 0, info.surface_width, info.surface_height) - cr:clip() - info.hierarchy:draw(info.context, cr) - end -end - --- Fit the scroll layout into the given space. --- @param context The context in which we are fit. --- @param width The available width. --- @param height The available height. -function scroll:fit(context, width, height) - if not self._private.widget then - return 0, 0 - end - local info = calculate_info(self, context, width, height) - return info.fit_width, info.fit_height -end - --- Internal function used for triggering redraws for scrolling. --- The purpose is to start a timer for redrawing the widget for scrolling. --- Redrawing works by simply emitting the `widget::redraw_needed` signal. --- Pausing is implemented in this function: We just don't start a timer. --- This function must be idempotent (calling it multiple times right after --- another does not make a difference). -_need_scroll_redraw = function(self) - if not self._private.paused and not self._private.scroll_timer then - self._private.scroll_timer = timer.start_new(1 / self._private.fps, function() - self._private.scroll_timer = nil - self:emit_signal("widget::redraw_needed") - end) - end -end - ---- Pause the scrolling animation. --- @see continue -function scroll:pause() - if self._private.paused then - return - end - self._private.paused = true - self._private.timer:stop() -end - ---- Continue the scrolling animation. --- @see pause -function scroll:continue() - if not self._private.paused then - return - end - self._private.paused = false - self._private.timer:continue() - self:emit_signal("widget::redraw_needed") -end - ---- Reset the scrolling state to its initial condition. --- For must scroll step functions, the effect of this function should be to --- display the widget without any scrolling applied. --- This function does not undo the effect of @{pause}. -function scroll:reset_scrolling() - self._private.timer:start() - if self._private.paused then - self._private.timer:stop() - end -end - ---- Set the direction in which this widget scroll. --- @param dir Either "h" for horizontal scrolling or "v" for vertical scrolling -function scroll:set_direction(dir) - if dir == self._private.dir then - return - end - if dir ~= "h" and dir ~= "v" then - error("Invalid direction, can only be 'h' or 'v'") - end - self._private.dir = dir - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::redraw_needed") -end - ---- The widget to be scrolled. --- @property widget --- @tparam widget widget The widget - -function scroll:set_widget(widget) - if widget == self._private.widget then - return - end - if widget then - base.check_widget(widget) - end - self._private.widget = widget - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::redraw_needed") -end - -function scroll:get_widget() - return self._private.widget -end - ---- Get the number of children element --- @treturn table The children -function scroll:get_children() - return {self._private.widget} -end - ---- Replace the layout children --- This layout only accept one children, all others will be ignored --- @tparam table children A table composed of valid widgets -function scroll:set_children(children) - self:set_widget(children[1]) -end - ---- Specify the expand mode that is used for extra space. --- @tparam boolean expand If true, the widget is expanded to include the extra --- space. If false, the extra space is simply left empty. --- @see set_extra_space -function scroll:set_expand(expand) - if expand == self._private.expand then - return - end - self._private.expand = expand - self:emit_signal("widget::redraw_needed") -end - ---- Set the number of frames per second that this widget should draw. --- @tparam number fps The number of frames per second -function scroll:set_fps(fps) - if fps == self._private.fps then - return - end - self._private.fps = fps - -- No signal needed: If we are scrolling, the next redraw will apply the new - -- FPS, else it obviously doesn't make a difference. -end - ---- Set the amount of extra space that should be included in the scrolling. This --- extra space will likely be left empty between repetitions of the widgets. --- @tparam number extra_space The amount of extra space --- @see set_expand -function scroll:set_extra_space(extra_space) - if extra_space == self._private.extra_space then - return - end - self._private.extra_space = extra_space - self:emit_signal("widget::redraw_needed") -end - ---- Set the speed of the scrolling animation. The exact meaning depends on the --- step function that is used, but for the simplest step functions, this will be --- in pixels per second. --- @tparam number speed The speed for the animation -function scroll:set_speed(speed) - if speed == self._private.speed then - return - end - self._private.speed = speed - self:emit_signal("widget::redraw_needed") -end - ---- Set the maximum size of this widget in the direction set by --- @{set_direction}. If the child widget is smaller than this size, no scrolling --- is done. If the child widget is larger, then only this size will be visible --- and the rest is made visible via scrolling. --- @tparam number max_size The maximum size of this widget or nil for unlimited. -function scroll:set_max_size(max_size) - if max_size == self._private.max_size then - return - end - self._private.max_size = max_size - self:emit_signal("widget::layout_changed") -end - ---- Set the step function that determines the exact behaviour of the scrolling --- animation. --- The step function is called with five arguments: --- --- * The time in seconds since the state of the animation --- * The size of the child widget --- * The size of the visible part of the widget --- * The speed of the animation. This should have a linear effect on this --- function's behaviour. --- * The extra space configured by @{set_extra_space}. This was not yet added to --- the size of the child widget, but should likely be added to it in most --- cases. --- --- The step function should return a single number. This number is the offset at --- which the widget is drawn and should be between 0 and `size+extra_space`. --- @tparam function step_function A step function. --- @see step_functions -function scroll:set_step_function(step_function) - -- Call the step functions once to see if it works - step_function(0, 42, 10, 10, 5) - if step_function == self._private.step_function then - return - end - self._private.step_function = step_function - self:emit_signal("widget::redraw_needed") -end - ---- Set an upper limit for the space for scrolling. --- This restricts the child widget's maximal size. --- @tparam number space_for_scrolling The space for scrolling -function scroll:set_space_for_scrolling(space_for_scrolling) - if space_for_scrolling == self._private.space_for_scrolling then - return - end - self._private.space_for_scrolling = space_for_scrolling - self:emit_signal("widget::layout_changed") -end - -local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - ret._private.paused = false - ret._private.timer = GLib.Timer() - ret._private.scroll_timer = nil - - setmetatable(ret, scroll_mt) - - ret:set_direction(dir) - ret:set_widget(widget) - ret:set_fps(fps or 20) - ret:set_speed(speed or 10) - ret:set_extra_space(extra_space or 0) - ret:set_expand(expand) - ret:set_max_size(max_size) - ret:set_step_function(step_function or scroll.step_functions.linear_increase) - ret:set_space_for_scrolling(space_for_scrolling or 2^1024) - - return ret -end - ---- Get a new horizontal scrolling container. --- @param[opt] widget The widget that should be scrolled --- @param[opt=20] fps The number of frames per second --- @param[opt=10] speed The speed of the animation --- @param[opt=0] extra_space The amount of extra space to include --- @tparam[opt=false] boolean expand Should the widget be expanded to include the --- extra space? --- @param[opt] max_size The maximum size of the child widget --- @param[opt=step_functions.linear_increase] step_function The step function to be used --- @param[opt=2^1024] space_for_scrolling The space for scrolling -function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling) - return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling) -end - ---- Get a new vertical scrolling container. --- @param[opt] widget The widget that should be scrolled --- @param[opt=20] fps The number of frames per second --- @param[opt=10] speed The speed of the animation --- @param[opt=0] extra_space The amount of extra space to include --- @tparam[opt=false] boolean expand Should the widget be expanded to include the --- extra space? --- @param[opt] max_size The maximum size of the child widget --- @param[opt=step_functions.linear_increase] step_function The step function to be used --- @param[opt=2^1024] space_for_scrolling The space for scrolling -function scroll.vertical(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling) - return get_layout("v", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling) -end - ---- A selection of step functions --- @see set_step_function -scroll.step_functions = {} - ---- A step function that scrolls the widget in an increasing direction with --- constant speed. -function scroll.step_functions.linear_increase(elapsed, size, _, speed, extra_space) - return (elapsed * speed) % (size + extra_space) -end - ---- A step function that scrolls the widget in an decreasing direction with --- constant speed. -function scroll.step_functions.linear_decrease(elapsed, size, _, speed, extra_space) - return (-elapsed * speed) % (size + extra_space) -end - ---- A step function that scrolls the widget to its end and back to its --- beginning, then back to its end, etc. The speed is constant. -function scroll.step_functions.linear_back_and_forth(elapsed, size, visible_size, speed) - local state = ((elapsed * speed) % (2 * size)) / size - state = state <= 1 and state or 2 - state - return (size - visible_size) * state -end - ---- A step function that scrolls the widget to its end and back to its --- beginning, then back to its end, etc. The speed is null at the ends and --- maximal in the middle. -function scroll.step_functions.nonlinear_back_and_forth(elapsed, size, visible_size, speed) - local state = ((elapsed * speed) % (2 * size)) / size - local negate = false - if state > 1 then - negate = true - state = state - 1 - end - if state < 1/3 then - -- In the first 1/3rd of time, do a quadratic increase in speed - state = 2 * state * state - elseif state < 2/3 then - -- In the center, do a linear increase. That means we need: - -- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3 - -- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3) - state = 5/3*state - 3/9 - else - -- In the last 1/3rd of time, do a quadratic decrease in speed - state = 1 - 2 * (1 - state) * (1 - state) - end - if negate then - state = 1 - state - end - return (size - visible_size) * state -end - ---- A step function that scrolls the widget to its end and back to its --- beginning, then back to its end, etc. The speed is null at the ends and --- maximal in the middle. At both ends the widget stands still for a moment. -function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, visible_size, speed) - local state = ((elapsed * speed) % (2 * size)) / size - local negate = false - if state > 1 then - negate = true - state = state - 1 - end - if state < 1/5 or state > 4/5 then - -- One fifth of time, nothing moves - state = state < 1/5 and 0 or 1 - else - state = (state - 1/5) * 5/3 - if state < 1/3 then - -- In the first 1/3rd of time, do a quadratic increase in speed - state = 2 * state * state - elseif state < 2/3 then - -- In the center, do a linear increase. That means we need: - -- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3 - -- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3) - state = 5/3*state - 3/9 - else - -- In the last 1/3rd of time, do a quadratic decrease in speed - state = 1 - 2 * (1 - state) * (1 - state) - end - end - if negate then - state = 1 - state - end - return (size - visible_size) * state -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return scroll - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/drawable.lua b/awesome/lib/wibox/drawable.lua deleted file mode 100644 index 330edc3..0000000 --- a/awesome/lib/wibox/drawable.lua +++ /dev/null @@ -1,489 +0,0 @@ ---------------------------------------------------------------------------- ---- Handling of drawables. A drawable is something that can be drawn to. --- --- @author Uli Schlachter --- @copyright 2012 Uli Schlachter --- @classmod wibox.drawable ---------------------------------------------------------------------------- - -local drawable = {} -local capi = { - awesome = awesome, - root = root, - screen = screen -} -local beautiful = require("beautiful") -local cairo = require("lgi").cairo -local color = require("gears.color") -local object = require("gears.object") -local surface = require("gears.surface") -local timer = require("gears.timer") -local grect = require("gears.geometry").rectangle -local matrix = require("gears.matrix") -local hierarchy = require("wibox.hierarchy") -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) - -local visible_drawables = {} - --- Get the widget context. This should always return the same table (if --- possible), so that our draw and fit caches can work efficiently. -local function get_widget_context(self) - local geom = self.drawable:geometry() - - local s = self._forced_screen - if not s then - local sgeos = {} - - for scr in capi.screen do - sgeos[scr] = scr.geometry - end - - s = grect.get_by_coord(sgeos, geom.x, geom.y) or capi.screen.primary - end - - local context = self._widget_context - local dpi = beautiful.xresources.get_dpi(s) - if (not context) or context.screen ~= s or context.dpi ~= dpi then - context = { - screen = s, - dpi = dpi, - drawable = self, - } - for k, v in pairs(self._widget_context_skeleton) do - context[k] = v - end - self._widget_context = context - - -- Give widgets a chance to react to the new context - self._need_complete_repaint = true - end - return context -end - -local function do_redraw(self) - if not self.drawable.valid then return end - if self._forced_screen and not self._forced_screen.valid then return end - - local surf = surface.load_silently(self.drawable.surface, false) - -- The surface can be nil if the drawable's parent was already finalized - if not surf then return end - local cr = cairo.Context(surf) - local geom = self.drawable:geometry(); - local x, y, width, height = geom.x, geom.y, geom.width, geom.height - local context = get_widget_context(self) - - -- Relayout - if self._need_relayout or self._need_complete_repaint then - self._need_relayout = false - if self._widget_hierarchy and self.widget then - self._widget_hierarchy:update(context, - self.widget, width, height, self._dirty_area) - else - self._need_complete_repaint = true - if self.widget then - self._widget_hierarchy_callback_arg = {} - self._widget_hierarchy = hierarchy.new(context, self.widget, width, height, - self._redraw_callback, self._layout_callback, self._widget_hierarchy_callback_arg) - else - self._widget_hierarchy = nil - end - end - - if self._need_complete_repaint then - self._need_complete_repaint = false - self._dirty_area:union_rectangle(cairo.RectangleInt{ - x = 0, y = 0, width = width, height = height - }) - end - end - - -- Clip to the dirty area - if self._dirty_area:is_empty() then - return - end - for i = 0, self._dirty_area:num_rectangles() - 1 do - local rect = self._dirty_area:get_rectangle(i) - cr:rectangle(rect.x, rect.y, rect.width, rect.height) - end - self._dirty_area = cairo.Region.create() - cr:clip() - - -- Draw the background - cr:save() - - if not capi.awesome.composite_manager_running then - -- This is pseudo-transparency: We draw the wallpaper in the background - local wallpaper = surface.load_silently(capi.root.wallpaper(), false) - if wallpaper then - cr.operator = cairo.Operator.SOURCE - cr:set_source_surface(wallpaper, -x, -y) - cr:paint() - end - cr.operator = cairo.Operator.OVER - else - -- This is true transparency: We draw a translucent background - cr.operator = cairo.Operator.SOURCE - end - - cr:set_source(self.background_color) - cr:paint() - - cr:restore() - - -- Paint the background image - if self.background_image then - cr:save() - if type(self.background_image) == "function" then - self.background_image(context, cr, width, height, unpack(self.background_image_args)) - else - local pattern = cairo.Pattern.create_for_surface(self.background_image) - cr:set_source(pattern) - cr:paint() - end - cr:restore() - end - - -- Draw the widget - if self._widget_hierarchy then - cr:set_source(self.foreground_color) - self._widget_hierarchy:draw(context, cr) - end - - self.drawable:refresh() - - assert(cr.status == "SUCCESS", "Cairo context entered error state: " .. cr.status) -end - -local function find_widgets(_drawable, result, _hierarchy, x, y) - local m = _hierarchy:get_matrix_from_device() - - -- Is (x,y) inside of this hierarchy or any child (aka the draw extents) - local x1, y1 = m:transform_point(x, y) - local x2, y2, w2, h2 = _hierarchy:get_draw_extents() - if x1 < x2 or x1 >= x2 + w2 then - return - end - if y1 < y2 or y1 >= y2 + h2 then - return - end - - -- Is (x,y) inside of this widget? - local width, height = _hierarchy:get_size() - if x1 >= 0 and y1 >= 0 and x1 <= width and y1 <= height then - -- Get the extents of this widget in the device space - local x3, y3, w3, h3 = matrix.transform_rectangle(_hierarchy:get_matrix_to_device(), - 0, 0, width, height) - table.insert(result, { - x = x3, y = y3, width = w3, height = h3, - widget_width = width, - widget_height = height, - drawable = _drawable, - widget = _hierarchy:get_widget(), - hierarchy = _hierarchy - }) - end - for _, child in ipairs(_hierarchy:get_children()) do - find_widgets(_drawable, result, child, x, y) - end -end - ---- Find a widget by a point. --- The drawable must have drawn itself at least once for this to work. --- @param x X coordinate of the point --- @param y Y coordinate of the point --- @treturn table A table containing a description of all the widgets that --- contain the given point. Each entry is a table containing this drawable as --- its `.drawable` entry, the widget under `.widget` and the instance of --- `wibox.hierarchy` describing the size and position of the widget under --- `.hierarchy`. For convenience, `.x`, `.y`, `.width` and `.height` contain an --- approximation of the widget's extents on the surface. `widget_width` and --- `widget_height` contain the exact size of the widget in its own, local --- coordinate system (which may e.g. be rotated and scaled). -function drawable:find_widgets(x, y) - local result = {} - if self._widget_hierarchy then - find_widgets(self, result, self._widget_hierarchy, x, y) - end - return result -end - - ---- Set the widget that the drawable displays -function drawable:set_widget(widget) - self.widget = widget - - -- Make sure the widget gets drawn - self._need_relayout = true - self.draw() -end - ---- Set the background of the drawable --- @param c The background to use. This must either be a cairo pattern object, --- nil or a string that gears.color() understands. --- @see gears.color -function drawable:set_bg(c) - c = c or "#000000" - local t = type(c) - - if t == "string" or t == "table" then - c = color(c) - end - - -- If the background is completely opaque, we don't need to redraw when - -- the drawable is moved - -- XXX: This isn't needed when awesome.composite_manager_running is true, - -- but a compositing manager could stop/start and we'd have to properly - -- handle this. So for now we choose the lazy approach. - local redraw_on_move = not color.create_opaque_pattern(c) - if self._redraw_on_move ~= redraw_on_move then - self._redraw_on_move = redraw_on_move - if redraw_on_move then - self.drawable:connect_signal("property::x", self._do_complete_repaint) - self.drawable:connect_signal("property::y", self._do_complete_repaint) - else - self.drawable:disconnect_signal("property::x", self._do_complete_repaint) - self.drawable:disconnect_signal("property::y", self._do_complete_repaint) - end - end - - self.background_color = c - self._do_complete_repaint() -end - ---- Set the background image of the drawable --- If `image` is a function, it will be called with `(context, cr, width, height)` --- as arguments. Any other arguments passed to this method will be appended. --- @param image A background image or a function -function drawable:set_bgimage(image, ...) - if type(image) ~= "function" then - image = surface(image) - end - - self.background_image = image - self.background_image_args = {...} - - self._do_complete_repaint() -end - ---- Set the foreground of the drawable --- @param c The foreground to use. This must either be a cairo pattern object, --- nil or a string that gears.color() understands. --- @see gears.color -function drawable:set_fg(c) - c = c or "#FFFFFF" - if type(c) == "string" or type(c) == "table" then - c = color(c) - end - self.foreground_color = c - self._do_complete_repaint() -end - -function drawable:_force_screen(s) - self._forced_screen = s -end - -function drawable:_inform_visible(visible) - self._visible = visible - if visible then - visible_drawables[self] = true - -- The wallpaper or widgets might have changed - self:_do_complete_repaint() - else - visible_drawables[self] = nil - end -end - -local function emit_difference(name, list, skip) - local function in_table(table, val) - for _, v in pairs(table) do - if v.widget == val.widget then - return true - end - end - return false - end - - for _, v in pairs(list) do - if not in_table(skip, v) then - v.widget:emit_signal(name,v) - end - end -end - -local function handle_leave(_drawable) - emit_difference("mouse::leave", _drawable._widgets_under_mouse, {}) - _drawable._widgets_under_mouse = {} -end - -local function handle_motion(_drawable, x, y) - if x < 0 or y < 0 or x > _drawable.drawable:geometry().width or y > _drawable.drawable:geometry().height then - return handle_leave(_drawable) - end - - -- Build a plain list of all widgets on that point - local widgets_list = _drawable:find_widgets(x, y) - - -- First, "leave" all widgets that were left - emit_difference("mouse::leave", _drawable._widgets_under_mouse, widgets_list) - -- Then enter some widgets - emit_difference("mouse::enter", widgets_list, _drawable._widgets_under_mouse) - - _drawable._widgets_under_mouse = widgets_list -end - -local function setup_signals(_drawable) - local d = _drawable.drawable - - local function clone_signal(name) - -- When "name" is emitted on wibox.drawin, also emit it on wibox - d:connect_signal(name, function(_, ...) - _drawable:emit_signal(name, ...) - end) - end - clone_signal("button::press") - clone_signal("button::release") - clone_signal("mouse::enter") - clone_signal("mouse::leave") - clone_signal("mouse::move") - clone_signal("property::surface") - clone_signal("property::width") - clone_signal("property::height") - clone_signal("property::x") - clone_signal("property::y") -end - -function drawable.new(d, widget_context_skeleton, drawable_name) - local ret = object() - ret.drawable = d - ret._widget_context_skeleton = widget_context_skeleton - ret._need_complete_repaint = true - ret._need_relayout = true - ret._dirty_area = cairo.Region.create() - setup_signals(ret) - - for k, v in pairs(drawable) do - if type(v) == "function" then - ret[k] = v - end - end - - -- Only redraw a drawable once, even when we get told to do so multiple times. - ret._redraw_pending = false - ret._do_redraw = function() - ret._redraw_pending = false - do_redraw(ret) - end - - -- Connect our signal when we need a redraw - ret.draw = function() - if not ret._redraw_pending then - timer.delayed_call(ret._do_redraw) - ret._redraw_pending = true - end - end - ret._do_complete_repaint = function() - ret._need_complete_repaint = true - ret:draw() - end - - -- Do a full redraw if the surface changes (the new surface has no content yet) - d:connect_signal("property::surface", ret._do_complete_repaint) - - -- Do a normal redraw when the drawable moves. This will likely do nothing - -- in most cases, but it makes us do a complete repaint when we are moved to - -- a different screen. - d:connect_signal("property::x", ret.draw) - d:connect_signal("property::y", ret.draw) - - -- Currently we aren't redrawing on move (signals not connected). - -- :set_bg() will later recompute this. - ret._redraw_on_move = false - - -- Set the default background - ret:set_bg(beautiful.bg_normal) - ret:set_fg(beautiful.fg_normal) - - -- Initialize internals - ret._widgets_under_mouse = {} - - local function button_signal(name) - d:connect_signal(name, function(_, x, y, button, modifiers) - local widgets = ret:find_widgets(x, y) - for _, v in pairs(widgets) do - -- Calculate x/y inside of the widget - local lx, ly = v.hierarchy:get_matrix_from_device():transform_point(x, y) - v.widget:emit_signal(name, lx, ly, button, modifiers,v) - end - end) - end - button_signal("button::press") - button_signal("button::release") - - d:connect_signal("mouse::move", function(_, x, y) handle_motion(ret, x, y) end) - d:connect_signal("mouse::leave", function() handle_leave(ret) end) - - -- Set up our callbacks for repaints - ret._redraw_callback = function(hierar, arg) - -- Avoid crashes when a drawable was partly finalized and dirty_area is broken. - if not ret._visible then - return - end - if ret._widget_hierarchy_callback_arg ~= arg then - return - end - local m = hierar:get_matrix_to_device() - local x, y, width, height = matrix.transform_rectangle(m, hierar:get_draw_extents()) - local x1, y1 = math.floor(x), math.floor(y) - local x2, y2 = math.ceil(x + width), math.ceil(y + height) - ret._dirty_area:union_rectangle(cairo.RectangleInt{ - x = x1, y = y1, width = x2 - x1, height = y2 - y1 - }) - ret:draw() - end - ret._layout_callback = function(_, arg) - if ret._widget_hierarchy_callback_arg ~= arg then - return - end - ret._need_relayout = true - -- When not visible, we will be redrawn when we become visible. In the - -- mean-time, the layout does not matter much. - if ret._visible then - ret:draw() - end - end - - -- Add __tostring method to metatable. - ret.drawable_name = drawable_name or object.modulename(3) - local mt = {} - local orig_string = tostring(ret) - mt.__tostring = function() - return string.format("%s (%s)", ret.drawable_name, orig_string) - end - ret = setmetatable(ret, mt) - - -- Make sure the drawable is drawn at least once - ret._do_complete_repaint() - - return ret -end - --- Redraw all drawables when the wallpaper changes -capi.awesome.connect_signal("wallpaper_changed", function() - for d in pairs(visible_drawables) do - d:_do_complete_repaint() - end -end) - --- Give drawables a chance to react to screen changes -local function draw_all() - for d in pairs(visible_drawables) do - d:draw() - end -end -screen.connect_signal("property::geometry", draw_all) -screen.connect_signal("added", draw_all) -screen.connect_signal("removed", draw_all) - -return setmetatable(drawable, { __call = function(_, ...) return drawable.new(...) end }) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/hierarchy.lua b/awesome/lib/wibox/hierarchy.lua deleted file mode 100644 index 6bf2167..0000000 --- a/awesome/lib/wibox/hierarchy.lua +++ /dev/null @@ -1,333 +0,0 @@ ---------------------------------------------------------------------------- --- Management of widget hierarchies. Each widget hierarchy object has a widget --- for which it saves e.g. size and transformation in its parent. Also, each --- widget has a number of children. --- --- @author Uli Schlachter --- @copyright 2015 Uli Schlachter --- @module wibox.hierarchy ---------------------------------------------------------------------------- - -local matrix = require("gears.matrix") -local protected_call = require("gears.protected_call") -local cairo = require("lgi").cairo -local base = require("wibox.widget.base") -local no_parent = base.no_parent_I_know_what_I_am_doing - -local hierarchy = {} - -local function hierarchy_new(redraw_callback, layout_callback, callback_arg) - local result = { - _matrix = matrix.identity, - _matrix_to_device = matrix.identity, - _need_update = true, - _widget = nil, - _context = nil, - _redraw_callback = redraw_callback, - _layout_callback = layout_callback, - _callback_arg = callback_arg, - _size = { - width = nil, - height = nil - }, - _draw_extents = { - x = 0, - y = 0, - width = 0, - height = 0 - }, - _parent = nil, - _children = {} - } - - function result._redraw() - redraw_callback(result, callback_arg) - end - function result._layout() - local h = result - while h do - h._need_update = true - h = h._parent - end - layout_callback(result, callback_arg) - end - function result._emit_recursive(widget, name, ...) - local cur = result - assert(widget == cur._widget) - while cur do - if cur._widget then - cur._widget:emit_signal(name, ...) - end - cur = cur._parent - end - end - - for k, f in pairs(hierarchy) do - if type(f) == "function" then - result[k] = f - end - end - return result -end - -local hierarchy_update -function hierarchy_update(self, context, widget, width, height, region, matrix_to_parent, matrix_to_device) - if (not self._need_update) and self._widget == widget and - self._context == context and - self._size.width == width and self._size.height == height and - matrix.equals(self._matrix, matrix_to_parent) and - matrix.equals(self._matrix_to_device, matrix_to_device) then - -- Nothing changed - return - end - - self._need_update = false - - local old_x, old_y, old_width, old_height - local old_widget = self._widget - if self._size.width and self._size.height then - local x, y, w, h = matrix.transform_rectangle(self._matrix_to_device, 0, 0, self._size.width, self._size.height) - old_x, old_y = math.floor(x), math.floor(y) - old_width, old_height = math.ceil(x + w) - old_x, math.ceil(y + h) - old_y - else - old_x, old_y, old_width, old_height = 0, 0, 0, 0 - end - - -- Disconnect old signals - if old_widget and old_widget ~= widget then - self._widget:disconnect_signal("widget::redraw_needed", self._redraw) - self._widget:disconnect_signal("widget::layout_changed", self._layout) - self._widget:disconnect_signal("widget::emit_recursive", self._emit_recursive) - end - - -- Save the arguments we need to save - self._widget = widget - self._context = context - self._size.width = width - self._size.height = height - self._matrix = matrix_to_parent - self._matrix_to_device = matrix_to_device - - -- Connect signals - if old_widget ~= widget then - widget:weak_connect_signal("widget::redraw_needed", self._redraw) - widget:weak_connect_signal("widget::layout_changed", self._layout) - widget:weak_connect_signal("widget::emit_recursive", self._emit_recursive) - end - - -- Update children - local old_children = self._children - local layout_result = base.layout_widget(no_parent, context, widget, width, height) - self._children = {} - for _, w in ipairs(layout_result or {}) do - local r = table.remove(old_children, 1) - if not r then - r = hierarchy_new(self._redraw_callback, self._layout_callback, self._callback_arg) - r._parent = self - end - hierarchy_update(r, context, w._widget, w._width, w._height, region, w._matrix, w._matrix * matrix_to_device) - table.insert(self._children, r) - end - - -- Calculate the draw extents - local x1, y1, x2, y2 = 0, 0, width, height - for _, h in ipairs(self._children) do - local px, py, pwidth, pheight = matrix.transform_rectangle(h._matrix, h:get_draw_extents()) - x1 = math.min(x1, px) - y1 = math.min(y1, py) - x2 = math.max(x2, px + pwidth) - y2 = math.max(y2, py + pheight) - end - self._draw_extents = { - x = x1, y = y1, - width = x2 - x1, - height = y2 - y1 - } - - -- Check which part needs to be redrawn - - -- Are there any children which were removed? Their area needs a redraw. - for _, child in ipairs(old_children) do - local x, y, w, h = matrix.transform_rectangle(child._matrix_to_device, child:get_draw_extents()) - region:union_rectangle(cairo.RectangleInt{ - x = x, y = y, width = w, height = h - }) - child._parent = nil - end - - -- Did we change and need to be redrawn? - local x, y, w, h = matrix.transform_rectangle(self._matrix_to_device, 0, 0, self._size.width, self._size.height) - local new_x, new_y = math.floor(x), math.floor(y) - local new_width, new_height = math.ceil(x + w) - new_x, math.ceil(y + h) - new_y - if new_x ~= old_x or new_y ~= old_y or new_width ~= old_width or new_height ~= old_height or - widget ~= old_widget then - region:union_rectangle(cairo.RectangleInt{ - x = old_x, y = old_y, width = old_width, height = old_height - }) - region:union_rectangle(cairo.RectangleInt{ - x = new_x, y = new_y, width = new_width, height = new_height - }) - end -end - ---- Create a new widget hierarchy that has no parent. --- @param context The context in which we are laid out. --- @param widget The widget that is at the base of the hierarchy. --- @param width The available width for this hierarchy. --- @param height The available height for this hierarchy. --- @param redraw_callback Callback that is called with the corresponding widget --- hierarchy on widget::redraw_needed on some widget. --- @param layout_callback Callback that is called with the corresponding widget --- hierarchy on widget::layout_changed on some widget. --- @param callback_arg A second argument that is given to the above callbacks. --- @return A new widget hierarchy -function hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, callback_arg) - local result = hierarchy_new(redraw_callback, layout_callback, callback_arg) - result:update(context, widget, width, height) - return result -end - ---- Update a widget hierarchy with some new state. --- @param context The context in which we are laid out. --- @param widget The widget that is at the base of the hierarchy. --- @param width The available width for this hierarchy. --- @param height The available height for this hierarchy. --- @param[opt] region A region to use for accumulating changed parts --- @return A cairo region describing the changed parts (either the `region` --- argument or a new, internally created region). -function hierarchy:update(context, widget, width, height, region) - region = region or cairo.Region.create() - hierarchy_update(self, context, widget, width, height, region, self._matrix, self._matrix_to_device) - return region -end - ---- Get the widget that this hierarchy manages. -function hierarchy:get_widget() - return self._widget -end - ---- Get a matrix that transforms to the parent's coordinate space from this --- hierarchy's coordinate system. --- @return A matrix describing the transformation. -function hierarchy:get_matrix_to_parent() - return self._matrix -end - ---- Get a matrix that transforms to the base of this hierarchy's coordinate --- system (aka the coordinate system of the device that this --- hierarchy is applied upon) from this hierarchy's coordinate system. --- @return A matrix describing the transformation. -function hierarchy:get_matrix_to_device() - return self._matrix_to_device -end - ---- Get a matrix that transforms from the parent's coordinate space into this --- hierarchy's coordinate system. --- @return A matrix describing the transformation. -function hierarchy:get_matrix_from_parent() - local m = self:get_matrix_to_parent() - return m:invert() -end - ---- Get a matrix that transforms from the base of this hierarchy's coordinate --- system (aka the coordinate system of the device that this --- hierarchy is applied upon) into this hierarchy's coordinate system. --- @return A matrix describing the transformation. -function hierarchy:get_matrix_from_device() - local m = self:get_matrix_to_device() - return m:invert() -end - ---- Get the extents that this hierarchy possibly draws to (in the current coordinate space). --- This includes the size of this element plus the size of all children --- (after applying the corresponding transformation). --- @return x, y, width, height -function hierarchy:get_draw_extents() - local ext = self._draw_extents - return ext.x, ext.y, ext.width, ext.height -end - ---- Get the size that this hierarchy logically covers (in the current coordinate space). --- @return width, height -function hierarchy:get_size() - local ext = self._size - return ext.width, ext.height -end - ---- Get a list of all children. --- @return List of all children hierarchies. -function hierarchy:get_children() - return self._children -end - ---- Does the given cairo context have an empty clip (aka "no drawing possible")? -local function empty_clip(cr) - local _, _, width, height = cr:clip_extents() - return width == 0 or height == 0 -end - ---- Draw a hierarchy to some cairo context. --- This function draws the widgets in this widget hierarchy to the given cairo --- context. The context's clip is used to skip parts that aren't visible. --- @param context The context in which widgets are drawn. --- @param cr The cairo context that is used for drawing. -function hierarchy:draw(context, cr) - local widget = self:get_widget() - if not widget._private.visible then - return - end - - cr:save() - cr:transform(self:get_matrix_to_parent():to_cairo_matrix()) - - -- Clip to the draw extents - cr:rectangle(self:get_draw_extents()) - cr:clip() - - -- Draw if needed - if not empty_clip(cr) then - local opacity = widget:get_opacity() - local function call(func, extra_arg1, extra_arg2) - if not func then return end - if not extra_arg2 then - protected_call(func, widget, context, cr, self:get_size()) - else - protected_call(func, widget, context, extra_arg1, extra_arg2, cr, self:get_size()) - end - end - - -- Prepare opacity handling - if opacity ~= 1 then - cr:push_group() - end - - -- Draw the widget - cr:save() - cr:rectangle(0, 0, self:get_size()) - cr:clip() - call(widget.draw) - cr:restore() - - -- Draw its children (We already clipped to the draw extents above) - call(widget.before_draw_children) - for i, wi in ipairs(self:get_children()) do - call(widget.before_draw_child, i, wi:get_widget()) - wi:draw(context, cr) - call(widget.after_draw_child, i, wi:get_widget()) - end - call(widget.after_draw_children) - - -- Apply opacity - if opacity ~= 1 then - cr:pop_group_to_source() - cr.operator = cairo.Operator.OVER - cr:paint_with_alpha(opacity) - end - end - - cr:restore() -end - -return hierarchy - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/init.lua b/awesome/lib/wibox/init.lua deleted file mode 100644 index 3fc89ce..0000000 --- a/awesome/lib/wibox/init.lua +++ /dev/null @@ -1,479 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox ---------------------------------------------------------------------------- - -local capi = { - drawin = drawin, - root = root, - awesome = awesome, - screen = screen -} -local setmetatable = setmetatable -local pairs = pairs -local type = type -local object = require("gears.object") -local grect = require("gears.geometry").rectangle -local beautiful = require("beautiful") -local base = require("wibox.widget.base") - ---- This provides widget box windows. Every wibox can also be used as if it were --- a drawin. All drawin functions and properties are also available on wiboxes! --- wibox -local wibox = { mt = {}, object = {} } -wibox.layout = require("wibox.layout") -wibox.container = require("wibox.container") -wibox.widget = require("wibox.widget") -wibox.drawable = require("wibox.drawable") -wibox.hierarchy = require("wibox.hierarchy") - -local force_forward = { - shape_bounding = true, - shape_clip = true, -} - ---Imported documentation - ---- Border width. --- --- **Signal:** --- --- * *property::border_width* --- --- @property border_width --- @param integer - ---- Border color. --- --- Please note that this property only support string based 24 bit or 32 bit --- colors: --- --- Red Blue --- _| _| --- #FF00FF --- T‾ --- Green --- --- --- Red Blue --- _| _| --- #FF00FF00 --- T‾ ‾T --- Green Alpha --- --- **Signal:** --- --- * *property::border_color* --- --- @property border_color --- @param string - ---- On top of other windows. --- --- **Signal:** --- --- * *property::ontop* --- --- @property ontop --- @param boolean - ---- The mouse cursor. --- --- **Signal:** --- --- * *property::cursor* --- --- @property cursor --- @param string --- @see mouse - ---- Visibility. --- --- **Signal:** --- --- * *property::visible* --- --- @property visible --- @param boolean - ---- The opacity of the wibox, between 0 and 1. --- --- **Signal:** --- --- * *property::opacity* --- --- @property opacity --- @tparam number opacity (between 0 and 1) - ---- The window type (desktop, normal, dock, ...). --- --- **Signal:** --- --- * *property::type* --- --- @property type --- @param string --- @see client.type - ---- The x coordinates. --- --- **Signal:** --- --- * *property::x* --- --- @property x --- @param integer - ---- The y coordinates. --- --- **Signal:** --- --- * *property::y* --- --- @property y --- @param integer - ---- The width of the wibox. --- --- **Signal:** --- --- * *property::width* --- --- @property width --- @param width - ---- The height of the wibox. --- --- **Signal:** --- --- * *property::height* --- --- @property height --- @param height - ---- The wibox screen. --- --- @property screen --- @param screen - ---- The wibox's `drawable`. --- --- **Signal:** --- --- * *property::drawable* --- --- @property drawable --- @tparam drawable drawable - ---- The widget that the `wibox` displays. --- @property widget --- @param widget - ---- The X window id. --- --- **Signal:** --- --- * *property::window* --- --- @property window --- @param string --- @see client.window - ---- The wibox's bounding shape as a (native) cairo surface. --- --- **Signal:** --- --- * *property::shape_bounding* --- --- @property shape_bounding --- @param surface._native - ---- The wibox's clip shape as a (native) cairo surface. --- --- **Signal:** --- --- * *property::shape_clip* --- --- @property shape_clip --- @param surface._native - ---- Get or set mouse buttons bindings to a wibox. --- --- @param buttons_table A table of buttons objects, or nothing. --- @function buttons - ---- Get or set wibox geometry. That's the same as accessing or setting the x, --- y, width or height properties of a wibox. --- --- @param A table with coordinates to modify. --- @return A table with wibox coordinates and geometry. --- @function geometry - ---- Get or set wibox struts. --- --- @param strut A table with new strut, or nothing --- @return The wibox strut in a table. --- @function struts --- @see client.struts - ---- The default background color. --- @beautiful beautiful.bg_normal --- @see bg - ---- The default foreground (text) color. --- @beautiful beautiful.fg_normal --- @see fg - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @name setup --- @class function - ---- The background of the wibox. --- @param c The background to use. This must either be a cairo pattern object, --- nil or a string that gears.color() understands. --- @property bg --- @see gears.color - ---- The background image of the drawable. --- If `image` is a function, it will be called with `(context, cr, width, height)` --- as arguments. Any other arguments passed to this method will be appended. --- @param image A background image or a function --- @property bgimage --- @see gears.surface - ---- The foreground (text) of the wibox. --- @param c The foreground to use. This must either be a cairo pattern object, --- nil or a string that gears.color() understands. --- @property fg --- @see gears.color - ---- Find a widget by a point. --- The wibox must have drawn itself at least once for this to work. --- @tparam number x X coordinate of the point --- @tparam number y Y coordinate of the point --- @treturn table A sorted table of widgets positions. The first element is the biggest --- container while the last is the topmost widget. The table contains *x*, *y*, --- *width*, *height* and *widget*. --- @name find_widgets --- @class function - - -function wibox:set_widget(widget) - self._drawable:set_widget(widget) -end - -function wibox:get_widget() - return self._drawable.widget -end - -wibox.setup = base.widget.setup - -function wibox:set_bg(c) - self._drawable:set_bg(c) -end - -function wibox:set_bgimage(image, ...) - self._drawable:set_bgimage(image, ...) -end - -function wibox:set_fg(c) - self._drawable:set_fg(c) -end - -function wibox:find_widgets(x, y) - return self._drawable:find_widgets(x, y) -end - -function wibox:get_screen() - if self.screen_assigned and self.screen_assigned.valid then - return self.screen_assigned - else - self.screen_assigned = nil - end - local sgeos = {} - - for s in capi.screen do - sgeos[s] = s.geometry - end - - return grect.get_closest_by_coord(sgeos, self.x, self.y) -end - -function wibox:set_screen(s) - s = capi.screen[s or 1] - if s ~= self:get_screen() then - self.x = s.geometry.x - self.y = s.geometry.y - end - - -- Remember this screen so things work correctly if screens overlap and - -- (x,y) is not enough to figure out the correct screen. - self.screen_assigned = s - self._drawable:_force_screen(s) -end - -for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do - wibox[k] = function(self, ...) - return self.drawin[k](self.drawin, ...) - end -end - -local function setup_signals(_wibox) - local obj - local function clone_signal(name) - -- When "name" is emitted on wibox.drawin, also emit it on wibox - obj:connect_signal(name, function(_, ...) - _wibox:emit_signal(name, ...) - end) - end - - obj = _wibox.drawin - clone_signal("property::border_color") - clone_signal("property::border_width") - clone_signal("property::buttons") - clone_signal("property::cursor") - clone_signal("property::height") - clone_signal("property::ontop") - clone_signal("property::opacity") - clone_signal("property::struts") - clone_signal("property::visible") - clone_signal("property::width") - clone_signal("property::x") - clone_signal("property::y") - clone_signal("property::geometry") - clone_signal("property::shape_bounding") - clone_signal("property::shape_clip") - - obj = _wibox._drawable - clone_signal("button::press") - clone_signal("button::release") - clone_signal("mouse::enter") - clone_signal("mouse::leave") - clone_signal("mouse::move") - clone_signal("property::surface") -end - ---- Create a wibox. --- @tparam[opt=nil] table args --- @tparam integer args.border_width Border width. --- @tparam string args.border_color Border color. --- @tparam boolean args.ontop On top of other windows. --- @tparam string args.cursor The mouse cursor. --- @tparam boolean args.visible Visibility. --- @tparam number args.opacity The opacity of the wibox, between 0 and 1. --- @tparam string args.type The window type (desktop, normal, dock, …). --- @tparam integer args.x The x coordinates. --- @tparam integer args.y The y coordinates. --- @tparam integer args.width The width of the wibox. --- @tparam integer args.height The height of the wibox. --- @tparam screen args.screen The wibox screen. --- @tparam wibox.widget args.widget The widget that the wibox displays. --- @param args.shape_bounding The wibox’s bounding shape as a (native) cairo surface. --- @param args.shape_clip The wibox’s clip shape as a (native) cairo surface. --- @tparam color args.bg The background of the wibox. --- @tparam surface args.bgimage The background image of the drawable. --- @tparam color args.fg The foreground (text) of the wibox. --- @treturn wibox The new wibox --- @function .wibox - -local function new(args) - args = args or {} - local ret = object() - local w = capi.drawin(args) - - function w.get_wibox() - return ret - end - - ret.drawin = w - ret._drawable = wibox.drawable(w.drawable, { wibox = ret }, - "wibox drawable (" .. object.modulename(3) .. ")") - - ret._drawable:_inform_visible(w.visible) - w:connect_signal("property::visible", function() - ret._drawable:_inform_visible(w.visible) - end) - - for k, v in pairs(wibox) do - if type(v) == "function" then - ret[k] = v - end - end - - setup_signals(ret) - ret.draw = ret._drawable.draw - - -- Set the default background - ret:set_bg(args.bg or beautiful.bg_normal) - ret:set_fg(args.fg or beautiful.fg_normal) - - -- Add __tostring method to metatable. - local mt = {} - local orig_string = tostring(ret) - mt.__tostring = function() - return string.format("wibox: %s (%s)", - tostring(ret._drawable), orig_string) - end - ret = setmetatable(ret, mt) - - -- Make sure the wibox is drawn at least once - ret.draw() - - -- If a value is not found, look in the drawin - setmetatable(ret, { - __index = function(self, k) - if rawget(self, "get_"..k) then - return self["get_"..k](self) - else - return w[k] - end - end, - __newindex = function(self, k,v) - if rawget(self, "set_"..k) then - self["set_"..k](self, v) - elseif w[k] ~= nil or force_forward[k] then - w[k] = v - else - rawset(self, k, v) - end - end - }) - - -- Set other wibox specific arguments - if args.bgimage then - ret:set_bgimage( args.bgimage ) - end - - if args.widget then - ret:set_widget ( args.widget ) - end - - if args.screen then - ret:set_screen ( args.screen ) - end - - return ret -end - ---- Redraw a wibox. You should never have to call this explicitely because it is --- automatically called when needed. --- @param wibox --- @function draw - -function wibox.mt:__call(...) - return new(...) -end - --- Extend the luaobject -object.properties(capi.drawin, { - getter_class = wibox.object, - setter_class = wibox.object, - auto_emit = true, -}) - -return setmetatable(wibox, wibox.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/align.lua b/awesome/lib/wibox/layout/align.lua deleted file mode 100644 index 92a5582..0000000 --- a/awesome/lib/wibox/layout/align.lua +++ /dev/null @@ -1,526 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_layout_defaults_align.svg) --- --- @usage ---wibox.widget { --- generic_widget( 'first' ), --- generic_widget( 'second' ), --- generic_widget( 'third' ), --- layout = wibox.layout.align.horizontal ---} --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.layout.align ---------------------------------------------------------------------------- - -local table = table -local pairs = pairs -local type = type -local floor = math.floor -local util = require("awful.util") -local base = require("wibox.widget.base") - -local align = {} - --- Calculate the layout of an align layout. --- @param context The context in which we are drawn. --- @param width The available width. --- @param height The available height. -function align:layout(context, width, height) - local result = {} - - -- Draw will have to deal with all three align modes and should work in a - -- way that makes sense if one or two of the widgets are missing (if they - -- are all missing, it won't draw anything.) It should also handle the case - -- where the fit something that isn't set to expand (for instance the - -- outside widgets when the expand mode is "inside" or any of the widgets - -- when the expand mode is "none" wants to take up more space than is - -- allowed. - local size_first = 0 - -- start with all the space given by the parent, subtract as we go along - local size_remains = self._private.dir == "y" and height or width - -- This is only set & used if expand ~= "inside" and we have second width. - -- It contains the size allocated to the second widget. - local size_second - - -- we will prioritize the middle widget unless the expand mode is "inside" - -- if it is, we prioritize the first widget by not doing this block also, - -- if the second widget doesn't exist, we will prioritise the first one - -- instead - if self._private.expand ~= "inside" and self._private.second then - local w, h = base.fit_widget(self, context, self._private.second, width, height) - size_second = self._private.dir == "y" and h or w - -- if all the space is taken, skip the rest, and draw just the middle - -- widget - if size_second >= size_remains then - return { base.place_widget_at(self._private.second, 0, 0, width, height) } - else - -- the middle widget is sized first, the outside widgets are given - -- the remaining space if available we will draw later - size_remains = floor((size_remains - size_second) / 2) - end - end - if self._private.first then - local w, h, _ = width, height, nil - -- we use the fit function for the "inside" and "none" modes, but - -- ignore it for the "outside" mode, which will force it to expand - -- into the remaining space - if self._private.expand ~= "outside" then - if self._private.dir == "y" then - _, h = base.fit_widget(self, context, self._private.first, width, size_remains) - size_first = h - -- for "inside", the third widget will get a chance to use the - -- remaining space, then the middle widget. For "none" we give - -- the third widget the remaining space if there was no second - -- widget to take up any space (as the first if block is skipped - -- if this is the case) - if self._private.expand == "inside" or not self._private.second then - size_remains = size_remains - h - end - else - w, _ = base.fit_widget(self, context, self._private.first, size_remains, height) - size_first = w - if self._private.expand == "inside" or not self._private.second then - size_remains = size_remains - w - end - end - else - if self._private.dir == "y" then - h = size_remains - else - w = size_remains - end - end - table.insert(result, base.place_widget_at(self._private.first, 0, 0, w, h)) - end - -- size_remains will be <= 0 if first used all the space - if self._private.third and size_remains > 0 then - local w, h, _ = width, height, nil - if self._private.expand ~= "outside" then - if self._private.dir == "y" then - _, h = base.fit_widget(self, context, self._private.third, width, size_remains) - -- give the middle widget the rest of the space for "inside" mode - if self._private.expand == "inside" then - size_remains = size_remains - h - end - else - w, _ = base.fit_widget(self, context, self._private.third, size_remains, height) - if self._private.expand == "inside" then - size_remains = size_remains - w - end - end - else - if self._private.dir == "y" then - h = size_remains - else - w = size_remains - end - end - local x, y = width - w, height - h - table.insert(result, base.place_widget_at(self._private.third, x, y, w, h)) - end - -- here we either draw the second widget in the space set aside for it - -- in the beginning, or in the remaining space, if it is "inside" - if self._private.second and size_remains > 0 then - local x, y, w, h = 0, 0, width, height - if self._private.expand == "inside" then - if self._private.dir == "y" then - h = size_remains - x, y = 0, size_first - else - w = size_remains - x, y = size_first, 0 - end - else - local _ - if self._private.dir == "y" then - _, h = base.fit_widget(self, context, self._private.second, width, size_second) - y = floor( (height - h)/2 ) - else - w, _ = base.fit_widget(self, context, self._private.second, size_second, height) - x = floor( (width -w)/2 ) - end - end - table.insert(result, base.place_widget_at(self._private.second, x, y, w, h)) - end - return result -end - ---- Set the layout's first widget. --- This is the widget that is at the left/top --- @property first - -function align:set_first(widget) - if self._private.first == widget then - return - end - self._private.first = widget - self:emit_signal("widget::layout_changed") -end - ---- Set the layout's second widget. This is the centered one. --- @property second - -function align:set_second(widget) - if self._private.second == widget then - return - end - self._private.second = widget - self:emit_signal("widget::layout_changed") -end - ---- Set the layout's third widget. --- This is the widget that is at the right/bottom --- @property third - -function align:set_third(widget) - if self._private.third == widget then - return - end - self._private.third = widget - self:emit_signal("widget::layout_changed") -end - -for _, prop in ipairs {"first", "second", "third", "expand" } do - align["get_"..prop] = function(self) - return self._private[prop] - end -end - ---- All direct children of this layout. --- This can be used to replace all 3 widgets at once. --- @treturn table a list of all widgets --- @property children - -function align:get_children() - return util.from_sparse {self._private.first, self._private.second, self._private.third} -end - -function align:set_children(children) - self:set_first(children[1]) - self:set_second(children[2]) - self:set_third(children[3]) -end - --- Fit the align layout into the given space. The align layout will --- ask for the sum of the sizes of its sub-widgets in its direction --- and the largest sized sub widget in the other direction. --- @param context The context in which we are fit. --- @param orig_width The available width. --- @param orig_height The available height. -function align:fit(context, orig_width, orig_height) - local used_in_dir = 0 - local used_in_other = 0 - - for _, v in pairs{self._private.first, self._private.second, self._private.third} do - local w, h = base.fit_widget(self, context, v, orig_width, orig_height) - - local max = self._private.dir == "y" and w or h - if max > used_in_other then - used_in_other = max - end - - used_in_dir = used_in_dir + (self._private.dir == "y" and h or w) - end - - if self._private.dir == "y" then - return used_in_other, used_in_dir - end - return used_in_dir, used_in_other -end - ---- Set the expand mode which determines how sub widgets expand to take up --- unused space. --- --- @tparam[opt=inside] string mode How to use unused space. --- --- * "inside" - Default option. Size of outside widgets is determined using --- their fit function. Second, middle, or center widget expands to fill --- remaining space. --- * "outside" - Center widget is sized using its fit function and placed in --- the center of the allowed space. Outside widgets expand (or contract) to --- fill remaining space on their side. --- * "none" - All widgets are sized using their fit function, drawn to only the --- returned space, or remaining space, whichever is smaller. Center widget --- gets priority. --- @property expand - -function align:set_expand(mode) - if mode == "none" or mode == "outside" then - self._private.expand = mode - else - self._private.expand = "inside" - end - self:emit_signal("widget::layout_changed") -end - -function align:reset() - for _, v in pairs({ "first", "second", "third" }) do - self[v] = nil - end - self:emit_signal("widget::layout_changed") -end - -local function get_layout(dir, first, second, third) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - ret._private.dir = dir - - for k, v in pairs(align) do - if type(v) == "function" then - rawset(ret, k, v) - end - end - - ret:set_expand("inside") - ret:set_first(first) - ret:set_second(second) - ret:set_third(third) - - -- An align layout allow set_children to have empty entries - ret.allow_empty_widget = true - - return ret -end - ---- Returns a new horizontal align layout. An align layout can display up to --- three widgets. The widget set via :set_left() is left-aligned. :set_right() --- sets a widget which will be right-aligned. The remaining space between those --- two will be given to the widget set via :set_middle(). --- @tparam[opt] widget left Widget to be put to the left. --- @tparam[opt] widget middle Widget to be put to the middle. --- @tparam[opt] widget right Widget to be put to the right. -function align.horizontal(left, middle, right) - local ret = get_layout("x", left, middle, right) - - rawset(ret, "set_left" , ret.set_first ) - rawset(ret, "set_middle", ret.set_second ) - rawset(ret, "set_right" , ret.set_third ) - - return ret -end - ---- Returns a new vertical align layout. An align layout can display up to --- three widgets. The widget set via :set_top() is top-aligned. :set_bottom() --- sets a widget which will be bottom-aligned. The remaining space between those --- two will be given to the widget set via :set_middle(). --- @tparam[opt] widget top Widget to be put to the top. --- @tparam[opt] widget middle Widget to be put to the middle. --- @tparam[opt] widget bottom Widget to be put to the right. -function align.vertical(top, middle, bottom) - local ret = get_layout("y", top, middle, bottom) - - rawset(ret, "set_top" , ret.set_first ) - rawset(ret, "set_middle", ret.set_second ) - rawset(ret, "set_bottom", ret.set_third ) - - return ret -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return align - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/constraint.lua b/awesome/lib/wibox/layout/constraint.lua deleted file mode 100644 index 5333b38..0000000 --- a/awesome/lib/wibox/layout/constraint.lua +++ /dev/null @@ -1,17 +0,0 @@ ---------------------------------------------------------------------------- --- This class has been moved to `wibox.container.` --- --- @author Lukáš Hrázký --- @copyright 2012 Lukáš Hrázký --- @classmod wibox.layout.constraint ---------------------------------------------------------------------------- - -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.container.constraint"), - "wibox.layout.constraint", - "wibox.container.constraint" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/fixed.lua b/awesome/lib/wibox/layout/fixed.lua deleted file mode 100644 index 7258438..0000000 --- a/awesome/lib/wibox/layout/fixed.lua +++ /dev/null @@ -1,585 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_layout_defaults_fixed.svg) --- --- @usage ---wibox.widget { --- generic_widget( 'first' ), --- generic_widget( 'second' ), --- generic_widget( 'third' ), --- layout = wibox.layout.fixed.horizontal ---} --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.layout.fixed ---------------------------------------------------------------------------- - -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local base = require("wibox.widget.base") -local table = table -local pairs = pairs -local util = require("awful.util") - -local fixed = {} - ---Imported documentation - ---- Set a widget at a specific index, replace the current one. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @tparam number index A widget or a widget index --- @param widget2 The widget to take the place of the first one --- @treturn boolean If the operation is successful --- @name set --- @class function - ---- Replace the first instance of `widget` in the layout with `widget2`. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @param widget The widget to replace --- @param widget2 The widget to replace `widget` with --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name replace_widget --- @class function - ---- Swap 2 widgets in a layout. --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- @tparam number index1 The first widget index --- @tparam number index2 The second widget index --- @treturn boolean If the operation is successful --- @name swap --- @class function - ---- Swap 2 widgets in a layout. --- If widget1 is present multiple time, only the first instance is swapped --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- if the layouts not the same, then only `widget::replaced` will be emitted. --- @param widget1 The first widget --- @param widget2 The second widget --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name swap_widgets --- @class function - ---- Get all direct children of this layout. --- @param layout The layout you are modifying. --- @property children - ---- Reset a ratio layout. This removes all widgets from the layout. --- **Signal:** widget::reset --- @param layout The layout you are modifying. --- @name reset --- @class function - - --- Layout a fixed layout. Each widget gets just the space it asks for. --- @param context The context in which we are drawn. --- @param width The available width. --- @param height The available height. -function fixed:layout(context, width, height) - local result = {} - local pos,spacing = 0, self._private.spacing - - for k, v in pairs(self._private.widgets) do - local x, y, w, h, _ - if self._private.dir == "y" then - x, y = 0, pos - w, h = width, height - pos - if k ~= #self._private.widgets or not self._private.fill_space then - _, h = base.fit_widget(self, context, v, w, h); - end - pos = pos + h + spacing - else - x, y = pos, 0 - w, h = width - pos, height - if k ~= #self._private.widgets or not self._private.fill_space then - w, _ = base.fit_widget(self, context, v, w, h); - end - pos = pos + w + spacing - end - - if (self._private.dir == "y" and pos-spacing > height) or - (self._private.dir ~= "y" and pos-spacing > width) then - break - end - table.insert(result, base.place_widget_at(v, x, y, w, h)) - end - return result -end - ---- Add some widgets to the given fixed layout --- @param ... Widgets that should be added (must at least be one) -function fixed:add(...) - -- No table.pack in Lua 5.1 :-( - local args = { n=select('#', ...), ... } - assert(args.n > 0, "need at least one widget to add") - for i=1, args.n do - base.check_widget(args[i]) - table.insert(self._private.widgets, args[i]) - end - self:emit_signal("widget::layout_changed") -end - - ---- Remove a widget from the layout --- @tparam number index The widget index to remove --- @treturn boolean index If the operation is successful -function fixed:remove(index) - if not index or index < 1 or index > #self._private.widgets then return false end - - table.remove(self._private.widgets, index) - - self:emit_signal("widget::layout_changed") - - return true -end - ---- Remove one or more widgets from the layout --- The last parameter can be a boolean, forcing a recursive seach of the --- widget(s) to remove. --- @param widget ... Widgets that should be removed (must at least be one) --- @treturn boolean If the operation is successful -function fixed:remove_widgets(...) - local args = { ... } - - local recursive = type(args[#args]) == "boolean" and args[#args] - - local ret = true - for k, rem_widget in ipairs(args) do - if recursive and k == #args then break end - - local idx, l = self:index(rem_widget, recursive) - - if idx and l and l.remove then - l:remove(idx, false) - else - ret = false - end - - end - - return #args > (recursive and 1 or 0) and ret -end - -function fixed:get_children() - return self._private.widgets -end - -function fixed:set_children(children) - self:reset() - if #children > 0 then - self:add(unpack(children)) - end -end - ---- Replace the first instance of `widget` in the layout with `widget2` --- @param widget The widget to replace --- @param widget2 The widget to replace `widget` with --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful -function fixed:replace_widget(widget, widget2, recursive) - local idx, l = self:index(widget, recursive) - - if idx and l then - l:set(idx, widget2) - return true - end - - return false -end - -function fixed:swap(index1, index2) - if not index1 or not index2 or index1 > #self._private.widgets - or index2 > #self._private.widgets then - return false - end - - local widget1, widget2 = self._private.widgets[index1], self._private.widgets[index2] - - self:set(index1, widget2) - self:set(index2, widget1) - - self:emit_signal("widget::swapped", widget1, widget2, index2, index1) - - return true -end - -function fixed:swap_widgets(widget1, widget2, recursive) - base.check_widget(widget1) - base.check_widget(widget2) - - local idx1, l1 = self:index(widget1, recursive) - local idx2, l2 = self:index(widget2, recursive) - - if idx1 and l1 and idx2 and l2 and (l1.set or l1.set_widget) and (l2.set or l2.set_widget) then - if l1.set then - l1:set(idx1, widget2) - if l1 == self then - self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1) - end - elseif l1.set_widget then - l1:set_widget(widget2) - end - if l2.set then - l2:set(idx2, widget1) - if l2 == self then - self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1) - end - elseif l2.set_widget then - l2:set_widget(widget1) - end - - return true - end - - return false -end - -function fixed:set(index, widget2) - if (not widget2) or (not self._private.widgets[index]) then return false end - - base.check_widget(widget2) - - local w = self._private.widgets[index] - - self._private.widgets[index] = widget2 - - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::replaced", widget2, w, index) - - return true -end - ---- Insert a new widget in the layout at position `index` --- **Signal:** widget::inserted The arguments are the widget and the index --- @tparam number index The position --- @param widget The widget --- @treturn boolean If the operation is successful -function fixed:insert(index, widget) - if not index or index < 1 or index > #self._private.widgets + 1 then return false end - - base.check_widget(widget) - table.insert(self._private.widgets, index, widget) - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::inserted", widget, #self._private.widgets) - - return true -end - --- Fit the fixed layout into the given space --- @param context The context in which we are fit. --- @param orig_width The available width. --- @param orig_height The available height. -function fixed:fit(context, orig_width, orig_height) - local width, height = orig_width, orig_height - local used_in_dir, used_max = 0, 0 - - for _, v in pairs(self._private.widgets) do - local w, h = base.fit_widget(self, context, v, width, height) - local in_dir, max - if self._private.dir == "y" then - max, in_dir = w, h - height = height - in_dir - else - in_dir, max = w, h - width = width - in_dir - end - if max > used_max then - used_max = max - end - used_in_dir = used_in_dir + in_dir - - if width <= 0 or height <= 0 then - if self._private.dir == "y" then - used_in_dir = orig_height - else - used_in_dir = orig_width - end - break - end - end - - local spacing = self._private.spacing * (#self._private.widgets-1) - - if self._private.dir == "y" then - return used_max, used_in_dir + spacing - end - return used_in_dir + spacing, used_max -end - -function fixed:reset() - self._private.widgets = {} - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::reseted") -end - ---- Set the layout's fill_space property. If this property is true, the last --- widget will get all the space that is left. If this is false, the last widget --- won't be handled specially and there can be space left unused. --- @property fill_space - -function fixed:fill_space(val) - if self._private.fill_space ~= val then - self._private.fill_space = not not val - self:emit_signal("widget::layout_changed") - end -end - -local function get_layout(dir, widget1, ...) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - util.table.crush(ret, fixed, true) - - ret._private.dir = dir - ret._private.widgets = {} - ret:set_spacing(0) - ret:fill_space(false) - - if widget1 then - ret:add(widget1, ...) - end - - return ret -end - ---- Returns a new horizontal fixed layout. Each widget will get as much space as it --- asks for and each widget will be drawn next to its neighboring widget. --- Widgets can be added via :add() or as arguments to this function. --- @tparam widget ... Widgets that should be added to the layout. --- @function wibox.layout.fixed.horizontal -function fixed.horizontal(...) - return get_layout("x", ...) -end - ---- Returns a new vertical fixed layout. Each widget will get as much space as it --- asks for and each widget will be drawn next to its neighboring widget. --- Widgets can be added via :add() or as arguments to this function. --- @tparam widget ... Widgets that should be added to the layout. --- @function wibox.layout.fixed.vertical -function fixed.vertical(...) - return get_layout("y", ...) -end - ---- Add spacing between each layout widgets --- @property spacing --- @tparam number spacing Spacing between widgets. - -function fixed:set_spacing(spacing) - if self._private.spacing ~= spacing then - self._private.spacing = spacing - self:emit_signal("widget::layout_changed") - end -end - -function fixed:get_spacing() - return self._private.spacing or 0 -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return fixed - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/flex.lua b/awesome/lib/wibox/layout/flex.lua deleted file mode 100644 index 1326f31..0000000 --- a/awesome/lib/wibox/layout/flex.lua +++ /dev/null @@ -1,429 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_layout_defaults_flex.svg) --- --- @usage ---wibox.widget { --- generic_widget( 'first' ), --- generic_widget( 'second' ), --- generic_widget( 'third' ), --- layout = wibox.layout.flex.horizontal ---} --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.layout.flex ---------------------------------------------------------------------------- - -local base = require("wibox.widget.base") -local fixed = require("wibox.layout.fixed") -local table = table -local pairs = pairs -local floor = math.floor -local util = require("awful.util") - -local flex = {} - ---Imported documentation - ---- Set a widget at a specific index, replace the current one. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @tparam number index A widget or a widget index --- @param widget2 The widget to take the place of the first one --- @treturn boolean If the operation is successful --- @name set --- @class function - ---- Replace the first instance of `widget` in the layout with `widget2`. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @param widget The widget to replace --- @param widget2 The widget to replace `widget` with --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name replace_widget --- @class function - ---- Swap 2 widgets in a layout. --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- @tparam number index1 The first widget index --- @tparam number index2 The second widget index --- @treturn boolean If the operation is successful --- @name swap --- @class function - ---- Swap 2 widgets in a layout. --- If widget1 is present multiple time, only the first instance is swapped --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- if the layouts not the same, then only `widget::replaced` will be emitted. --- @param widget1 The first widget --- @param widget2 The second widget --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name swap_widgets --- @class function - ---- Get all direct children of this layout. --- @param layout The layout you are modifying. --- @property children - ---- Reset a ratio layout. This removes all widgets from the layout. --- **Signal:** widget::reset --- @param layout The layout you are modifying. --- @name reset --- @class function - - ---- Replace the layout children --- @tparam table children A table composed of valid widgets --- @name set_children --- @class function - ---- Add some widgets to the given fixed layout --- @param layout The layout you are modifying. --- @tparam widget ... Widgets that should be added (must at least be one) --- @name add --- @class function - ---- Remove a widget from the layout --- @tparam index The widget index to remove --- @treturn boolean index If the operation is successful --- @name remove --- @class function - ---- Remove one or more widgets from the layout --- The last parameter can be a boolean, forcing a recursive seach of the --- widget(s) to remove. --- @param widget ... Widgets that should be removed (must at least be one) --- @treturn boolean If the operation is successful --- @name remove_widgets --- @class function - ---- Insert a new widget in the layout at position `index` --- @tparam number index The position --- @param widget The widget --- @treturn boolean If the operation is successful --- @name insert --- @class function - -function flex:layout(_, width, height) - local result = {} - local pos,spacing = 0, self._private.spacing - local num = #self._private.widgets - local total_spacing = (spacing*(num-1)) - - local space_per_item - if self._private.dir == "y" then - space_per_item = height / num - total_spacing/num - else - space_per_item = width / num - total_spacing/num - end - - if self._private.max_widget_size then - space_per_item = math.min(space_per_item, self._private.max_widget_size) - end - - for _, v in pairs(self._private.widgets) do - local x, y, w, h - if self._private.dir == "y" then - x, y = 0, util.round(pos) - w, h = width, floor(space_per_item) - else - x, y = util.round(pos), 0 - w, h = floor(space_per_item), height - end - - table.insert(result, base.place_widget_at(v, x, y, w, h)) - - pos = pos + space_per_item + spacing - - if (self._private.dir == "y" and pos-spacing >= height) or - (self._private.dir ~= "y" and pos-spacing >= width) then - break - end - end - - return result -end - --- Fit the flex layout into the given space. --- @param context The context in which we are fit. --- @param orig_width The available width. --- @param orig_height The available height. -function flex:fit(context, orig_width, orig_height) - local used_in_dir = 0 - local used_in_other = 0 - - -- Figure out the maximum size we can give out to sub-widgets - local sub_height = self._private.dir == "x" and orig_height or orig_height / #self._private.widgets - local sub_width = self._private.dir == "y" and orig_width or orig_width / #self._private.widgets - - for _, v in pairs(self._private.widgets) do - local w, h = base.fit_widget(self, context, v, sub_width, sub_height) - - local max = self._private.dir == "y" and w or h - if max > used_in_other then - used_in_other = max - end - - used_in_dir = used_in_dir + (self._private.dir == "y" and h or w) - end - - if self._private.max_widget_size then - used_in_dir = math.min(used_in_dir, - #self._private.widgets * self._private.max_widget_size) - end - - local spacing = self._private.spacing * (#self._private.widgets-1) - - if self._private.dir == "y" then - return used_in_other, used_in_dir + spacing - end - return used_in_dir + spacing, used_in_other -end - ---- Set the maximum size the widgets in this layout will take. ---That is, maximum width for horizontal and maximum height for vertical. --- @property max_widget_size --- @param number - -function flex:set_max_widget_size(val) - if self._private.max_widget_size ~= val then - self._private.max_widget_size = val - self:emit_signal("widget::layout_changed") - end -end - -local function get_layout(dir, widget1, ...) - local ret = fixed[dir](widget1, ...) - - util.table.crush(ret, flex, true) - - ret._private.fill_space = nil - - return ret -end - ---- Returns a new horizontal flex layout. A flex layout shares the available space --- equally among all widgets. Widgets can be added via :add(widget). --- @tparam widget ... Widgets that should be added to the layout. --- @function wibox.layout.flex.horizontal -function flex.horizontal(...) - return get_layout("horizontal", ...) -end - ---- Returns a new vertical flex layout. A flex layout shares the available space --- equally among all widgets. Widgets can be added via :add(widget). --- @tparam widget ... Widgets that should be added to the layout. --- @function wibox.layout.flex.vertical -function flex.vertical(...) - return get_layout("vertical", ...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return flex - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/init.lua b/awesome/lib/wibox/layout/init.lua deleted file mode 100644 index 4a9b006..0000000 --- a/awesome/lib/wibox/layout/init.lua +++ /dev/null @@ -1,23 +0,0 @@ ---------------------------------------------------------------------------- ---- Collection of layouts that can be used in widget boxes --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.layout ---------------------------------------------------------------------------- -local base = require("wibox.widget.base") - -return setmetatable({ - fixed = require("wibox.layout.fixed"); - align = require("wibox.layout.align"); - flex = require("wibox.layout.flex"); - rotate = require("wibox.layout.rotate"); - margin = require("wibox.layout.margin"); - mirror = require("wibox.layout.mirror"); - constraint = require("wibox.layout.constraint"); - scroll = require("wibox.layout.scroll"); - ratio = require("wibox.layout.ratio"); - stack = require("wibox.layout.stack"); -}, {__call = function(_, args) return base.make_widget_declarative(args) end}) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/margin.lua b/awesome/lib/wibox/layout/margin.lua deleted file mode 100644 index 8d2eba2..0000000 --- a/awesome/lib/wibox/layout/margin.lua +++ /dev/null @@ -1,17 +0,0 @@ ---------------------------------------------------------------------------- --- This class has been moved to `wibox.container.margin` --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.layout.margin ---------------------------------------------------------------------------- - -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.container.margin"), - "wibox.layout.margin", - "wibox.container.margin" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/mirror.lua b/awesome/lib/wibox/layout/mirror.lua deleted file mode 100644 index 16be754..0000000 --- a/awesome/lib/wibox/layout/mirror.lua +++ /dev/null @@ -1,17 +0,0 @@ ---------------------------------------------------------------------------- --- This class has been moved to `wibox.container.mirror` --- --- @author dodo --- @copyright 2012 dodo --- @classmod wibox.layout.mirror ---------------------------------------------------------------------------- - -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.container.mirror"), - "wibox.layout.mirror", - "wibox.container.mirror" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/ratio.lua b/awesome/lib/wibox/layout/ratio.lua deleted file mode 100644 index bcae443..0000000 --- a/awesome/lib/wibox/layout/ratio.lua +++ /dev/null @@ -1,583 +0,0 @@ ---------------------------------------------------------------------------- ---- A layout filling all the available space. Each widget is assigned a --- ratio (percentage) of the total space. Multiple methods are available to --- ajust this ratio. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_layout_defaults_ratio.svg) --- --- @usage ---local w = wibox.widget { --- generic_widget( 'first' ), --- generic_widget( 'second' ), --- generic_widget( 'third' ), --- layout = wibox.layout.ratio.horizontal ---} ---w:ajust_ratio(2, 0.44, 0.33, 0.22) --- @author Emmanuel Lepage Vallee --- @copyright 2016 Emmanuel Lepage Vallee --- @classmod wibox.layout.ratio ---------------------------------------------------------------------------- - -local base = require("wibox.widget.base" ) -local flex = require("wibox.layout.flex" ) -local table = table -local pairs = pairs -local floor = math.floor -local util = require("awful.util") - -local ratio = {} - ---Imported documentation - ---- Set a widget at a specific index, replace the current one. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @tparam number index A widget or a widget index --- @param widget2 The widget to take the place of the first one --- @treturn boolean If the operation is successful --- @name set --- @class function - ---- Replace the first instance of `widget` in the layout with `widget2`. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @param widget The widget to replace --- @param widget2 The widget to replace `widget` with --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name replace_widget --- @class function - ---- Swap 2 widgets in a layout. --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- @tparam number index1 The first widget index --- @tparam number index2 The second widget index --- @treturn boolean If the operation is successful --- @name swap --- @class function - ---- Swap 2 widgets in a layout. --- If widget1 is present multiple time, only the first instance is swapped --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- if the layouts not the same, then only `widget::replaced` will be emitted. --- @param widget1 The first widget --- @param widget2 The second widget --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name swap_widgets --- @class function - ---- Get all direct children of this layout. --- @param layout The layout you are modifying. --- @property children - ---- Reset a ratio layout. This removes all widgets from the layout. --- **Signal:** widget::reset --- @param layout The layout you are modifying. --- @name reset --- @class function - - --- Compute the sum of all ratio (ideally, it should be 1) -local function gen_sum(self, i_s, i_e) - local sum, new_w = 0,0 - - for i = i_s or 1, i_e or #self._private.widgets do - if self._private.ratios[i] then - sum = sum + self._private.ratios[i] - else - new_w = new_w + 1 - end - end - - return sum, new_w -end - --- The ratios are expressed as percentages. For this to work, the sum of all --- ratio must be 1. This function attempt to ajust them. Space can be taken --- from or added to a ratio when widgets are being added or removed. If a --- specific ratio must be enforced for a widget, it has to be done with the --- `ajust_ratio` method after each insertion or deletion -local function normalize(self) - local count = #self._private.widgets - if count == 0 then return end - - -- Instead of adding "if" everywhere, just handle this common case - if count == 1 then - self._private.ratios = { 1 } - return - end - - local sum, new_w = gen_sum(self) - local old_count = #self._private.widgets - new_w - - local to_add = (sum == 0) and 1 or (sum / old_count) - - -- Make sure all widgets have a ratio - for i=1, #self._private.widgets do - if not self._private.ratios[i] then - self._private.ratios[i] = to_add - end - end - - sum = sum + to_add*new_w - - local delta, new_sum = (1 - sum) / count,0 - - -- Increase or decrease each ratio so it the sum become 1 - for i=1, #self._private.widgets do - self._private.ratios[i] = self._private.ratios[i] + delta - new_sum = new_sum + self._private.ratios[i] - end - - -- Floating points is not an exact science, but it should still be close - -- to 1.00. - assert(new_sum > 0.99 and new_sum < 1.01) -end - -function ratio:layout(_, width, height) - local result = {} - local pos,spacing = 0, self._private.spacing - - for k, v in ipairs(self._private.widgets) do - local space - local x, y, w, h - - if self._private.dir == "y" then - space = height * self._private.ratios[k] - x, y = 0, util.round(pos) - w, h = width, floor(space) - else - space = width * self._private.ratios[k] - x, y = util.round(pos), 0 - w, h = floor(space), height - end - - table.insert(result, base.place_widget_at(v, x, y, w, h)) - - pos = pos + space + spacing - - -- Make sure all widgets fit in the layout, if they aren't, something - -- went wrong - if (self._private.dir == "y" and util.round(pos) >= height) or - (self._private.dir ~= "y" and util.round(pos) >= width) then - break - end - end - - return result -end - ---- Increase the ratio of "widget" --- If the increment produce an invalid ratio (not between 0 and 1), the method --- do nothing. --- @tparam number index The widget index to change --- @tparam number increment An floating point value between -1 and 1 where the --- end result is within 0 and 1 -function ratio:inc_ratio(index, increment) - if #self._private.widgets == 1 or (not index) or (not self._private.ratios[index]) - or increment < -1 or increment > 1 then - return - end - - assert(self._private.ratios[index]) - - self:set_ratio(index, self._private.ratios[index] + increment) -end - ---- Increment the ratio of the first instance of `widget` --- If the increment produce an invalid ratio (not between 0 and 1), the method --- do nothing. --- @param widget The widget to ajust --- @tparam number increment An floating point value between -1 and 1 where the --- end result is within 0 and 1 -function ratio:inc_widget_ratio(widget, increment) - if not widget or not increment then return end - - local index = self:index(widget) - - self:inc_ratio(index, increment) -end - ---- Set the ratio of the widget at position `index` --- @tparam number index The index of the widget to change --- @tparam number percent An floating point value between 0 and 1 -function ratio:set_ratio(index, percent) - if not percent or #self._private.widgets == 1 or not index or not self._private.widgets[index] - or percent < 0 or percent > 1 then - return - end - - local old = self._private.ratios[index] - - -- Remove what has to be cleared from all widget - local delta = ( (percent-old) / (#self._private.widgets-1) ) - - for k in pairs(self._private.widgets) do - self._private.ratios[k] = self._private.ratios[k] - delta - end - - -- Set the new ratio - self._private.ratios[index] = percent - - -- As some widgets may now have a slightly negative ratio, normalize again - normalize(self) - - self:emit_signal("widget::layout_changed") -end - ---- Get the ratio at `index`. --- @tparam number index The widget index to query --- @treturn number The index (between 0 and 1) -function ratio:get_ratio(index) - if not index then return end - return self._private.ratios[index] -end - ---- Set the ratio of `widget` to `percent`. --- @tparam widget widget The widget to ajust. --- @tparam number percent A floating point value between 0 and 1. -function ratio:set_widget_ratio(widget, percent) - local index = self:index(widget) - - self:set_ratio(index, percent) -end - ---- Update all widgets to match a set of a ratio. --- The sum of before, itself and after must be 1 or nothing will be done --- @tparam number index The index of the widget to change --- @tparam number before The sum of the ratio before the widget --- @tparam number itself The ratio for "widget" --- @tparam number after The sum of the ratio after the widget -function ratio:ajust_ratio(index, before, itself, after) - if not self._private.widgets[index] or not before or not itself or not after then - return - end - - local sum = before + itself + after - - -- As documented, it is the caller job to come up with valid numbers - if math.min(before, itself, after) < 0 then return end - if sum > 1.01 or sum < -0.99 then return end - - -- Compute the before and after offset to be applied to each widgets - local before_count, after_count = index-1, #self._private.widgets - index - - local b, a = gen_sum(self, 1, index-1), gen_sum(self, index+1) - - local db, da = (before - b)/before_count, (after - a)/after_count - - -- Apply the new ratio - self._private.ratios[index] = itself - - -- Equality split the delta among widgets before and after - for i = 1, index -1 do - self._private.ratios[i] = self._private.ratios[i] + db - end - for i = index+1, #self._private.widgets do - self._private.ratios[i] = self._private.ratios[i] + da - end - - -- Remove potential negative ratio - normalize(self) - - self:emit_signal("widget::layout_changed") -end - ---- Update all widgets to match a set of a ratio --- @param widget The widget to ajust --- @tparam number before The sum of the ratio before the widget --- @tparam number itself The ratio for "widget" --- @tparam number after The sum of the ratio after the widget -function ratio:ajust_widget_ratio(widget, before, itself, after) - local index = self:index(widget) - self:ajust_ratio(index, before, itself, after) -end - ---- Add some widgets to the given fixed layout --- **Signal:** widget::added The argument are the widgets --- @tparam widget ... Widgets that should be added (must at least be one) -function ratio:add(...) - -- No table.pack in Lua 5.1 :-( - local args = { n=select('#', ...), ... } - assert(args.n > 0, "need at least one widget to add") - for i=1, args.n do - base.check_widget(args[i]) - table.insert(self._private.widgets, args[i]) - end - - normalize(self) - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::added", ...) -end - ---- Remove a widget from the layout --- **Signal:** widget::removed The arguments are the widget and the index --- @tparam number index The widget index to remove --- @treturn boolean index If the operation is successful -function ratio:remove(index) - if not index or not self._private.widgets[index] then return false end - - local w = self._private.widgets[index] - - table.remove(self._private.ratios, index) - table.remove(self._private.widgets, index) - - normalize(self) - - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::removed", w, index) - - return true -end - ---- Insert a new widget in the layout at position `index` --- **Signal:** widget::inserted The arguments are the widget and the index --- @tparam number index The position --- @param widget The widget -function ratio:insert(index, widget) - if not index or index < 1 or index > #self._private.widgets + 1 then return false end - - base.check_widget(widget) - - table.insert(self._private.widgets, index, widget) - - normalize(self) - - self:emit_signal("widget::layout_changed") - self:emit_signal("widget::inserted", widget, #self._private.widgets) -end - -local function get_layout(dir, widget1, ...) - local ret = flex[dir](widget1, ...) - - util.table.crush(ret, ratio, true) - - ret._private.fill_space = nil - - ret._private.ratios = {} - - return ret -end - ---- Returns a new horizontal ratio layout. A ratio layout shares the available space --- equally among all widgets. Widgets can be added via :add(widget). --- @tparam widget ... Widgets that should be added to the layout. -function ratio.horizontal(...) - return get_layout("horizontal", ...) -end - ---- Returns a new vertical ratio layout. A ratio layout shares the available space --- equally among all widgets. Widgets can be added via :add(widget). --- @tparam widget ... Widgets that should be added to the layout. -function ratio.vertical(...) - return get_layout("vertical", ...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return ratio - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/rotate.lua b/awesome/lib/wibox/layout/rotate.lua deleted file mode 100644 index a6b5d7a..0000000 --- a/awesome/lib/wibox/layout/rotate.lua +++ /dev/null @@ -1,17 +0,0 @@ ---------------------------------------------------------------------------- --- This class has been moved to `wibox.container.rotate` --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.layout.rotate ---------------------------------------------------------------------------- - -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.container.rotate"), - "wibox.layout.rotate", - "wibox.container.rotate" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/scroll.lua b/awesome/lib/wibox/layout/scroll.lua deleted file mode 100644 index e0be79f..0000000 --- a/awesome/lib/wibox/layout/scroll.lua +++ /dev/null @@ -1,16 +0,0 @@ ---------------------------------------------------------------------------- --- This class has been moved to `wibox.container.scroll` --- --- @author Uli Schlachter (based on ideas from Saleur Geoffrey) --- @copyright 2015 Uli Schlachter --- @classmod wibox.layout.scroll ---------------------------------------------------------------------------- -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.container.scroll"), - "wibox.layout.scroll", - "wibox.container.scroll" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/layout/stack.lua b/awesome/lib/wibox/layout/stack.lua deleted file mode 100644 index bd28703..0000000 --- a/awesome/lib/wibox/layout/stack.lua +++ /dev/null @@ -1,402 +0,0 @@ ---------------------------------------------------------------------------- --- A stacked layout. --- --- This layout display widgets on top of each other. It can be used to overlay --- a `wibox.widget.textbox` on top of a `awful.widget.progressbar` or manage --- "pages" where only one is visible at any given moment. --- --- The indices are going from 1 (the bottom of the stack) up to the top of --- the stack. The order can be changed either using `:swap` or `:raise`. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_layout_defaults_stack.svg) --- --- @usage ---wibox.widget { --- generic_widget( 'first' ), --- generic_widget( 'second' ), --- generic_widget( 'third' ), --- layout = wibox.layout.stack ---} --- @author Emmanuel Lepage Vallee --- @copyright 2016 Emmanuel Lepage Vallee --- @classmod wibox.layout.stack ---------------------------------------------------------------------------- - -local base = require("wibox.widget.base" ) -local fixed = require("wibox.layout.fixed") -local table = table -local pairs = pairs -local util = require("awful.util") - -local stack = {mt={}} - ---Imported documentation - ---- Set a widget at a specific index, replace the current one. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @tparam number index A widget or a widget index --- @param widget2 The widget to take the place of the first one --- @treturn boolean If the operation is successful --- @name set --- @class function - ---- Replace the first instance of `widget` in the layout with `widget2`. --- **Signal:** widget::replaced The argument is the new widget and the old one --- and the index. --- @param widget The widget to replace --- @param widget2 The widget to replace `widget` with --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name replace_widget --- @class function - ---- Swap 2 widgets in a layout. --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- @tparam number index1 The first widget index --- @tparam number index2 The second widget index --- @treturn boolean If the operation is successful --- @name swap --- @class function - ---- Swap 2 widgets in a layout. --- If widget1 is present multiple time, only the first instance is swapped --- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. --- if the layouts not the same, then only `widget::replaced` will be emitted. --- @param widget1 The first widget --- @param widget2 The second widget --- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. --- @treturn boolean If the operation is successful --- @name swap_widgets --- @class function - ---- Get all direct children of this layout. --- @param layout The layout you are modifying. --- @property children - ---- Reset a ratio layout. This removes all widgets from the layout. --- **Signal:** widget::reset --- @param layout The layout you are modifying. --- @name reset --- @class function - - ---- Add some widgets to the given stack layout --- @param layout The layout you are modifying. --- @tparam widget ... Widgets that should be added (must at least be one) --- @name add --- @class function - ---- Remove a widget from the layout --- @tparam index The widget index to remove --- @treturn boolean index If the operation is successful --- @name remove --- @class function - ---- Insert a new widget in the layout at position `index` --- @tparam number index The position --- @param widget The widget --- @treturn boolean If the operation is successful --- @name insert --- @class function - ---- Remove one or more widgets from the layout --- The last parameter can be a boolean, forcing a recursive seach of the --- widget(s) to remove. --- @param widget ... Widgets that should be removed (must at least be one) --- @treturn boolean If the operation is successful --- @name remove_widgets --- @class function - ---- Add spacing between each layout widgets --- @property spacing --- @tparam number spacing Spacing between widgets. - -function stack:layout(_, width, height) - local result = {} - local spacing = self._private.spacing - - for _, v in pairs(self._private.widgets) do - table.insert(result, base.place_widget_at(v, spacing, spacing, width - 2*spacing, height - 2*spacing)) - if self._private.top_only then break end - end - - return result -end - -function stack:fit(context, orig_width, orig_height) - local max_w, max_h = 0,0 - local spacing = self._private.spacing - - for _, v in pairs(self._private.widgets) do - local w, h = base.fit_widget(self, context, v, orig_width, orig_height) - max_w, max_h = math.max(max_w, w+2*spacing), math.max(max_h, h+2*spacing) - end - - return math.min(max_w, orig_width), math.min(max_h, orig_height) -end - ---- If only the first stack widget is drawn --- @property top_only - -function stack:get_top_only() - return self._private.top_only -end - -function stack:set_top_only(top_only) - self._private.top_only = top_only -end - ---- Raise a widget at `index` to the top of the stack --- @tparam number index the widget index to raise -function stack:raise(index) - if (not index) or self._private.widgets[index] then return end - - local w = self._private.widgets[index] - table.remove(self._private.widgets, index) - table.insert(self._private.widgets, w) - - self:emit_signal("widget::layout_changed") -end - ---- Raise the first instance of `widget` --- @param widget The widget to raise --- @tparam[opt=false] boolean recursive Also look deeper in the hierarchy to --- find the widget -function stack:raise_widget(widget, recursive) - local idx, layout = self:index(widget, recursive) - - if not idx or not layout then return end - - -- Bubble up in the stack until the right index is found - while layout and layout ~= self do - idx, layout = self:index(layout, recursive) - end - - if layout == self and idx ~= 1 then - self:raise(idx) - end -end - ---- Create a new stack layout. --- @function wibox.layout.stack --- @treturn widget A new stack layout - -local function new(...) - local ret = fixed.horizontal(...) - - util.table.crush(ret, stack, true) - - return ret -end - -function stack.mt:__call(_, ...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(stack, stack.mt) --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/background.lua b/awesome/lib/wibox/widget/background.lua deleted file mode 100644 index 3c35a0b..0000000 --- a/awesome/lib/wibox/widget/background.lua +++ /dev/null @@ -1,16 +0,0 @@ ---------------------------------------------------------------------------- --- This class has been moved to `wibox.container.background` --- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.widget.background ---------------------------------------------------------------------------- -local util = require("awful.util") - -return util.deprecate_class( - require("wibox.container.background"), - "wibox.widget.background", - "wibox.container.background" -) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/base.lua b/awesome/lib/wibox/widget/base.lua deleted file mode 100644 index dd80ec7..0000000 --- a/awesome/lib/wibox/widget/base.lua +++ /dev/null @@ -1,694 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.widget.base ---------------------------------------------------------------------------- - -local object = require("gears.object") -local cache = require("gears.cache") -local matrix = require("gears.matrix") -local protected_call = require("gears.protected_call") -local util = require("awful.util") -local setmetatable = setmetatable -local pairs = pairs -local type = type -local table = table - -local base = {} - --- {{{ Functions on widgets - ---- Functions available on all widgets. -base.widget = {} - ---- Set/get a widget's buttons. --- @tab _buttons The table of buttons that is bound to the widget. --- @function buttons -function base.widget:buttons(_buttons) - if _buttons then - self._private.widget_buttons = _buttons - end - return self._private.widget_buttons -end - ---- Set a widget's visibility. --- @tparam boolean b Whether the widget is visible. --- @function set_visible -function base.widget:set_visible(b) - if b ~= self._private.visible then - self._private.visible = b - self:emit_signal("widget::layout_changed") - -- In case something ignored fit and drew the widget anyway. - self:emit_signal("widget::redraw_needed") - end -end - ---- Is the widget visible? --- @treturn boolean --- @function get_visible -function base.widget:get_visible() - return self._private.visible or false -end - ---- Set a widget's opacity. --- @tparam number o The opacity to use (a number from 0 (transparent) to 1 --- (opaque)). --- @function set_opacity -function base.widget:set_opacity(o) - if o ~= self._private.opacity then - self._private.opacity = o - self:emit_signal("widget::redraw") - end -end - ---- Get the widget's opacity. --- @treturn number The opacity (between 0 (transparent) and 1 (opaque)). --- @function get_opacity -function base.widget:get_opacity() - return self._private.opacity -end - ---- Set the widget's forced width. --- @tparam[opt] number width With `nil` the default mechanism of calling the --- `:fit` method is used. --- @see fit_widget --- @function set_forced_width -function base.widget:set_forced_width(width) - if width ~= self._private.forced_width then - self._private.forced_width = width - self:emit_signal("widget::layout_changed") - end -end - ---- Get the widget's forced width. --- --- Note that widget instances can be used in different places simultaneously, --- and therefore can have multiple dimensions. --- If there is no forced width/height, then the only way to get the widget's --- actual size is during a `mouse::enter`, `mouse::leave` or button event. --- @treturn[opt] number The forced width (nil if automatic). --- @see fit_widget --- @function get_forced_width -function base.widget:get_forced_width() - return self._private.forced_width -end - ---- Set the widget's forced height. --- @tparam[opt] number height With `nil` the default mechanism of calling the --- `:fit` method is used. --- @see fit_widget --- @function set_height -function base.widget:set_forced_height(height) - if height ~= self._private.forced_height then - self._private.forced_height = height - self:emit_signal("widget::layout_changed") - end -end - ---- Get the widget's forced height. --- --- Note that widget instances can be used in different places simultaneously, --- and therefore can have multiple dimensions. --- If there is no forced width/height, then the only way to get the widget's --- actual size is during a `mouse::enter`, `mouse::leave` or button event. --- @treturn[opt] number The forced height (nil if automatic). --- @function get_forced_height -function base.widget:get_forced_height() - return self._private.forced_height -end - ---- Get the widget's direct children widgets. --- --- This method should be re-implemented by the relevant widgets. --- @treturn table The children --- @function get_children -function base.widget:get_children() - return {} -end - ---- Replace the layout children. --- --- The default implementation does nothing, this must be re-implemented by --- all layout and container widgets. --- @tab children A table composed of valid widgets. --- @function set_children -function base.widget:set_children(children) -- luacheck: no unused - -- Nothing on purpose -end - --- It could have been merged into `get_all_children`, but it's not necessary. -local function digg_children(ret, tlw) - for _, w in ipairs(tlw:get_children()) do - table.insert(ret, w) - digg_children(ret, w) - end -end - ---- Get all direct and indirect children widgets. --- --- This will scan all containers recursively to find widgets. --- --- *Warning*: This method it prone to stack overflow if the widget, or any of --- its children, contains (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children -function base.widget:get_all_children() - local ret = {} - digg_children(ret, self) - return ret -end - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- --- Note that this function has two flaws: --- --- 1. The signal is only forwarded once the widget tree has been built. This --- happens after all currently scheduled functions have been executed. --- Therefore, it will not start to work right away. --- 2. In case the widget is present multiple times in a single widget tree, --- this function will also forward the signal multiple time (one per upward --- tree path). --- --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive -function base.widget:emit_signal_recursive(signal_name, ...) - -- This is a convenience wrapper, the real implementation is in the - -- hierarchy. - - self:emit_signal("widget::emit_recursive", signal_name, ...) -end - ---- Get the index of a widget. --- @tparam widget widget The widget to look for. --- @tparam[opt] boolean recursive Also check sub-widgets? --- @tparam[opt] widget ... Additional widgets to add at the end of the "path" --- @treturn number The index. --- @treturn widget The parent widget. --- @treturn table The path between "self" and "widget". --- @function index -function base.widget:index(widget, recursive, ...) - local widgets = self:get_children() - for idx, w in ipairs(widgets) do - if w == widget then - return idx, self, {...} - elseif recursive then - local child_idx, l, path = w:index(widget, true, self, ...) - if child_idx and l then - return child_idx, l, path - end - end - end - return nil, self, {} -end --- }}} - --- {{{ Caches - --- Indexes are widgets, allow them to be garbage-collected. -local widget_dependencies = setmetatable({}, { __mode = "kv" }) - --- Get the cache of the given kind for this widget. This returns a gears.cache --- that calls the callback of kind `kind` on the widget. -local function get_cache(widget, kind) - if not widget._private.widget_caches[kind] then - widget._private.widget_caches[kind] = cache.new(function(...) - return protected_call(widget[kind], widget, ...) - end) - end - return widget._private.widget_caches[kind] -end - --- Special value to skip the dependency recording that is normally done by --- base.fit_widget() and base.layout_widget(). The caller must ensure that no --- caches depend on the result of the call and/or must handle the children's --- widget::layout_changed signal correctly when using this. -base.no_parent_I_know_what_I_am_doing = {} - --- Record a dependency from parent to child: The layout of `parent` depends on --- the layout of `child`. -local function record_dependency(parent, child) - if parent == base.no_parent_I_know_what_I_am_doing then - return - end - - base.check_widget(parent) - base.check_widget(child) - - local deps = widget_dependencies[child] or {} - deps[parent] = true - widget_dependencies[child] = deps -end - --- Clear the caches for `widget` and all widgets that depend on it. -local clear_caches -function clear_caches(widget) - local deps = widget_dependencies[widget] or {} - widget_dependencies[widget] = {} - widget._private.widget_caches = {} - for w in pairs(deps) do - clear_caches(w) - end -end - --- }}} - ---- Figure out the geometry in the device coordinate space. --- --- This gives only tight bounds if no rotations by non-multiples of 90° are --- used. --- @function wibox.widget.base.rect_to_device_geometry -function base.rect_to_device_geometry(cr, x, y, width, height) - return matrix.transform_rectangle(cr.matrix, x, y, width, height) -end - ---- Fit a widget for the given available width and height. --- --- This calls the widget's `:fit` callback and caches the result for later use. --- Never call `:fit` directly, but always through this function! --- @tparam widget parent The parent widget which requests this information. --- @tab context The context in which we are fit. --- @tparam widget widget The widget to fit (this uses --- `widget:fit(context, width, height)`). --- @tparam number width The available width for the widget. --- @tparam number height The available height for the widget. --- @treturn number The width that the widget wants to use. --- @treturn number The height that the widget wants to use. --- @function wibox.widget.base.fit_widget -function base.fit_widget(parent, context, widget, width, height) - record_dependency(parent, widget) - - if not widget._private.visible then - return 0, 0 - end - - -- Sanitize the input. This also filters out e.g. NaN. - width = math.max(0, width) - height = math.max(0, height) - - local w, h = 0, 0 - if widget.fit then - w, h = get_cache(widget, "fit"):get(context, width, height) - else - -- If it has no fit method, calculate based on the size of children - local children = base.layout_widget(parent, context, widget, width, height) - for _, info in ipairs(children or {}) do - local x, y, w2, h2 = matrix.transform_rectangle(info._matrix, - 0, 0, info._width, info._height) - w, h = math.max(w, x + w2), math.max(h, y + h2) - end - end - - -- Apply forced size and handle nil's - w = widget._private.forced_width or w or 0 - h = widget._private.forced_height or h or 0 - - -- Also sanitize the output. - w = math.max(0, math.min(w, width)) - h = math.max(0, math.min(h, height)) - return w, h -end - ---- Lay out a widget for the given available width and height. --- --- This calls the widget's `:layout` callback and caches the result for later --- use. Never call `:layout` directly, but always through this function! --- However, normally there shouldn't be any reason why you need to use this --- function. --- @tparam widget parent The parent widget which requests this information. --- @tab context The context in which we are laid out. --- @tparam widget widget The widget to layout (this uses --- `widget:layout(context, width, height)`). --- @tparam number width The available width for the widget. --- @tparam number height The available height for the widget. --- @treturn[opt] table The result from the widget's `:layout` callback. --- @function wibox.widget.base.layout_widget -function base.layout_widget(parent, context, widget, width, height) - record_dependency(parent, widget) - - if not widget._private.visible then - return - end - - -- Sanitize the input. This also filters out e.g. NaN. - width = math.max(0, width) - height = math.max(0, height) - - if widget.layout then - return get_cache(widget, "layout"):get(context, width, height) - end -end - ---- Handle a button event on a widget. --- --- This is used internally and should not be called directly. --- @function wibox.widget.base.handle_button -function base.handle_button(event, widget, x, y, button, modifiers, geometry) - x = x or y -- luacheck: no unused - local function is_any(mod) - return #mod == 1 and mod[1] == "Any" - end - - local function tables_equal(a, b) - if #a ~= #b then - return false - end - for k, v in pairs(b) do - if a[k] ~= v then - return false - end - end - return true - end - - -- Find all matching button objects. - local matches = {} - for _, v in pairs(widget._private.widget_buttons) do - local match = true - -- Is it the right button? - if v.button ~= 0 and v.button ~= button then match = false end - -- Are the correct modifiers pressed? - if (not is_any(v.modifiers)) and (not tables_equal(v.modifiers, modifiers)) then match = false end - if match then - table.insert(matches, v) - end - end - - -- Emit the signals. - for _, v in pairs(matches) do - v:emit_signal(event,geometry) - end -end - ---- Create widget placement information. This should be used in a widget's --- `:layout()` callback. --- @tparam widget widget The widget that should be placed. --- @param mat A matrix transforming from the parent widget's coordinate --- system. For example, use matrix.create_translate(1, 2) to draw a --- widget at position (1, 2) relative to the parent widget. --- @tparam number width The width of the widget in its own coordinate system. --- That is, after applying the transformation matrix. --- @tparam number height The height of the widget in its own coordinate system. --- That is, after applying the transformation matrix. --- @treturn table An opaque object that can be returned from `:layout()`. --- @function wibox.widget.base.place_widget_via_matrix -function base.place_widget_via_matrix(widget, mat, width, height) - return { - _widget = widget, - _width = width, - _height = height, - _matrix = mat - } -end - ---- Create widget placement information. This should be used for a widget's --- `:layout()` callback. --- @tparam widget widget The widget that should be placed. --- @tparam number x The x coordinate for the widget. --- @tparam number y The y coordinate for the widget. --- @tparam number width The width of the widget in its own coordinate system. --- That is, after applying the transformation matrix. --- @tparam number height The height of the widget in its own coordinate system. --- That is, after applying the transformation matrix. --- @treturn table An opaque object that can be returned from `:layout()`. --- @function wibox.widget.base.place_widget_at -function base.place_widget_at(widget, x, y, width, height) - return base.place_widget_via_matrix(widget, matrix.create_translate(x, y), width, height) -end - --- Read the table, separate attributes from widgets. -local function parse_table(t, leave_empty) - local max = 0 - local attributes, widgets = {}, {} - for k,v in pairs(t) do - if type(k) == "number" then - if v then - -- Since `ipairs` doesn't always work on sparse tables, update - -- the maximum. - if k > max then - max = k - end - - widgets[k] = v - end - else - attributes[k] = v - end - end - - -- Pack the sparse table, if the container doesn't support sparse tables. - if not leave_empty then - widgets = util.table.from_sparse(widgets) - max = #widgets - end - - return max, attributes, widgets -end - --- Recursively build a container from a declarative table. -local function drill(ids, content) - if not content then return end - - -- Alias `widget` to `layout` as they are handled the same way. - content.layout = content.layout or content.widget - - -- Make sure the layout is not indexed on a function. - local layout = type(content.layout) == "function" and content.layout() or content.layout - - -- Create layouts based on metatable's __call. - local l = layout.is_widget and layout or layout() - - -- Get the number of children widgets (including nil widgets). - local max, attributes, widgets = parse_table(content, l.allow_empty_widget) - - -- Get the optional identifier to create a virtual widget tree to place - -- in an "access table" to be able to retrieve the widget. - local id = attributes.id - - -- Clear the internal attributes. - attributes.id, attributes.layout, attributes.widget = nil, nil, nil - - -- Set layout attributes. - -- This has to be done before the widgets are added because it might affect - -- the output. - for attr, val in pairs(attributes) do - if l["set_"..attr] then - l["set_"..attr](l, val) - elseif type(l[attr]) == "function" then - l[attr](l, val) - else - l[attr] = val - end - end - - -- Add all widgets. - for k = 1, max do - -- ipairs cannot be used on sparse tables. - local v, id2, e = widgets[k], id, nil - if v then - -- It is another declarative container, parse it. - if not v.is_widget then - e, id2 = drill(ids, v) - widgets[k] = e - end - base.check_widget(widgets[k]) - - -- Place the widget in the access table. - if id2 then - l [id2] = e - ids[id2] = ids[id2] or {} - table.insert(ids[id2], e) - end - end - end - -- Replace all children (if any) with the new ones. - l:set_children(widgets) - return l, id -end - --- Only available when the declarative system is used. -local function get_children_by_id(self, name) - if rawget(self, "_private") then - return self._private.by_id[name] or {} - else - return rawget(self, "_by_id")[name] or {} - end -end - ---- Set a declarative widget hierarchy description. --- --- See [The declarative layout system](../documentation/03-declarative-layout.md.html). --- @tab args A table containing the widget's disposition. --- @function setup -function base.widget:setup(args) - local f,ids = self.set_widget or self.add or self.set_first,{} - local w, id = drill(ids, args) - f(self,w) - if id then - -- Avoid being dropped by wibox metatable -> drawin - rawset(self, id, w) - ids[id] = ids[id] or {} - table.insert(ids[id], 1, w) - end - - if rawget(self, "_private") then - self._private.by_id = ids - else - rawset(self, "_by_id", ids) - end - - rawset(self, "get_children_by_id", get_children_by_id) -end - ---- Create a widget from a declarative description. --- --- See [The declarative layout system](../documentation/03-declarative-layout.md.html). --- @tab args A table containing the widgets disposition. --- @function wibox.widget.base.make_widget_declarative -function base.make_widget_declarative(args) - local ids = {} - - if (not args.layout) and (not args.widget) then - args.widget = base.make_widget(nil, args.id) - end - - local w, id = drill(ids, args) - - local mt = getmetatable(w) or {} - local orig_string = tostring(w) - - -- Add the main id (if any) - if id then - ids[id] = ids[id] or {} - table.insert(ids[id], 1, w) - end - - if rawget(w, "_private") then - w._private.by_id = ids - else - rawset(w, "_by_id", ids) - end - - rawset(w, "get_children_by_id", get_children_by_id) - - mt.__tostring = function() - return string.format("%s (%s)", id or w.widget_name or "N/A", orig_string) - end - - return setmetatable(w, mt) -end - ---- Create an empty widget skeleton. --- --- See [Creating new widgets](../documentation/04-new-widget.md.html). --- @tparam[opt] widget proxy If this is set, the returned widget will be a --- proxy for this widget. It will be equivalent to this widget. --- This means it looks the same on the screen. --- @tparam[opt] string widget_name Name of the widget. If not set, it will be --- set automatically via @{gears.object.modulename}. --- @tparam[opt={}] table args Widget settings --- @tparam[opt=false] boolean args.enable_properties Enable automatic getter --- and setter methods. --- @tparam[opt=nil] table args.class The widget class --- @see fit_widget --- @function wibox.widget.base.make_widget -function base.make_widget(proxy, widget_name, args) - args = args or {} - local ret = object { - enable_properties = args.enable_properties, - class = args.class, - } - - -- Backwards compatibility. - -- TODO: Remove this - ret:connect_signal("widget::updated", function() - ret:emit_signal("widget::layout_changed") - ret:emit_signal("widget::redraw_needed") - end) - - -- Create a table used to store the widgets internal data. - rawset(ret, "_private", {}) - - -- No buttons yet. - ret._private.widget_buttons = {} - - -- Widget is visible. - ret._private.visible = true - - -- Widget is fully opaque. - ret._private.opacity = 1 - - -- Differentiate tables from widgets. - rawset(ret, "is_widget", true) - - -- Size is not restricted/forced. - ret._private.forced_width = nil - ret._private.forced_height = nil - - -- Make buttons work. - ret:connect_signal("button::press", function(...) - return base.handle_button("press", ...) - end) - ret:connect_signal("button::release", function(...) - return base.handle_button("release", ...) - end) - - if proxy then - rawset(ret, "fit", function(_, context, width, height) - return base.fit_widget(ret, context, proxy, width, height) - end) - rawset(ret, "layout", function(_, _, width, height) - return { base.place_widget_at(proxy, 0, 0, width, height) } - end) - proxy:connect_signal("widget::layout_changed", function() - ret:emit_signal("widget::layout_changed") - end) - proxy:connect_signal("widget::redraw_needed", function() - ret:emit_signal("widget::redraw_needed") - end) - end - - -- Set up caches. - clear_caches(ret) - ret:connect_signal("widget::layout_changed", function() - clear_caches(ret) - end) - - -- Add functions. - for k, v in pairs(base.widget) do - rawset(ret, k, v) - end - - -- Add __tostring method to metatable. - rawset(ret, "widget_name", widget_name or object.modulename(3)) - local mt = getmetatable(ret) or {} - local orig_string = tostring(ret) - mt.__tostring = function() - return string.format("%s (%s)", ret.widget_name, orig_string) - end - return setmetatable(ret, mt) -end - ---- Generate an empty widget which takes no space and displays nothing. --- @function wibox.widget.base.empty_widget -function base.empty_widget() - return base.make_widget() -end - ---- Do some sanity checking on a widget. --- --- This function raises an error if the widget is not valid. --- @function wibox.widget.base.check_widget -function base.check_widget(widget) - assert(type(widget) == "table", "Type should be table, but is " .. tostring(type(widget))) - assert(widget.is_widget, "Argument is not a widget!") - for _, func in pairs({ "connect_signal", "disconnect_signal" }) do - assert(type(widget[func]) == "function", func .. " is not a function") - end -end - -return base - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/checkbox.lua b/awesome/lib/wibox/widget/checkbox.lua deleted file mode 100644 index 57bdaa3..0000000 --- a/awesome/lib/wibox/widget/checkbox.lua +++ /dev/null @@ -1,530 +0,0 @@ ---------------------------------------------------------------------------- --- A boolean display widget. --- --- If necessary, themes can implement custom shape: --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_checkbox_custom.svg) --- --- --- wibox.widget { --- checked = true, --- color = beautiful.bg_normal, --- paddings = 2, --- check_shape = function(cr, width, height) --- local rs = math.min(width, height) --- cr:move_to( 0 , 0 ) --- cr:line_to( rs , 0 ) --- cr:move_to( 0 , 0 ) --- cr:line_to( 0 , rs ) --- cr:move_to( 0 , rs ) --- cr:line_to( rs , rs ) --- cr:move_to( rs , 0 ) --- cr:line_to( rs , rs ) --- cr:move_to( 0 , 0 ) --- cr:line_to( rs , rs ) --- cr:move_to( 0 , rs ) --- cr:line_to( rs , 0 ) --- end, --- check_border_color = '#ff0000', --- check_color = '#00000000', --- check_border_width = 1, --- widget = wibox.widget.checkbox --- } --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_checkbox.svg) --- --- @usage ---wibox.widget { --- checked = true, --- color = beautiful.bg_normal, --- paddings = 2, --- shape = gears.shape.circle, --- widget = wibox.widget.checkbox ---} --- @author Emmanuel Lepage Valle --- @copyright 2010 Emmanuel Lepage Vallee --- @classmod wibox.widget.checkbox ---------------------------------------------------------------------------- - -local color = require( "gears.color" ) -local base = require( "wibox.widget.base" ) -local beautiful = require( "beautiful" ) -local shape = require( "gears.shape" ) -local util = require( "awful.util" ) - -local checkbox = {} - ---- The outer (unchecked area) border width. --- @beautiful beautiful.checkbox_border_width - ---- The outer (unchecked area) background color, pattern or gradient. --- @beautiful beautiful.checkbox_bg - ---- The outer (unchecked area) border color. --- @beautiful beautiful.checkbox_border_color - ---- The checked part border color. --- @beautiful beautiful.checkbox_check_border_color - ---- The checked part border width. --- @beautiful beautiful.checkbox_check_border_width - ---- The checked part filling color. --- @beautiful beautiful.checkbox_check_color - ---- The outer (unchecked area) shape. --- @beautiful beautiful.checkbox_shape --- @see gears.shape - ---- The checked part shape. --- If none is set, then the `shape` property will be used. --- @beautiful beautiful.checkbox_check_shape --- @see gears.shape - ---- The padding between the outline and the progressbar. --- @beautiful beautiful.checkbox_paddings --- @tparam[opt=0] table|number paddings A number or a table --- @tparam[opt=0] number paddings.top --- @tparam[opt=0] number paddings.bottom --- @tparam[opt=0] number paddings.left --- @tparam[opt=0] number paddings.right - ---- The checkbox color. --- This will be used for the unchecked part border color and the checked part --- filling color. Note that `check_color` and `border_color` have priority --- over this property. --- @beautiful beautiful.checkbox_color - ---- The outer (unchecked area) border width. --- @property border_width - ---- The outer (unchecked area) background color, pattern or gradient. --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_checkbox_bg.svg) --- --- @usage ---wibox.widget { --- checked = true, --- color = beautiful.bg_normal, --- bg = '#ff00ff', --- border_width = 3, --- paddings = 4, --- border_color = '#0000ff', --- check_color = '#ff0000', --- check_border_color = '#ffff00', --- check_border_width = 1, --- widget = wibox.widget.checkbox ---} --- @property bg - ---- The outer (unchecked area) border color. --- @property border_color - ---- The checked part border color. --- @property check_border_color - ---- The checked part border width. --- @property check_border_width - ---- The checked part filling color. --- @property check_color - ---- The outer (unchecked area) shape. --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_checkbox_shape.svg) --- --- @usage ---for _, s in ipairs {'rectangle', 'circle', 'losange', 'octogon'} do --- wibox.widget { --- checked = true, --- color = beautiful.bg_normal, --- paddings = 2, --- shape = gears.shape[s], --- widget = wibox.widget.checkbox --- } ---end --- @property shape --- @see gears.shape - ---- The checked part shape. --- If none is set, then the `shape` property will be used. --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_checkbox_check_shape.svg) --- --- @usage ---for _, s in ipairs {'rectangle', 'circle', 'losange', 'octogon'} do --- wibox.widget { --- checked = true, --- color = beautiful.bg_normal, --- paddings = 2, --- check_shape = gears.shape[s], --- widget = wibox.widget.checkbox --- } ---end --- @property check_shape --- @see gears.shape - ---- The padding between the outline and the progressbar. --- @property paddings --- @tparam[opt=0] table|number paddings A number or a table --- @tparam[opt=0] number paddings.top --- @tparam[opt=0] number paddings.bottom --- @tparam[opt=0] number paddings.left --- @tparam[opt=0] number paddings.right - ---- The checkbox color. --- This will be used for the unchecked part border color and the checked part --- filling color. Note that `check_color` and `border_color` have priority --- over this property. --- @property color - -local function outline_workarea(self, width, height) - local offset = (self._private.border_width or - beautiful.checkbox_border_width or 1)/2 - - return { - x = offset, - y = offset, - width = width-2*offset, - height = height-2*offset - } -end - --- The child widget area -local function content_workarea(self, width, height) - local padding = self._private.paddings or {} - local offset = self:get_check_border_width() or 0 - local wa = outline_workarea(self, width, height) - - wa.x = offset + wa.x + (padding.left or 1) - wa.y = offset + wa.y + (padding.top or 1) - wa.width = wa.width - (padding.left or 1) - (padding.right or 1) - 2*offset - wa.height = wa.height - (padding.top or 1) - (padding.bottom or 1) - 2*offset - - return wa -end - -local function draw(self, _, cr, width, height) - local size = math.min(width, height) - - local background_shape = self:get_shape() or shape.rectangle - local border_width = self:get_border_width() or 1 - - local main_color = self:get_color() - local bg = self:get_bg() - local border_color = self:get_border_color() - - -- If no color is set, it will fallback to the default one - if border_color or main_color then - cr:set_source(color(border_color or main_color)) - end - - local wa = outline_workarea(self, size, size) - cr:translate(wa.x, wa.y) - background_shape(cr, wa.width, wa.height) - cr:set_line_width(border_width) - - if bg then - cr:save() - cr:set_source(color(bg)) - cr:fill_preserve() - cr:restore() - end - - cr:stroke() - - cr:translate(-wa.x, -wa.y) - - -- Draw the checked part - if self._private.checked then - local col = self:get_check_color() or main_color - border_color = self:get_check_border_color() - border_width = self:get_check_border_width() or 0 - local check_shape = self:get_check_shape() or background_shape - - wa = content_workarea(self, size, size) - cr:translate(wa.x, wa.y) - - check_shape(cr, wa.width, wa.height) - - if col then - cr:set_source(color(col)) - end - - if border_width > 0 then - cr:fill_preserve() - cr:set_line_width(border_width) - cr:set_source(color(border_color)) - cr:stroke() - else - cr:fill() - end - end -end - -local function fit(_, _, w, h) - local size = math.min(w, h) - return size, size -end - ---- If the checkbox is checked. --- @property checked --- @param boolean - -for _, prop in ipairs {"border_width", "bg", "border_color", "check_border_color", - "check_border_width", "check_color", "shape", "check_shape", "paddings", - "checked", "color" } do - checkbox["set_"..prop] = function(self, value) - self._private[prop] = value - self:emit_signal("property::"..prop) - self:emit_signal("widget::redraw_needed") - end - checkbox["get_"..prop] = function(self) - return self._private[prop] or beautiful["checkbox_"..prop] - end -end - ---- The checkbox color. --- @property color - -function checkbox:set_paddings(val) - self._private.paddings = type(val) == "number" and { - left = val, - right = val, - top = val, - bottom = val, - } or val or {} - self:emit_signal("property::paddings") - self:emit_signal("widget::redraw_needed") -end - -local function new(checked, args) - checked, args = checked or false, args or {} - - local ret = base.make_widget(nil, nil, { - enable_properties = true, - }) - - util.table.crush(ret, checkbox) - - ret._private.checked = checked - ret._private.color = args.color and color(args.color) or nil - - rawset(ret, "fit" , fit ) - rawset(ret, "draw", draw) - - return ret -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable({}, { __call = function(_, ...) return new(...) end}) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/graph.lua b/awesome/lib/wibox/widget/graph.lua deleted file mode 100644 index c03c726..0000000 --- a/awesome/lib/wibox/widget/graph.lua +++ /dev/null @@ -1,575 +0,0 @@ ---------------------------------------------------------------------------- ---- A graph widget. --- --- The graph goes from left to right. To change this to right to left, use --- a `wibox.container.mirror` widget. This can also be used to have data --- shown from top to bottom. --- --- To add text on top of the graph, use a `wibox.layout.stack` and a --- `wibox.container.align` widgets. --- --- To display the graph vertically, use a `wibox.container.rotate` widget. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_graph.svg) --- --- @usage ---wibox.widget { --- max_value = 29, --- widget = wibox.widget.graph ---} --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod wibox.widget.graph ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local ipairs = ipairs -local math = math -local table = table -local type = type -local color = require("gears.color") -local base = require("wibox.widget.base") -local beautiful = require("beautiful") - -local graph = { mt = {} } - ---- Set the graph border color. --- If the value is nil, no border will be drawn. --- --- @property border_color --- @tparam gears.color border_color The border color to set. --- @see gears.color - ---- Set the graph foreground color. --- --- @property color --- @tparam color color The graph color. --- @see gears.color - ---- Set the graph background color. --- --- @property background_color --- @tparam gears.color background_color The graph background color. --- @see gears.color - ---- Set the maximum value the graph should handle. --- If "scale" is also set, the graph never scales up below this value, but it --- automatically scales down to make all data fit. --- --- @property max_value --- @param number - ---- The minimum value. --- Note that the min_value is not supported when used along with the stack --- property. --- @property min_value --- @param number - ---- Set the graph to automatically scale its values. Default is false. --- --- @property scale --- @param boolean - ---- Set the width or the individual steps. --- --- Note that it isn't supported when used along with stacked graphs. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_graph_step.svg) --- --- @usage ---wibox.widget { --- max_value = 29, --- step_width = 3, --- step_spacing = 1, --- step_shape = function(cr, width, height) --- gears.shape.rounded_rect(cr, width, height, 2) --- end, --- widget = wibox.widget.graph ---} --- --- @property step_width --- @param[opt=1] number - ---- Set the spacing between the steps. --- --- Note that it isn't supported when used along with stacked graphs. --- --- @property step_spacing --- @param[opt=0] number - ---- The step shape. --- @property step_shape --- @param[opt=rectangle] shape --- @see gears.shape - ---- Set the graph to draw stacks. Default is false. --- --- @property stack --- @param boolean - ---- Set the graph stacking colors. Order matters. --- --- @property stack_colors --- @param stack_colors A table with stacking colors. - ---- The graph background color. --- @beautiful beautiful.graph_bg - ---- The graph foreground color. --- @beautiful beautiful.graph_fg - ---- The graph border color. --- @beautiful beautiful.graph_border_color - -local properties = { "width", "height", "border_color", "stack", - "stack_colors", "color", "background_color", - "max_value", "scale", "min_value", "step_shape", - "step_spacing", "step_width" } - -function graph.draw(_graph, _, cr, width, height) - local max_value = _graph._private.max_value - local min_value = _graph._private.min_value or ( - _graph._private.scale and math.huge or 0) - local values = _graph._private.values - - local step_shape = _graph._private.step_shape - local step_spacing = _graph._private.step_spacing or 0 - local step_width = _graph._private.step_width or 1 - - cr:set_line_width(1) - - -- Draw the background first - cr:set_source(color(_graph._private.background_color or beautiful.graph_bg or "#000000aa")) - cr:paint() - - -- Account for the border width - cr:save() - if _graph._private.border_color then - cr:translate(1, 1) - width, height = width - 2, height - 2 - end - - -- Draw a stacked graph - if _graph._private.stack then - - if _graph._private.scale then - for _, v in ipairs(values) do - for _, sv in ipairs(v) do - if sv > max_value then - max_value = sv - end - if min_value > sv then - min_value = sv - end - end - end - end - - for i = 0, width do - local rel_i = 0 - local rel_x = i + 0.5 - - if _graph._private.stack_colors then - for idx, col in ipairs(_graph._private.stack_colors) do - local stack_values = values[idx] - if stack_values and i < #stack_values then - local value = stack_values[#stack_values - i] + rel_i - cr:move_to(rel_x, height * (1 - (rel_i / max_value))) - cr:line_to(rel_x, height * (1 - (value / max_value))) - cr:set_source(color(col or beautiful.graph_fg or "#ff0000")) - cr:stroke() - rel_i = value - end - end - end - end - else - if _graph._private.scale then - for _, v in ipairs(values) do - if v > max_value then - max_value = v - end - if min_value > v then - min_value = v - end - end - end - - -- Draw the background on no value - if #values ~= 0 then - -- Draw reverse - for i = 0, #values - 1 do - local value = values[#values - i] - if value >= 0 then - local x = i*step_width + ((i-1)*step_spacing) + 0.5 - value = (value - min_value) / max_value - cr:move_to(x, height * (1 - value)) - - if step_shape then - cr:translate(step_width + (i>1 and step_spacing or 0), height * (1 - value)) - step_shape(cr, step_width, height) - cr:translate(0, -(height * (1 - value))) - elseif step_width > 1 then - cr:rectangle(x, height * (1 - value), step_width, height) - else - cr:line_to(x, height) - end - end - end - cr:set_source(color(_graph._private.color or beautiful.graph_fg or "#ff0000")) - - if step_shape or step_width > 1 then - cr:fill() - else - cr:stroke() - end - end - - end - - -- Undo the cr:translate() for the border and step shapes - cr:restore() - - -- Draw the border last so that it overlaps already drawn values - if _graph._private.border_color then - -- We decremented these by two above - width, height = width + 2, height + 2 - - -- Draw the border - cr:rectangle(0.5, 0.5, width - 1, height - 1) - cr:set_source(color(_graph._private.border_color or beautiful.graph_border_color or "#ffffff")) - cr:stroke() - end -end - -function graph.fit(_graph) - return _graph._private.width, _graph._private.height -end - ---- Add a value to the graph --- --- @param value The value to be added to the graph --- @param group The stack color group index. -function graph:add_value(value, group) - value = value or 0 - local values = self._private.values - local max_value = self._private.max_value - value = math.max(0, value) - if not self._private.scale then - value = math.min(max_value, value) - end - - if self._private.stack and group then - if not self._private.values[group] - or type(self._private.values[group]) ~= "table" - then - self._private.values[group] = {} - end - values = self._private.values[group] - end - table.insert(values, value) - - local border_width = 0 - if self._private.border_color then border_width = 2 end - - -- Ensure we never have more data than we can draw - while #values > self._private.width - border_width do - table.remove(values, 1) - end - - self:emit_signal("widget::redraw_needed") - return self -end - ---- Clear the graph. -function graph:clear() - self._private.values = {} - self:emit_signal("widget::redraw_needed") - return self -end - ---- Set the graph height. --- @param height The height to set. -function graph:set_height(height) - if height >= 5 then - self._private.height = height - self:emit_signal("widget::layout_changed") - end - return self -end - ---- Set the graph width. --- @param width The width to set. -function graph:set_width(width) - if width >= 5 then - self._private.width = width - self:emit_signal("widget::layout_changed") - end - return self -end - --- Build properties function -for _, prop in ipairs(properties) do - if not graph["set_" .. prop] then - graph["set_" .. prop] = function(_graph, value) - if _graph._private[prop] ~= value then - _graph._private[prop] = value - _graph:emit_signal("widget::redraw_needed") - end - return _graph - end - end - if not graph["get_" .. prop] then - graph["get_" .. prop] = function(_graph) - return _graph._private[prop] - end - end -end - ---- Create a graph widget. --- @param args Standard widget() arguments. You should add width and height --- key to set graph geometry. --- @return A new graph widget. --- @function wibox.widget.graph -function graph.new(args) - args = args or {} - - local width = args.width or 100 - local height = args.height or 20 - - if width < 5 or height < 5 then return end - - local _graph = base.make_widget(nil, nil, {enable_properties = true}) - - _graph._private.width = width - _graph._private.height = height - _graph._private.values = {} - _graph._private.max_value = 1 - - -- Set methods - _graph.add_value = graph["add_value"] - _graph.clear = graph["clear"] - _graph.draw = graph.draw - _graph.fit = graph.fit - - for _, prop in ipairs(properties) do - _graph["set_" .. prop] = graph["set_" .. prop] - _graph["get_" .. prop] = graph["get_" .. prop] - end - - return _graph -end - -function graph.mt:__call(...) - return graph.new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(graph, graph.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/imagebox.lua b/awesome/lib/wibox/widget/imagebox.lua deleted file mode 100644 index bdfa499..0000000 --- a/awesome/lib/wibox/widget/imagebox.lua +++ /dev/null @@ -1,395 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_imagebox.svg) --- --- @usage ---wibox.widget { --- image = beautiful.awesome_icon, --- resize = false, --- widget = wibox.widget.imagebox ---} --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.widget.imagebox ---------------------------------------------------------------------------- - -local base = require("wibox.widget.base") -local surface = require("gears.surface") -local util = require("awful.util") -local setmetatable = setmetatable -local type = type -local print = print -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) - -local imagebox = { mt = {} } - --- Draw an imagebox with the given cairo context in the given geometry. -function imagebox:draw(_, cr, width, height) - if not self._private.image then return end - if width == 0 or height == 0 then return end - - if not self._private.resize_forbidden then - -- Let's scale the image so that it fits into (width, height) - local w = self._private.image:get_width() - local h = self._private.image:get_height() - local aspect = width / w - local aspect_h = height / h - if aspect > aspect_h then aspect = aspect_h end - - cr:scale(aspect, aspect) - end - - -- Set the clip - if self._private.clip_shape then - cr:clip(self._private.clip_shape(cr, width, height, unpack(self._private.clip_args))) - end - - cr:set_source_surface(self._private.image, 0, 0) - cr:paint() -end - --- Fit the imagebox into the given geometry -function imagebox:fit(_, width, height) - if not self._private.image then - return 0, 0 - end - - local w = self._private.image:get_width() - local h = self._private.image:get_height() - - if w > width then - h = h * width / w - w = width - end - if h > height then - w = w * height / h - h = height - end - - if h == 0 or w == 0 then - return 0, 0 - end - - if not self._private.resize_forbidden then - local aspect = width / w - local aspect_h = height / h - - -- Use the smaller one of the two aspect ratios. - if aspect > aspect_h then aspect = aspect_h end - - w, h = w * aspect, h * aspect - end - - return w, h -end - ---- Set an imagebox' image --- @property image --- @param image Either a string or a cairo image surface. A string is --- interpreted as the path to a png image file. --- @return true on success, false if the image cannot be used - -function imagebox:set_image(image) - if type(image) == "string" then - image = surface.load(image) - if not image then - print(debug.traceback()) - return false - end - end - - image = surface.load(image) - - if image then - local w = image.width - local h = image.height - if w <= 0 or h <= 0 then - return false - end - end - - if self._private.image == image then - -- The image could have been modified, so better redraw - self:emit_signal("widget::redraw_needed") - return - end - - self._private.image = image - - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - return true -end - ---- Set a clip shape for this imagebox --- A clip shape define an area where the content is displayed and one where it --- is trimmed. --- --- @property clip_shape --- @param clip_shape A `gears_shape` compatible shape function --- @see gears.shape --- @see set_clip_shape - ---- Set a clip shape for this imagebox --- A clip shape define an area where the content is displayed and one where it --- is trimmed. --- --- Any other parameters will be passed to the clip shape function --- --- @param clip_shape A `gears_shape` compatible shape function --- @see gears.shape --- @see clip_shape -function imagebox:set_clip_shape(clip_shape, ...) - self._private.clip_shape = clip_shape - self._private.clip_args = {...} - self:emit_signal("widget::redraw_needed") -end - ---- Should the image be resized to fit into the available space? --- @property resize --- @param allowed If false, the image will be clipped, else it will be resized --- to fit into the available space. - -function imagebox:set_resize(allowed) - self._private.resize_forbidden = not allowed - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") -end - ---- Returns a new imagebox. --- Any other arguments will be passed to the clip shape function --- @param image the image to display, may be nil --- @param resize_allowed If false, the image will be clipped, else it will be resized --- to fit into the available space. --- @param clip_shape A `gears.shape` compatible function --- @treturn table A new `imagebox` --- @function wibox.widget.imagebox -local function new(image, resize_allowed, clip_shape) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - util.table.crush(ret, imagebox, true) - - if image then - ret:set_image(image) - end - if resize_allowed ~= nil then - ret:set_resize(resize_allowed) - end - - ret._private.clip_shape = clip_shape - ret._private.clip_args = {} - - return ret -end - -function imagebox.mt:__call(...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(imagebox, imagebox.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/init.lua b/awesome/lib/wibox/widget/init.lua deleted file mode 100644 index 43c6fc0..0000000 --- a/awesome/lib/wibox/widget/init.lua +++ /dev/null @@ -1,22 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.widget ---------------------------------------------------------------------------- -local base = require("wibox.widget.base") - -return setmetatable({ - base = base; - textbox = require("wibox.widget.textbox"); - imagebox = require("wibox.widget.imagebox"); - background = require("wibox.widget.background"); - systray = require("wibox.widget.systray"); - textclock = require("wibox.widget.textclock"); - progressbar = require("wibox.widget.progressbar"); - graph = require("wibox.widget.graph"); - checkbox = require("wibox.widget.checkbox"); - piechart = require("wibox.widget.piechart"); - slider = require("wibox.widget.slider"); -}, {__call = function(_, args) return base.make_widget_declarative(args) end}) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/piechart.lua b/awesome/lib/wibox/widget/piechart.lua deleted file mode 100644 index 5a1c185..0000000 --- a/awesome/lib/wibox/widget/piechart.lua +++ /dev/null @@ -1,467 +0,0 @@ ---------------------------------------------------------------------------- --- Display percentage in a circle. --- --- Note that this widget makes no attempts to prevent overlapping labels or --- labels drawn outside of the widget boundaries. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_piechart.svg) --- --- @usage ---wibox.widget { --- data_list = { --- { 'L1', 100 }, --- { 'L2', 200 }, --- { 'L3', 300 }, --- }, --- border_width = 1, --- colors = { --- beautiful.bg_normal, --- beautiful.bg_highlight, --- beautiful.border_color, --- }, --- widget = wibox.widget.piechart ---} --- @author Emmanuel Lepage Valle --- @copyright 2012 Emmanuel Lepage Vallee --- @classmod wibox.widget.piechart ---------------------------------------------------------------------------- - -local color = require( "gears.color" ) -local base = require( "wibox.widget.base" ) -local beautiful = require( "beautiful" ) -local util = require( "awful.util" ) -local pie = require( "gears.shape" ).pie -local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) - -local module = {} - -local piechart = {} - -local function draw_label(cr,angle,radius,center_x,center_y,text) - local edge_x = center_x+(radius/2)*math.cos(angle) - local edge_y = center_y+(radius/2)*math.sin(angle) - - cr:move_to(edge_x, edge_y) - - cr:rel_line_to(radius*math.cos(angle), radius*math.sin(angle)) - - local x,y = cr:get_current_point() - - cr:rel_line_to(x > center_x and radius/2 or -radius/2, 0) - - local ext = cr:text_extents(text) - - cr:rel_move_to( - (x>center_x and radius/2.5 or (-radius/2.5 - ext.width)), - ext.height/2 - ) - - cr:show_text(text) --TODO eventually port away from the toy API - cr:stroke() - - cr:arc(edge_x, edge_y,2,0,2*math.pi) - cr:arc(x+(x>center_x and radius/2 or -radius/2),y,2,0,2*math.pi) - - cr:fill() -end - -local function compute_sum(data) - local ret = 0 - for _, entry in ipairs(data) do - ret = ret + entry[2] - end - - return ret -end - -local function draw(self, _, cr, width, height) - if not self._private.data_list then return end - - local radius = (height > width and width or height) / 4 - local sum, start, count = compute_sum(self._private.data_list),0,0 - local has_label = self._private.display_labels ~= false - - -- Labels need to be drawn later so the original source is kept - -- use get_source() wont work are the reference cannot be set from Lua(?) - local labels = {} - - local border_width = self:get_border_width() or 1 - local border_color = self:get_border_color() - border_color = border_color and color(border_color) - - -- Draw the pies - cr:save() - cr:set_line_width(border_width) - - -- Alternate from a given sets or colors - local colors = self:get_colors() - local col_count = colors and #colors or 0 - - for _, entry in ipairs(self._private.data_list) do - local k, v = entry[1], entry[2] - local end_angle = start + 2*math.pi*(v/sum) - - local col = colors and color(colors[math.fmod(count,col_count)+1]) or nil - - pie(cr, width, height, start, end_angle, radius) - - if col then - cr:save() - cr:set_source(color(col)) - end - - if border_width > 0 then - if col then - cr:fill_preserve() - cr:restore() - end - - -- By default, it uses the fg color - if border_color then - cr:set_source(border_color) - end - cr:stroke() - elseif col then - cr:fill() - cr:restore() - end - - -- Store the label position for later - if has_label then - table.insert(labels, { - --[[angle ]] start+(end_angle-start)/2, - --[[radius ]] radius, - --[[center_x]] width/2, - --[[center_y]] height/2, - --[[text ]] k, - }) - end - start,count = end_angle,count+1 - end - cr:restore() - - -- Draw the labels - if has_label then - for _, v in ipairs(labels) do - draw_label(cr, unpack(v)) - end - end -end - -local function fit(_, _, width, height) - return width, height -end - ---- The pie chart data list. --- @property data_list --- @tparam table data_list Sorted table where each entry has a label as its --- first value and a number as its second value. - ---- The pie chart data. --- @property data --- @tparam table data Labels as keys and number as value. - ---- The border color. --- If none is set, it will use current foreground (text) color. --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_piechart_border_color.svg) --- --- @property border_color --- @param color --- @see gears.color - ---- The pie elements border width. --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_piechart_border_width.svg) --- --- @property border_width --- @tparam[opt=1] number border_width - ---- The pie chart colors. --- If no color is set, only the border will be drawn. If less colors than --- required are set, colors will be re-used in order. --- @property colors --- @tparam table colors A table of colors, one for each elements --- @see gears.color - ---- The border color. --- If none is set, it will use current foreground (text) color. --- @beautiful beautiful.piechart_border_color --- @param color --- @see gears.color - ---- If the pie chart has labels. --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_piechart_label.svg) --- --- @property display_labels --- @param[opt=true] boolean - ---- The pie elements border width. --- @beautiful beautiful.piechart_border_width --- @tparam[opt=1] number border_width - ---- The pie chart colors. --- If no color is set, only the border will be drawn. If less colors than --- required are set, colors will be re-used in order. --- @beautiful beautiful.piechart_colors --- @tparam table colors A table of colors, one for each elements --- @see gears.color - -for _, prop in ipairs {"data_list", "border_color", "border_width", "colors", - "display_labels" - } do - piechart["set_"..prop] = function(self, value) - self._private[prop] = value - self:emit_signal("property::"..prop) - if prop == "data_list" then - self:emit_signal("property::data") - end - self:emit_signal("widget::redraw_needed") - end - piechart["get_"..prop] = function(self) - return self._private[prop] or beautiful["piechart_"..prop] - end -end - -function piechart:set_data(value) - local list = {} - for k, v in pairs(value) do - table.insert(list, { k, v }) - end - self:set_data_list(list) -end - -function piechart:get_data() - local list = {} - for _, entry in ipairs(self:get_data_list()) do - list[entry[1]] = entry[2] - end - return list -end - -local function new(data_list) - - local ret = base.make_widget(nil, nil, { - enable_properties = true, - }) - - util.table.crush(ret, piechart) - - rawset(ret, "fit" , fit ) - rawset(ret, "draw", draw) - - ret:set_data_list(data_list) - - return ret -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(module, { __call = function(_, ...) return new(...) end }) --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/progressbar.lua b/awesome/lib/wibox/widget/progressbar.lua deleted file mode 100644 index 943c49f..0000000 --- a/awesome/lib/wibox/widget/progressbar.lua +++ /dev/null @@ -1,754 +0,0 @@ ---------------------------------------------------------------------------- ---- A progressbar widget. --- --- To add text on top of the progressbar, a `wibox.layout.stack` can be used: --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_progressbar_text.svg) --- --- --- wibox.widget { --- { --- max_value = 1, --- value = 0.5, --- forced_height = 20, --- forced_width = 100, --- paddings = 1, --- border_width = 1, --- border_color = beautiful.border_color, --- widget = wibox.widget.progressbar, --- }, --- { --- text = '50%', --- widget = wibox.widget.textbox, --- }, --- layout = wibox.layout.stack --- } --- --- To display the progressbar vertically, use a `wibox.container.rotate` widget: --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_progressbar_vertical.svg) --- --- --- wibox.widget { --- { --- max_value = 1, --- value = 0.33, --- widget = wibox.widget.progressbar, --- }, --- forced_height = 100, --- forced_width = 20, --- direction = 'east', --- layout = wibox.container.rotate, --- } --- --- By default, this widget will take all the available size. To prevent this, --- a `wibox.container.constraint` widget or the `forced_width`/`forced_height` --- properties have to be used. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_progressbar.svg) --- --- @usage ---wibox.widget { --- max_value = 1, --- value = 0.33, --- forced_height = 20, --- forced_width = 100, --- shape = gears.shape.rounded_bar, --- border_width = 2, --- border_color = beautiful.border_color, --- widget = wibox.widget.progressbar, ---} --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod wibox.widget.progressbar ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local ipairs = ipairs -local math = math -local util = require("awful.util") -local base = require("wibox.widget.base") -local color = require("gears.color") -local beautiful = require("beautiful") -local shape = require("gears.shape") - -local progressbar = { mt = {} } - ---- The progressbar border color. --- If the value is nil, no border will be drawn. --- --- @property border_color --- @tparam gears.color color The border color to set. --- @see gears.color - ---- The progressbar border width. --- @property border_width - ---- The progressbar inner border color. --- If the value is nil, no border will be drawn. --- --- @property bar_border_color --- @tparam gears.color color The border color to set. --- @see gears.color - ---- The progressbar inner border width. --- @property bar_border_width - ---- The progressbar foreground color. --- --- @property color --- @tparam gears.color color The progressbar color. --- @see gears.color - ---- The progressbar background color. --- --- @property background_color --- @tparam gears.color color The progressbar background color. --- @see gears.color - ---- The progressbar inner shape. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_progressbar_bar_shape.svg) --- --- @usage ---for _, shape in ipairs {'rounded_bar', 'octogon', 'hexagon', 'powerline' } do --- l:add(wibox.widget { --- value = 0.33, --- bar_shape = gears.shape[shape], --- bar_border_color = beautiful.border_color, --- bar_border_width = 1, --- border_width = 2, --- border_color = beautiful.border_color, --- paddings = 1, --- widget = wibox.widget.progressbar, --- }) ---end --- --- @property bar_shape --- @tparam[opt=gears.shape.rectangle] gears.shape shape --- @see gears.shape - ---- The progressbar shape. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_progressbar_shape.svg) --- --- @usage ---for _, shape in ipairs {'rounded_bar', 'octogon', 'hexagon', 'powerline' } do --- l:add(wibox.widget { --- value = 0.33, --- shape = gears.shape[shape], --- border_width = 2, --- border_color = beautiful.border_color, --- widget = wibox.widget.progressbar, --- }) ---end --- --- @property shape --- @tparam[opt=gears.shape.rectangle] gears.shape shape --- @see gears.shape - ---- Set the progressbar to draw vertically. --- This doesn't do anything anymore, use a `wibox.container.rotate` widget. --- @deprecated set_vertical --- @tparam boolean vertical - ---- Force the inner part (the bar) to fit in the background shape. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_progressbar_clip.svg) --- --- @usage ---wibox.widget { --- value = 75, --- max_value = 100, --- border_width = 2, --- border_color = beautiful.border_color, --- color = beautiful.border_color, --- shape = gears.shape.rounded_bar, --- bar_shape = gears.shape.rounded_bar, --- clip = false, --- forced_height = 30, --- forced_width = 100, --- paddings = 5, --- margins = { --- top = 12, --- bottom = 12, --- }, --- widget = wibox.widget.progressbar, ---} --- --- @property clip --- @tparam[opt=true] boolean clip - ---- The progressbar to draw ticks. Default is false. --- --- @property ticks --- @param boolean - ---- The progressbar ticks gap. --- --- @property ticks_gap --- @param number - ---- The progressbar ticks size. --- --- @property ticks_size --- @param number - ---- The maximum value the progressbar should handle. --- --- @property max_value --- @param number - ---- The progressbar background color. --- @beautiful beautiful.progressbar_bg - ---- The progressbar foreground color. --- @beautiful beautiful.progressbar_fg - ---- The progressbar shape. --- @beautiful beautiful.progressbar_shape --- @see gears.shape - ---- The progressbar border color. --- @beautiful beautiful.progressbar_border_color - ---- The progressbar outer border width. --- @beautiful beautiful.progressbar_border_width - ---- The progressbar inner shape. --- @beautiful beautiful.progressbar_bar_shape --- @see gears.shape - ---- The progressbar bar border width. --- @beautiful beautiful.progressbar_bar_border_width - ---- The progressbar bar border color. --- @beautiful beautiful.progressbar_bar_border_color - ---- The progressbar margins. --- Note that if the `clip` is disabled, this allows the background to be smaller --- than the bar. --- --- See the `clip` example. --- --- @tparam[opt=0] (table|number|nil) margins A table for each side or a number --- @tparam[opt=0] number margins.top --- @tparam[opt=0] number margins.bottom --- @tparam[opt=0] number margins.left --- @tparam[opt=0] number margins.right --- @property margins --- @see clip - ---- The progressbar padding. --- Note that if the `clip` is disabled, this allows the bar to be taller --- than the background. --- --- See the `clip` example. --- --- @tparam[opt=0] (table|number|nil) padding A table for each side or a number --- @tparam[opt=0] number padding.top --- @tparam[opt=0] number padding.bottom --- @tparam[opt=0] number padding.left --- @tparam[opt=0] number padding.right --- @property paddings --- @see clip - ---- The progressbar margins. --- Note that if the `clip` is disabled, this allows the background to be smaller --- than the bar. --- @tparam[opt=0] (table|number|nil) margins A table for each side or a number --- @tparam[opt=0] number margins.top --- @tparam[opt=0] number margins.bottom --- @tparam[opt=0] number margins.left --- @tparam[opt=0] number margins.right --- @beautiful beautiful.progressbar_margins --- @see clip - ---- The progressbar padding. --- Note that if the `clip` is disabled, this allows the bar to be taller --- than the background. --- @tparam[opt=0] (table|number|nil) padding A table for each side or a number --- @tparam[opt=0] number padding.top --- @tparam[opt=0] number padding.bottom --- @tparam[opt=0] number padding.left --- @tparam[opt=0] number padding.right --- @beautiful beautiful.progressbar_paddings --- @see clip - -local properties = { "border_color", "color" , "background_color", - "value" , "max_value" , "ticks", - "ticks_gap" , "ticks_size", "border_width", - "shape" , "bar_shape" , "bar_border_width", - "clip" , "margins" , "bar_border_color", - "paddings", - } - -function progressbar.draw(pbar, _, cr, width, height) - local ticks_gap = pbar._private.ticks_gap or 1 - local ticks_size = pbar._private.ticks_size or 4 - - -- We want one pixel wide lines - cr:set_line_width(1) - - local max_value = pbar._private.max_value - - local value = math.min(max_value, math.max(0, pbar._private.value)) - - if value >= 0 then - value = value / max_value - end - local border_width = pbar._private.border_width - or beautiful.progressbar_border_width or 0 - - local bcol = pbar._private.border_color or beautiful.progressbar_border_color - - border_width = bcol and border_width or 0 - - local bg = pbar._private.background_color or - beautiful.progressbar_bg or "#ff0000aa" - - local bg_width, bg_height = width, height - - local clip = pbar._private.clip ~= false and beautiful.progressbar_clip ~= false - - -- Apply the margins - local margin = pbar._private.margins or beautiful.progressbar_margins - - if margin then - if type(margin) == "number" then - cr:translate(margin, margin) - bg_width, bg_height = bg_width - 2*margin, bg_height - 2*margin - else - cr:translate(margin.left or 0, margin.top or 0) - bg_height = bg_height - - (margin.top or 0) - (margin.bottom or 0) - bg_width = bg_width - - (margin.left or 0) - (margin.right or 0) - end - end - - -- Draw the background shape - if border_width > 0 then - -- Cairo draw half of the border outside of the path area - cr:translate(border_width/2, border_width/2) - bg_width, bg_height = bg_width - border_width, bg_height - border_width - cr:set_line_width(border_width) - end - - local background_shape = pbar._private.shape or - beautiful.progressbar_shape or shape.rectangle - - background_shape(cr, bg_width, bg_height) - - cr:set_source(color(bg)) - - local over_drawn_width = bg_width + border_width - local over_drawn_height = bg_height + border_width - - if border_width > 0 then - cr:fill_preserve() - - -- Draw the border - cr:set_source(color(bcol)) - - cr:stroke() - - over_drawn_width = over_drawn_width - 2*border_width - over_drawn_height = over_drawn_height - 2*border_width - else - cr:fill() - end - - -- Undo the translation - cr:translate(-border_width/2, -border_width/2) - - -- Make sure the bar stay in the shape - if clip then - background_shape(cr, bg_width, bg_height) - cr:clip() - cr:translate(border_width, border_width) - else - -- Assume the background size is irrelevant to the bar itself - if type(margin) == "number" then - cr:translate(-margin, -margin) - else - cr:translate(-(margin.left or 0), -(margin.top or 0)) - end - - over_drawn_height = height - over_drawn_width = width - end - - -- Apply the padding - local padding = pbar._private.paddings or beautiful.progressbar_paddings - - if padding then - if type(padding) == "number" then - cr:translate(padding, padding) - over_drawn_height = over_drawn_height - 2*padding - over_drawn_width = over_drawn_width - 2*padding - else - cr:translate(padding.left or 0, padding.top or 0) - - over_drawn_height = over_drawn_height - - (padding.top or 0) - (padding.bottom or 0) - over_drawn_width = over_drawn_width - - (padding.left or 0) - (padding.right or 0) - end - end - - over_drawn_width = math.max(over_drawn_width , 0) - over_drawn_height = math.max(over_drawn_height, 0) - - local rel_x = over_drawn_width * value - - - -- Draw the progressbar shape - - local bar_shape = pbar._private.bar_shape or - beautiful.progressbar_bar_shape or shape.rectangle - - local bar_border_width = pbar._private.bar_border_width or - beautiful.progressbar_bar_border_width or pbar._private.border_width or - beautiful.progressbar_border_width or 0 - - local bar_border_color = pbar._private.bar_border_color or - beautiful.progressbar_bar_border_color - - bar_border_width = bar_border_color and bar_border_width or 0 - - over_drawn_width = over_drawn_width - bar_border_width - over_drawn_height = over_drawn_height - bar_border_width - cr:translate(bar_border_width/2, bar_border_width/2) - - bar_shape(cr, rel_x, over_drawn_height) - - cr:set_source(color(pbar._private.color or beautiful.progressbar_fg or "#ff0000")) - - if bar_border_width > 0 then - cr:fill_preserve() - cr:set_source(color(bar_border_color)) - cr:set_line_width(bar_border_width) - cr:stroke() - else - cr:fill() - end - - if pbar._private.ticks then - for i=0, width / (ticks_size+ticks_gap)-border_width do - local rel_offset = over_drawn_width / 1 - (ticks_size+ticks_gap) * i - - if rel_offset <= rel_x then - cr:rectangle(rel_offset, - border_width, - ticks_gap, - over_drawn_height) - end - end - cr:set_source(color(pbar._private.background_color or "#000000aa")) - cr:fill() - end -end - -function progressbar:fit(_, width, height) - return width, height -end - ---- Set the progressbar value. --- @param value The progress bar value between 0 and 1. -function progressbar:set_value(value) - value = value or 0 - - self._private.value = value - - self:emit_signal("widget::redraw_needed") - return self -end - -function progressbar:set_max_value(max_value) - - self._private.max_value = max_value - - self:emit_signal("widget::redraw_needed") -end - ---- Set the progressbar height. --- This method is deprecated. Use a `wibox.container.constraint` widget or --- `forced_height`. --- @param height The height to set. --- @deprecated set_height -function progressbar:set_height(height) - util.deprecate("Use a `wibox.container.constraint` widget or `forced_height`") - self:set_forced_height(height) -end - ---- Set the progressbar width. --- This method is deprecated. Use a `wibox.container.constraint` widget or --- `forced_width`. --- @param width The width to set. --- @deprecated set_width -function progressbar:set_width(width) - util.deprecate("Use a `wibox.container.constraint` widget or `forced_width`") - self:set_forced_width(width) -end - --- Build properties function -for _, prop in ipairs(properties) do - if not progressbar["set_" .. prop] then - progressbar["set_" .. prop] = function(pbar, value) - pbar._private[prop] = value - pbar:emit_signal("widget::redraw_needed") - return pbar - end - end -end - -function progressbar:set_vertical(value) --luacheck: no unused_args - util.deprecate("Use a `wibox.container.rotate` widget") -end - - ---- Create a progressbar widget. --- @param args Standard widget() arguments. You should add width and height --- key to set progressbar geometry. --- @return A progressbar widget. --- @function wibox.widget.progressbar -function progressbar.new(args) - args = args or {} - - local pbar = base.make_widget(nil, nil, { - enable_properties = true, - }) - - pbar._private.width = args.width or 100 - pbar._private.height = args.height or 20 - pbar._private.value = 0 - pbar._private.max_value = 1 - - util.table.crush(pbar, progressbar, true) - - return pbar -end - -function progressbar.mt:__call(...) - return progressbar.new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(progressbar, progressbar.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/slider.lua b/awesome/lib/wibox/widget/slider.lua deleted file mode 100644 index fd590c6..0000000 --- a/awesome/lib/wibox/widget/slider.lua +++ /dev/null @@ -1,709 +0,0 @@ ---------------------------------------------------------------------------- --- An interactive mouse based slider widget. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_slider.svg) --- --- @usage ---wibox.widget { --- bar_shape = gears.shape.rounded_rect, --- bar_height = 3, --- bar_color = beautiful.border_color, --- handle_color = beautiful.bg_normal, --- handle_shape = gears.shape.circle, --- handle_border_color = beautiful.border_color, --- handle_border_width = 1, --- value = 25, --- widget = wibox.widget.slider, ---} --- --- @author Grigory Mishchenko <grishkokot@gmail.com> --- @author Emmanuel Lepage Vallee <elv1313@gmail.com> --- @copyright 2015 Grigory Mishchenko, 2016 Emmanuel Lepage Vallee --- @classmod wibox.widget.slider ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local type = type -local color = require("gears.color") -local util = require("awful.util") -local beautiful = require("beautiful") -local base = require("wibox.widget.base") -local shape = require("gears.shape") -local capi = { - mouse = mouse, - mousegrabber = mousegrabber, - root = root, -} - -local slider = {mt={}} - ---- The slider handle shape. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_shape.svg) --- --- --- @property handle_shape --- @tparam[opt=gears shape rectangle] gears.shape shape --- @see gears.shape - ---- The slider handle color. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_color.svg) --- --- --- @property handle_color --- @param color - ---- The slider handle margins. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_margins.svg) --- --- --- @property handle_margins --- @tparam[opt={}] table margins --- @tparam[opt=0] number margins.left --- @tparam[opt=0] number margins.right --- @tparam[opt=0] number margins.top --- @tparam[opt=0] number margins.bottom - ---- The slider handle width. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_width.svg) --- --- --- @property handle_width --- @param number - ---- The handle border_color. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_border.svg) --- --- --- @property handle_border_color --- @param color - ---- The handle border width. --- @property handle_border_width --- @param[opt=0] number - ---- The bar (background) shape. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_shape.svg) --- --- --- @property bar_shape --- @tparam[opt=gears shape rectangle] gears.shape shape --- @see gears.shape - ---- The bar (background) height. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_height.svg) --- --- --- @property bar_height --- @param number - ---- The bar (background) color. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_color.svg) --- --- --- @property bar_color --- @param color - ---- The bar (background) margins. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_margins.svg) --- --- --- @property bar_margins --- @tparam[opt={}] table margins --- @tparam[opt=0] number margins.left --- @tparam[opt=0] number margins.right --- @tparam[opt=0] number margins.top --- @tparam[opt=0] number margins.bottom - ---- The bar (background) border width. --- @property bar_border_width --- @param[opt=0] numbergb - ---- The bar (background) border_color. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_border.svg) --- --- --- @property bar_border_color --- @param color - ---- The slider value. --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_slider_value.svg) --- --- --- @property value --- @param[opt=0] number - ---- The slider minimum value. --- @property minimum --- @param[opt=0] number - ---- The slider maximum value. --- @property maximum --- @param[opt=100] number - ---- The bar (background) border width. --- @beautiful beautiful.slider_bar_border_width --- @param number - ---- The bar (background) border color. --- @beautiful beautiful.slider_bar_border_color --- @param color - ---- The handle border_color. --- @beautiful beautiful.slider_handle_border_color --- @param color - ---- The handle border width. --- @beautiful beautiful.slider_handle_border_width --- @param number - ---- The handle . --- @beautiful beautiful.slider_handle_width --- @param number - --- @beautiful beautiful.slider_handle_color --- @param color - ---- The handle shape. --- @beautiful beautiful.slider_handle_shape --- @tparam[opt=gears shape rectangle] gears.shape shape --- @see gears.shape - ---- The bar (background) shape. --- @beautiful beautiful.slider_bar_shape --- @tparam[opt=gears shape rectangle] gears.shape shape --- @see gears.shape - ---- The bar (background) height. --- @beautiful beautiful.slider_bar_height --- @param number - ---- The bar (background) margins. --- @beautiful beautiful.slider_bar_margins --- @tparam[opt={}] table margins --- @tparam[opt=0] number margins.left --- @tparam[opt=0] number margins.right --- @tparam[opt=0] number margins.top --- @tparam[opt=0] number margins.bottom - ---- The slider handle margins. --- @beautiful beautiful.slider_handle_margins --- @tparam[opt={}] table margins --- @tparam[opt=0] number margins.left --- @tparam[opt=0] number margins.right --- @tparam[opt=0] number margins.top --- @tparam[opt=0] number margins.bottom - ---- The bar (background) color. --- @beautiful beautiful.slider_bar_color --- @param color - -local properties = { - -- Handle - handle_shape = shape.rectangle, - handle_color = false, - handle_margins = {}, - handle_width = false, - handle_border_width = 0, - handle_border_color = false, - - -- Bar - bar_shape = shape.rectangle, - bar_height = false, - bar_color = false, - bar_margins = {}, - bar_border_width = 0, - bar_border_color = false, - - -- Content - value = 0, - minimum = 0, - maximum = 100, -} - --- Create the accessors -for prop in pairs(properties) do - slider["set_"..prop] = function(self, value) - local changed = self._private[prop] ~= value - self._private[prop] = value - - if changed then - self:emit_signal("property::"..prop) - self:emit_signal("widget::redraw_needed") - end - end - - slider["get_"..prop] = function(self) - -- Ignoring the false's is on purpose - return self._private[prop] == nil - and properties[prop] - or self._private[prop] - end -end - --- Add some validation to set_value -function slider:set_value(value) - value = math.min(value, self:get_maximum()) - value = math.max(value, self:get_minimum()) - local changed = self._private.value ~= value - - self._private.value = value - - if changed then - self:emit_signal( "property::value" ) - self:emit_signal( "widget::redraw_needed" ) - end -end - -local function get_extremums(self) - local min = self._private.minimum or properties.minimum - local max = self._private.maximum or properties.maximum - local interval = max - min - - return min, max, interval -end - -function slider:draw(_, cr, width, height) - local bar_height = self._private.bar_height - - -- If there is no background, then skip this - local bar_color = self._private.bar_color - or beautiful.slider_bar_color - - if bar_color then - cr:set_source(color(bar_color)) - end - - local margins = self._private.bar_margins - or beautiful.slider_bar_margins - - local x_offset, right_margin, y_offset = 0, 0 - - if margins then - if type(margins) == "number" then - bar_height = bar_height or (height - 2*margins) - x_offset, y_offset = margins, margins - right_margin = margins - else - bar_height = bar_height or ( - height - (margins.top or 0) - (margins.bottom or 0) - ) - x_offset, y_offset = margins.left or 0, margins.top or 0 - right_margin = margins.right or 0 - end - else - bar_height = bar_height or beautiful.slider_bar_height or height - y_offset = (height - bar_height)/2 - end - - - cr:translate(x_offset, y_offset) - - local bar_shape = self._private.bar_shape - or beautiful.slider_bar_shape - or properties.bar_shape - - local bar_border_width = self._private.bar_border_width - or beautiful.slider_bar_border_width - or properties.bar_border_width - - bar_shape(cr, width - x_offset - right_margin, bar_height or height) - - if bar_color then - if bar_border_width == 0 then - cr:fill() - else - cr:fill_preserve() - end - end - - -- Draw the bar border - if bar_border_width > 0 then - local bar_border_color = self._private.bar_border_color - or beautiful.slider_bar_border_color - or properties.bar_border_color - - cr:set_line_width(bar_border_width) - - if bar_border_color then - cr:save() - cr:set_source(color(bar_border_color)) - cr:stroke() - cr:restore() - else - cr:stroke() - end - end - - cr:translate(-x_offset, -y_offset) - - -- Paint the handle - local handle_color = self._private.handle_color - or beautiful.slider_handle_color - - -- It is ok if there is no color, it will be inherited - if handle_color then - cr:set_source(color(handle_color)) - end - - local handle_height, handle_width = height, self._private.handle_width - or beautiful.slider_handle_width - or height/2 - - local handle_shape = self._private.handle_shape - or beautiful.slider_handle_shape - or properties.handle_shape - - -- Lets get the margins for the handle - margins = self._private.handle_margins - or beautiful.slider_handle_margins - - x_offset, y_offset = 0, 0 - - if margins then - if type(margins) == "number" then - x_offset, y_offset = margins, margins - handle_width = handle_width - 2*margins - handle_height = handle_height - 2*margins - else - x_offset, y_offset = margins.left or 0, margins.top or 0 - handle_width = handle_width - - (margins.left or 0) - (margins.right or 0) - handle_height = handle_height - - (margins.top or 0) - (margins.bottom or 0) - end - end - - local value = self._private.value or self._private.min or 0 - - -- Get the widget size back to it's non-transfored value - local min, _, interval = get_extremums(self) - local rel_value = ((value-min)/interval) * (width-handle_width) - - cr:translate(x_offset + rel_value, y_offset) - - local handle_border_width = self._private.handle_border_width - or beautiful.slider_handle_border_width - or properties.handle_border_width or 0 - - handle_shape(cr, handle_width, handle_height) - - if handle_border_width > 0 then - cr:fill_preserve() - else - cr:fill() - end - - -- Draw the handle border - if handle_border_width > 0 then - local handle_border_color = self._private.handle_border_color - or beautiful.slider_handle_border_color - or properties.handle_border_color - - if handle_border_color then - cr:set_source(color(handle_border_color)) - end - - cr:set_line_width(handle_border_width) - cr:stroke() - end -end - -function slider:fit(_, width, height) - -- Use all the space, this should be used with a constraint widget - return width, height -end - --- Move the handle to the correct location -local function move_handle(self, width, x, _) - local _, _, interval = get_extremums(self) - self:set_value(math.floor((x*interval)/width)) -end - -local function mouse_press(self, x, y, button_id, _, geo) - if button_id ~= 1 then return end - - local matrix_from_device = geo.hierarchy:get_matrix_from_device() - - -- Sigh. geo.width/geo.height is in device space. We need it in our own - -- coordinate system - local width = geo.widget_width - - move_handle(self, width, x, y) - - -- Calculate a matrix transforming from screen coordinates into widget coordinates - local wgeo = geo.drawable.drawable:geometry() - local matrix = matrix_from_device:translate(-wgeo.x, -wgeo.y) - - capi.mousegrabber.run(function(mouse) - if not mouse.buttons[1] then - return false - end - - -- Calculate the point relative to the widget - move_handle(self, width, matrix:transform_point(mouse.x, mouse.y)) - - return true - end,"fleur") -end - ---- Create a slider widget. --- @tparam[opt={}] table args --- @function wibox.widget.slider -local function new(args) - local ret = base.make_widget(nil, nil, { - enable_properties = true, - }) - - util.table.crush(ret._private, args or {}) - - util.table.crush(ret, slider, true) - - ret:connect_signal("button::press", mouse_press) - - return ret -end - -function slider.mt:__call(_, ...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(slider, slider.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/systray.lua b/awesome/lib/wibox/widget/systray.lua deleted file mode 100644 index e83347c..0000000 --- a/awesome/lib/wibox/widget/systray.lua +++ /dev/null @@ -1,186 +0,0 @@ ---------------------------------------------------------------------------- --- @author Uli Schlachter --- @copyright 2010 Uli Schlachter --- @classmod wibox.widget.systray ---------------------------------------------------------------------------- - -local wbase = require("wibox.widget.base") -local beautiful = require("beautiful") -local util = require("awful.util") -local capi = { - awesome = awesome, - screen = screen -} -local setmetatable = setmetatable -local error = error -local abs = math.abs - -local systray = { mt = {} } - -local instance = nil -local horizontal = true -local base_size = nil -local reverse = false -local display_on_screen = "primary" - ---- The systray background color. --- @beautiful beautiful.bg_systray --- @param string The color (string like "#ff0000" only) - ---- The systray icon spacing. --- @beautiful beautiful.systray_icon_spacing --- @tparam[opt=0] integer The icon spacing - -local function should_display_on(s) - if display_on_screen == "primary" then - return s == capi.screen.primary - end - return s == display_on_screen -end - -function systray:draw(context, cr, width, height) - if not should_display_on(context.screen) then - return - end - - local x, y, _, _ = wbase.rect_to_device_geometry(cr, 0, 0, width, height) - local num_entries = capi.awesome.systray() - local bg = beautiful.bg_systray or beautiful.bg_normal or "#000000" - local spacing = beautiful.systray_icon_spacing or 0 - - if context and not context.wibox then - error("The systray widget can only be placed inside a wibox.") - end - - -- Figure out if the cairo context is rotated - local dir_x, dir_y = cr:user_to_device_distance(1, 0) - local is_rotated = abs(dir_x) < abs(dir_y) - - local in_dir, ortho, base - if horizontal then - in_dir, ortho = width, height - is_rotated = not is_rotated - else - ortho, in_dir = width, height - end - if ortho * num_entries <= in_dir then - base = ortho - else - base = in_dir / num_entries - end - capi.awesome.systray(context.wibox.drawin, math.ceil(x), math.ceil(y), - base, is_rotated, bg, reverse, spacing) -end - -function systray:fit(context, width, height) - if not should_display_on(context.screen) then - return 0, 0 - end - - local num_entries = capi.awesome.systray() - local base = base_size - local spacing = beautiful.systray_icon_spacing or 0 - if num_entries == 0 then - return 0, 0 - end - if base == nil then - if width < height then - base = width - else - base = height - end - end - base = base + spacing - if horizontal then - return base * num_entries - spacing, base - end - return base, base * num_entries - spacing -end - --- Check if the function was called like :foo() or .foo() and do the right thing -local function get_args(self, ...) - if self == instance then - return ... - end - return self, ... -end - ---- Set the size of a single icon. --- If this is set to nil, then the size is picked dynamically based on the --- available space. Otherwise, any single icon has a size of `size`x`size`. --- @tparam integer|nil size The base size -function systray:set_base_size(size) - base_size = get_args(self, size) - if instance then - instance:emit_signal("widget::layout_changed") - end -end - ---- Decide between horizontal or vertical display. --- @tparam boolean horiz Use horizontal mode? -function systray:set_horizontal(horiz) - horizontal = get_args(self, horiz) - if instance then - instance:emit_signal("widget::layout_changed") - end -end - ---- Should the systray icons be displayed in reverse order? --- @tparam boolean rev Display in reverse order -function systray:set_reverse(rev) - reverse = get_args(self, rev) - if instance then - instance:emit_signal("widget::redraw_needed") - end -end - ---- Set the screen that the systray should be displayed on. --- This can either be a screen, in which case the systray will be displayed on --- exactly that screen, or the string `"primary"`, in which case it will be --- visible on the primary screen. The default value is "primary". --- @tparam screen|"primary" s The screen to display on. -function systray:set_screen(s) - display_on_screen = get_args(self, s) - if instance then - instance:emit_signal("widget::layout_changed") - end -end - ---- Create the systray widget. --- Note that this widget can only exist once. --- @tparam boolean revers Show in the opposite direction --- @treturn table The new `systray` widget --- @function wibox.widget.systray - -local function new(revers) - local ret = wbase.make_widget() - - util.table.crush(ret, systray, true) - - if revers then - ret:set_reverse(true) - end - - capi.awesome.connect_signal("systray::update", function() - ret:emit_signal("widget::layout_changed") - ret:emit_signal("widget::redraw_needed") - end) - capi.screen.connect_signal("primary_changed", function() - if display_on_screen == "primary" then - ret:emit_signal("widget::layout_changed") - end - end) - - return ret -end - -function systray.mt:__call(...) - if not instance then - instance = new(...) - end - return instance -end - -return setmetatable(systray, systray.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/textbox.lua b/awesome/lib/wibox/widget/textbox.lua deleted file mode 100644 index add35e9..0000000 --- a/awesome/lib/wibox/widget/textbox.lua +++ /dev/null @@ -1,507 +0,0 @@ ---------------------------------------------------------------------------- --- --- --- ---![Usage example](../images/AUTOGEN_wibox_widget_defaults_textbox.svg) --- --- @usage ---wibox.widget{ --- markup = 'This <i>is</i> a <b>textbox</b>!!!', --- align = 'center', --- valign = 'center', --- widget = wibox.widget.textbox ---} --- @author Uli Schlachter --- @author dodo --- @copyright 2010, 2011 Uli Schlachter, dodo --- @classmod wibox.widget.textbox ---------------------------------------------------------------------------- - -local base = require("wibox.widget.base") -local gdebug = require("gears.debug") -local beautiful = require("beautiful") -local lgi = require("lgi") -local util = require("awful.util") -local Pango = lgi.Pango -local PangoCairo = lgi.PangoCairo -local setmetatable = setmetatable - -local textbox = { mt = {} } - ---- The textbox font. --- @beautiful beautiful.font - ---- Set the DPI of a Pango layout -local function setup_dpi(box, dpi) - if box._private.dpi ~= dpi then - box._private.dpi = dpi - box._private.ctx:set_resolution(dpi) - box._private.layout:context_changed() - end -end - ---- Setup a pango layout for the given textbox and dpi -local function setup_layout(box, width, height, dpi) - box._private.layout.width = Pango.units_from_double(width) - box._private.layout.height = Pango.units_from_double(height) - setup_dpi(box, dpi) -end - --- Draw the given textbox on the given cairo context in the given geometry -function textbox:draw(context, cr, width, height) - setup_layout(self, width, height, context.dpi) - cr:update_layout(self._private.layout) - local _, logical = self._private.layout:get_pixel_extents() - local offset = 0 - if self._private.valign == "center" then - offset = (height - logical.height) / 2 - elseif self._private.valign == "bottom" then - offset = height - logical.height - end - cr:move_to(0, offset) - cr:show_layout(self._private.layout) -end - -local function do_fit_return(self) - local _, logical = self._private.layout:get_pixel_extents() - if logical.width == 0 or logical.height == 0 then - return 0, 0 - end - return logical.width, logical.height -end - --- Fit the given textbox -function textbox:fit(context, width, height) - setup_layout(self, width, height, context.dpi) - return do_fit_return(self) -end - ---- Get the preferred size of a textbox. --- This returns the size that the textbox would use if infinite space were --- available. --- @tparam integer|screen s The screen on which the textbox will be displayed. --- @treturn number The preferred width. --- @treturn number The preferred height. -function textbox:get_preferred_size(s) - return self:get_preferred_size_at_dpi(beautiful.xresources.get_dpi(s)) -end - ---- Get the preferred height of a textbox at a given width. --- This returns the height that the textbox would use when it is limited to the --- given width. --- @tparam number width The available width. --- @tparam integer|screen s The screen on which the textbox will be displayed. --- @treturn number The needed height. -function textbox:get_height_for_width(width, s) - return self:get_height_for_width_at_dpi(width, beautiful.xresources.get_dpi(s)) -end - ---- Get the preferred size of a textbox. --- This returns the size that the textbox would use if infinite space were --- available. --- @tparam number dpi The DPI value to render at. --- @treturn number The preferred width. --- @treturn number The preferred height. -function textbox:get_preferred_size_at_dpi(dpi) - local max_lines = 2^20 - setup_dpi(self, dpi) - self._private.layout.width = -1 -- no width set - self._private.layout.height = -max_lines -- show this many lines per paragraph - return do_fit_return(self) -end - ---- Get the preferred height of a textbox at a given width. --- This returns the height that the textbox would use when it is limited to the --- given width. --- @tparam number width The available width. --- @tparam number dpi The DPI value to render at. --- @treturn number The needed height. -function textbox:get_height_for_width_at_dpi(width, dpi) - local max_lines = 2^20 - setup_dpi(self, dpi) - self._private.layout.width = Pango.units_from_double(width) - self._private.layout.height = -max_lines -- show this many lines per paragraph - local _, h = do_fit_return(self) - return h -end - ---- Set the text of the textbox (with --- [Pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html)). --- @tparam string text The text to set. This can contain pango markup (e.g. --- `<b>bold</b>`). You can use `awful.util.escape` to escape --- parts of it. --- @treturn[1] boolean true --- @treturn[2] boolean false --- @treturn[2] string Error message explaining why the markup was invalid. -function textbox:set_markup_silently(text) - if self._private.markup == text then - return true - end - - local attr, parsed = Pango.parse_markup(text, -1, 0) - -- In case of error, attr is false and parsed is a GLib.Error instance. - if not attr then - return false, parsed.message or tostring(parsed) - end - - self._private.markup = text - self._private.layout.text = parsed - self._private.layout.attributes = attr - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - return true -end - ---- Set the text of the textbox (with --- [Pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html)). --- @property markup --- @tparam string text The text to set. This can contain pango markup (e.g. --- `<b>bold</b>`). You can use `awful.util.escape` to escape --- parts of it. --- @see text - -function textbox:set_markup(text) - local success, message = self:set_markup_silently(text) - if not success then - gdebug.print_error(message) - end -end - -function textbox:get_markup() - return self._private.markup -end - ---- Set a textbox' text. --- @property text --- @param text The text to display. Pango markup is ignored and shown as-is. --- @see markup - -function textbox:set_text(text) - if self._private.layout.text == text and self._private.layout.attributes == nil then - return - end - self._private.markup = nil - self._private.layout.text = text - self._private.layout.attributes = nil - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") -end - -function textbox:get_text() - return self._private.layout.text -end - ---- Set a textbox' ellipsize mode. --- @property ellipsize --- @param mode Where should long lines be shortened? "start", "middle" or "end" - -function textbox:set_ellipsize(mode) - local allowed = { none = "NONE", start = "START", middle = "MIDDLE", ["end"] = "END" } - if allowed[mode] then - if self._private.layout:get_ellipsize() == allowed[mode] then - return - end - self._private.layout:set_ellipsize(allowed[mode]) - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - end -end - ---- Set a textbox' wrap mode. --- @property wrap --- @param mode Where to wrap? After "word", "char" or "word_char" - -function textbox:set_wrap(mode) - local allowed = { word = "WORD", char = "CHAR", word_char = "WORD_CHAR" } - if allowed[mode] then - if self._private.layout:get_wrap() == allowed[mode] then - return - end - self._private.layout:set_wrap(allowed[mode]) - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - end -end - ---- The textbox' vertical alignment --- @property valign --- @param mode Where should the textbox be drawn? "top", "center" or "bottom" - -function textbox:set_valign(mode) - local allowed = { top = true, center = true, bottom = true } - if allowed[mode] then - if self._private.valign == mode then - return - end - self._private.valign = mode - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - end -end - ---- Set a textbox' horizontal alignment. --- @property align --- @param mode Where should the textbox be drawn? "left", "center" or "right" - -function textbox:set_align(mode) - local allowed = { left = "LEFT", center = "CENTER", right = "RIGHT" } - if allowed[mode] then - if self._private.layout:get_alignment() == allowed[mode] then - return - end - self._private.layout:set_alignment(allowed[mode]) - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") - end -end - ---- Set a textbox' font --- @property font --- @param font The font description as string - -function textbox:set_font(font) - self._private.layout:set_font_description(beautiful.get_font(font)) - self:emit_signal("widget::redraw_needed") - self:emit_signal("widget::layout_changed") -end - ---- Create a new textbox. --- @tparam[opt=""] string text The textbox content --- @tparam[opt=false] boolean ignore_markup Ignore the pango/HTML markup --- @treturn table A new textbox widget --- @function wibox.widget.textbox -local function new(text, ignore_markup) - local ret = base.make_widget(nil, nil, {enable_properties = true}) - - util.table.crush(ret, textbox, true) - - ret._private.dpi = -1 - ret._private.ctx = PangoCairo.font_map_get_default():create_context() - ret._private.layout = Pango.Layout.new(ret._private.ctx) - - ret:set_ellipsize("end") - ret:set_wrap("word_char") - ret:set_valign("center") - ret:set_align("left") - ret:set_font(beautiful and beautiful.font) - - if text then - if ignore_markup then - ret:set_text(text) - else - ret:set_markup(text) - end - end - - return ret -end - -function textbox.mt.__call(_, ...) - return new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(textbox, textbox.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/lib/wibox/widget/textclock.lua b/awesome/lib/wibox/widget/textclock.lua deleted file mode 100644 index c688028..0000000 --- a/awesome/lib/wibox/widget/textclock.lua +++ /dev/null @@ -1,254 +0,0 @@ ---------------------------------------------------------------------------- ---- Text clock widget. --- --- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou --- @classmod wibox.widget.textclock ---------------------------------------------------------------------------- - -local setmetatable = setmetatable -local os = os -local textbox = require("wibox.widget.textbox") -local timer = require("gears.timer") -local DateTime = require("lgi").GLib.DateTime - -local textclock = { mt = {} } - ---- This lowers the timeout so that it occurs "correctly". For example, a timeout --- of 60 is rounded so that it occurs the next time the clock reads ":00 seconds". -local function calc_timeout(real_timeout) - return real_timeout - os.time() % real_timeout -end - ---- Create a textclock widget. It draws the time it is in a textbox. --- --- @tparam[opt=" %a %b %d, %H:%M "] string format The time format. --- @tparam[opt=60] number timeout How often update the time (in seconds). --- @treturn table A textbox widget. --- @function wibox.widget.textclock -function textclock.new(format, timeout) - format = format or " %a %b %d, %H:%M " - timeout = timeout or 60 - - local w = textbox() - local t - function w._private.textclock_update_cb() - w:set_markup(DateTime.new_now_local():format(format)) - t.timeout = calc_timeout(timeout) - t:again() - return true -- Continue the timer - end - t = timer.weak_start_new(timeout, w._private.textclock_update_cb) - t:emit_signal("timeout") - return w -end - -function textclock.mt:__call(...) - return textclock.new(...) -end - ---Imported documentation - - ---- Get a widex index. --- @param widget The widget to look for --- @param[opt] recursive Also check sub-widgets --- @param[opt] ... Aditional widgets to add at the end of the \"path\" --- @return The index --- @return The parent layout --- @return The path between \"self\" and \"widget\" --- @function index - ---- Get all direct and indirect children widgets. --- This will scan all containers recursively to find widgets --- Warning: This method it prone to stack overflow id the widget, or any of its --- children, contain (directly or indirectly) itself. --- @treturn table The children --- @function get_all_children - ---- Set a declarative widget hierarchy description. --- See [The declarative layout system](../documentation/03-declarative-layout.md.html) --- @param args An array containing the widgets disposition --- @function setup - ---- Force a widget height. --- @property forced_height --- @tparam number|nil height The height (`nil` for automatic) - ---- Force a widget width. --- @property forced_width --- @tparam number|nil width The width (`nil` for automatic) - ---- The widget opacity (transparency). --- @property opacity --- @tparam[opt=1] number opacity The opacity (between 0 and 1) - ---- The widget visibility. --- @property visible --- @param boolean - ---- Set/get a widget's buttons. --- @param _buttons The table of buttons that should bind to the widget. --- @function buttons - ---- Emit a signal and ensure all parent widgets in the hierarchies also --- forward the signal. This is useful to track signals when there is a dynamic --- set of containers and layouts wrapping the widget. --- @tparam string signal_name --- @param ... Other arguments --- @function emit_signal_recursive - ---- When the layout (size) change. --- This signal is emitted when the previous results of `:layout()` and `:fit()` --- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()` --- must return the same result when called with the same arguments. --- @signal widget::layout_changed --- @see widget::redraw_needed - ---- When the widget content changed. --- This signal is emitted when the content of the widget changes. The widget will --- be redrawn, it is not re-layouted. Put differently, it is assumed that --- `:layout()` and `:fit()` would still return the same results as before. --- @signal widget::redraw_needed --- @see widget::layout_changed - ---- When a mouse button is pressed over the widget. --- @signal button::press --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When a mouse button is released over the widget. --- @signal button::release --- @tparam number lx The horizontal position relative to the (0,0) position in --- the widget. --- @tparam number ly The vertical position relative to the (0,0) position in the --- widget. --- @tparam number button The button number. --- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse enter a widget. --- @signal mouse::enter --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - ---- When the mouse leave a widget. --- @signal mouse::leave --- @tparam table find_widgets_result The entry from the result of --- @{wibox.drawable:find_widgets} for the position that the mouse hit. --- @tparam wibox.drawable find_widgets_result.drawable The drawable containing --- the widget. --- @tparam widget find_widgets_result.widget The widget being displayed. --- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy --- managing the widget's geometry. --- @tparam number find_widgets_result.x An approximation of the X position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.y An approximation of the Y position that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.width An approximation of the width that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.height An approximation of the height that --- the widget is visible at on the surface. --- @tparam number find_widgets_result.widget_width The exact width of the widget --- in its local coordinate system. --- @tparam number find_widgets_result.widget_height The exact height of the widget --- in its local coordinate system. --- @see mouse - - ---Imported documentation - - ---- Disconnect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback that should be disconnected --- @function disconnect_signal - ---- Emit a signal. --- --- @tparam string name The name of the signal --- @param ... Extra arguments for the callback functions. Each connected --- function receives the object as first argument and then any extra arguments --- that are given to emit_signal() --- @function emit_signal - ---- Connect to a signal. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function connect_signal - ---- Connect to a signal weakly. This allows the callback function to be garbage --- collected and automatically disconnects the signal when that happens. --- --- **Warning:** --- Only use this function if you really, really, really know what you --- are doing. --- @tparam string name The name of the signal --- @tparam function func The callback to call when the signal is emitted --- @function weak_connect_signal - - -return setmetatable(textclock, textclock.mt) - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 |