Merge pull request #2894 from Elv13/xmas_2k18_2_merge_p3
API standardization part 2
This commit is contained in:
commit
9bc6d4aa40
145
awesomerc.lua
145
awesomerc.lua
|
@ -219,25 +219,56 @@ end)
|
|||
|
||||
-- {{{ Mouse bindings
|
||||
-- @DOC_ROOT_BUTTONS@
|
||||
root.buttons = {
|
||||
awful.mouse.append_global_mousebindings({
|
||||
awful.button({ }, 3, function () mymainmenu:toggle() end),
|
||||
awful.button({ }, 4, awful.tag.viewnext),
|
||||
awful.button({ }, 5, awful.tag.viewprev),
|
||||
}
|
||||
})
|
||||
-- }}}
|
||||
|
||||
-- {{{ Key bindings
|
||||
-- @DOC_GLOBAL_KEYBINDINGS@
|
||||
globalkeys = {
|
||||
|
||||
-- General Awesome keys
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({ modkey, }, "s", hotkeys_popup.show_help,
|
||||
{description="show help", group="awesome"}),
|
||||
awful.key({ modkey, }, "w", function () mymainmenu:show() end,
|
||||
{description = "show main menu", group = "awesome"}),
|
||||
awful.key({ modkey, "Control" }, "r", awesome.restart,
|
||||
{description = "reload awesome", group = "awesome"}),
|
||||
awful.key({ modkey, "Shift" }, "q", awesome.quit,
|
||||
{description = "quit awesome", group = "awesome"}),
|
||||
awful.key({ modkey }, "x",
|
||||
function ()
|
||||
awful.prompt.run {
|
||||
prompt = "Run Lua code: ",
|
||||
textbox = awful.screen.focused().mypromptbox.widget,
|
||||
exe_callback = awful.util.eval,
|
||||
history_path = awful.util.get_cache_dir() .. "/history_eval"
|
||||
}
|
||||
end,
|
||||
{description = "lua execute prompt", group = "awesome"}),
|
||||
awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
|
||||
{description = "open a terminal", group = "launcher"}),
|
||||
awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
|
||||
{description = "run prompt", group = "launcher"}),
|
||||
awful.key({ modkey }, "p", function() menubar.show() end,
|
||||
{description = "show the menubar", group = "launcher"}),
|
||||
})
|
||||
|
||||
-- Tags related keybindings
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({ modkey, }, "Left", awful.tag.viewprev,
|
||||
{description = "view previous", group = "tag"}),
|
||||
awful.key({ modkey, }, "Right", awful.tag.viewnext,
|
||||
{description = "view next", group = "tag"}),
|
||||
awful.key({ modkey, }, "Escape", awful.tag.history.restore,
|
||||
{description = "go back", group = "tag"}),
|
||||
})
|
||||
|
||||
-- Focus related keybindings
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({ modkey, }, "j",
|
||||
function ()
|
||||
awful.client.focus.byidx( 1)
|
||||
|
@ -250,20 +281,6 @@ globalkeys = {
|
|||
end,
|
||||
{description = "focus previous by index", group = "client"}
|
||||
),
|
||||
awful.key({ modkey, }, "w", function () mymainmenu:show() end,
|
||||
{description = "show main menu", group = "awesome"}),
|
||||
|
||||
-- Layout manipulation
|
||||
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
|
||||
{description = "swap with next client by index", group = "client"}),
|
||||
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
|
||||
{description = "swap with previous client by index", group = "client"}),
|
||||
awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
|
||||
{description = "focus the next screen", group = "screen"}),
|
||||
awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
|
||||
{description = "focus the previous screen", group = "screen"}),
|
||||
awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
|
||||
{description = "jump to urgent client", group = "client"}),
|
||||
awful.key({ modkey, }, "Tab",
|
||||
function ()
|
||||
awful.client.focus.history.previous()
|
||||
|
@ -272,15 +289,31 @@ globalkeys = {
|
|||
end
|
||||
end,
|
||||
{description = "go back", group = "client"}),
|
||||
awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
|
||||
{description = "focus the next screen", group = "screen"}),
|
||||
awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
|
||||
{description = "focus the previous screen", group = "screen"}),
|
||||
awful.key({ modkey, "Control" }, "n",
|
||||
function ()
|
||||
local c = awful.client.restore()
|
||||
-- Focus restored client
|
||||
if c then
|
||||
c:emit_signal(
|
||||
"request::activate", "key.unminimize", {raise = true}
|
||||
)
|
||||
end
|
||||
end,
|
||||
{description = "restore minimized", group = "client"}),
|
||||
})
|
||||
|
||||
-- Standard program
|
||||
awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
|
||||
{description = "open a terminal", group = "launcher"}),
|
||||
awful.key({ modkey, "Control" }, "r", awesome.restart,
|
||||
{description = "reload awesome", group = "awesome"}),
|
||||
awful.key({ modkey, "Shift" }, "q", awesome.quit,
|
||||
{description = "quit awesome", group = "awesome"}),
|
||||
|
||||
-- Layout related keybindings
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
|
||||
{description = "swap with next client by index", group = "client"}),
|
||||
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
|
||||
{description = "swap with previous client by index", group = "client"}),
|
||||
awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
|
||||
{description = "jump to urgent client", group = "client"}),
|
||||
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
|
||||
{description = "increase master width factor", group = "layout"}),
|
||||
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
|
||||
|
@ -297,37 +330,7 @@ globalkeys = {
|
|||
{description = "select next", group = "layout"}),
|
||||
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
|
||||
{description = "select previous", group = "layout"}),
|
||||
|
||||
awful.key({ modkey, "Control" }, "n",
|
||||
function ()
|
||||
local c = awful.client.restore()
|
||||
-- Focus restored client
|
||||
if c then
|
||||
c:emit_signal(
|
||||
"request::activate", "key.unminimize", {raise = true}
|
||||
)
|
||||
end
|
||||
end,
|
||||
{description = "restore minimized", group = "client"}),
|
||||
|
||||
-- Prompt
|
||||
awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
|
||||
{description = "run prompt", group = "launcher"}),
|
||||
|
||||
awful.key({ modkey }, "x",
|
||||
function ()
|
||||
awful.prompt.run {
|
||||
prompt = "Run Lua code: ",
|
||||
textbox = awful.screen.focused().mypromptbox.widget,
|
||||
exe_callback = awful.util.eval,
|
||||
history_path = awful.util.get_cache_dir() .. "/history_eval"
|
||||
}
|
||||
end,
|
||||
{description = "lua execute prompt", group = "awesome"}),
|
||||
-- Menubar
|
||||
awful.key({ modkey }, "p", function() menubar.show() end,
|
||||
{description = "show the menubar", group = "launcher"}),
|
||||
}
|
||||
})
|
||||
|
||||
-- @DOC_CLIENT_KEYBINDINGS@
|
||||
clientkeys = {
|
||||
|
@ -380,7 +383,8 @@ clientkeys = {
|
|||
-- This should map on the top row of your keyboard, usually 1 to 9.
|
||||
for i = 1, 9 do
|
||||
-- View tag only.
|
||||
table.insert(globalkeys, awful.key({ modkey }, "#" .. i + 9,
|
||||
awful.keyboard.append_global_keybinding(awful.key(
|
||||
{ modkey }, "#" .. i + 9,
|
||||
function ()
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[i]
|
||||
|
@ -388,11 +392,12 @@ for i = 1, 9 do
|
|||
tag:view_only()
|
||||
end
|
||||
end,
|
||||
{description = "view tag #"..i, group = "tag"})
|
||||
)
|
||||
{description = "view tag #"..i, group = "tag"}
|
||||
))
|
||||
|
||||
-- Toggle tag display.
|
||||
table.insert(globalkeys, awful.key({ modkey, "Control" }, "#" .. i + 9,
|
||||
awful.keyboard.append_global_keybinding(awful.key(
|
||||
{ modkey, "Control" }, "#" .. i + 9,
|
||||
function ()
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[i]
|
||||
|
@ -400,11 +405,12 @@ for i = 1, 9 do
|
|||
awful.tag.viewtoggle(tag)
|
||||
end
|
||||
end,
|
||||
{description = "toggle tag #" .. i, group = "tag"})
|
||||
)
|
||||
{description = "toggle tag #" .. i, group = "tag"}
|
||||
))
|
||||
|
||||
-- Move client to tag.
|
||||
table.insert(globalkeys, awful.key({ modkey, "Shift" }, "#" .. i + 9,
|
||||
awful.keyboard.append_global_keybinding(awful.key(
|
||||
{ modkey, "Shift" }, "#" .. i + 9,
|
||||
function ()
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[i]
|
||||
|
@ -413,11 +419,12 @@ for i = 1, 9 do
|
|||
end
|
||||
end
|
||||
end,
|
||||
{description = "move focused client to tag #"..i, group = "tag"})
|
||||
)
|
||||
{description = "move focused client to tag #"..i, group = "tag"}
|
||||
))
|
||||
|
||||
-- Toggle tag on focused client.
|
||||
table.insert(globalkeys, awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
|
||||
awful.keyboard.append_global_keybinding(awful.key(
|
||||
{ modkey, "Control", "Shift" }, "#" .. i + 9,
|
||||
function ()
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[i]
|
||||
|
@ -426,8 +433,8 @@ for i = 1, 9 do
|
|||
end
|
||||
end
|
||||
end,
|
||||
{description = "toggle focused client on tag #" .. i, group = "tag"})
|
||||
)
|
||||
{description = "toggle focused client on tag #" .. i, group = "tag"}
|
||||
))
|
||||
end
|
||||
|
||||
-- @DOC_CLIENT_BUTTONS@
|
||||
|
@ -445,8 +452,6 @@ clientbuttons = {
|
|||
end),
|
||||
}
|
||||
|
||||
-- Set keys
|
||||
root.keys = globalkeys
|
||||
-- }}}
|
||||
|
||||
-- {{{ Rules
|
||||
|
|
|
@ -437,16 +437,23 @@ luaA_class_index(lua_State *L)
|
|||
|
||||
lua_class_property_t *prop = luaA_class_property_get(L, class, 2);
|
||||
|
||||
/* Is this the special 'data' property? This is available on all objects and
|
||||
* thus not implemented as a lua_class_property_t.
|
||||
/* This is the table storing the object private variables.
|
||||
*/
|
||||
if (A_STREQ(attr, "data"))
|
||||
if (A_STREQ(attr, "_private"))
|
||||
{
|
||||
luaA_checkudata(L, 1, class);
|
||||
luaA_getuservalue(L, 1);
|
||||
lua_getfield(L, -1, "data");
|
||||
return 1;
|
||||
}
|
||||
else if (A_STREQ(attr, "data"))
|
||||
{
|
||||
luaA_deprecate(L, "Use `._private` instead of `.data`");
|
||||
luaA_checkudata(L, 1, class);
|
||||
luaA_getuservalue(L, 1);
|
||||
lua_getfield(L, -1, "data");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Property does exist and has an index callback */
|
||||
if(prop)
|
||||
|
|
|
@ -69,4 +69,6 @@
|
|||
-- <tr><td><a href='../core_components/client.html#startup_id'>startup\_id</a></td><td>The FreeDesktop StartId</td></tr>
|
||||
-- <tr><td><a href='../core_components/client.html#valid'>valid</a></td><td>If the client that this object refers to is still managed by awesome</td></tr>
|
||||
-- <tr><td><a href='../core_components/client.html#first_tag'>first\_tag</a></td><td>The first tag of the client</td></tr>
|
||||
-- <tr><td><a href='../core_components/client.html#buttons'>buttons</a></td><td>Get or set mouse buttons bindings for a client</td></tr>
|
||||
-- <tr><td><a href='../core_components/client.html#keys'>keys</a></td><td>Get or set keys bindings for a client</td></tr>
|
||||
-- </table>
|
||||
|
|
|
@ -54,6 +54,7 @@ tparam_alias('screen_or_idx', 'screen|int')
|
|||
|
||||
-- The first stereotype are the constructors.
|
||||
new_type("constructorfct", "Constructors", false, "Parameters")
|
||||
new_type("constructorfct2", "ldoc_skip", false, "Parameters")
|
||||
-- Hack to get the functions on top of the signals and properties
|
||||
new_type("function", "Functions", false, "Parameters")
|
||||
-- For "classes", use an explicit type for static functions. This allows
|
||||
|
@ -100,6 +101,7 @@ sort_modules=true
|
|||
|
||||
-- Add more project level (left side index) types.
|
||||
new_type("coreclassmod", "Core_components" , true)
|
||||
new_type("inputmodule" , "Input handling" , true)
|
||||
new_type("widgetmod" , "Widgets" , true)
|
||||
new_type("containermod", "Widget_containers", true)
|
||||
new_type("layoutmod" , "Widget_layouts" , true)
|
||||
|
@ -266,6 +268,7 @@ local coreclassmap = {
|
|||
local add_mod = {
|
||||
["function"] = true,
|
||||
constructorfct = true,
|
||||
constructorfct2 = true,
|
||||
staticfct = true,
|
||||
deprecated = true,
|
||||
field = true,
|
||||
|
@ -274,6 +277,7 @@ local add_mod = {
|
|||
-- Add the arguments.
|
||||
local add_args = {
|
||||
constructorfct = true,
|
||||
constructorfct2 = true,
|
||||
staticfct = true,
|
||||
}
|
||||
|
||||
|
@ -289,6 +293,7 @@ local display_type = {
|
|||
local show_return = {
|
||||
["function"] = true,
|
||||
constructorfct = true,
|
||||
constructorfct2 = true,
|
||||
staticfct = true,
|
||||
method = true,
|
||||
deprecated = true,
|
||||
|
|
|
@ -49,22 +49,28 @@
|
|||
<h2>Contents</h2>
|
||||
<ul>
|
||||
# for kind,items in module.kinds() do
|
||||
# if not kind:match("^ldoc_skip") then
|
||||
<li><a href="#$(no_spaces(kind))">$(kind)</a></li>
|
||||
# end
|
||||
# end
|
||||
</ul>
|
||||
# end
|
||||
|
||||
|
||||
# if ldoc.no_summary and module and not ldoc.one then -- bang out the functions on the side
|
||||
# for kind, items in module.kinds() do
|
||||
<h2>$(kind)</h2>
|
||||
# if not kind:match("^ldoc_skip") then
|
||||
<h2>$(kind)dasdasd</h2>
|
||||
<ul class="nowrap">
|
||||
# end
|
||||
# for item in items() do
|
||||
<li><a href="#$(item.name)">$(display_name(item))</a></li>
|
||||
# end
|
||||
# if not kind:match("^ldoc_skip") then
|
||||
</ul>
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# -------- contents of project ----------
|
||||
# local this_mod = module and module.name
|
||||
# for kind, mods, type in ldoc.kinds() do
|
||||
|
@ -125,9 +131,15 @@
|
|||
|
||||
# if not ldoc.no_summary then
|
||||
# -- bang out the tables of item types for this module (e.g Functions, Tables, etc)
|
||||
# local last_kind = ""
|
||||
# for kind,items in module.kinds() do
|
||||
# if not kind:match("^ldoc_skip") then
|
||||
# if last_kind ~= "" then
|
||||
</table>
|
||||
# end
|
||||
<h2><a href="#$(no_spaces(kind))">$(kind)</a></h2>
|
||||
<table class="function_list">
|
||||
# end
|
||||
# for item in items() do
|
||||
# local dn = display_name(item)
|
||||
# if item.sanitize_type then item.sanitize_type(item, ldoc) end
|
||||
|
@ -141,8 +153,9 @@
|
|||
<td class="summary">$(M(item.summary,item))</td>
|
||||
</tr>
|
||||
# end -- for items
|
||||
</table>
|
||||
# last_kind = kind
|
||||
#end -- for kinds
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
@ -152,11 +165,16 @@
|
|||
# --- currently works for both Functions and Tables. The params field either contains
|
||||
# --- function parameters or table fields.
|
||||
# local show_return = not ldoc.no_return_or_parms
|
||||
# local show_parms = show_return
|
||||
# local show_parms, last_kind = show_return, ""
|
||||
# for kind, items in module.kinds() do
|
||||
# local kitem = module.kinds:get_item(kind)
|
||||
# local has_description = kitem and ldoc.descript(kitem) ~= ""
|
||||
# if not kind:match("^ldoc_skip") then
|
||||
# if last_kind ~= "" then
|
||||
</dl>
|
||||
# end
|
||||
<h2 class="section-header $(has_description and 'has-description')"><a name="$(no_spaces(kind))"></a>$(kind)</h2>
|
||||
# end
|
||||
$(M(module.kinds:get_section_description(kind),nil))
|
||||
# if kitem then
|
||||
# if has_description then
|
||||
|
@ -169,7 +187,9 @@
|
|||
<pre class="example">$(ldoc.prettify(kitem.usage[1]))</pre>
|
||||
# end
|
||||
# end
|
||||
# if not kind:match("^ldoc_skip") then
|
||||
<dl class="function">
|
||||
# end
|
||||
# for item in items() do
|
||||
<dt>
|
||||
<a name = "$(item.name)"></a>
|
||||
|
@ -289,8 +309,9 @@
|
|||
|
||||
</dd>
|
||||
# end -- for items
|
||||
</dl>
|
||||
# last_kind = kind
|
||||
# end -- for kinds
|
||||
</dl>
|
||||
|
||||
# else -- if module; project-level contents
|
||||
|
||||
|
|
|
@ -77,4 +77,4 @@ gprop._legacy_accessors(capi.root, "keys", "_keys", false, function(new_btns)
|
|||
) or false
|
||||
end, true)
|
||||
|
||||
assert(root.keys)
|
||||
require("awful.root")
|
||||
|
|
|
@ -2,19 +2,29 @@
|
|||
--- Create easily new buttons objects ignoring certain modifiers.
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
||||
-- @copyright 2018 Emmanuel Lepage Vallee
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @classmod awful.button
|
||||
-- @inputmodule awful.button
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
local capi = { button = button }
|
||||
local capi = { button = button, root = root }
|
||||
local gmath = require("gears.math")
|
||||
local gtable = require("gears.table")
|
||||
local gobject = require("gears.object")
|
||||
|
||||
local button = { mt = {} }
|
||||
|
||||
-- Due to non trivial abuse or `pairs` in older code, the private data cannot
|
||||
-- be stored in the object itself without creating subtle bugs. This cannot be
|
||||
-- fixed internally because the default `rc.lua` uses `gears.table.join`, which
|
||||
-- is affected.
|
||||
--TODO v6: Drop this
|
||||
local reverse_map = setmetatable({}, {__mode="k"})
|
||||
|
||||
--- Modifiers to ignore.
|
||||
--
|
||||
-- By default this is initialized as `{ "Lock", "Mod2" }`
|
||||
|
@ -24,38 +34,289 @@ local button = { mt = {} }
|
|||
-- @table ignore_modifiers
|
||||
local ignore_modifiers = { "Lock", "Mod2" }
|
||||
|
||||
--- The mouse buttons names.
|
||||
--
|
||||
-- It can be used instead of the button ids.
|
||||
--
|
||||
-- @table names
|
||||
button.names = {
|
||||
LEFT = 1,-- The left mouse button.
|
||||
MIDDLE = 2,-- The scrollwheel button.
|
||||
RIGHT = 3,-- The context menu button.
|
||||
SCROLL_UP = 4,-- A scroll up increment.
|
||||
SCROLL_DOWN = 5,-- A scroll down increment.
|
||||
}
|
||||
|
||||
--- The table of modifier keys.
|
||||
--
|
||||
-- A modifier, such as `Control` are a predetermined set of keys that can be
|
||||
-- used to implement keybindings. Note that this list is fix and cannot be
|
||||
-- extended using random key names, code or characters.
|
||||
--
|
||||
-- Common modifiers are:
|
||||
--
|
||||
-- <table class='widget_list' border=1>
|
||||
-- <tr style='font-weight: bold;'>
|
||||
-- <th align='center'>Name</th>
|
||||
-- <th align='center'>Description</th>
|
||||
-- </tr>
|
||||
-- <tr><td>Mod1</td><td>Usually called Alt on PCs and Option on Macs</td></tr>
|
||||
-- <tr><td>Mod4</td><td>Also called Super, Windows and Command ⌘</td></tr>
|
||||
-- <tr><td>Mod5</td><td>Also called AltGr or ISO Level 3</td></tr>
|
||||
-- <tr><td>Shift</td><td>Both left and right shift keys</td></tr>
|
||||
-- <tr><td>Control</td><td>Also called CTRL on some keyboards</td></tr>
|
||||
-- </table>
|
||||
--
|
||||
-- Please note that Awesome ignores the status of "Lock" and "Mod2" (Num Lock).
|
||||
--
|
||||
-- @property modifiers
|
||||
|
||||
--- The mouse button identifier.
|
||||
--
|
||||
-- ![Mouse buttons](../images/mouse.svg)
|
||||
--
|
||||
-- @property button
|
||||
-- @param integer
|
||||
|
||||
--- The button description.
|
||||
--
|
||||
-- @property description
|
||||
-- @param string
|
||||
|
||||
--- The button name.
|
||||
--
|
||||
-- @property name
|
||||
-- @param string
|
||||
|
||||
--- The button group.
|
||||
--
|
||||
-- @property group
|
||||
-- @param string
|
||||
|
||||
--- The callback when this button is pressed.
|
||||
--
|
||||
-- @property on_press
|
||||
-- @param function
|
||||
|
||||
--- The callback when this button is released.
|
||||
--
|
||||
-- @property on_release
|
||||
-- @param function
|
||||
|
||||
--- Execute this mousebinding.
|
||||
-- @method :trigger
|
||||
|
||||
function button:set_button(b)
|
||||
for _, v in ipairs(self) do
|
||||
v.button = b
|
||||
end
|
||||
end
|
||||
|
||||
function button:set_modifiers(mod)
|
||||
local subsets = gmath.subsets(ignore_modifiers)
|
||||
for k, set in ipairs(subsets) do
|
||||
self[k].modifiers = gtable.join(mod, set)
|
||||
end
|
||||
end
|
||||
|
||||
for _, prop in ipairs { "description", "group", "name" } do
|
||||
button["get_"..prop] = function(self)
|
||||
return reverse_map[self][prop]
|
||||
end
|
||||
button["set_"..prop] = function(self, value)
|
||||
reverse_map[self][prop] = value
|
||||
end
|
||||
end
|
||||
|
||||
-- Store the callbacks as weakly as possible.
|
||||
--
|
||||
-- Lua 5.1 GC is not very smart with reference loops. When the titlebar has
|
||||
-- buttons, they usually contain the client in their lambda. In turn, storing
|
||||
-- the callback in something stored by the titlebar, which is stored by the
|
||||
-- clients, will not be GC-able as-is.
|
||||
--
|
||||
-- To work around this, we use weak `v` references stored within a weak `k`
|
||||
-- table. So both the `awful.button` and the callbacks are weak in their own
|
||||
-- realm. To avoid the GC of the callback, it is important to use
|
||||
-- `connect_signal` on the `capi.button` to keep a reference alive.
|
||||
for _, prop in ipairs { "press", "release" } do
|
||||
local long_name = "on_"..prop
|
||||
|
||||
button["get_"..long_name] = function(self)
|
||||
return reverse_map[self].weak_content[long_name]
|
||||
end
|
||||
button["set_"..long_name] = function(self, value)
|
||||
local old = reverse_map[self].weak_content[long_name]
|
||||
local new = function(_, ...) value(...) end
|
||||
|
||||
if old then
|
||||
for i=1, 4 do
|
||||
self[i]:disconnect_signal(prop, old)
|
||||
end
|
||||
end
|
||||
|
||||
reverse_map[self].weak_content[prop] = new
|
||||
|
||||
for i=1, 4 do
|
||||
self[i]:connect_signal(prop, new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function button:get_button()
|
||||
return self[1].button
|
||||
end
|
||||
|
||||
function button:trigger()
|
||||
local data = reverse_map[self]
|
||||
|
||||
local press = self.on_press or data.weak_content.press
|
||||
|
||||
if press then
|
||||
press()
|
||||
end
|
||||
|
||||
local release = self.on_release or data.weak_content.release
|
||||
|
||||
if release then
|
||||
release()
|
||||
end
|
||||
end
|
||||
|
||||
function button:get_has_root_binding()
|
||||
return capi.root.has_button(self)
|
||||
end
|
||||
|
||||
-- This is used by the keygrabber and prompt to identify valid awful.button
|
||||
-- objects. It *cannot* be put directly in the object since `capi` uses a lot
|
||||
-- of `next` internally and fixing that would suck more.
|
||||
function button:get__is_awful_button()
|
||||
return true
|
||||
end
|
||||
|
||||
local function index_handler(self, k)
|
||||
if button["get_"..k] then
|
||||
return button["get_"..k](self)
|
||||
end
|
||||
|
||||
if type(button[k]) == "function" then
|
||||
return button[k]
|
||||
end
|
||||
|
||||
local data = reverse_map[self]
|
||||
assert(data)
|
||||
|
||||
if data[k] ~= nil then
|
||||
return data[k]
|
||||
else
|
||||
return data.weak_content[k]
|
||||
end
|
||||
end
|
||||
|
||||
local function newindex_handler(self, key, value)
|
||||
if button["set_"..key] then
|
||||
return button["set_"..key](self, value)
|
||||
end
|
||||
|
||||
local data = reverse_map[self]
|
||||
assert(data)
|
||||
|
||||
if data.weak_content[key] ~= nil then
|
||||
data.weak_content[key] = value
|
||||
else
|
||||
data[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
local obj_mt = {
|
||||
__index = index_handler,
|
||||
__newindex = newindex_handler
|
||||
}
|
||||
|
||||
--- 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.
|
||||
-- @constructorfct awful.button
|
||||
-- @tparam table mod A list of modifier keys. Valid modifiers are:
|
||||
-- `Any`, `Mod1`, Mod2`, `Mod3`, `Mod4`, `Mod5`, `Shift`, `Lock` and `Control`.
|
||||
-- This argument is (**mandatory**).
|
||||
-- @tparam number button The mouse button (it is recommended to use the
|
||||
-- `awful.button.names` constants.
|
||||
-- @tparam function press Callback for when the button is pressed.
|
||||
-- @tparam function release Callback for when the button is released.
|
||||
-- @treturn table An `awful.button` object.
|
||||
|
||||
--- Create a new button to use as binding.
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
-- @treturn table A table with one or several button objects.
|
||||
function button.new(mod, _button, press, release)
|
||||
-- @constructorfct2 awful.button
|
||||
-- @tparam table args
|
||||
-- @tparam table args.modifiers A list of modifier keys. Valid modifiers are:
|
||||
-- `Any`, `Mod1`, Mod2`, `Mod3`, `Mod4`, `Mod5`, `Shift`, `Lock` and `Control`.
|
||||
-- This argument is (**mandatory**).
|
||||
-- @tparam number args.button The mouse button (it is recommended to use the
|
||||
-- `awful.button.names` constants.
|
||||
-- @tparam function args.on_press Callback for when the button is pressed.
|
||||
-- @tparam function args.on_release Callback for when the button is released.
|
||||
-- @treturn table An `awful.button` object.
|
||||
|
||||
local function new_common(mod, _button, press, release)
|
||||
local ret = {}
|
||||
local subsets = gmath.subsets(ignore_modifiers)
|
||||
|
||||
for _, set in ipairs(subsets) do
|
||||
ret[#ret + 1] = capi.button({ modifiers = gtable.join(mod, set),
|
||||
button = _button })
|
||||
local sub_button = capi.button {
|
||||
modifiers = gtable.join(mod, set),
|
||||
button = _button
|
||||
}
|
||||
|
||||
sub_button._private._legacy_convert_to = ret
|
||||
|
||||
ret[#ret + 1] = sub_button
|
||||
end
|
||||
|
||||
reverse_map[ret] = {
|
||||
-- Use weak tables to let Lua 5.1 and Luajit GC the `awful.buttons`,
|
||||
-- Lua 5.3 is smart enough to figure this out.
|
||||
weak_content = setmetatable({
|
||||
press = press,
|
||||
release = release,
|
||||
}, {__mode = "v"}),
|
||||
_is_capi_button = false
|
||||
}
|
||||
|
||||
if press then
|
||||
ret[#ret]:connect_signal("press", function(_, ...) press(...) end)
|
||||
button.set_on_press(ret, press)
|
||||
end
|
||||
|
||||
if release then
|
||||
ret[#ret]:connect_signal("release", function (_, ...) release(...) end)
|
||||
button.set_on_release(ret, release)
|
||||
end
|
||||
|
||||
return setmetatable(ret, obj_mt)
|
||||
end
|
||||
|
||||
function button.new(args, _button, press, release)
|
||||
-- Assume this is the new constructor.
|
||||
if not _button then
|
||||
assert(not (press or release), "Calling awful.button() requires a button name")
|
||||
return new_common(
|
||||
args.modifiers,
|
||||
args.button,
|
||||
args.on_press,
|
||||
args.on_release
|
||||
)
|
||||
else
|
||||
return new_common(args, _button, press, release)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function button.mt:__call(...)
|
||||
return button.new(...)
|
||||
end
|
||||
|
||||
gobject.properties(capi.button, {
|
||||
auto_emit = true,
|
||||
})
|
||||
|
||||
return setmetatable(button, button.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1167,8 +1167,8 @@ end)
|
|||
-- @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
|
||||
if not c._private._persistent_properties_loaded then
|
||||
c._private._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
|
||||
|
@ -1176,8 +1176,8 @@ function client.property.get(c, prop)
|
|||
end
|
||||
end
|
||||
end
|
||||
if c.data.awful_client_properties then
|
||||
return c.data.awful_client_properties[prop]
|
||||
if c._private.awful_client_properties then
|
||||
return c._private.awful_client_properties[prop]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1191,14 +1191,14 @@ end
|
|||
-- @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 = {}
|
||||
if not c._private.awful_client_properties then
|
||||
c._private.awful_client_properties = {}
|
||||
end
|
||||
if c.data.awful_client_properties[prop] ~= value then
|
||||
if c._private.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._private.awful_client_properties[prop] = value
|
||||
c:emit_signal("property::" .. prop)
|
||||
end
|
||||
end
|
||||
|
@ -1216,8 +1216,8 @@ function client.property.persist(prop, kind)
|
|||
|
||||
-- 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])
|
||||
if c._private.awful_client_properties and c._private.awful_client_properties[prop] ~= nil then
|
||||
c:set_xproperty(xprop, c._private.awful_client_properties[prop])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,6 +24,7 @@ return
|
|||
mouse = require("awful.mouse");
|
||||
remote = require("awful.remote");
|
||||
key = require("awful.key");
|
||||
keyboard = require("awful.keyboard");
|
||||
button = require("awful.button");
|
||||
wibar = require("awful.wibar");
|
||||
wibox = require("awful.wibox");
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
--- Create easily new key objects ignoring certain modifiers.
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @classmod awful.key
|
||||
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
||||
-- @copyright 2018 Emmanuel Lepage Vallee
|
||||
-- @inputmodule awful.key
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
|
@ -12,41 +13,168 @@ local ipairs = ipairs
|
|||
local capi = { key = key, root = root, awesome = awesome }
|
||||
local gmath = require("gears.math")
|
||||
local gtable = require("gears.table")
|
||||
local gdebug = require("gears.debug")
|
||||
local gobject = require("gears.object")
|
||||
|
||||
--- The keyboard key used to trigger this keybinding.
|
||||
--
|
||||
-- It can be the key symbol, such as `space`, the character, such as ` ` or the
|
||||
-- keycode such as `#65`.
|
||||
--
|
||||
-- @property key
|
||||
-- @param string
|
||||
|
||||
--- The table of modifier keys.
|
||||
--
|
||||
-- A modifier, such as `Control` are a predetermined set of keys that can be
|
||||
-- used to implement keybindings. Note that this list is fix and cannot be
|
||||
-- extended using random key names, code or characters.
|
||||
--
|
||||
-- Common modifiers are:
|
||||
--
|
||||
-- <table class='widget_list' border=1>
|
||||
-- <tr style='font-weight: bold;'>
|
||||
-- <th align='center'>Name</th>
|
||||
-- <th align='center'>Description</th>
|
||||
-- </tr>
|
||||
-- <tr><td>Mod1</td><td>Usually called Alt on PCs and Option on Macs</td></tr>
|
||||
-- <tr><td>Mod4</td><td>Also called Super, Windows and Command ⌘</td></tr>
|
||||
-- <tr><td>Mod5</td><td>Also called AltGr or ISO Level 3</td></tr>
|
||||
-- <tr><td>Shift</td><td>Both left and right shift keys</td></tr>
|
||||
-- <tr><td>Control</td><td>Also called CTRL on some keyboards</td></tr>
|
||||
-- </table>
|
||||
--
|
||||
-- Please note that Awesome ignores the status of "Lock" and "Mod2" (Num Lock).
|
||||
--
|
||||
-- @property modifiers
|
||||
-- @tparam table modifiers
|
||||
|
||||
--- The key description.
|
||||
--
|
||||
-- This is used, for example, by the `awful.hotkey_popup`.
|
||||
--
|
||||
-- @property description
|
||||
-- @param string
|
||||
|
||||
--- The key name.
|
||||
--
|
||||
-- This can be useful when searching for keybindings by keywords.
|
||||
--
|
||||
-- @property name
|
||||
-- @param string
|
||||
|
||||
--- The key group.
|
||||
--
|
||||
-- This is used, for example, by the `awful.hotkey_popup`.
|
||||
--
|
||||
-- @property group
|
||||
-- @param string
|
||||
|
||||
--- The callback when this key is pressed.
|
||||
--
|
||||
-- @property on_press
|
||||
-- @param function
|
||||
|
||||
--- The callback when this key is released.
|
||||
--
|
||||
-- @property on_release
|
||||
-- @param function
|
||||
|
||||
local key = { mt = {}, hotkeys = {} }
|
||||
|
||||
local reverse_map = setmetatable({}, {__mode="k"})
|
||||
|
||||
function key:set_key(k)
|
||||
for _, v in ipairs(self) do
|
||||
v.key = k
|
||||
end
|
||||
end
|
||||
|
||||
function key:get_key()
|
||||
return self[1].key
|
||||
end
|
||||
|
||||
function key:set_modifiers(mod)
|
||||
local subsets = gmath.subsets(key.ignore_modifiers)
|
||||
for k, set in ipairs(subsets) do
|
||||
self[k].modifiers = gtable.join(mod, set)
|
||||
end
|
||||
end
|
||||
|
||||
for _, prop in ipairs { "description", "group", "on_press", "on_release", "name" } do
|
||||
key["get_"..prop] = function(self)
|
||||
return reverse_map[self][prop]
|
||||
end
|
||||
key["set_"..prop] = function(self, value)
|
||||
reverse_map[self][prop] = value
|
||||
end
|
||||
end
|
||||
|
||||
--- Execute this keybinding.
|
||||
--
|
||||
-- @method :trigger
|
||||
|
||||
function key:trigger()
|
||||
local data = reverse_map[self]
|
||||
if data.on_press then
|
||||
data.on_press()
|
||||
end
|
||||
|
||||
if data.on_release then
|
||||
data.on_release()
|
||||
end
|
||||
end
|
||||
|
||||
function key:get_has_root_binding()
|
||||
return capi.root.has_key(self)
|
||||
end
|
||||
|
||||
-- This is used by the keygrabber and prompt to identify valid awful.key
|
||||
-- objects. It *cannot* be put directly in the object since `capi` uses a lot
|
||||
-- of `next` internally and fixing that would suck more.
|
||||
function key:get__is_awful_key()
|
||||
return true
|
||||
end
|
||||
|
||||
local function index_handler(self, k)
|
||||
if key["get_"..k] then
|
||||
return key["get_"..k](self)
|
||||
end
|
||||
|
||||
if type(key[k]) == "function" then
|
||||
return key[k]
|
||||
end
|
||||
|
||||
local data = reverse_map[self]
|
||||
assert(data)
|
||||
|
||||
return data[k]
|
||||
end
|
||||
|
||||
local function newindex_handler(self, k, value)
|
||||
if key["set_"..k] then
|
||||
return key["set_"..k](self, value)
|
||||
end
|
||||
|
||||
local data = reverse_map[self]
|
||||
assert(data)
|
||||
|
||||
data[k] = value
|
||||
end
|
||||
|
||||
local obj_mt = {
|
||||
__index = index_handler,
|
||||
__newindex = newindex_handler
|
||||
}
|
||||
|
||||
--- Modifiers to ignore.
|
||||
-- By default this is initialized as { "Lock", "Mod2" }
|
||||
-- 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 = nil
|
||||
|
||||
local function generate_conversion_map()
|
||||
if conversion then return conversion end
|
||||
|
||||
local mods = capi.awesome._modifiers
|
||||
assert(mods)
|
||||
|
||||
conversion = {}
|
||||
|
||||
for mod, keysyms in pairs(mods) do
|
||||
for _, keysym in ipairs(keysyms) do
|
||||
assert(keysym.keysym)
|
||||
conversion[mod] = conversion[mod] or keysym.keysym
|
||||
conversion[keysym.keysym] = mod
|
||||
end
|
||||
end
|
||||
|
||||
return conversion
|
||||
end
|
||||
|
||||
capi.awesome.connect_signal("xkb::map_changed" , function() conversion = nil end)
|
||||
|
||||
--- Execute a key combination.
|
||||
-- If an awesome keybinding is assigned to the combination, it should be
|
||||
-- executed.
|
||||
|
@ -59,89 +187,106 @@ capi.awesome.connect_signal("xkb::map_changed" , function() conversion = nil en
|
|||
-- @tparam table mod A modified table. Valid modifiers are: Any, Mod1,
|
||||
-- Mod2, Mod3, Mod4, Mod5, Shift, Lock and Control.
|
||||
-- @tparam string k The key
|
||||
-- @staticfct awful.key.execute
|
||||
-- @deprecated awful.key.execute
|
||||
function key.execute(mod, k)
|
||||
local modmap = generate_conversion_map()
|
||||
local active = capi.awesome._active_modifiers
|
||||
gdebug.deprecate("Use `awful.keyboard.emulate_key_combination` or "..
|
||||
"`my_key:trigger()` instead of `awful.key.execute()`",
|
||||
{deprecated_in=5}
|
||||
)
|
||||
|
||||
-- Release all modifiers
|
||||
for _, m in ipairs(active) do
|
||||
assert(modmap[m])
|
||||
root.fake_input("key_release", modmap[m])
|
||||
end
|
||||
|
||||
for _, v in ipairs(mod) do
|
||||
local m = modmap[v]
|
||||
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 = modmap[v]
|
||||
if m then
|
||||
root.fake_input("key_release", m)
|
||||
end
|
||||
end
|
||||
|
||||
-- Restore the previous modifiers all modifiers. Please note that yes,
|
||||
-- there is a race condition if the user was fast enough to release the
|
||||
-- key during this operation.
|
||||
for _, m in ipairs(active) do
|
||||
root.fake_input("key_press", modmap[m])
|
||||
end
|
||||
require("awful.keyboard").emulate_key_combination(mod, k)
|
||||
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.
|
||||
--- Create a new key binding.
|
||||
--
|
||||
-- @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.
|
||||
-- @constructorfct2 awful.key
|
||||
-- @tparam table args
|
||||
-- @tparam function args.key The key to trigger an event. It can be the character
|
||||
-- itself of `#+keycode` (**mandatory**).
|
||||
-- @tparam function args.modifiers A list of modifier keys. Valid modifiers are:
|
||||
-- `Any`, `Mod1`, Mod2`, `Mod3`, `Mod4`, `Mod5`, `Shift`, `Lock` and `Control`.
|
||||
-- This argument is (**mandatory**).
|
||||
-- @tparam function args.on_press Callback for when the key is pressed.
|
||||
-- @tparam function args.on_release Callback for when the key is released.
|
||||
|
||||
--- Create a new key binding (alternate constructor).
|
||||
--
|
||||
-- @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. It can be the character
|
||||
-- itself of `#+keycode`.
|
||||
-- @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,
|
||||
-- @tparam[opt] table data User data for key,
|
||||
-- for example {description="select next tag", group="tag"}.
|
||||
-- @treturn table A table with one or several key objects.
|
||||
-- @constructorfct awful.key
|
||||
|
||||
function key.new(mod, _key, press, release, data)
|
||||
local function new_common(mod, _key, press, release, data)
|
||||
if type(release)=='table' then
|
||||
data=release
|
||||
release=nil
|
||||
end
|
||||
|
||||
local ret = {}
|
||||
local subsets = gmath.subsets(key.ignore_modifiers)
|
||||
for _, set in ipairs(subsets) do
|
||||
ret[#ret + 1] = capi.key({ modifiers = gtable.join(mod, set),
|
||||
key = _key })
|
||||
if press then
|
||||
ret[#ret]:connect_signal("press", function(_, ...) press(...) end)
|
||||
local sub_key = capi.key {
|
||||
modifiers = gtable.join(mod, set),
|
||||
key = _key
|
||||
}
|
||||
|
||||
sub_key._private._legacy_convert_to = ret
|
||||
|
||||
sub_key:connect_signal("press", function(_, ...)
|
||||
if ret.on_press then
|
||||
ret.on_press(...)
|
||||
end
|
||||
if release then
|
||||
ret[#ret]:connect_signal("release", function(_, ...) release(...) end)
|
||||
end)
|
||||
|
||||
sub_key:connect_signal("release", function(_, ...)
|
||||
if ret.on_release then
|
||||
ret.on_release(...)
|
||||
end
|
||||
end)
|
||||
|
||||
ret[#ret + 1] = sub_key
|
||||
end
|
||||
|
||||
-- append custom userdata (like description) to a hotkey
|
||||
data = data and gtable.clone(data) or {}
|
||||
data.mod = mod
|
||||
data.key = _key
|
||||
data.press = press
|
||||
data.release = release
|
||||
data.on_press = press
|
||||
data.on_release = release
|
||||
data._is_capi_key = false
|
||||
table.insert(key.hotkeys, data)
|
||||
data.execute = function(_) key.execute(mod, _key) end
|
||||
|
||||
return ret
|
||||
-- Store the private data
|
||||
reverse_map[ret] = data
|
||||
|
||||
--WARNING this object needs to expose only ordered keys for legacy reasons.
|
||||
-- All other properties needs to be fully handled by the meta table and never
|
||||
-- be stored directly in the object.
|
||||
|
||||
return setmetatable(ret, obj_mt)
|
||||
end
|
||||
|
||||
function key.new(args, _key, press, release, data)
|
||||
-- Assume this is the new constructor.
|
||||
if not _key then
|
||||
assert(not (press or release or data), "Calling awful.key() requires a key name")
|
||||
return new_common(
|
||||
args.modifiers,
|
||||
args.key,
|
||||
args.on_press,
|
||||
args.on_release,
|
||||
args
|
||||
)
|
||||
else
|
||||
return new_common(args, _key, press, release, data)
|
||||
end
|
||||
end
|
||||
|
||||
--- Compare a key object with modifiers and key.
|
||||
|
@ -172,6 +317,10 @@ function key.mt:__call(...)
|
|||
return key.new(...)
|
||||
end
|
||||
|
||||
gobject.properties(capi.key, {
|
||||
auto_emit = true,
|
||||
})
|
||||
|
||||
return setmetatable(key, key.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Utilities related to the keyboard and keybindings.
|
||||
--
|
||||
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
||||
-- @copyright 2018-2019 Emmanuel Lepage Vallee
|
||||
-- @inputmodule awful.keyboard
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local capi = {root = root, awesome = awesome}
|
||||
local module = {}
|
||||
|
||||
--- Convert the modifiers into pc105 key names
|
||||
local conversion = nil
|
||||
|
||||
local function generate_conversion_map()
|
||||
if conversion then return conversion end
|
||||
|
||||
local mods = capi.awesome._modifiers
|
||||
assert(mods)
|
||||
|
||||
conversion = {}
|
||||
|
||||
for mod, keysyms in pairs(mods) do
|
||||
for _, keysym in ipairs(keysyms) do
|
||||
assert(keysym.keysym)
|
||||
conversion[mod] = conversion[mod] or keysym.keysym
|
||||
conversion[keysym.keysym] = mod
|
||||
end
|
||||
end
|
||||
|
||||
return conversion
|
||||
end
|
||||
|
||||
capi.awesome.connect_signal("xkb::map_changed", function() conversion = nil end)
|
||||
|
||||
--- Execute a key combination.
|
||||
--
|
||||
-- If an awesome keybinding is assigned to the combination, it should be
|
||||
-- executed.
|
||||
--
|
||||
-- To limit the chances of accidentally leaving a modifier key locked when
|
||||
-- calling this function from a keybinding, make sure is attached to the
|
||||
-- release event and not the press event.
|
||||
--
|
||||
-- @see root.fake_input
|
||||
-- @tparam table modifiers A modified table. Valid modifiers are: `Any`, `Mod1`,
|
||||
-- `Mod2`, `Mod3`, `Mod4`, `Mod5`, `Shift`, `Lock` and `Control`.
|
||||
-- @tparam string key The key.
|
||||
-- @staticfct awful.keyboard.emulate_key_combination
|
||||
function module.emulate_key_combination(modifiers, key)
|
||||
local modmap = generate_conversion_map()
|
||||
local active = capi.awesome._active_modifiers
|
||||
|
||||
-- Release all modifiers
|
||||
for _, m in ipairs(active) do
|
||||
assert(modmap[m])
|
||||
capi.root.fake_input("key_release", modmap[m])
|
||||
end
|
||||
|
||||
for _, v in ipairs(modifiers) do
|
||||
local m = modmap[v]
|
||||
if m then
|
||||
capi.root.fake_input("key_press", m)
|
||||
end
|
||||
end
|
||||
|
||||
capi.root.fake_input("key_press" , key)
|
||||
capi.root.fake_input("key_release", key)
|
||||
|
||||
for _, v in ipairs(modifiers) do
|
||||
local m = modmap[v]
|
||||
if m then
|
||||
capi.root.fake_input("key_release", m)
|
||||
end
|
||||
end
|
||||
|
||||
-- Restore the previous modifiers all modifiers. Please note that yes,
|
||||
-- there is a race condition if the user was fast enough to release the
|
||||
-- key during this operation.
|
||||
for _, m in ipairs(active) do
|
||||
capi.root.fake_input("key_press", modmap[m])
|
||||
end
|
||||
end
|
||||
|
||||
--- Add an `awful.key` based keybinding to the global set.
|
||||
--
|
||||
-- A **global** keybinding is one which is always present, even when there is
|
||||
-- no focused client. If your intent is too add a keybinding which acts on
|
||||
-- the focused client do **not** use this.
|
||||
--
|
||||
-- @staticfct awful.keyboard.append_global_keybinding
|
||||
-- @tparam awful.key key The key object.
|
||||
-- @see awful.key
|
||||
-- @see awful.keyboard.append_global_keybindings
|
||||
-- @see awful.keyboard.remove_global_keybinding
|
||||
|
||||
function module.append_global_keybinding(key)
|
||||
capi.root._append_key(key)
|
||||
end
|
||||
|
||||
--- Add multiple `awful.key` based keybindings to the global set.
|
||||
--
|
||||
-- A **global** keybinding is one which is always present, even when there is
|
||||
-- no focused client. If your intent is too add a keybinding which acts on
|
||||
-- the focused client do **not** use this
|
||||
--
|
||||
-- @tparam table keys A table of `awful.key` objects. Optionally, it can have
|
||||
-- a `group` entry. If set, the `group` property will be set on all `awful.keys`
|
||||
-- objects.
|
||||
-- @see awful.key
|
||||
-- @see awful.keyboard.append_global_keybinding
|
||||
-- @see awful.keyboard.remove_global_keybinding
|
||||
|
||||
function module.append_global_keybindings(keys)
|
||||
local g = keys.group
|
||||
keys.group = nil
|
||||
|
||||
-- Avoid the boilerplate. If the user is adding multiple keys at once, then
|
||||
-- they are probably related.
|
||||
if g then
|
||||
for _, k in ipairs(keys) do
|
||||
k.group = g
|
||||
end
|
||||
end
|
||||
|
||||
capi.root._append_keys(keys)
|
||||
keys.group = g
|
||||
end
|
||||
|
||||
--- Remove a keybinding from the global set.
|
||||
--
|
||||
-- @staticfct awful.keyboard.remove_global_keybinding
|
||||
-- @tparam awful.key key The key object.
|
||||
-- @see awful.key
|
||||
-- @see awful.keyboard.append_global_keybinding
|
||||
|
||||
function module.remove_global_keybinding(key)
|
||||
capi.root._remove_key(key)
|
||||
end
|
||||
|
||||
return module
|
|
@ -71,6 +71,7 @@ local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility
|
|||
local gtable = require("gears.table")
|
||||
local gobject = require("gears.object")
|
||||
local gtimer = require("gears.timer")
|
||||
local akeyboard = require("awful.keyboard")
|
||||
local glib = require("lgi").GLib
|
||||
local capi = { keygrabber = keygrabber, root = root, awesome = awesome }
|
||||
|
||||
|
@ -90,9 +91,6 @@ local conversion = nil
|
|||
--BEGIN one day create a proper API to add and remove keybindings at runtime.
|
||||
-- Doing it this way is horrible.
|
||||
|
||||
-- This list of keybindings to add in the next event loop cycle.
|
||||
local delay_list = {}
|
||||
|
||||
-- Read the modifiers name and map their keysyms to the modkeys
|
||||
local function generate_conversion_map()
|
||||
if conversion then return conversion end
|
||||
|
@ -119,60 +117,24 @@ local function add_root_keybindings(self, list)
|
|||
list, "`add_root_keybindings` needs to be called with a list of keybindings"
|
||||
)
|
||||
|
||||
local was_started = #delay_list > 0
|
||||
|
||||
-- When multiple `awful.keygrabber` objects are created in `rc.lua`, avoid
|
||||
-- unpacking and repacking all keys for each instance and instead merge
|
||||
-- everything into one operation. In not so extreme cases, not doing so
|
||||
-- would slow down `awesome.restart()` by a small, but noticeable amount
|
||||
-- of time.
|
||||
table.insert(delay_list, {self, list})
|
||||
|
||||
-- As of Awesome v4.3, `root.keys()` is an all or nothing API and there
|
||||
-- isn't a standard mechanism to add and remove keybindings at runtime
|
||||
-- without replacing the full list. Given `rc.lua` sets this list, not
|
||||
-- using a delayed call would cause all `awful.keygrabber` created above
|
||||
-- `root.keys(globalkeys)` to be silently overwritten. --FIXME v5
|
||||
if not was_started then
|
||||
gtimer.delayed_call(function()
|
||||
local ret = {}
|
||||
|
||||
for _, obj in ipairs(delay_list) do
|
||||
local obj_self, obj_list = obj[1], obj[2]
|
||||
|
||||
for _, v in ipairs(obj_list) do
|
||||
local mods, key, press, release, data = unpack(v)
|
||||
|
||||
if type(release) == 'table' then
|
||||
data = release
|
||||
release = nil
|
||||
end
|
||||
|
||||
if press then
|
||||
local old_press = press
|
||||
press = function(...)
|
||||
obj_self:start()
|
||||
for _, kb in ipairs(list) do
|
||||
if kb.on_press then
|
||||
local old_press = kb.on_press
|
||||
kb.on_press = function(...)
|
||||
self:start()
|
||||
old_press(...)
|
||||
end
|
||||
end
|
||||
|
||||
if release then
|
||||
local old_release = release
|
||||
release = function(...)
|
||||
obj_self:start()
|
||||
if kb.on_release then
|
||||
local old_release = kb.on_release
|
||||
kb.on_release = function(...)
|
||||
self:start()
|
||||
old_release(...)
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(ret, akey(mods, key, press, release, data))
|
||||
end
|
||||
end
|
||||
|
||||
-- Wow...
|
||||
capi.root.keys(gtable.join( capi.root.keys(), unpack(ret) ))
|
||||
|
||||
delay_list = {}
|
||||
end)
|
||||
akeyboard.append_global_keybinding(kb)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -249,13 +211,13 @@ local function runner(self, modifiers, key, event)
|
|||
end
|
||||
|
||||
for _,v in ipairs(self._private.keybindings[key]) do
|
||||
if #filtered_modifiers == #v[1] then
|
||||
if #filtered_modifiers == #v.modifiers then
|
||||
local match = true
|
||||
for _,v2 in ipairs(v[1]) do
|
||||
for _,v2 in ipairs(v.modifiers) do
|
||||
match = match and mod[v2]
|
||||
end
|
||||
if match then
|
||||
v[3](self)
|
||||
if match and v.on_press then
|
||||
v.on_press(self)
|
||||
|
||||
if self.mask_event_callback ~= false then
|
||||
return
|
||||
|
@ -400,20 +362,13 @@ end
|
|||
|
||||
--- The keybindings associated with this keygrabber.
|
||||
--
|
||||
-- The keybindings syntax is the same as `awful.key` or `awful.prompt.hooks`. It
|
||||
-- consists of a table with 4 entries.
|
||||
--
|
||||
-- * `mods` A table with modifier keys, such as `shift`, `mod4`, `mod1` (alt) or
|
||||
-- `control`.
|
||||
-- * `key` The key name, such as `left` or `f`
|
||||
-- * `callback` A function that will be called when the key combination is
|
||||
-- pressed.
|
||||
-- * `description` A table various metadata to be used for `awful.hotkeys_popup`.
|
||||
-- This property contains a table of `awful.key` objects.
|
||||
--
|
||||
-- @property keybindings
|
||||
-- @param table
|
||||
-- @see export_keybindings
|
||||
-- @see root_keybindings
|
||||
-- @see awful.key
|
||||
|
||||
--- If any key is pressed that is not in this list, the keygrabber is stopped.
|
||||
--
|
||||
|
@ -538,27 +493,62 @@ end
|
|||
-- Those keybindings will automatically start the keygrabbing when hit.
|
||||
--
|
||||
-- @method add_keybinding
|
||||
-- @tparam table mods A table with modifier keys, such as `shift`, `mod4`, `mod1` (alt) or
|
||||
-- `control`.
|
||||
-- @tparam string key The key name, such as `left` or `f`
|
||||
-- @tparam function callback A function that will be called when the key
|
||||
-- combination is pressed.
|
||||
-- @tparam[opt] table description A table various metadata to be used for `awful.hotkeys_popup`.
|
||||
-- @tparam string description.description The keybinding description
|
||||
-- @tparam awful.key key The key.
|
||||
-- @tparam string description.group The keybinding group
|
||||
function keygrabber:add_keybinding(mods, key, callback, description)
|
||||
|
||||
function keygrabber:add_keybinding(key, _keycode, _callback, _description)
|
||||
local mods = not akey._is_awful_key and akey or nil
|
||||
|
||||
if mods then
|
||||
gdebug.deprecate(":add_keybinding now takes `awful.key` objects instead"
|
||||
.. " of multiple parameters",
|
||||
{deprecated_in=5}
|
||||
)
|
||||
|
||||
key = akey {
|
||||
modifiers = mods,
|
||||
key = _keycode,
|
||||
description = _description,
|
||||
on_press = _callback
|
||||
}
|
||||
else
|
||||
_keycode = key.key
|
||||
end
|
||||
|
||||
self._private.keybindings[key] = self._private.keybindings[key] or {}
|
||||
table.insert(self._private.keybindings[key], {
|
||||
mods, key, callback, description
|
||||
})
|
||||
table.insert(self._private.keybindings[_keycode], key)
|
||||
|
||||
if self.export_keybindings then
|
||||
add_root_keybindings(self, {{mods, key, callback, description}})
|
||||
add_root_keybindings(self, {key})
|
||||
end
|
||||
end
|
||||
|
||||
function keygrabber:set_root_keybindings(keys)
|
||||
add_root_keybindings(self, keys)
|
||||
local real_keys = {}
|
||||
|
||||
-- Handle the pre-object-oriented input structures.
|
||||
for _, key in ipairs(keys) do
|
||||
if key._is_awful_key then
|
||||
table.insert(real_keys, key)
|
||||
else
|
||||
gdebug.deprecate(":set_root_keybindings now takes `awful.key` "
|
||||
.. " objects instead of tables",
|
||||
{deprecated_in=5}
|
||||
)
|
||||
|
||||
local mods, keycode, press, release, data = unpack(key)
|
||||
|
||||
table.insert(real_keys, akey {
|
||||
modifiers = mods,
|
||||
key = keycode,
|
||||
description = (data or {}).description,
|
||||
on_press = press,
|
||||
on_release = release,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
add_root_keybindings(self, real_keys)
|
||||
end
|
||||
|
||||
-- Turn into a set.
|
||||
|
@ -689,26 +679,41 @@ function keygrab.run_with_keybindings(args)
|
|||
|
||||
-- Build the hook map
|
||||
for _,v in ipairs(args.keybindings or {}) do
|
||||
if #v >= 3 and #v <= 4 then
|
||||
local _,key,callback = unpack(v)
|
||||
if v._is_awful_key then
|
||||
ret._private.keybindings[v.key] = ret._private.keybindings[v.key] or {}
|
||||
table.insert(ret._private.keybindings[v.key], v)
|
||||
elseif #v >= 3 and #v <= 4 then
|
||||
gdebug.deprecate("keybindings now contains `awful.key` objects"
|
||||
.. "instead of multiple tables",
|
||||
{deprecated_in=5}
|
||||
)
|
||||
|
||||
local modifiers, key, callback = unpack(v)
|
||||
if type(callback) == "function" then
|
||||
|
||||
local k = akey {
|
||||
modifiers = modifiers,
|
||||
key = key,
|
||||
on_press = callback,
|
||||
}
|
||||
|
||||
ret._private.keybindings[key] = ret._private.keybindings[key] or {}
|
||||
table.insert(ret._private.keybindings[key], v)
|
||||
table.insert(ret._private.keybindings[key], k)
|
||||
else
|
||||
gdebug.print_warning(
|
||||
"The hook's 3rd parameter has to be a function. " ..
|
||||
gdebug.dump(v)
|
||||
gdebug.dump(v or {})
|
||||
)
|
||||
end
|
||||
else
|
||||
gdebug.print_warning(
|
||||
"The hook has to have at least 3 parameters. ".. gdebug.dump(v)
|
||||
"The keybindings should be awful.key objects".. gdebug.dump(v or {})
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if args.export_keybindings then
|
||||
add_root_keybindings(ret, args.keybindings)
|
||||
ret:set_root_keybindings(args.keybindings)
|
||||
end
|
||||
|
||||
local mt = getmetatable(ret)
|
||||
|
|
|
@ -370,6 +370,57 @@ end
|
|||
-- @property is_middle_mouse_button_pressed
|
||||
-- @param boolean
|
||||
|
||||
--- Add an `awful.button` based mousebinding to the global set.
|
||||
--
|
||||
-- A **global** mousebinding is one which is always present, even when there is
|
||||
-- no focused client. If your intent is too add a mousebinding which acts on
|
||||
-- the focused client do **not** use this.
|
||||
--
|
||||
-- @staticfct awful.mouse.append_global_mousebinding
|
||||
-- @tparam awful.button button The button object.
|
||||
-- @see awful.button
|
||||
|
||||
function mouse.append_global_mousebinding(button)
|
||||
capi.root._append_button(button)
|
||||
end
|
||||
|
||||
--- Add multiple `awful.button` based mousebindings to the global set.
|
||||
--
|
||||
-- A **global** mousebinding is one which is always present, even when there is
|
||||
-- no focused client. If your intent is too add a mousebinding which acts on
|
||||
-- the focused client do **not** use this
|
||||
--
|
||||
-- @tparam table buttons A table of `awful.button` objects. Optionally, it can have
|
||||
-- a `group` entry. If set, the `group` property will be set on all `awful.buttons`
|
||||
-- objects.
|
||||
-- @see awful.button
|
||||
|
||||
function mouse.append_global_mousebindings(buttons)
|
||||
local g = buttons.group
|
||||
buttons.group = nil
|
||||
|
||||
-- Avoid the boilerplate. If the user is adding multiple buttons at once, then
|
||||
-- they are probably related.
|
||||
if g then
|
||||
for _, k in ipairs(buttons) do
|
||||
k.group = g
|
||||
end
|
||||
end
|
||||
|
||||
capi.root._append_buttons(buttons)
|
||||
buttons.group = g
|
||||
end
|
||||
|
||||
--- Remove a mousebinding from the global set.
|
||||
--
|
||||
-- @staticfct awful.mouse.remove_global_mousebinding
|
||||
-- @tparam awful.button button The button object.
|
||||
-- @see awful.button
|
||||
|
||||
function mouse.remove_global_mousebinding(button)
|
||||
capi.root._remove_button(button)
|
||||
end
|
||||
|
||||
for _, b in ipairs {"left", "right", "middle"} do
|
||||
mouse.object["is_".. b .."_mouse_button_pressed"] = function()
|
||||
return capi.mouse.coords().buttons[1]
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Emmanuel Lepage-Vallee <elv1313@gmail.com>
|
||||
-- @copyright 2018-2019 Emmanuel Lepage-Vallee
|
||||
-- @module root
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local capi = { root = root }
|
||||
local gtable = require("gears.table")
|
||||
local gtimer = require("gears.timer")
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
for _, type_name in ipairs { "button", "key" } do
|
||||
local prop_name = type_name.."s"
|
||||
|
||||
-- The largest amount of wall clock time when loading Awesome 3.4 rc.lua
|
||||
-- was the awful.util.table.join (now gears.table.join). While the main
|
||||
-- bottleneck in the newer releases moved into LGI, doing all these `join`
|
||||
-- slow startup down quite a lot. On top of that, with the ability to add
|
||||
-- and remove keys and buttons can cause a large overhead of its own. To
|
||||
-- mitigate that, only set the actual content once per main loop iteration.
|
||||
--
|
||||
-- The C code also delay uploading these keys into the X server to prevent
|
||||
-- too many keyboard map changes from freezing Awesome.
|
||||
local has_delayed, added, removed = false, {}, {}
|
||||
|
||||
local function delay(value)
|
||||
if value then
|
||||
table.insert(added, value)
|
||||
end
|
||||
|
||||
if has_delayed then return end
|
||||
|
||||
has_delayed = true
|
||||
|
||||
gtimer.delayed_call(function()
|
||||
local new_values = capi.root["_"..prop_name]()
|
||||
|
||||
-- In theory, because they are inserted ordered, it is safe to assume
|
||||
-- the once found, the capi.key/button will be next to each other.
|
||||
for _, v in ipairs(removed) do
|
||||
local idx = gtable.hasitem(new_values, v[1])
|
||||
|
||||
if idx then
|
||||
for i=1, #v do
|
||||
assert(
|
||||
new_values[idx] == v[i],
|
||||
"The root private "..type_name.." table is corrupted"
|
||||
)
|
||||
|
||||
table.remove(new_values, idx)
|
||||
end
|
||||
end
|
||||
|
||||
idx = gtable.hasitem(added, v)
|
||||
|
||||
if idx then
|
||||
table.remove(added, idx)
|
||||
end
|
||||
end
|
||||
|
||||
local joined = gtable.join(unpack(added))
|
||||
new_values = gtable.merge(new_values, joined)
|
||||
|
||||
capi.root["_"..prop_name](new_values)
|
||||
|
||||
has_delayed, added, removed = false, {}, {}
|
||||
end)
|
||||
end
|
||||
|
||||
capi.root["_append_"..type_name] = function(value)
|
||||
if not value then return end
|
||||
|
||||
local t1 = capi.root._private[prop_name]
|
||||
|
||||
-- Simple case
|
||||
if (not t1) or not next(t1) then
|
||||
capi.root[prop_name] = {value}
|
||||
assert(capi.root._private[prop_name])
|
||||
return
|
||||
end
|
||||
|
||||
delay(value)
|
||||
end
|
||||
|
||||
capi.root["_append_"..prop_name] = function(values)
|
||||
-- It's pointless to use gears.table.merge, in the background it has the
|
||||
-- same loop anyway. Also, this isn't done very often.
|
||||
for _, value in ipairs(values) do
|
||||
capi.root["_append_"..type_name](value)
|
||||
end
|
||||
end
|
||||
|
||||
capi.root["_remove_"..type_name] = function(value)
|
||||
if not capi.root._private[prop_name] then return end
|
||||
|
||||
local k = gtable.hasitem(capi.root._private[prop_name], value)
|
||||
|
||||
if k then
|
||||
table.remove(capi.root._private[prop_name], k)
|
||||
end
|
||||
|
||||
-- Because of the legacy API, it is possible the capi.key/buttons will
|
||||
-- be in the formatted table but not of the awful.key/button one.
|
||||
assert(value[1])
|
||||
|
||||
table.insert(removed, value)
|
||||
end
|
||||
|
||||
capi.root["has_"..type_name] = function(item)
|
||||
if not item["_is_capi_"..type_name] then
|
||||
item = item[1]
|
||||
end
|
||||
|
||||
return gtable.hasitem(capi.root["_"..prop_name](), item) ~= nil
|
||||
end
|
||||
|
||||
assert(root[prop_name])
|
||||
|
||||
end
|
|
@ -290,7 +290,7 @@ function screen.object.get_outputs(s)
|
|||
local ret = {}
|
||||
|
||||
local outputs = s._custom_outputs
|
||||
or (s.data.viewport and s.data.viewport.outputs or s._outputs)
|
||||
or (s._private.viewport and s._private.viewport.outputs or s._outputs)
|
||||
|
||||
-- The reason this exists is because output with name as keys is very
|
||||
-- convenient for quick name lookup by the users, but inconvenient in
|
||||
|
@ -671,9 +671,9 @@ function screen.object.split(s, ratios, mode, _geo)
|
|||
table.insert(ret, ns)
|
||||
|
||||
if s then
|
||||
ns.data.viewport = s.data.viewport
|
||||
ns._private.viewport = s._private.viewport
|
||||
|
||||
if not ns.data.viewport then
|
||||
if not ns._private.viewport then
|
||||
ns.outputs = s.outputs
|
||||
end
|
||||
end
|
||||
|
@ -708,7 +708,7 @@ end
|
|||
-- @staticfct awful.screen.set_auto_dpi_enabled
|
||||
function screen.set_auto_dpi_enabled(enabled)
|
||||
for s in capi.screen do
|
||||
s.data.dpi_cache = nil
|
||||
s._private.dpi_cache = nil
|
||||
end
|
||||
data.autodpi = enabled
|
||||
end
|
||||
|
|
|
@ -150,7 +150,7 @@ end
|
|||
-- Compute more useful viewport metadata frrom_sparse(add)om the list of output.
|
||||
-- @treturn table An viewport with more information.
|
||||
local function update_screen_viewport(s)
|
||||
local viewport = s.data.viewport
|
||||
local viewport = s._private.viewport
|
||||
|
||||
if #ascreen._viewports == 0 then
|
||||
ascreen._viewports = update_viewports(false)
|
||||
|
@ -171,7 +171,7 @@ local function update_screen_viewport(s)
|
|||
end
|
||||
|
||||
if big_a then
|
||||
viewport, s.data.viewport = big_a, big_a
|
||||
viewport, s._private.viewport = big_a, big_a
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -203,7 +203,7 @@ end
|
|||
|
||||
function module.remove_screen_handler(viewport)
|
||||
for s in capi.screen do
|
||||
if s.data.viewport and s.data.viewport.id == viewport.id then
|
||||
if s._private.viewport and s._private.viewport.id == viewport.id then
|
||||
s:fake_remove()
|
||||
return
|
||||
end
|
||||
|
@ -212,12 +212,12 @@ end
|
|||
|
||||
function module.resize_screen_handler(old_viewport, new_viewport)
|
||||
for s in capi.screen do
|
||||
if s.data.viewport and s.data.viewport.id == old_viewport.id then
|
||||
if s._private.viewport and s._private.viewport.id == old_viewport.id then
|
||||
local ngeo = new_viewport.geometry
|
||||
s:fake_resize(
|
||||
ngeo.x, ngeo.y, ngeo.width, ngeo.height
|
||||
)
|
||||
s.data.viewport = new_viewport
|
||||
s._private.viewport = new_viewport
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -274,32 +274,32 @@ function module._get_viewports()
|
|||
end
|
||||
|
||||
local function get_dpi(s)
|
||||
if s.data.dpi or s.data.dpi_cache then
|
||||
return s.data.dpi or s.data.dpi_cache
|
||||
if s._private.dpi or s._private.dpi_cache then
|
||||
return s._private.dpi or s._private.dpi_cache
|
||||
end
|
||||
|
||||
if not s.data.viewport then
|
||||
if not s._private.viewport then
|
||||
update_screen_viewport(s)
|
||||
end
|
||||
|
||||
-- Pick a DPI (from best to worst).
|
||||
local dpi = ascreen._get_xft_dpi()
|
||||
or (s.data.viewport and s.data.viewport.preferred_dpi or nil)
|
||||
or (s._private.viewport and s._private.viewport.preferred_dpi or nil)
|
||||
or get_fallback_dpi()
|
||||
|
||||
-- Pick the screen DPI depending on the `autodpi` settings.
|
||||
-- Historically, AwesomeWM size unit was the pixel. This assumption is
|
||||
-- present in a lot, if not most, user config and is why this cannot be
|
||||
-- enable by default for existing users.
|
||||
s.data.dpi_cache = data.autodpi and dpi
|
||||
s._private.dpi_cache = data.autodpi and dpi
|
||||
or ascreen._get_xft_dpi()
|
||||
or get_fallback_dpi()
|
||||
|
||||
return s.data.dpi_cache
|
||||
return s._private.dpi_cache
|
||||
end
|
||||
|
||||
local function set_dpi(s, dpi)
|
||||
s.data.dpi = dpi
|
||||
s._private.dpi = dpi
|
||||
end
|
||||
|
||||
screen.connect_signal("request::create", module.create_screen_handler)
|
||||
|
@ -362,7 +362,7 @@ capi.screen.connect_signal("property::_viewports", function(a)
|
|||
|
||||
-- Drop the cache.
|
||||
for s in capi.screen do
|
||||
s.data.dpi_cache = nil
|
||||
s._private.dpi_cache = nil
|
||||
end
|
||||
|
||||
capi.screen.emit_signal("property::viewports", ascreen._get_viewports())
|
||||
|
@ -402,11 +402,11 @@ return function(screen, d)
|
|||
"preferred_dpi" } do
|
||||
|
||||
screen.object["get_"..prop] = function(s)
|
||||
if not s.data.viewport then
|
||||
if not s._private.viewport then
|
||||
update_screen_viewport(s)
|
||||
end
|
||||
|
||||
local a = s.data.viewport or {}
|
||||
local a = s._private.viewport or {}
|
||||
|
||||
return a[prop] or nil
|
||||
end
|
||||
|
|
|
@ -283,7 +283,7 @@ function tag.add(name, props)
|
|||
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._private.awful_tag_properties = {screen=properties.screen, index=properties.index}
|
||||
|
||||
newtag.activated = true
|
||||
|
||||
|
@ -402,7 +402,7 @@ function tag.object.delete(self, fallback_tag, force)
|
|||
end
|
||||
|
||||
-- delete the tag
|
||||
self.data.awful_tag_properties.screen = nil
|
||||
self._private.awful_tag_properties.screen = nil
|
||||
self.activated = false
|
||||
|
||||
-- Update all indexes
|
||||
|
@ -1519,7 +1519,7 @@ end
|
|||
-- @tparam tag _tag The tag.
|
||||
-- @return The data table.
|
||||
function tag.getdata(_tag)
|
||||
return _tag.data.awful_tag_properties
|
||||
return _tag._private.awful_tag_properties
|
||||
end
|
||||
|
||||
--- Get a tag property.
|
||||
|
@ -1532,8 +1532,9 @@ end
|
|||
-- @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]
|
||||
|
||||
if _tag._private.awful_tag_properties then
|
||||
return _tag._private.awful_tag_properties[prop]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1548,12 +1549,12 @@ end
|
|||
-- @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 = {}
|
||||
if not _tag._private.awful_tag_properties then
|
||||
_tag._private.awful_tag_properties = {}
|
||||
end
|
||||
|
||||
if _tag.data.awful_tag_properties[prop] ~= value then
|
||||
_tag.data.awful_tag_properties[prop] = value
|
||||
if _tag._private.awful_tag_properties[prop] ~= value then
|
||||
_tag._private.awful_tag_properties[prop] = value
|
||||
_tag:emit_signal("property::" .. prop)
|
||||
end
|
||||
end
|
||||
|
@ -1731,8 +1732,8 @@ capi.screen.connect_signal("removed", function(s)
|
|||
for _, t in pairs(s.tags) do
|
||||
t.activated = false
|
||||
|
||||
if t.data.awful_tag_properties then
|
||||
t.data.awful_tag_properties.screen = nil
|
||||
if t._private.awful_tag_properties then
|
||||
t._private.awful_tag_properties.screen = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -54,7 +54,8 @@ function object.capi_index_fallback(class, args)
|
|||
end
|
||||
|
||||
-- Use the fallback property table
|
||||
return cobj.data[prop]
|
||||
assert(prop ~= "_private")
|
||||
return cobj._private[prop]
|
||||
end
|
||||
|
||||
local setter = args.setter or function(cobj, prop, value)
|
||||
|
@ -74,7 +75,7 @@ function object.capi_index_fallback(class, args)
|
|||
end
|
||||
|
||||
-- Use the fallback property table
|
||||
cobj.data[prop] = value
|
||||
cobj._private[prop] = value
|
||||
|
||||
-- Emit the signal
|
||||
if args.auto_emit then
|
||||
|
@ -87,6 +88,36 @@ function object.capi_index_fallback(class, args)
|
|||
class.set_newindex_miss_handler(setter)
|
||||
end
|
||||
|
||||
-- Convert the capi objects back into awful ones.
|
||||
local function deprecated_to_current(content)
|
||||
local first = content[1]
|
||||
|
||||
local current = first and first._private and
|
||||
first._private._legacy_convert_to or nil
|
||||
|
||||
if not current then return nil end
|
||||
|
||||
local ret = {current}
|
||||
|
||||
for _, o in ipairs(content) do
|
||||
-- If this is false, someone tried to mix things in a
|
||||
-- way that is definitely not intentional.
|
||||
assert(o._private and o._private._legacy_convert_to)
|
||||
|
||||
if o._private._legacy_convert_to ~= current then
|
||||
-- If this is false, someone tried to mix things in a
|
||||
-- way that is definitely not intentional.
|
||||
assert(o._private._legacy_convert_to)
|
||||
|
||||
table.insert(
|
||||
ret, o._private._legacy_convert_to
|
||||
)
|
||||
current = o._private._legacy_convert_to
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
-- (private api)
|
||||
-- Many legacy Awesome APIs such as `client:tags()`, `root.buttons()`,
|
||||
|
@ -129,7 +160,15 @@ local function copy_object(obj, to_set, name, capi_name, is_object, join_if, set
|
|||
local result = is_formatted and
|
||||
new_objs or gtable.join(unpack(new_objs))
|
||||
|
||||
if capi_name and is_object then
|
||||
-- First, when possible, get rid of the legacy format and go
|
||||
-- back to the non-deprecated code path.
|
||||
local current = self["set_"..name]
|
||||
and deprecated_to_current(result) or nil
|
||||
|
||||
if current then
|
||||
self["set_"..name](self, current)
|
||||
return capi_name and self[capi_name](self) or self[name]
|
||||
elseif capi_name and is_object then
|
||||
return self[capi_name](self, result)
|
||||
elseif capi_name then
|
||||
return self[capi_name](result)
|
||||
|
@ -161,18 +200,13 @@ function object._legacy_accessors(obj, name, capi_name, is_object, join_if, set_
|
|||
magic_obj["get_"..name] = function(self)
|
||||
self = is_object and self or obj
|
||||
|
||||
--FIXME v5 all objects should use _private instead of getproperty.
|
||||
if not self._private then
|
||||
self._private = {}
|
||||
end
|
||||
|
||||
self._private[name] = self._private[name] or copy_object(
|
||||
obj, {}, name, capi_name, is_object, join_if, set_empty
|
||||
)
|
||||
|
||||
local current = deprecated_to_current(self._private[name])
|
||||
|
||||
assert(self._private[name])
|
||||
return self._private[name]
|
||||
return current or self._private[name]
|
||||
end
|
||||
|
||||
magic_obj["set_"..name] = function(self, objs)
|
||||
|
@ -181,7 +215,25 @@ function object._legacy_accessors(obj, name, capi_name, is_object, join_if, set_
|
|||
if not is_object then
|
||||
objs, self = self, obj
|
||||
end
|
||||
assert(objs)
|
||||
|
||||
-- When using lua expressions like `false and true and my_objects`,
|
||||
-- it is possible the code ends up as a boolean rather than `nil`
|
||||
-- the resulting type is sometime counter intuitive and different
|
||||
-- from similar languages such as JavaScript. Be forgiving and correct
|
||||
-- course.
|
||||
if objs == false then
|
||||
objs = nil
|
||||
end
|
||||
|
||||
-- Sometime, setting `nil` might be volontary since the user might
|
||||
-- expect it will act as "clear". The correct thing would be to set
|
||||
-- `{}`, but allow it nevertheless.
|
||||
|
||||
if objs == nil then
|
||||
objs = {}
|
||||
end
|
||||
|
||||
assert(self)
|
||||
|
||||
-- When called from a declarative property list, "buttons" will be set
|
||||
-- using the result of gears.table.join, detect this
|
||||
|
|
|
@ -66,7 +66,8 @@ function wibox:find_widgets(x, y)
|
|||
end
|
||||
|
||||
function wibox:_buttons(btns)
|
||||
return self.drawin:_buttons(btns)
|
||||
-- The C code uses the argument count, `nil` counts.
|
||||
return btns and self.drawin:_buttons(btns) or self.drawin:_buttons()
|
||||
end
|
||||
|
||||
--- Create a widget that reflects the current state of this wibox.
|
||||
|
@ -277,7 +278,6 @@ local function new(args)
|
|||
return ret
|
||||
end
|
||||
|
||||
w._private = {}
|
||||
ret.drawin = w
|
||||
ret._drawable = wibox.drawable(w.drawable, { wibox = ret },
|
||||
"wibox drawable (" .. object.modulename(3) .. ")")
|
||||
|
|
2
mouse.c
2
mouse.c
|
@ -57,7 +57,7 @@
|
|||
*
|
||||
* @author Julien Danjou <julien@danjou.info>
|
||||
* @copyright 2008-2009 Julien Danjou
|
||||
* @coreclassmod mouse
|
||||
* @inputmodule mouse
|
||||
*/
|
||||
|
||||
#include "mouse.h"
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
-- @copyright 2015 Uli Schlachter and Kazunobu Kuriyama
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- luacheck: globals button
|
||||
_G.button = setmetatable({
|
||||
set_index_miss_handler = function() end,
|
||||
set_newindex_miss_handler = function() end
|
||||
}, {
|
||||
__call = function() return {} end
|
||||
})
|
||||
|
||||
local kb = require("awful.widget.keyboardlayout")
|
||||
|
||||
describe("awful.widget.keyboardlayout get_groups_from_group_names", function()
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
_G.key = setmetatable({
|
||||
set_index_miss_handler = function() end,
|
||||
set_newindex_miss_handler = function() end
|
||||
}, {
|
||||
__call = function() return {} end
|
||||
})
|
||||
|
||||
local function assert_markup_format(markup)
|
||||
if #markup == 0 then
|
||||
return
|
||||
|
|
|
@ -752,7 +752,7 @@ function module.display_tags()
|
|||
selected = t.selected,
|
||||
icon = t.icon,
|
||||
screen = t.screen,
|
||||
data = t.data,
|
||||
_private = t._private,
|
||||
clients = t.clients,
|
||||
layout = t.layout,
|
||||
master_width_factor = t.master_width_factor,
|
||||
|
|
|
@ -6,7 +6,10 @@ local gears_obj = require("gears.object")
|
|||
-- handlers.
|
||||
local function _shim_fake_class()
|
||||
local obj = gears_obj()
|
||||
obj.data = {}
|
||||
obj._private = {}
|
||||
|
||||
-- Deprecated.
|
||||
obj.data = obj._private
|
||||
|
||||
local meta = {
|
||||
__index = function()end,
|
||||
|
|
|
@ -1,7 +1,35 @@
|
|||
return function() return {
|
||||
data = {},
|
||||
_is_capi_button = true,
|
||||
connect_signal = function() end
|
||||
} end
|
||||
local gears_obj = require("gears.object")
|
||||
|
||||
local button, meta = awesome._shim_fake_class()
|
||||
|
||||
local function new_button(_, args)
|
||||
local ret = gears_obj()
|
||||
ret._private = args or {}
|
||||
|
||||
-- The miss handler wont work for this.
|
||||
for k, v in pairs(ret._private) do
|
||||
rawset(ret, k, v)
|
||||
end
|
||||
|
||||
if not rawget(ret, "modifiers") then
|
||||
rawset(ret, "modifiers", {})
|
||||
end
|
||||
|
||||
--TODO v5: remove this.
|
||||
ret.data = ret._private
|
||||
|
||||
rawset(ret, "_is_capi_button", true)
|
||||
|
||||
local md = setmetatable(ret, {
|
||||
__index = function(...) return meta.__index(...) end,
|
||||
__newindex = function(...) return meta.__newindex(...) end
|
||||
})
|
||||
|
||||
assert((not args) or args.button == md.button)
|
||||
|
||||
return md
|
||||
end
|
||||
|
||||
return setmetatable(button, { __call = new_button, })
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -28,11 +28,11 @@ local properties = {}
|
|||
for _, prop in ipairs {
|
||||
"maximized", "maximized_horizontal", "maximized_vertical", "fullscreen" } do
|
||||
properties["get_"..prop] = function(self)
|
||||
return self.data[prop] or false
|
||||
return self._private[prop] or false
|
||||
end
|
||||
|
||||
properties["set_"..prop] = function(self, value)
|
||||
self.data[prop] = value or false
|
||||
self._private[prop] = value or false
|
||||
|
||||
if value then
|
||||
self:emit_signal("request::geometry", prop, nil)
|
||||
|
@ -43,12 +43,12 @@ for _, prop in ipairs {
|
|||
end
|
||||
|
||||
function properties.get_screen(self)
|
||||
return self.data.screen or screen[1]
|
||||
return self._private.screen or screen[1]
|
||||
end
|
||||
|
||||
function properties.set_screen(self, s)
|
||||
s = screen[s]
|
||||
self.data.screen = s
|
||||
self._private.screen = s
|
||||
|
||||
if self.x < s.geometry.x or self.x > s.geometry.x+s.geometry.width then
|
||||
self:geometry { x = s.geometry.x }
|
||||
|
@ -66,14 +66,18 @@ function client.gen_fake(args)
|
|||
local ret = gears_obj()
|
||||
awesome._forward_class(ret, client)
|
||||
|
||||
ret.data = {}
|
||||
ret._private = {}
|
||||
ret.type = "normal"
|
||||
ret.valid = true
|
||||
ret.size_hints = {}
|
||||
ret.border_width = 1
|
||||
ret.icon_sizes = {{16,16}}
|
||||
ret.name = "Example Client"
|
||||
ret.data._struts = { top = 0, right = 0, left = 0, bottom = 0 }
|
||||
ret._private._struts = { top = 0, right = 0, left = 0, bottom = 0 }
|
||||
|
||||
--TODO v5: remove this. This was a private API and thus doesn't need to be
|
||||
-- officially deprecated.
|
||||
ret.data = ret._private
|
||||
|
||||
-- This is a hack because there's a `:is_transient_for(c2)` method
|
||||
-- and a `transient_for` property. It will cause a stack overflow
|
||||
|
@ -194,10 +198,10 @@ function client.gen_fake(args)
|
|||
|
||||
function ret:struts(new)
|
||||
for k, v in pairs(new or {}) do
|
||||
ret.data._struts[k] = v
|
||||
ret._private._struts[k] = v
|
||||
end
|
||||
|
||||
return ret.data._struts
|
||||
return ret._private._struts
|
||||
end
|
||||
|
||||
-- Set a dummy one for now since set_screen will corrupt it.
|
||||
|
@ -243,6 +247,23 @@ function client.gen_fake(args)
|
|||
ret.above = false
|
||||
ret.sticky = false
|
||||
|
||||
-- Declare the deprecated buttons and keys methods.
|
||||
function ret:_keys(new)
|
||||
if new then
|
||||
ret._private.keys = new
|
||||
end
|
||||
|
||||
return ret._private.keys or {}
|
||||
end
|
||||
|
||||
function ret:_buttons(new)
|
||||
if new then
|
||||
ret._private.buttons = new
|
||||
end
|
||||
|
||||
return ret._private.buttons or {}
|
||||
end
|
||||
|
||||
-- Add to the client list
|
||||
table.insert(clients, ret)
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ local cairo = require("lgi").cairo
|
|||
|
||||
local function new_drawin(_, args)
|
||||
local ret = gears_obj()
|
||||
ret.data = {drawable = gears_obj()}
|
||||
ret._private = {drawable = gears_obj()}
|
||||
|
||||
-- Deprecated.
|
||||
ret.data = ret._private
|
||||
|
||||
ret.x=0
|
||||
ret.y=0
|
||||
|
@ -31,11 +34,11 @@ local function new_drawin(_, args)
|
|||
}
|
||||
end
|
||||
|
||||
ret.data.drawable.valid = true
|
||||
ret.data.drawable.surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
|
||||
ret.data.drawable.geometry = ret.geometry
|
||||
ret.data.drawable.refresh = function() end
|
||||
ret.data._struts = { top = 0, right = 0, left = 0, bottom = 0 }
|
||||
ret._private.drawable.valid = true
|
||||
ret._private.drawable.surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
|
||||
ret._private.drawable.geometry = ret.geometry
|
||||
ret._private.drawable.refresh = function() end
|
||||
ret._private._struts = { top = 0, right = 0, left = 0, bottom = 0 }
|
||||
|
||||
for _, k in pairs{ "_buttons", "get_xproperty", "set_xproperty" } do
|
||||
ret[k] = function() end
|
||||
|
@ -43,10 +46,10 @@ local function new_drawin(_, args)
|
|||
|
||||
function ret:struts(new)
|
||||
for k, v in pairs(new or {}) do
|
||||
ret.data._struts[k] = v
|
||||
ret._private._struts[k] = v
|
||||
end
|
||||
|
||||
return ret.data._struts
|
||||
return ret._private._struts
|
||||
end
|
||||
|
||||
local md = setmetatable(ret, {
|
||||
|
|
|
@ -1,6 +1,31 @@
|
|||
local gobject = require("gears.object")
|
||||
local gtable = require("gears.table")
|
||||
local gears_obj = require("gears.object")
|
||||
|
||||
return setmetatable({_is_capi_key = true}, {__call = function(_, args)
|
||||
return gtable.crush(gobject(), args)
|
||||
end})
|
||||
local key, meta = awesome._shim_fake_class()
|
||||
|
||||
local function new_key(_, args)
|
||||
local ret = gears_obj()
|
||||
ret._private = args or {}
|
||||
|
||||
-- The miss handler wont work for this.
|
||||
for k, v in pairs(ret._private) do
|
||||
rawset(ret, k, v)
|
||||
end
|
||||
|
||||
--TODO v5: remove this.
|
||||
ret.data = ret._private
|
||||
|
||||
rawset(ret, "_is_capi_key", true)
|
||||
|
||||
local md = setmetatable(ret, {
|
||||
__index = function(...) return meta.__index(...) end,
|
||||
__newindex = function(...) return meta.__newindex(...) end
|
||||
})
|
||||
|
||||
assert((not args) or args.key == md.key)
|
||||
|
||||
return md
|
||||
end
|
||||
|
||||
return setmetatable(key, { __call = new_key, })
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -2,8 +2,6 @@ local root = {_tags={}}
|
|||
|
||||
local gtable = require("gears.table")
|
||||
|
||||
local hotkeys = nil
|
||||
|
||||
function root:tags()
|
||||
return root._tags
|
||||
end
|
||||
|
@ -86,15 +84,9 @@ local function match_modifiers(mods1, mods2)
|
|||
end
|
||||
|
||||
local function execute_keybinding(key, event)
|
||||
-- It *could* be extracted from gears.object private API, but it's equally
|
||||
-- ugly as using the list used by the hotkey widget.
|
||||
if not hotkeys then
|
||||
hotkeys = require("awful.key").hotkeys
|
||||
end
|
||||
|
||||
for _, v in ipairs(hotkeys) do
|
||||
if key == v.key and match_modifiers(v.mod, get_mods()) and v[event] then
|
||||
v[event]()
|
||||
for _, v in ipairs(keys) do
|
||||
if key == v.key and match_modifiers(v.modifiers, get_mods()) then
|
||||
v:emit_signal(event)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,9 +31,12 @@ local function create_screen(args)
|
|||
local s = gears_obj()
|
||||
awesome._forward_class(s, screen)
|
||||
|
||||
s.data = {}
|
||||
s._private = {}
|
||||
s.valid = true
|
||||
|
||||
-- Deprecated.
|
||||
s.data = s._private
|
||||
|
||||
-- Copy the geo in case the args are mutated
|
||||
local geo = {
|
||||
x = args.x ,
|
||||
|
|
|
@ -15,11 +15,14 @@ local function new_tag(_, args)
|
|||
local ret = gears_obj()
|
||||
awesome._forward_class(ret, tag)
|
||||
|
||||
ret.data = {}
|
||||
ret._private = {}
|
||||
ret.name = tostring(args.name) or "test"
|
||||
ret.activated = true
|
||||
ret.selected = not has_selected_tag(args.screen)
|
||||
|
||||
-- Deprecated.
|
||||
ret.data = ret._private
|
||||
|
||||
function ret:clients(_) --TODO handle new
|
||||
local list = {}
|
||||
for _, c in ipairs(client.get()) do
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
local was_called = {} --DOC_HIDE
|
||||
|
||||
local awful = {keygrabber = require("awful.keygrabber"), --DOC_HIDE
|
||||
local awful = { keygrabber = require("awful.keygrabber"), --DOC_HIDE
|
||||
key = require("awful.key"), --DOC_HIDE
|
||||
client={focus={history={--DOC_HIDE
|
||||
disable_tracking = function() was_called[1] = true end, --DOC_HIDE
|
||||
enable_tracking = function() was_called[2] = true end, --DOC_HIDE
|
||||
|
@ -12,8 +13,16 @@ local awful = {keygrabber = require("awful.keygrabber"), --DOC_HIDE
|
|||
|
||||
awful.keygrabber {
|
||||
keybindings = {
|
||||
{{"Mod1" }, "Tab", awful.client.focus.history.select_previous},
|
||||
{{"Mod1", "Shift"}, "Tab", awful.client.focus.history.select_next },
|
||||
awful.key {
|
||||
modifiers = {"Mod1"},
|
||||
key = "Tab",
|
||||
on_press = awful.client.focus.history.select_previous
|
||||
},
|
||||
awful.key {
|
||||
modifiers = {"Mod1", "Shift"},
|
||||
key = "Tab",
|
||||
on_press = awful.client.focus.history.select_next
|
||||
},
|
||||
},
|
||||
-- Note that it is using the key name and not the modifier name.
|
||||
stop_key = "Mod1",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
--DOC_GEN_OUTPUT --DOC_HIDE
|
||||
local awful = { keygrabber = require("awful.keygrabber") } --DOC_HIDE
|
||||
local awful = { keygrabber = require("awful.keygrabber"), --DOC_HIDE
|
||||
key = require("awful.key") } --DOC_HIDE
|
||||
|
||||
local keybinding_works = {} --DOC_HIDE
|
||||
|
||||
|
@ -7,17 +8,25 @@ local g = --DOC_HIDE
|
|||
awful.keygrabber {
|
||||
mask_modkeys = true,
|
||||
root_keybindings = {
|
||||
{{"Mod4"}, "i", function(self)
|
||||
awful.key {
|
||||
modifiers = {"Mod4"},
|
||||
key = "i",
|
||||
on_press = function(self)
|
||||
print("Is now active!", self)
|
||||
keybinding_works[1] = true --DOC_HIDE
|
||||
end},
|
||||
end
|
||||
},
|
||||
},
|
||||
keybindings = {
|
||||
{{"Mod4", "Shift"}, "i", function(self)
|
||||
awful.key {
|
||||
modifiers = {"Mod4", "Shift"},
|
||||
key = "i",
|
||||
on_press = function(self)
|
||||
print("Called again!")
|
||||
keybinding_works[3] = true --DOC_HIDE
|
||||
self:stop()
|
||||
end},
|
||||
end
|
||||
},
|
||||
},
|
||||
keypressed_callback = function(_, modifiers, key)
|
||||
print("A key was pressed:", key, "with", #modifiers, "modifier!")
|
||||
|
@ -52,7 +61,6 @@ assert(keybinding_works[2] == 2) --DOC_HIDE because mask_modkeys is set
|
|||
assert(g == awful.keygrabber.current_instance) --DOC_HIDE
|
||||
assert(not keybinding_works[3])--DOC_HIDE
|
||||
|
||||
|
||||
--DOC_NEWLINE
|
||||
-- Now the keygrabber own keybindings will work
|
||||
root._execute_keybinding({"Mod4", "Shift"}, "i")
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
local gears = {table = require("gears.table")} --DOC_HIDE
|
||||
|
||||
local awful = { keygrabber = require("awful.keygrabber") } --DOC_HIDE
|
||||
local awful = { keygrabber = require("awful.keygrabber"), --DOC_HIDE
|
||||
key = require("awful.key") } --DOC_HIDE
|
||||
|
||||
local map, actions = {
|
||||
verbs = {
|
||||
|
@ -44,6 +45,6 @@ local awful = { keygrabber = require("awful.keygrabber") } --DOC_HIDE
|
|||
stop_callback = parse,
|
||||
stop_key = gears.table.keys(map.verbs),
|
||||
root_keybindings = {
|
||||
{{"Mod4"}, "v"}
|
||||
awful.key({"Mod4"}, "v")
|
||||
},
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ local steps = {
|
|||
local l = old_c.screen.selected_tag.layout
|
||||
assert(l)
|
||||
|
||||
--awful.key.execute({modkey}, " ")
|
||||
--awful.keyboard.emulate_key_combination({modkey}, " ")
|
||||
awful.layout.inc(1)
|
||||
|
||||
assert(old_c.screen.selected_tag.layout ~= l)
|
||||
|
@ -56,7 +56,7 @@ local steps = {
|
|||
-- Test ontop
|
||||
|
||||
assert(not old_c.ontop)
|
||||
awful.key.execute({modkey}, "t")
|
||||
awful.keyboard.emulate_key_combination({modkey}, "t")
|
||||
awesome.sync()
|
||||
|
||||
return true
|
||||
|
@ -74,7 +74,7 @@ local steps = {
|
|||
-- Now, test the master_width_factor
|
||||
assert(t.master_width_factor == 0.5)
|
||||
|
||||
awful.key.execute({modkey}, "l")
|
||||
awful.keyboard.emulate_key_combination({modkey}, "l")
|
||||
awesome.sync()
|
||||
|
||||
return true
|
||||
|
@ -89,7 +89,7 @@ local steps = {
|
|||
-- Now, test the master_count
|
||||
assert(t.master_count == 1)
|
||||
|
||||
awful.key.execute({modkey, "Shift"}, "h")
|
||||
awful.keyboard.emulate_key_combination({modkey, "Shift"}, "h")
|
||||
awesome.sync()
|
||||
|
||||
return true
|
||||
|
@ -104,8 +104,8 @@ local steps = {
|
|||
-- Now, test the column_count
|
||||
assert(t.column_count == 1)
|
||||
|
||||
awful.key.execute({modkey, "Control"}, "h")
|
||||
awful.key.execute({modkey, "Shift" }, "l")
|
||||
awful.keyboard.emulate_key_combination({modkey, "Control"}, "h")
|
||||
awful.keyboard.emulate_key_combination({modkey, "Shift" }, "l")
|
||||
awesome.sync()
|
||||
|
||||
return true
|
||||
|
@ -120,7 +120,7 @@ local steps = {
|
|||
-- Now, test the switching tag
|
||||
assert(t.index == 1)
|
||||
|
||||
awful.key.execute({modkey, }, "Right")
|
||||
awful.keyboard.emulate_key_combination({modkey, }, "Right")
|
||||
awesome.sync()
|
||||
|
||||
return true
|
||||
|
@ -200,7 +200,7 @@ local steps = {
|
|||
-- tags[1] and the client history should be kept
|
||||
assert(client.focus == old_c)
|
||||
|
||||
--awful.key.execute({modkey, "Shift" }, "#"..(9+i)) --FIXME
|
||||
--awful.keyboard.emulate_key_combination({modkey, "Shift" }, "#"..(9+i)) --FIXME
|
||||
client.focus:move_to_tag(tags[2])
|
||||
|
||||
assert(not client.focus)
|
||||
|
@ -235,7 +235,7 @@ local steps = {
|
|||
|
||||
if count == 1 then
|
||||
assert(num_pairs(cached_wiboxes) == 0)
|
||||
awful.key.execute({modkey}, "s")
|
||||
awful.keyboard.emulate_key_combination({modkey}, "s")
|
||||
return nil
|
||||
|
||||
elseif count == 2 then
|
||||
|
@ -280,7 +280,7 @@ local steps = {
|
|||
test_context.hotkeys01_clients_before < #client.get()
|
||||
) then
|
||||
-- open hotkeys popup with vim hotkeys:
|
||||
awful.key.execute({modkey}, "s")
|
||||
awful.keyboard.emulate_key_combination({modkey}, "s")
|
||||
test_context.hotkeys01_count_vim = count
|
||||
end
|
||||
|
||||
|
|
|
@ -64,27 +64,27 @@ local function fake_replay(viewports)
|
|||
local s = screen[k]
|
||||
|
||||
-- Check if the extra metadata are computed.
|
||||
assert(s.data.viewport.maximum_dpi)
|
||||
assert(s.data.viewport.minimum_dpi)
|
||||
assert(s.data.viewport.preferred_dpi)
|
||||
assert(s._private.viewport.maximum_dpi)
|
||||
assert(s._private.viewport.minimum_dpi)
|
||||
assert(s._private.viewport.preferred_dpi)
|
||||
assert(s.dpi)
|
||||
assert(s.maximum_dpi == s.data.viewport.maximum_dpi )
|
||||
assert(s.minimum_dpi == s.data.viewport.minimum_dpi )
|
||||
assert(s.preferred_dpi == s.data.viewport.preferred_dpi)
|
||||
assert(s.maximum_dpi == s._private.viewport.maximum_dpi )
|
||||
assert(s.minimum_dpi == s._private.viewport.minimum_dpi )
|
||||
assert(s.preferred_dpi == s._private.viewport.preferred_dpi)
|
||||
|
||||
-- Make sure it enters either the main `if` or the fallback one.
|
||||
assert(s.data.viewport.minimum_dpi ~= math.huge)
|
||||
assert(s.data.viewport.preferred_dpi ~= math.huge)
|
||||
assert(s._private.viewport.minimum_dpi ~= math.huge)
|
||||
assert(s._private.viewport.preferred_dpi ~= math.huge)
|
||||
|
||||
-- Check the range.
|
||||
assert(s.data.viewport.maximum_dpi >= s.data.viewport.minimum_dpi)
|
||||
assert(s.data.viewport.preferred_dpi >= s.data.viewport.minimum_dpi)
|
||||
assert(s.data.viewport.preferred_dpi <= s.data.viewport.maximum_dpi)
|
||||
assert(s._private.viewport.maximum_dpi >= s._private.viewport.minimum_dpi)
|
||||
assert(s._private.viewport.preferred_dpi >= s._private.viewport.minimum_dpi)
|
||||
assert(s._private.viewport.preferred_dpi <= s._private.viewport.maximum_dpi)
|
||||
|
||||
-- Check if the screen was created using the right viewport
|
||||
-- (order *is* relevant).
|
||||
assert(#s.data.viewport.outputs == #a.outputs)
|
||||
assert(s.data.viewport and s.data.viewport.id == a.id)
|
||||
assert(#s._private.viewport.outputs == #a.outputs)
|
||||
assert(s._private.viewport and s._private.viewport.id == a.id)
|
||||
end
|
||||
|
||||
-- The original shall not be modified, the CAPI for this is read-only.
|
||||
|
@ -314,7 +314,7 @@ end,
|
|||
|
||||
-- Test adding an output.
|
||||
function()
|
||||
local viewport = screen[1].data.viewport
|
||||
local viewport = screen[1]._private.viewport
|
||||
|
||||
add_output(fake_viewports[1], {
|
||||
name = "foobar",
|
||||
|
@ -328,24 +328,24 @@ function()
|
|||
})
|
||||
|
||||
-- It should have been kept.
|
||||
assert(viewport == screen[1].data.viewport)
|
||||
assert(viewport == screen[1]._private.viewport)
|
||||
|
||||
-- If this isn't true, then auto-dpi didn't do its job.
|
||||
assert(screen[1].dpi ~= saved_dpi1)
|
||||
|
||||
-- Now that there is multiple DPIs for the same viewport, the number
|
||||
-- should double.
|
||||
assert(#screen[1].data.viewport.outputs == 3)
|
||||
assert(#screen[1]._private.viewport.outputs == 3)
|
||||
assert(screen[1].maximum_dpi == saved_dpi2*2)
|
||||
assert(screen[1].minimum_dpi == saved_dpi3/2)
|
||||
assert(screen[1].dpi == saved_dpi1/2)
|
||||
|
||||
remove_output(fake_viewports[1], "leet")
|
||||
assert(#screen[1].data.viewport.outputs == 2)
|
||||
assert(#screen[1]._private.viewport.outputs == 2)
|
||||
remove_output(fake_viewports[1], "foobar")
|
||||
|
||||
-- At this point, only 1 DPI is left.
|
||||
assert(#screen[1].data.viewport.outputs == 1)
|
||||
assert(#screen[1]._private.viewport.outputs == 1)
|
||||
assert(screen[1].maximum_dpi == saved_dpi1/2)
|
||||
assert(screen[1].minimum_dpi == saved_dpi1/2)
|
||||
assert(screen[1].dpi == saved_dpi1/2)
|
||||
|
@ -368,25 +368,25 @@ function()
|
|||
}
|
||||
|
||||
assert(screen.count() == 2)
|
||||
assert(screen[1].data.viewport.id == 10)
|
||||
assert(screen[2].data.viewport.id == 11)
|
||||
assert(grect.are_equal(screen[1].data.viewport.geometry, screen[1].geometry))
|
||||
assert(grect.are_equal(screen[2].data.viewport.geometry, screen[2].geometry))
|
||||
assert(screen[1]._private.viewport.id == 10)
|
||||
assert(screen[2]._private.viewport.id == 11)
|
||||
assert(grect.are_equal(screen[1]._private.viewport.geometry, screen[1].geometry))
|
||||
assert(grect.are_equal(screen[2]._private.viewport.geometry, screen[2].geometry))
|
||||
assert(#ascreen._viewports == 2)
|
||||
|
||||
remove_viewport(10)
|
||||
|
||||
assert(#ascreen._viewports == 1)
|
||||
assert(screen.count() == 1)
|
||||
assert(screen[1].data.viewport.id == 11)
|
||||
assert(grect.are_equal(screen[1].data.viewport.geometry, screen[1].geometry))
|
||||
assert(screen[1]._private.viewport.id == 11)
|
||||
assert(grect.are_equal(screen[1]._private.viewport.geometry, screen[1].geometry))
|
||||
|
||||
return true
|
||||
end,
|
||||
|
||||
-- Test resizing.
|
||||
function()
|
||||
local s, sa = screen[1], screen[1].data.viewport
|
||||
local s, sa = screen[1], screen[1]._private.viewport
|
||||
assert(screen.count() == 1)
|
||||
assert(#ascreen._viewports == 1)
|
||||
|
||||
|
@ -403,8 +403,8 @@ function()
|
|||
|
||||
assert(screen.count() == 1)
|
||||
assert(s == screen[1])
|
||||
assert(s.data.viewport ~= sa)
|
||||
assert(s.data.viewport.id == 12)
|
||||
assert(s._private.viewport ~= sa)
|
||||
assert(s._private.viewport.id == 12)
|
||||
|
||||
-- Now 2 smaller (resolution) screens side by side to make sure it doesn't
|
||||
-- go haywire with overlapping
|
||||
|
@ -423,7 +423,7 @@ function()
|
|||
|
||||
assert(screen.count() == 2)
|
||||
assert(s == screen[1])
|
||||
assert(s.data.viewport.id == 13)
|
||||
assert(s._private.viewport.id == 13)
|
||||
assert(s.geometry.x == 1337)
|
||||
assert(s.geometry.width == 680)
|
||||
|
||||
|
@ -453,8 +453,8 @@ function()
|
|||
}
|
||||
|
||||
assert(screen.count() == 2)
|
||||
assert(screen[1].data.viewport.id == 15)
|
||||
assert(screen[2].data.viewport.id == 16)
|
||||
assert(screen[1]._private.viewport.id == 15)
|
||||
assert(screen[2]._private.viewport.id == 16)
|
||||
|
||||
-- Connect custom handler and see if the internals accidently depend on
|
||||
-- implementation details.
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
require("awful._compat")
|
||||
|
||||
local runner = require( "_runner" )
|
||||
local placement = require( "awful.placement" )
|
||||
local gtable = require( "gears.table" )
|
||||
local test_client = require( "_client" )
|
||||
|
||||
local module = {
|
||||
key = require( "awful.key" ),
|
||||
button = require( "awful.button" )
|
||||
}
|
||||
|
||||
local steps = {}
|
||||
|
||||
local second = {
|
||||
key = { "a", "b", "c", "d" },
|
||||
button = { 1 , 2 , 3 , 4 },
|
||||
}
|
||||
|
||||
local function send_events(event_type, step)
|
||||
root.fake_input("key_press" , "Alt_L")
|
||||
root.fake_input(event_type.."_press" , second[event_type][step])
|
||||
root.fake_input(event_type.."_release", second[event_type][step])
|
||||
root.fake_input("key_release", "Alt_L")
|
||||
end
|
||||
|
||||
-- Test the shared API between the keys and buttons
|
||||
for _, type_name in ipairs { "key", "button" } do
|
||||
local objects = {}
|
||||
|
||||
local pressed, released = {}, {}
|
||||
|
||||
table.insert(steps, function()
|
||||
objects[1] = module[type_name](
|
||||
{"Mod1"}, second[type_name][1], function() pressed[1] = true end, function() released[1] = true end
|
||||
)
|
||||
|
||||
assert(objects[1].has_root_binding == false)
|
||||
assert(not pressed [1])
|
||||
assert(not released[1])
|
||||
|
||||
root["_append_"..type_name](objects[1])
|
||||
|
||||
-- It is async, the result need to be verified later
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
assert(objects[1].has_root_binding)
|
||||
|
||||
-- Test "artificial" execution
|
||||
objects[1]:trigger()
|
||||
|
||||
assert(pressed [1])
|
||||
assert(released[1])
|
||||
|
||||
-- Test adding and removing in the same iteration
|
||||
root["_remove_"..type_name](objects[1])
|
||||
|
||||
assert(second[type_name][2])
|
||||
|
||||
-- Use the multiple parameters syntax.
|
||||
objects[2] = module[type_name](
|
||||
{"Mod1"}, second[type_name][2], function() pressed[2] = true end, function() released[2] = true end
|
||||
)
|
||||
|
||||
root["_append_"..type_name](objects[2])
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
assert(objects[2].has_root_binding == true )
|
||||
assert(objects[1].has_root_binding == false)
|
||||
|
||||
-- Make sure the cursor is not over the wibar
|
||||
placement.centered(mouse)
|
||||
|
||||
assert(second[type_name][2])
|
||||
send_events(type_name, 2)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Wait until the events are registered.
|
||||
table.insert(steps, function()
|
||||
if (not pressed[2]) or (not released[2]) then return end
|
||||
|
||||
-- Spawn a client.
|
||||
test_client("myclient")
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
--FIXME it works when manually tested, but automated testing is too flacky
|
||||
-- to enable...
|
||||
if type_name == "key" then
|
||||
table.insert(steps, function()
|
||||
if #mouse.screen.clients ~= 1 then return end
|
||||
|
||||
placement.maximize(mouse.screen.clients[1])
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
local o1, o2 = nil
|
||||
|
||||
table.insert(steps, function()
|
||||
local c = mouse.screen.clients[1]
|
||||
|
||||
-- This time, use the `args` syntax.
|
||||
local args = {
|
||||
modifiers = {"Mod1"},
|
||||
on_press = function() pressed [3] = true end,
|
||||
on_release = function() released[3] = true end
|
||||
}
|
||||
|
||||
args[type_name] = second[type_name][3]
|
||||
|
||||
-- This time, use the `args` syntax.
|
||||
o1 = module[type_name](args)
|
||||
|
||||
-- Test the old API.
|
||||
c[type_name.."s"](c, gtable.join(o1))
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- This wont work until the client buttons/keys are updated, there is no
|
||||
-- way to know ahead of time.
|
||||
table.insert(steps, function(count)
|
||||
|
||||
if count < 5 then awesome.sync(); return end
|
||||
|
||||
send_events(type_name, 3)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
if (not pressed[3]) or (not released[3]) then return end
|
||||
|
||||
local c = mouse.screen.clients[1]
|
||||
|
||||
-- Unset the events to make sure keys can be removed.
|
||||
pressed[3], released[3] = false, false
|
||||
|
||||
o2 = module[type_name](
|
||||
{"Mod1"}, second[type_name][4], function() pressed[4] = true end, function() released[4] = true end
|
||||
)
|
||||
|
||||
-- Test the new API
|
||||
c[type_name.."s"] = {o2}
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function(count)
|
||||
if count < 5 then awesome.sync(); return end
|
||||
|
||||
send_events(type_name, 3)
|
||||
send_events(type_name, 4)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
if (not pressed[4]) or (not released[4]) then return end
|
||||
|
||||
assert(not pressed [3])
|
||||
assert(not released[3])
|
||||
|
||||
local c = mouse.screen.clients[1]
|
||||
|
||||
-- Make sure mixing the 2 syntaxes doesn't create a chimera state
|
||||
pressed[4], released[4] = false, false
|
||||
|
||||
-- This *will* happen with older configs because `awful.rules` will
|
||||
-- loop the properties, find the old capi list and fail to understand
|
||||
-- that the content should use the legacy API.
|
||||
|
||||
local joined = gtable.join(o1)
|
||||
|
||||
assert(#joined == 4)
|
||||
|
||||
c[type_name.."s"] = joined
|
||||
|
||||
-- It should have been converted to the new format.
|
||||
assert(#c[type_name.."s"] == 1)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function(count)
|
||||
if count < 5 then awesome.sync(); return end
|
||||
|
||||
send_events(type_name, 3)
|
||||
send_events(type_name, 4)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
if (not pressed[3]) or (not released[3]) then return end
|
||||
|
||||
assert(not pressed [4])
|
||||
assert(not released[4])
|
||||
|
||||
local c = mouse.screen.clients[1]
|
||||
|
||||
assert(#c[type_name.."s"] == 1)
|
||||
|
||||
-- Test setting the object to `false` to simulate an inline Lua
|
||||
-- expression gone wrong. This used to work and is rather
|
||||
-- convenient, so lets not break it even if it is technically a bug.
|
||||
c[type_name.."s"] = false
|
||||
|
||||
assert(#c[type_name.."s"] == 0)
|
||||
|
||||
c[type_name.."s"] = {o1}
|
||||
|
||||
assert(#c[type_name.."s"] == 1)
|
||||
|
||||
-- Test removing the objects using `nil`.
|
||||
c[type_name.."s"] = nil
|
||||
|
||||
assert(#c[type_name.."s"] == 0)
|
||||
|
||||
c[type_name.."s"] = {o1}
|
||||
|
||||
assert(#c[type_name.."s"] == 1)
|
||||
|
||||
-- Test removing using `{}`
|
||||
c[type_name.."s"] = {}
|
||||
|
||||
assert(#c[type_name.."s"] == 0)
|
||||
|
||||
c:kill()
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Cleanup (otherwise there is a race with the root.buttons tests)
|
||||
table.insert(steps, function()
|
||||
if #mouse.screen.clients ~= 0 then return end
|
||||
|
||||
return true
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
runner.run_steps(steps)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -7,11 +7,20 @@ local awful = require("awful")
|
|||
local keygrabber_a_active = false
|
||||
local keygrabber_b_active = false
|
||||
|
||||
-- Disable the deprecation to test both the current and legacy APIs.
|
||||
local gdebug = require("gears.debug")
|
||||
gdebug.deprecate = function() end
|
||||
|
||||
local steps = {
|
||||
function()
|
||||
|
||||
awful.keygrabber {
|
||||
keybindings = {
|
||||
{{}, "a", function() keygrabber_a_active = true end},
|
||||
awful.key {
|
||||
modifiers = {},
|
||||
key = "a",
|
||||
on_press = function() keygrabber_a_active = true end
|
||||
}
|
||||
},
|
||||
stop_key = "Escape",
|
||||
stop_callback = function() keygrabber_a_active = false end,
|
||||
|
|
Loading…
Reference in New Issue