Merge pull request #790 from Elv13/client_properties

Client, tag and screen API cleanup.
This commit is contained in:
Emmanuel Lepage Vallée 2016-04-11 23:58:22 -04:00
commit ae96ed0827
42 changed files with 3634 additions and 823 deletions

View File

@ -141,12 +141,20 @@ mypromptbox = {}
mylayoutbox = {}
mytaglist = {}
mytaglist.buttons = awful.util.table.join(
awful.button({ }, 1, awful.tag.viewonly),
awful.button({ modkey }, 1, awful.client.movetotag),
awful.button({ }, 1, function(t) t:view_only() end),
awful.button({ modkey }, 1, function(t)
if client.focus then
client.focus:move_to_tag(t)
end
end),
awful.button({ }, 3, awful.tag.viewtoggle),
awful.button({ modkey }, 3, awful.client.toggletag),
awful.button({ }, 4, function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end),
awful.button({ }, 5, function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end)
awful.button({ modkey }, 3, function(t)
if client.focus then
client.focus:toggle_tag(t)
end
end),
awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
)
mytasklist = {}
@ -158,8 +166,8 @@ mytasklist.buttons = awful.util.table.join(
-- Without this, the following
-- :isvisible() makes no sense
c.minimized = false
if not c:isvisible() then
awful.tag.viewonly(c.first_tag)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
-- This will also un-minimize
-- the client, if needed
@ -335,7 +343,7 @@ clientkeys = awful.util.table.join(
{description = "toggle floating", group = "client"}),
awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
{description = "move to master", group = "client"}),
awful.key({ modkey, }, "o", awful.client.movetoscreen ,
awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
{description = "move to screen", group = "client"}),
awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
{description = "toggle keep on top", group = "client"}),
@ -363,9 +371,9 @@ for i = 1, 9 do
awful.key({ modkey }, "#" .. i + 9,
function ()
local screen = awful.screen.focused()
local tag = awful.tag.gettags(screen)[i]
local tag = screen.tags[i]
if tag then
awful.tag.viewonly(tag)
tag:view_only()
end
end,
{description = "view tag #"..i, group = "tag"}),
@ -373,7 +381,7 @@ for i = 1, 9 do
awful.key({ modkey, "Control" }, "#" .. i + 9,
function ()
local screen = awful.screen.focused()
local tag = awful.tag.gettags(screen)[i]
local tag = screen.tags[i]
if tag then
awful.tag.viewtoggle(tag)
end
@ -383,9 +391,9 @@ for i = 1, 9 do
awful.key({ modkey, "Shift" }, "#" .. i + 9,
function ()
if client.focus then
local tag = awful.tag.gettags(client.focus.screen)[i]
local tag = client.focus.screen.tags[i]
if tag then
awful.client.movetotag(tag)
client.focus:move_to_tag(tag)
end
end
end,
@ -394,9 +402,9 @@ for i = 1, 9 do
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
function ()
if client.focus then
local tag = awful.tag.gettags(client.focus.screen)[i]
local tag = client.focus.screen.tags[i]
if tag then
awful.client.toggletag(tag)
client.focus:toggle_tag(tag)
end
end
end,

View File

@ -0,0 +1,6 @@
---------------------------------------------------------------------------
--- This module is deprecated, use `client`
-- ===============================
--
-- @module awful.client
---------------------------------------------------------------------------

View File

@ -0,0 +1,6 @@
---------------------------------------------------------------------------
--- This module is deprecated, use `screen`
-- ===============================
--
-- @module awful.screen
---------------------------------------------------------------------------

View File

@ -0,0 +1,6 @@
---------------------------------------------------------------------------
--- This module is deprecated, use `tag`
-- ===============================
--
-- @module awful.tag
---------------------------------------------------------------------------

View File

@ -28,8 +28,19 @@ tparam_alias('client', 'client.object')
tparam_alias('tag', 'tag')
-- Should be default, but is not. Sets up "@tab" => "@tparam table".
tparam_alias('tab', 'table')
-- Hack to get the functions and method on top of the signals and properties
new_type("function", "Functions")
-- Documentation for objects properties
new_type("property", "Object properties", false, "Type")
-- New type for signals
new_type("signal", "Signals", false, "Arguments")
-- Allow objects to define a set of beautiful properties affecting them
new_type("beautiful", "Theme variables", false, "Type")
-- Put deprecated methods in their own section
new_type("deprecated", "Deprecated functions", false, "param")
-- For the legacy stateless layout related functions
new_type("legacylayout", "Layout related functions", false, "param")
-- More fitting section names
kind_names={topic='Documentation', module='Libraries'}
@ -52,6 +63,10 @@ file = {
'../objects/',
-- LUA libraries
'../lib/',
-- Old APIs the user should not longer use directly
'../../docs/aliases/awful_client.lua',
'../../docs/aliases/awful_screen.lua',
'../../docs/aliases/awful_tag.lua',
exclude = {
-- exclude these modules, as they do not contain any written
-- documentation

385
docs/images/client_geo.svg Normal file
View File

@ -0,0 +1,385 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="519pt"
height="240pt"
viewBox="0 0 519.00001 240"
version="1.1"
id="svg6069"
inkscape:version="0.91 r13725"
sodipodi:docname="client_geo.svg">
<metadata
id="metadata6144">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6142">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6269">
<circle
r="26.388889"
cy="32.5"
cx="276.94446"
id="circle6271"
style="opacity:1;fill:#806600;fill-opacity:1;stroke:#617fff;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</clipPath>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1032"
id="namedview6140"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.44"
inkscape:cx="449.22086"
inkscape:cy="116.99803"
inkscape:window-x="0"
inkscape:window-y="16"
inkscape:window-maximized="1"
inkscape:current-layer="g6212" />
<path
inkscape:connector-curvature="0"
id="path6072"
d="m 58.889889,0.75 402.388891,0 0,238.5 -402.388891,0 z"
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:10, 4;stroke-dashoffset:1;stroke-opacity:0.26666703"
sodipodi:nodetypes="ccccc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:13.13514996px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:0.2;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="63.513626"
y="13.124383"
id="text6180"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6182"
x="63.513626"
y="13.124383">Screen</tspan></text>
<g
id="g6212"
transform="translate(34.806558,12.777778)">
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 30.606602,25.392837 c 0,-2.761719 2.238281,-5 5,-5 l 245.644098,0 c 2.76172,0 5,2.238281 5,5 l 0,190.000003 c 0,2.76172 -2.23828,5 -5,5 l -245.644098,0 c -2.761719,0 -5,-2.23828 -5,-5 z"
id="path6078"
inkscape:connector-curvature="0" />
<g
id="g6483">
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 31.289175,23.996573 c 0,-1.344985 1.090066,-2.435051 2.435051,-2.435051 l 248.876614,0 c 1.34498,0 2.43505,1.090066 2.43505,2.435051 l 0,7.679111 c 0,1.34499 -1.09007,2.43506 -2.43505,2.43506 l -248.876614,0 c -1.344985,0 -2.435051,-1.09007 -2.435051,-2.43506 z"
id="path6184"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="131.39223"
y="30.661503"
id="text6192"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6194"
x="131.39223"
y="30.661503">Top titlebar</tspan></text>
</g>
<g
id="g6494">
<path
inkscape:connector-curvature="0"
id="path6186"
d="m 31.289175,209.41568 c 0,-1.34498 1.090066,-2.43505 2.435051,-2.43505 l 248.876614,0 c 1.34498,0 2.43505,1.09007 2.43505,2.43505 l 0,7.67912 c 0,1.34499 -1.09007,2.43506 -2.43505,2.43506 l -248.876614,0 c -1.344985,0 -2.435051,-1.09007 -2.435051,-2.43506 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<text
sodipodi:linespacing="125%"
id="text6196"
y="217.16113"
x="122.56128"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="217.16113"
x="122.56128"
id="tspan6198"
sodipodi:role="line">Bottom titlebar</tspan></text>
</g>
<g
id="g6478">
<path
inkscape:connector-curvature="0"
id="path6188"
d="m 34.31226,205.97371 c -1.34498,0 -2.43505,-1.09006 -2.43505,-2.43505 l 0,-166.37878 c 0,-1.34498 1.09007,-2.43505 2.43505,-2.43505 l 7.67911,0 c 1.34499,0 2.43506,1.090071 2.43506,2.43505 l 0,166.37878 c 0,1.34499 -1.09007,2.43505 -2.43506,2.43505 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:108.00000429%;font-family:sans-serif;letter-spacing:-0.024px;word-spacing:0px;writing-mode:tb-rl;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="37.922375"
y="38.963093"
id="text6200"
sodipodi:linespacing="108%"><tspan
sodipodi:role="line"
id="tspan6202"
x="38.963093"
y="37.922375"
style="line-height:100%;letter-spacing:-0.024px">Left titlebar</tspan></text>
</g>
<g
id="g6467">
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 274.72857,206.29548 c -1.34498,0 -2.43505,-1.09006 -2.43505,-2.43505 l 0,-166.378778 c 0,-1.34498 1.09007,-2.43505 2.43505,-2.43505 l 7.67911,0 c 1.34499,0 2.43506,1.090071 2.43506,2.43505 l 0,166.378778 c 0,1.34499 -1.09007,2.43505 -2.43506,2.43505 z"
id="path6190"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text6204"
y="32.857822"
x="278.37604"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="278.37604"
x="32.857822"
id="tspan6206"
sodipodi:role="line">Right titlebar</tspan></text>
</g>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="124.76434"
y="124.29873"
id="text6208"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6210"
x="124.76434"
y="124.29873">Client content</tspan></text>
</g>
<g
id="g6294"
transform="matrix(2.2305168,0,0,2.2305168,435.74175,23.132349)">
<g
clip-path="url(#clipPath6269)"
transform="translate(-296.66667,17.777778)"
id="g6229">
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 30.606602,25.392837 c 0,-2.761719 2.238281,-5 5,-5 l 245.644098,0 c 2.76172,0 5,2.238281 5,5 l 0,190.000003 c 0,2.76172 -2.23828,5 -5,5 l -245.644098,0 c -2.761719,0 -5,-2.23828 -5,-5 z"
id="path6231"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path6233"
d="m 31.289175,23.996573 c 0,-1.344985 1.090066,-2.435051 2.435051,-2.435051 l 248.876614,0 c 1.34498,0 2.43505,1.090066 2.43505,2.435051 l 0,7.679111 c 0,1.34499 -1.09007,2.43506 -2.43505,2.43506 l -248.876614,0 c -1.344985,0 -2.435051,-1.09007 -2.435051,-2.43506 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 31.289175,209.41568 c 0,-1.34498 1.090066,-2.43505 2.435051,-2.43505 l 248.876614,0 c 1.34498,0 2.43505,1.09007 2.43505,2.43505 l 0,7.67912 c 0,1.34499 -1.09007,2.43506 -2.43505,2.43506 l -248.876614,0 c -1.344985,0 -2.435051,-1.09007 -2.435051,-2.43506 z"
id="path6235"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 34.31226,205.97371 c -1.34498,0 -2.43505,-1.09006 -2.43505,-2.43505 l 0,-166.37878 c 0,-1.34498 1.09007,-2.43505 2.43505,-2.43505 l 7.67911,0 c 1.34499,0 2.43506,1.090071 2.43506,2.43505 l 0,166.37878 c 0,1.34499 -1.09007,2.43505 -2.43506,2.43505 z"
id="path6237"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path6239"
d="m 274.72857,206.29548 c -1.34498,0 -2.43505,-1.09006 -2.43505,-2.43505 l 0,-166.378778 c 0,-1.34498 1.09007,-2.43505 2.43505,-2.43505 l 7.67911,0 c 1.34499,0 2.43506,1.090071 2.43506,2.43505 l 0,166.378778 c 0,1.34499 -1.09007,2.43505 -2.43506,2.43505 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:0.68181419;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<text
sodipodi:linespacing="125%"
id="text6241"
y="30.661503"
x="131.39223"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="30.661503"
x="131.39223"
id="tspan6243"
sodipodi:role="line">Top titlebar</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="122.56128"
y="217.16113"
id="text6245"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6247"
x="122.56128"
y="217.16113">Bottom titlebar</tspan></text>
<text
sodipodi:linespacing="108%"
id="text6249"
y="38.963093"
x="37.922375"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:108.00000429%;font-family:sans-serif;letter-spacing:-0.024px;word-spacing:0px;writing-mode:tb-rl;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="line-height:100%;letter-spacing:-0.024px"
y="37.922375"
x="38.963093"
id="tspan6251"
sodipodi:role="line">Left titlebar</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="278.37604"
y="32.857822"
id="text6253"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6255"
x="32.857822"
y="278.37604">Right titlebar</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="124.76434"
y="124.29873"
id="text6257"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6259"
x="124.76434"
y="124.29873">Client content</tspan></text>
</g>
<circle
r="26.388889"
cy="50.277779"
cx="-19.722223"
id="path6261"
style="opacity:1;fill:none;fill-opacity:1;stroke:#617fff;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<circle
r="26.388889"
cy="44.166668"
cx="313.97321"
id="circle6292"
style="opacity:1;fill:none;fill-opacity:1;stroke:#617fff;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#000000;fill-opacity:0;fill-rule:evenodd;stroke:#617fff;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 327.02878,21.111111 419.251,82.222224"
id="path6313"
inkscape:connector-curvature="0" />
<path
style="fill:#000000;fill-opacity:0;fill-rule:evenodd;stroke:#617fff;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 295.08433,62.638889 339.251,162.77778"
id="path6315"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0202;stroke-width:2.88000011;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 386.5517,105.25687 c 7.05033,-0.0468 12.5887,0.3286 16.84282,0.41946 5.43752,0.11613 11.28508,5.54811 11.61592,10.79433 0.19715,3.12624 0.007,7.00671 0.21837,11.9636"
id="path6319"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssc" />
<path
sodipodi:nodetypes="cssc"
inkscape:connector-curvature="0"
id="path6321"
d="m 386.39337,110.80386 c 5.59189,-0.20902 10.42005,0.0276 14.15455,0.0712 5.96201,0.0696 9.42365,2.72239 9.41883,9.41645 -0.003,4.0189 -0.21637,9.3958 -0.25876,17.77458"
style="fill:none;fill-rule:evenodd;stroke:#ff0202;stroke-width:2.36934948;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text6192-0"
y="221.88589"
x="327.72714"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="221.88589"
x="327.72714"
id="tspan6194-9"
sodipodi:role="line">Shape bounding outline</tspan></text>
<text
sodipodi:linespacing="125%"
id="text6192-5"
y="208.45212"
x="328.16382"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="208.45212"
x="328.16382"
id="tspan6194-4"
sodipodi:role="line">Shape clip outline</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 415.22882,118.2205 40.06938,0 0,99.78062 -6.2854,0"
id="path6349"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 410.63989,133.61111 18.88889,0 0,71.11111 -6.94444,0"
id="path6351"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 418.93898,200.35818 3.33912,0 0,8.64241 -3.33912,0"
id="path6353"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path6355"
d="m 445.91815,214.03874 3.33912,0 0,8.64241 -3.33912,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path6357"
d="m 371.60211,105.68444 3.33912,0 0,5.30329 -3.33912,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
id="path6359"
d="m 385.31699,32.441513 -3.33912,0 0,8.64241 3.33912,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 375.36211,108.26388 2.77778,0 0,-71.319435 3.61111,0"
id="path6361"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="386.21936"
y="40.118782"
id="text6363"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6365"
x="386.21936"
y="40.118782">Border </tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

273
docs/images/tag_props.svg Normal file
View File

@ -0,0 +1,273 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="519pt"
height="400pt"
viewBox="0 0 519 400"
version="1.1"
id="svg5783"
inkscape:version="0.91 r13725"
sodipodi:docname="tag_props.svg">
<metadata
id="metadata5846">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5844" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1032"
id="namedview5842"
showgrid="false"
inkscape:zoom="1.44"
inkscape:cx="275.51935"
inkscape:cy="265.93078"
inkscape:window-x="0"
inkscape:window-y="16"
inkscape:window-maximized="1"
inkscape:current-layer="svg5783" />
<path
inkscape:connector-curvature="0"
id="path5786"
d="m 99.744949,82.18258 318.500001,0 0,238.5 -318.500001,0 z m 0,0"
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:10, 4;stroke-dashoffset:1;stroke-opacity:0.26666703" />
<path
inkscape:connector-curvature="0"
id="path5788"
d="m 108.99495,91.43258 300,0 0,220 -300,0 z m 0,0"
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:10, 4;stroke-dashoffset:1;stroke-opacity:0.2" />
<path
inkscape:connector-curvature="0"
id="path5792"
d="m 264.94334,104.86123 c 0,-2.76172 2.23828,-5 5,-5 l 121.90041,0 c 2.76172,0 5,2.23828 5,5 l 0,48.33333 c 0,2.76172 -2.23828,5 -5,5 l -121.90041,0 c -2.76172,0 -5,-2.23828 -5,-5 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.55999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.55999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 119.01924,104.86123 c 0,-2.76172 2.23828,-5 5,-5 l 121.9004,0 c 2.76172,0 5,2.23828 5,5 l 0,83.54115 c 0,2.76172 -2.23828,5 -5,5 l -121.9004,0 c -2.76172,0 -5,-2.23828 -5,-5 z"
id="path7583"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path7587"
d="m 119.01924,210.53441 c 0,-2.76172 2.23828,-5 5,-5 l 121.9004,0 c 2.76172,0 5,2.23828 5,5 l 0,83.54115 c 0,2.76172 -2.23828,5 -5,5 l -121.9004,0 c -2.76172,0 -5,-2.23828 -5,-5 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.55999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 118.6368,77.0879 0,-10.21376 135.92164,0 0,11.39227"
id="path7589"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 182.27641,66.4813 0,-10.99944"
id="path7595"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path7597"
d="m 427.60318,224.3777 10.21376,0 0,15.32064 -10.14227,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
id="path7599"
d="m 438.44336,232.64825 10.99944,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 265.37038,328.5978 0,10.21376 -15.32064,0 0,-10.14227"
id="path7601"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 258.99495,338.6548 0,9.44444 183.33334,0 0,-114.44443"
id="path7603"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
sodipodi:linespacing="125%"
id="text7607"
y="235.37877"
x="452.8934"
style="font-style:normal;font-weight:normal;font-size:11.81261539px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="235.37877"
x="452.8934"
id="tspan7609"
sodipodi:role="line">Gaps</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 399.82829,90.321468 0,-26.432579 -20.55556,0.04369"
id="path7611"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:11.81261539px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="320.79419"
y="67.281029"
id="text7613"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7615"
x="320.79419"
y="67.281029">Work area</tspan></text>
<path
inkscape:connector-curvature="0"
id="path7617"
d="m 123.14816,328.5978 0,10.21376 -15.32064,0 0,-10.14227"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 96.150273,107.47611 -10.213761,0 0,-15.32064 10.142271,0"
id="path7619"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10606,100.32147 -8.333333,0 0,248.33333 38.333333,0"
id="path7623"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 115.10606,339.21036 0,24.84505 4.91046,0.0712"
id="path7625"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:11.81261539px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="122.60548"
y="366.58011"
id="text7627"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7629"
x="122.60548"
y="366.58011">Screen padding</tspan></text>
<path
style="fill:#ff5555;fill-rule:evenodd;stroke:#9c39bf;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:9.6, 4.8;stroke-dashoffset:0;stroke-opacity:1"
d="m 257.88384,24.76591 0,276.66667"
id="path7631"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:11.81261539px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="130.15106"
y="52.780128"
id="text7591"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7593"
x="130.15106"
y="52.780128">Master width factor</tspan></text>
<path
sodipodi:nodetypes="sssssssss"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.55999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 264.94334,175.41679 c 0,-2.76172 2.23828,-5 5,-5 l 121.90041,0 c 2.76172,0 5,2.23828 5,5 l 0,48.33333 c 0,2.76172 -2.23828,5 -5,5 l -121.90041,0 c -2.76172,0 -5,-2.23828 -5,-5 z"
id="path7643"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path7645"
d="m 264.94334,246.5279 c 0,-2.76172 2.23828,-5 5,-5 l 121.90041,0 c 2.76172,0 5,2.23828 5,5 l 0,48.33333 c 0,2.76172 -2.23828,5 -5,5 l -121.90041,0 c -2.76172,0 -5,-2.23828 -5,-5 z"
style="fill:#617fff;fill-opacity:0.49019602;fill-rule:nonzero;stroke:#617fff;stroke-width:1.55999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sssssssss" />
<path
inkscape:connector-curvature="0"
id="path7647"
d="m 176.21717,144.76591 -107.222221,0 10e-7,114.44445 105.55556,0"
style="fill:none;fill-rule:evenodd;stroke:#9c39bf;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:9.6, 4.8;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
id="path7649"
d="m 68.578283,204.27776 -13.814013,-0.0674 -0.537961,175.00485 65.366651,0.22526"
style="fill:none;fill-rule:evenodd;stroke:#9c39bf;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:9.6, 4.8;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cccc" />
<text
sodipodi:linespacing="125%"
id="text7651"
y="382.34006"
x="122.60548"
style="font-style:normal;font-weight:normal;font-size:11.81261539px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="382.34006"
x="122.60548"
id="tspan7653"
sodipodi:role="line">Masters</tspan></text>
<path
inkscape:connector-curvature="0"
id="path8456"
d="m 118.6368,77.0879 0,-10.21376 135.92164,0 0,11.39227"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path8458"
d="m 413.99495,82.265912 0,-40.877023 -33.88889,0.321471"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text8460"
y="38.719765"
x="285.3501"
style="font-style:normal;font-weight:normal;font-size:17.02204132px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="38.719765"
x="285.3501"
id="tspan8462"
sodipodi:role="line" /><tspan
y="59.997314"
x="285.3501"
sodipodi:role="line"
id="tspan8464" /></text>
<text
sodipodi:linespacing="125%"
id="text8466"
y="45.725838"
x="310.60031"
style="font-style:normal;font-weight:normal;font-size:11.81261539px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="45.725838"
x="310.60031"
id="tspan8468"
sodipodi:role="line">Screen area</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.9279623px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="237.01671"
y="18.350338"
id="text6363"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6365"
x="237.01671"
y="18.350338">Columns</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -12,7 +12,6 @@
local client = client
local aclient = require("awful.client")
local atag = require("awful.tag")
local timer = require("gears.timer")
--- Give focus when clients appear/disappear.
@ -39,7 +38,7 @@ end
--
-- @param tag A tag object
local function check_focus_tag(t)
local s = atag.getscreen(t)
local s = t.screen
if not s then return end
s = screen[s]
check_focus({ screen = s })

File diff suppressed because it is too large Load Diff

218
lib/awful/client/focus.lua Normal file
View File

@ -0,0 +1,218 @@
---------------------------------------------------------------------------
--- Keep track of the focused clients.
--
-- @author Julien Danjou &lt;julien@danjou.info&gt;
-- @copyright 2008 Julien Danjou
-- @release @AWESOME_VERSION@
-- @submodule client
---------------------------------------------------------------------------
local util = require("awful.util")
local capi =
{
screen = screen,
client = client,
}
-- We use a metatable to prevent circular dependency loops.
local screen
do
screen = setmetatable({}, {
__index = function(_, k)
screen = require("awful.screen")
return screen[k]
end,
__newindex = error -- Just to be sure in case anything ever does this
})
end
local client
do
client = setmetatable({}, {
__index = function(_, k)
client = require("awful.client")
return client[k]
end,
__newindex = error -- Just to be sure in case anything ever does this
})
end
local focus = {history = {}}
local internal = {}
local function get_screen(s)
return s and capi.screen[s]
end
--- Remove a client from the focus history
--
-- @client c The client that must be removed.
-- @function awful.client.focus.history.delete
function focus.history.delete(c)
for k, v in ipairs(internal) do
if v == c then
table.remove(internal, k)
break
end
end
end
--- Focus a client by its relative index.
--
-- @function awful.client.focus.byidx
-- @param i The index.
-- @client[opt] c The client.
function focus.byidx(i, c)
local target = client.next(i, c)
if target then
target:emit_signal("request::activate", "client.focus.byidx",
{raise=true})
end
end
--- Filter out window that we do not want handled by focus.
-- This usually means that desktop, dock and splash windows are
-- not registered and cannot get focus.
--
-- @client c A client.
-- @return The same client if it's ok, nil otherwise.
-- @function awful.client.focus.filter
function focus.filter(c)
if c.type == "desktop"
or c.type == "dock"
or c.type == "splash"
or not c.focusable then
return nil
end
return c
end
--- Update client focus history.
--
-- @client c The client that has been focused.
-- @function awful.client.focus.history.add
function focus.history.add(c)
-- Remove the client if its in stack
focus.history.delete(c)
-- Record the client has latest focused
table.insert(internal, 1, c)
end
--- Get the latest focused client for a screen in history.
--
-- @tparam int|screen s The screen to look for.
-- @tparam int idx The index: 0 will return first candidate,
-- 1 will return second, etc.
-- @tparam function filter An optional filter. If no client is found in the
-- first iteration, `awful.client.focus.filter` is used by default to get any
-- client.
-- @treturn client.object A client.
-- @function awful.client.focus.history.get
function focus.history.get(s, idx, filter)
s = get_screen(s)
-- When this counter is equal to idx, we return the client
local counter = 0
local vc = client.visible(s, true)
for _, c in ipairs(internal) do
if get_screen(c.screen) == s then
if not filter or filter(c) then
for _, vcc in ipairs(vc) do
if vcc == c then
if counter == idx then
return c
end
-- We found one, increment the counter only.
counter = counter + 1
break
end
end
end
end
end
-- Argh nobody found in history, give the first one visible if there is one
-- that passes the filter.
filter = filter or focus.filter
if counter == 0 then
for _, v in ipairs(vc) do
if filter(v) then
return v
end
end
end
end
--- Focus the previous client in history.
-- @function awful.client.focus.history.previous
function focus.history.previous()
local sel = capi.client.focus
local s = sel and sel.screen or screen.focused()
local c = focus.history.get(s, 1)
if c then
c:emit_signal("request::activate", "client.focus.history.previous",
{raise=false})
end
end
--- Focus a client by the given direction.
--
-- @tparam string dir The direction, can be either
-- `"up"`, `"down"`, `"left"` or `"right"`.
-- @client[opt] c The client.
-- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom)
-- @function awful.client.focus.bydirection
function focus.bydirection(dir, c, stacked)
local sel = c or capi.client.focus
if sel then
local cltbl = client.visible(sel.screen, stacked)
local geomtbl = {}
for i,cl in ipairs(cltbl) do
geomtbl[i] = cl:geometry()
end
local target = util.get_rectangle_in_direction(dir, geomtbl, sel:geometry())
-- If we found a client to focus, then do it.
if target then
cltbl[target]:emit_signal("request::activate",
"client.focus.bydirection", {raise=false})
end
end
end
--- Focus a client by the given direction. Moves across screens.
--
-- @param dir The direction, can be either "up", "down", "left" or "right".
-- @client[opt] c The client.
-- @tparam[opt=false] boolean stacked Use stacking order? (top to bottom)
-- @function awful.client.focus.global_bydirection
function focus.global_bydirection(dir, c, stacked)
local sel = c or capi.client.focus
local scr = get_screen(sel and sel.screen or screen.focused())
-- change focus inside the screen
focus.bydirection(dir, sel)
-- if focus not changed, we must change screen
if sel == capi.client.focus then
screen.focus_bydirection(dir, scr)
if scr ~= get_screen(screen.focused()) then
local cltbl = client.visible(screen.focused(), stacked)
local geomtbl = {}
for i,cl in ipairs(cltbl) do
geomtbl[i] = cl:geometry()
end
local target = util.get_rectangle_in_direction(dir, geomtbl, scr.geometry)
if target then
cltbl[target]:emit_signal("request::activate",
"client.focus.global_bydirection",
{raise=false})
end
end
end
end
return focus
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -4,7 +4,7 @@
-- @author Uli Schlachter &lt;psychon@znc.in&gt;
-- @copyright 2014 Uli Schlachter
-- @release @AWESOME_VERSION@
-- @module awful.client.shape
-- @submodule client
---------------------------------------------------------------------------
-- Grab environment we need
@ -18,7 +18,8 @@ local capi =
local shape = {}
shape.update = {}
--- Get one of a client's shapes and transform it to include window decorations
--- Get one of a client's shapes and transform it to include window decorations.
-- @function awful.shape.get_transformed
-- @client c The client whose shape should be retrieved
-- @tparam string shape_name Either "bounding" or "clip"
function shape.get_transformed(c, shape_name)
@ -51,7 +52,8 @@ function shape.get_transformed(c, shape_name)
return result
end
--- Update a client's bounding shape from the shape the client set itself
--- Update a client's bounding shape from the shape the client set itself.
-- @function awful.shape.update.bounding
-- @client c The client to act on
function shape.update.bounding(c)
local res = shape.get_transformed(c, "bounding")
@ -62,7 +64,8 @@ function shape.update.bounding(c)
end
end
--- Update a client's clip shape from the shape the client set itself
--- Update a client's clip shape from the shape the client set itself.
-- @function awful.shape.update.clip
-- @client c The client to act on
function shape.update.clip(c)
local res = shape.get_transformed(c, "clip")
@ -73,7 +76,8 @@ function shape.update.clip(c)
end
end
--- Update all of a client's shapes from the shapes the client set itself
--- Update all of a client's shapes from the shapes the client set itself.
-- @function awful.shape.update.all
-- @client c The client to act on
function shape.update.all(c)
shape.update.bounding(c)

View File

@ -0,0 +1,89 @@
---------------------------------------------------------------------------
--- Keep track of the urgent clients.
--
-- @author Julien Danjou &lt;julien@danjou.info&gt;
-- @copyright 2008 Julien Danjou
-- @release @AWESOME_VERSION@
-- @submodule client
---------------------------------------------------------------------------
local urgent = {}
local capi =
{
client = client,
}
local client
do
client = setmetatable({}, {
__index = function(_, k)
client = require("awful.client")
return client[k]
end,
__newindex = error -- Just to be sure in case anything ever does this
})
end
local data = setmetatable({}, { __mode = 'k' })
--- Get the first client that got the urgent hint.
--
-- @function awful.urgent.get
-- @treturn client.object The first urgent client.
function urgent.get()
if #data > 0 then
return data[1]
else
-- fallback behaviour: iterate through clients and get the first urgent
local clients = capi.client.get()
for _, cl in pairs(clients) do
if cl.urgent then
return cl
end
end
end
end
--- Jump to the client that received the urgent hint first.
--
-- @function awful.urgent.jumpto
-- @tparam bool|function merge If true then merge tags (select the client's
-- first tag additionally) when the client is not visible.
-- If it is a function, it will be called with the client as argument.
function urgent.jumpto(merge)
local c = client.urgent.get()
if c then
client.jumpto(c, merge)
end
end
--- Adds client to urgent stack.
--
-- @function awful.urgent.add
-- @client c The client object.
-- @param prop The property which is updated.
function urgent.add(c, prop)
if type(c) == "client" and prop == "urgent" and c.urgent then
table.insert(data, c)
end
end
--- Remove client from urgent stack.
--
-- @function awful.urgent.delete
-- @client c The client object.
function urgent.delete(c)
for k, cl in ipairs(data) do
if c == cl then
table.remove(data, k)
break
end
end
end
capi.client.connect_signal("property::urgent", urgent.add)
capi.client.connect_signal("focus", urgent.delete)
capi.client.connect_signal("unmanage", urgent.delete)
return urgent

View File

@ -12,7 +12,6 @@ local client = client
local screen = screen
local ipairs = ipairs
local math = math
local atag = require("awful.tag")
local aclient = require("awful.client")
local ewmh = {}
@ -182,7 +181,7 @@ function ewmh.tag(c, t)
if not t then
c.sticky = true
else
c.screen = atag.getscreen(t)
c.screen = t.screen
c:tags({ t })
end
end

View File

@ -10,7 +10,7 @@
-- Grab environment we need
local setmetatable = setmetatable
local ipairs = ipairs
local capi = { key = key }
local capi = { key = key, root = root }
local util = require("awful.util")
@ -26,6 +26,40 @@ local key = { mt = {}, hotkeys = {} }
-- @class table
local ignore_modifiers = { "Lock", "Mod2" }
--- Convert the modifiers into pc105 key names
local conversion = {
mod4 = "Super_L",
control = "Control_L",
shift = "Shift_L",
mod1 = "Alt_L",
}
--- Execute a key combination.
-- If an awesome keybinding is assigned to the combination, it should be
-- executed.
-- @see root.fake_input
-- @tparam table mod A modified table. Valid modifiers are: Any, Mod1,
-- Mod2, Mod3, Mod4, Mod5, Shift, Lock and Control.
-- @tparam string k The key
function key.execute(mod, k)
for _, v in ipairs(mod) do
local m = conversion[v:lower()]
if m then
root.fake_input("key_press", m)
end
end
root.fake_input("key_press" , k)
root.fake_input("key_release", k)
for _, v in ipairs(mod) do
local m = conversion[v:lower()]
if m then
root.fake_input("key_release", m)
end
end
end
--- Create a new key to use as binding.
-- This function is useful to create several keys from one, because it will use
-- the ignore_modifier variable to create several keys with and without the
@ -66,6 +100,7 @@ function key.new(mod, _key, press, release, data)
data.mod = mod
data.key = _key
table.insert(key.hotkeys, data)
data.execute = function(_) key.execute(mod, _key) end
return ret
end

View File

@ -11,7 +11,6 @@
local ipairs = ipairs
local type = type
local util = require("awful.util")
local ascreen = require("awful.screen")
local capi = {
screen = screen,
mouse = mouse,
@ -21,6 +20,7 @@ local capi = {
}
local tag = require("awful.tag")
local client = require("awful.client")
local ascreen = require("awful.screen")
local timer = require("gears.timer")
local function get_screen(s)
@ -64,7 +64,8 @@ local delayed_arrange = {}
-- @param screen The screen.
-- @return The layout function.
function layout.get(screen)
local t = tag.selected(screen)
screen = screen or capi.mouse.screen
local t = get_screen(screen).selected_tag
return tag.getproperty(t, "layout") or layout.suit.floating
end
@ -78,8 +79,8 @@ function layout.inc(i, s, layouts)
-- this was changed so that 'layouts' can be an optional parameter
layouts, i, s = i, s, layouts
end
s = get_screen(s)
local t = tag.selected(s)
s = get_screen(s or ascreen.focused())
local t = s.selected_tag
layouts = layouts or layout.layouts
if t then
local curlayout = layout.get(s)
@ -109,10 +110,10 @@ end
--- Set the layout function of the current tag.
-- @param _layout Layout name.
-- @param t The tag to modify, if null tag.selected() is used.
-- @tparam[opt=mouse.screen.selected_tag] tag t The tag to modify.
function layout.set(_layout, t)
t = t or tag.selected()
tag.setproperty(t, "layout", _layout)
t = t or capi.mouse.screen.selected_tag
t.layout = _layout
end
--- Get the layout parameters used for the screen
@ -130,24 +131,24 @@ end
-- "geometries" table with client as keys and geometry as value
function layout.parameters(t, screen)
screen = get_screen(screen)
t = t or tag.selected(screen)
t = t or screen.selected_tag
screen = get_screen(t and tag.getscreen(t) or 1)
screen = get_screen(t and t.screen or 1)
local p = {}
local useless_gap = t and tag.getgap(t, #client.tiled(screen)) or 0
local useless_gap = t and t.gap or 0
p.workarea = ascreen.get_bounding_geometry(screen, {
p.workarea = screen:get_bounding_geometry {
honor_padding = true,
honor_workarea = true,
margins = useless_gap,
})
}
p.geometry = screen.geometry
p.clients = client.tiled(screen)
p.screen = screen.index
p.padding = ascreen.padding(screen)
p.padding = screen.padding
p.useless_gap = useless_gap
return p
@ -213,14 +214,14 @@ capi.client.connect_signal("property::screen", function(c, old_screen)
end)
local function arrange_tag(t)
layout.arrange(tag.getscreen(t))
layout.arrange(t.screen)
end
capi.screen.add_signal("arrange")
capi.tag.connect_signal("property::mwfact", arrange_tag)
capi.tag.connect_signal("property::nmaster", arrange_tag)
capi.tag.connect_signal("property::ncol", arrange_tag)
capi.tag.connect_signal("property::master_width_factor", arrange_tag)
capi.tag.connect_signal("property::master_count", arrange_tag)
capi.tag.connect_signal("property::column_count", arrange_tag)
capi.tag.connect_signal("property::layout", arrange_tag)
capi.tag.connect_signal("property::windowfact", arrange_tag)
capi.tag.connect_signal("property::selected", arrange_tag)

View File

@ -11,6 +11,7 @@
-- Grab environment we need
local ipairs = ipairs
local math = math
local capi = {screen = screen}
local tag = require("awful.tag")
--- Actually arrange clients of p.clients for corner layout
@ -19,7 +20,7 @@ local tag = require("awful.tag")
-- @param orientation String indicating in which corner is the master window.
-- Available values are : NE, NW, SW, SE
local function do_corner(p, orientation)
local t = p.tag or tag.selected(p.screen)
local t = p.tag or capi.screen[p.screen].selected_tag
local wa = p.workarea
local cls = p.clients
@ -29,9 +30,9 @@ local function do_corner(p, orientation)
local column = {}
local row = {}
-- Use the nmaster field of the tag in a cheaty way
local row_privileged = ((tag.getnmaster(tag.selected(cls[1].screen)) % 2) == 0)
local row_privileged = ((cls[1].screen.selected_tag.master_count % 2) == 0)
local master_factor = tag.getmwfact(tag.selected(cls[1].screen))
local master_factor = cls[1].screen.selected_tag.master_width_factor
master.width = master_factor * wa.width
master.height = master_factor * wa.height

View File

@ -10,7 +10,6 @@
-- Grab environment we need
local ipairs = ipairs
local math = math
local tag = require("awful.tag")
local capi =
{
client = client,
@ -18,7 +17,6 @@ local capi =
mouse = mouse,
mousegrabber = mousegrabber
}
local client = require("awful.client")
local magnifier = {}
@ -41,7 +39,8 @@ function magnifier.mouse_resize_handler(c, corner, x, y)
-- New master width factor
local mwfact = dist / maxdist_pow
tag.setmwfact(math.min(math.max(0.01, mwfact), 0.99), tag.selected(c.screen))
c.screen.selected_tag.master_width_factor
= math.min(math.max(0.01, mwfact), 0.99)
return true
end
end
@ -54,8 +53,8 @@ function magnifier.arrange(p)
local area = p.workarea
local cls = p.clients
local focus = p.focus or capi.client.focus
local t = p.tag or tag.selected(p.screen)
local mwfact = tag.getmwfact(t)
local t = p.tag or capi.screen[p.screen].selected_tag
local mwfact = t.master_width_factor
local fidx
-- Check that the focused window is on the right screen
@ -67,7 +66,7 @@ function magnifier.arrange(p)
end
-- If focused window is not tiled, take the first one which is tiled.
if client.floating.get(focus) then
if focus.floating then
focus = cls[1]
fidx = 1
end

View File

@ -29,7 +29,7 @@ tile.resize_jump_to_corner = true
local function mouse_resize_handler(c, _, _, _, orientation)
orientation = orientation or "tile"
local wa = capi.screen[c.screen].workarea
local mwfact = tag.getmwfact()
local mwfact = c.screen.selected_tag.master_width_factor
local cursor
local g = c:geometry()
local offset = 0
@ -126,7 +126,8 @@ local function mouse_resize_handler(c, _, _, _, orientation)
wfact = wfact_x
end
tag.setmwfact(math.min(math.max(new_mwfact, 0.01), 0.99), tag.selected(c.screen))
c.screen.selected_tag.master_width_factor
= math.min(math.max(new_mwfact, 0.01), 0.99)
client.setwfact(math.min(math.max(wfact,0.01), 0.99), c)
return true
end
@ -195,7 +196,7 @@ local function tile_group(gs, cls, wa, orientation, fact, group)
end
local function do_tile(param, orientation)
local t = param.tag or tag.selected(param.screen)
local t = param.tag or capi.screen[param.screen].selected_tag
orientation = orientation or "right"
-- This handles all different orientations.
@ -208,12 +209,12 @@ local function do_tile(param, orientation)
local gs = param.geometries
local cls = param.clients
local nmaster = math.min(tag.getnmaster(t), #cls)
local nmaster = math.min(t.master_count, #cls)
local nother = math.max(#cls - nmaster,0)
local mwfact = tag.getmwfact(t)
local mwfact = t.master_width_factor
local wa = param.workarea
local ncol = tag.getncol(t)
local ncol = t.column_count
local data = tag.getdata(t).windowfact
@ -229,7 +230,7 @@ local function do_tile(param, orientation)
place_master = false
end
local grow_master = tag.getmfpol(t) == "expand"
local grow_master = t.master_fill_policy == "expand"
-- this was easier than writing functions because there is a lot of data we need
for _ = 1,2 do
if place_master and nmaster > 0 then

View File

@ -609,7 +609,7 @@ end
-- terms[i] =
-- {c.name,
-- function()
-- awful.tag.viewonly(c.first_tag)
-- c.first_tag:view_only()
-- client.focus = c
-- end,
-- c.icon

View File

@ -111,13 +111,13 @@ function mouse.client.snap(c, snap, x, y, fixed_x, fixed_y)
-- Allow certain windows to snap to the edge of the workarea.
-- Only allow docking to workarea for consistency/to avoid problems.
if aclient.dockable.get(c) then
if c.dockable then
local struts = c:struts()
struts['left'] = 0
struts['right'] = 0
struts['top'] = 0
struts['bottom'] = 0
if edge ~= "none" and aclient.floating.get(c) then
if edge ~= "none" and c.floating then
if edge == "left" or edge == "right" then
struts[edge] = cur_geom.width
elseif edge == "top" or edge == "bottom" then
@ -177,7 +177,7 @@ function mouse.client.move(c, snap, finished_cb)
for _, v in ipairs(_mouse.buttons) do
if v then
local lay = layout.get(c.screen)
if lay == layout.suit.floating or aclient.floating.get(c) then
if lay == layout.suit.floating or c.floating then
local x = _mouse.x - dist_x
local y = _mouse.y - dist_y
c:geometry(mouse.client.snap(c, snap, x, y, fixed_x, fixed_y))
@ -195,7 +195,7 @@ function mouse.client.move(c, snap, finished_cb)
end
if layout.get(c.screen) ~= layout.suit.floating then
local c_u_m = mouse.client_under_pointer()
if c_u_m and not aclient.floating.get(c_u_m) then
if c_u_m and not c_u_m.floating then
if c_u_m ~= c then
c:swap(c_u_m)
end
@ -229,8 +229,8 @@ function mouse.client.dragtotag.border(c)
capi.mouse.coords({ x = wa.x + 1 })
end
if not button_down then
local tags = tag.gettags(c.screen)
local t = tag.selected()
local tags = c.screen.tags
local t = c.screen.selected_tag
local idx
for i, v in ipairs(tags) do
if v == t then
@ -239,11 +239,11 @@ function mouse.client.dragtotag.border(c)
end
if _mouse.x > wa.x + wa.width - 10 then
local newtag = tags[util.cycle(#tags, idx + 1)]
aclient.movetotag(newtag, c)
c:move_to_tag(newtag)
tag.viewnext()
elseif _mouse.x < wa.x + 10 then
local newtag = tags[util.cycle(#tags, idx - 1)]
aclient.movetotag(newtag, c)
c:move_to_tag(newtag)
tag.viewprev()
end
return false
@ -356,7 +356,7 @@ function mouse.client.resize(c, corner)
local lay = layout.get(c.screen)
local corner2, x, y = mouse.client.corner(c, corner)
if lay == layout.suit.floating or aclient.floating.get(c) then
if lay == layout.suit.floating or c.floating then
return layout.suit.floating.mouse_resize_handler(c, corner2, x, y)
elseif lay.mouse_resize_handler then
return lay.mouse_resize_handler(c, corner2, x, y)

View File

@ -19,7 +19,7 @@
--
-- **honor_padding** (*boolean*):
--
-- Take the screen padding into account (see `awful.screen.padding`)
-- Take the screen padding into account (see `screen.padding`)
--
-- **tag** (*tag*):
--
@ -158,7 +158,7 @@ local function geometry_common(obj, args, new_geo, ignore_border_width)
end
-- It is a screen, it doesn't support setting new sizes.
return a_screen.get_bounding_geometry(obj, args)
return obj:get_bounding_geometry(args)
else
assert(false, "Invalid object")
end
@ -453,7 +453,7 @@ function placement.no_overlap(c)
local curlay = layout.get()
local areas = { screen.workarea }
for _, cl in pairs(cls) do
if cl ~= c and cl.type ~= "desktop" and (client.floating.get(cl) or curlay == layout.suit.floating) then
if cl ~= c and cl.type ~= "desktop" and (cl.floating or curlay == layout.suit.floating) then
areas = area_remove(areas, area_common(cl))
end
end

View File

@ -13,8 +13,6 @@ local table = table
local type = type
local ipairs = ipairs
local pairs = pairs
local aclient = require("awful.client")
local atag = require("awful.tag")
local rules = {}
@ -199,13 +197,11 @@ function rules.execute(c, props, callbacks)
if property ~= "focus" and type(value) == "function" then
value = value(c)
end
if property == "floating" then
aclient.floating.set(c, value)
elseif property == "tag" then
c.screen = atag.getscreen(value)
if property == "tag" then
c.screen = value.screen
c:tags({ value })
elseif property == "switchtotag" and value and props.tag then
atag.viewonly(props.tag)
props.tag:view_only()
elseif property == "height" or property == "width" or
property == "x" or property == "y" then
local geo = c:geometry();

View File

@ -4,7 +4,7 @@
-- @author Julien Danjou &lt;julien@danjou.info&gt;
-- @copyright 2008 Julien Danjou
-- @release @AWESOME_VERSION@
-- @module awful.screen
-- @module screen
---------------------------------------------------------------------------
-- Grab environment we need
@ -24,7 +24,7 @@ end
-- we use require("awful.client") inside functions to prevent circular dependencies.
local client
local screen = {}
local screen = {object={}}
local data = {}
data.padding = {}
@ -44,13 +44,27 @@ local function apply_geometry_ajustments(geo, delta)
}
end
--- Get the square distance between a `screen` and a point
-- @deprecated awful.screen.getdistance_sq
-- @param s Screen
-- @param x X coordinate of point
-- @param y Y coordinate of point
-- @return The squared distance of the screen to the provided point
-- @see screen.get_square_distance
function screen.getdistance_sq(s, x, y)
s = get_screen(s)
local geom = s.geometry
util.deprecate "Use s:get_square_distance(x, y) instead of awful.screen.getdistance_sq"
return screen.object.get_square_distance(s, x, y)
end
--- Get the square distance between a `screen` and a point
-- @function screen.get_square_distance
-- @tparam number x X coordinate of point
-- @tparam number y Y coordinate of point
-- @treturn number The squared distance of the screen to the provided point
function screen.object.get_square_distance(self, x, y)
self = get_screen(self)
local geom = self.geometry
local dist_x, dist_y = 0, 0
if x < geom.x then
dist_x = geom.x - x
@ -69,13 +83,14 @@ end
-- Return screen number corresponding to the given (pixel) coordinates.
-- The number returned can be used as an index into the global
-- `screen` table/object.
-- @function awful.screen.getbycoord
-- @param x The x coordinate
-- @param y The y coordinate
function screen.getbycoord(x, y)
local s = capi.screen[1]
local dist = screen.getdistance_sq(s, x, y)
local dist = screen.object.get_square_distance(s, x, y)
for i in capi.screen do
local d = screen.getdistance_sq(i, x, y)
local d = screen.object.get_square_distance(i, x, y)
if d < dist then
s, dist = capi.screen[i], d
end
@ -85,6 +100,7 @@ end
--- Give the focus to a screen, and move pointer to last known position on this
-- screen, or keep position relative to the current focused screen
-- @function awful.screen.focus
-- @param _screen Screen number (defaults / falls back to mouse.screen).
function screen.focus(_screen)
client = client or require("awful.client")
@ -123,6 +139,7 @@ end
--- Give the focus to a screen, and move pointer to last known position on this
-- screen, or keep position relative to the current focused screen
-- @function awful.screen.focus_bydirection
-- @param dir The direction, can be either "up", "down", "left" or "right".
-- @param _screen Screen.
function screen.focus_bydirection(dir, _screen)
@ -141,6 +158,7 @@ end
--- Give the focus to a screen, and move pointer to last known position on this
-- screen, or keep position relative to the current focused screen
-- @function awful.screen.focus_relative
-- @param i Value to add to the current focused screen index. 1 will focus next
-- screen, -1 would focus the previous one.
function screen.focus_relative(i)
@ -148,28 +166,40 @@ function screen.focus_relative(i)
end
--- Get or set the screen padding.
-- @deprecated awful.screen.padding
-- @param _screen The screen object to change the padding on
-- @param[opt=nil] padding The padding, a table with 'top', 'left', 'right' and/or
-- 'bottom' or a number value to apply set the same padding on all sides. Can be
-- nil if you only want to retrieve padding
-- @treturn table A table with left, right, top and bottom number values.
-- @see padding
function screen.padding(_screen, padding)
if type(padding) == "number" then
padding = {
left = padding,
right = padding,
top = padding,
bottom = padding,
}
end
util.deprecate "Use _screen.padding = value instead of awful.screen.padding"
_screen = get_screen(_screen)
if padding then
data.padding[_screen] = padding
_screen:emit_signal("padding")
screen.object.set_padding(_screen, padding)
end
local p = data.padding[_screen] or {}
return screen.object.get_padding(_screen)
end
--- The screen padding.
-- Add a "buffer" section on each side of the screen where the tiled client
-- wont be.
--
-- **Signal:**
--
-- * *property::padding*
--
-- @property padding
-- @param table
-- @tfield integer table.x The horizontal position
-- @tfield integer table.y The vertical position
-- @tfield integer table.width The width
-- @tfield integer table.height The height
function screen.object.get_padding(self)
local p = data.padding[self] or {}
-- Create a copy to avoid accidental mutation and nil values
return {
@ -180,14 +210,36 @@ function screen.padding(_screen, padding)
}
end
function screen.object.set_padding(self, padding)
if type(padding) == "number" then
padding = {
left = padding,
right = padding,
top = padding,
bottom = padding,
}
end
self = get_screen(self)
if padding then
data.padding[self] = padding
self:emit_signal("padding")
end
end
--- The defaults arguments for `awful.screen.focused`
-- @tfield[opt=nil] table awful.screen.default_focused_args
--- Get the focused screen.
--
-- It is possible to set `awful.screen.default_focused_args` to override the
-- default settings.
--
-- @function awful.screen.focused
-- @tparam[opt] table args
-- @tparam[opt=false] table args.client Use the client screen instead of the
-- @tparam[opt=false] boolean args.client Use the client screen instead of the
-- mouse screen.
-- @tparam[opt=true] boolean args.mouse Use the mouse screen
-- @treturn ?screen The focused screen object, or `nil` in case no screen is
-- present currently.
function screen.focused(args)
@ -209,24 +261,31 @@ end
-- * **bounding_rect**: A bounding rectangle. This parameter is incompatible with
-- `honor_workarea`.
--
-- @tparam[opt=mouse.screen] screen s A screen
-- @function screen.get_bounding_geometry
-- @tparam[opt={}] table args The arguments
-- @treturn table A table with *x*, *y*, *width* and *height*.
function screen.get_bounding_geometry(s, args)
-- @usage local geo = screen:get_bounding_geometry {
-- honor_padding = true,
-- honor_workarea = true,
-- margins = {
-- left = 20,
-- },
-- }
function screen.object.get_bounding_geometry(self, args)
args = args or {}
-- If the tag has a geometry, assume it is right
if args.tag then
s = args.tag.screen
self = args.tag.screen
end
s = get_screen(s or capi.mouse.screen)
self = get_screen(self or capi.mouse.screen)
local geo = args.bounding_rect or (args.parent and args.parent:geometry()) or
s[args.honor_workarea and "workarea" or "geometry"]
self[args.honor_workarea and "workarea" or "geometry"]
if (not args.parent) and (not args.bounding_rect) and args.honor_padding then
local padding = screen.padding(s)
local padding = self.padding
geo = apply_geometry_ajustments(geo, padding)
end
@ -242,7 +301,100 @@ function screen.get_bounding_geometry(s, args)
return geo
end
--- Get the list of the screen visible clients.
--
-- Minimized and unmanaged clients are not included in this list as they are
-- technically not on the screen.
--
-- The clients on tags currently not visible are not part of this list.
--
-- @property clients
-- @param table The clients list, ordered top to bottom
-- @see all_clients
-- @see hidden_clients
-- @see client.get
function screen.object.get_clients(s)
local cls = capi.client.get(s, true)
local vcls = {}
for _, c in pairs(cls) do
if c:isvisible() then
table.insert(vcls, c)
end
end
return vcls
end
function screen.object.set_clients() end
--- Get the list of the clients assigned to the screen but not currently
-- visible.
--
-- This include minimized clients and clients on hidden tags.
--
-- @property hidden_clients
-- @param table The clients list, ordered top to bottom
-- @see clients
-- @see all_clients
-- @see client.get
function screen.object.get_hidden_clients(s)
local cls = capi.client.get(s, true)
local vcls = {}
for _, c in pairs(cls) do
if not c:isvisible() then
table.insert(vcls, c)
end
end
return vcls
end
function screen.object.set_hidden_clients() end
--- Get all clients assigned to the screen.
--
-- @property all_clients
-- @param table The clients list, ordered top to bottom
-- @see clients
-- @see hidden_clients
-- @see client.get
function screen.object.get_all_clients(s)
return capi.client.get(s, true)
end
function screen.object.set_all_clients() end
--- Get the list of the screen tiled clients.
--
-- Same as s.clients, but excluding:
--
-- * fullscreen clients
-- * maximized clients
-- * floating clients
--
-- @property tiled_clients
-- @param table The clients list, ordered top to bottom
function screen.object.get_tiled_clients(s)
local clients = s.clients
local tclients = {}
-- Remove floating clients
for _, c in pairs(clients) do
if not c.floating
and not c.fullscreen
and not c.maximized_vertical
and not c.maximized_horizontal then
table.insert(tclients, c)
end
end
return tclients
end
function screen.object.set_tiled_clients() end
--- Call a function for each existing and created-in-the-future screen.
-- @function awful.screen.connect_for_each_screen
-- @tparam function func The function to call.
-- @tparam screen func.screen The screen
function screen.connect_for_each_screen(func)
@ -253,15 +405,88 @@ function screen.connect_for_each_screen(func)
end
--- Undo the effect of connect_for_each_screen.
-- @function awful.screen.disconnect_for_each_screen
-- @tparam function func The function that should no longer be called.
function screen.disconnect_for_each_screen(func)
capi.screen.disconnect_signal("added", func)
end
--- A list of all tags on the screen.
--
-- This property is read only, use `tag.screen`, `awful.tag.add`, `awful.tag.new`
-- or `t:delete()` to alter this list.
--
-- @property tags
-- @param table
-- @treturn table A table with all available tags
function screen.object.get_tags(s, unordered)
local tags = {}
for _, t in ipairs(root.tags()) do
if get_screen(t.screen) == s then
table.insert(tags, t)
end
end
-- Avoid infinite loop, + save some time
if not unordered then
table.sort(tags, function(a, b)
return (a.index or 9999) < (b.index or 9999)
end)
end
return tags
end
function screen.object.set_tags() end
--- A list of all selected tags on the screen.
-- @property selected_tags
-- @param table
-- @treturn table A table with all selected tags.
-- @see tag.selected
-- @see client.to_selected_tags
function screen.object.get_selected_tags(s)
local tags = screen.object.get_tags(s, true)
local vtags = {}
for _, t in pairs(tags) do
if t.selected then
vtags[#vtags + 1] = t
end
end
return vtags
end
function screen.object.set_selected_tags() end
--- The first selected tag.
-- @property selected_tag
-- @param table
-- @treturn ?tag The first selected tag or nil
-- @see tag.selected
-- @see selected_tags
function screen.object.get_selected_tag(s)
return screen.object.get_selected_tags(s)[1]
end
function screen.object.set_selected_tag() end
--- When the tag history changed.
-- @signal tag::history::update
capi.screen.add_signal("padding")
-- Extend the luaobject
object.properties(capi.screen, {auto_emit=true})
object.properties(capi.screen, {
getter_class = screen.object,
setter_class = screen.object,
auto_emit = true,
})
return screen

File diff suppressed because it is too large Load Diff

View File

@ -256,7 +256,7 @@ end
--- Create a new float button for a client.
-- @param c The client for which the button is wanted.
function titlebar.widget.floatingbutton(c)
local widget = titlebar.widget.button(c, "floating", aclient.floating.get, aclient.floating.toggle)
local widget = titlebar.widget.button(c, "floating", aclient.object.get_floating, aclient.floating.toggle)
c:connect_signal("property::floating", widget.update)
return widget
end

View File

@ -31,7 +31,7 @@ local function update(w, screen)
end
local function update_from_tag(t)
local screen = get_screen(tag.getscreen(t))
local screen = get_screen(t.screen)
local w = boxes[screen]
if w then
update(w, screen)

View File

@ -111,8 +111,8 @@ function taglist.taglist_label(t, args)
text = text .. "</span>"
end
if not taglist_disable_icon then
if tag.geticon(t) then
icon = surface.load(tag.geticon(t))
if t.icon then
icon = surface.load(t.icon)
end
end
@ -121,7 +121,7 @@ end
local function taglist_update(s, w, buttons, filter, data, style, update_function)
local tags = {}
for _, t in ipairs(tag.gettags(s)) do
for _, t in ipairs(s.tags) do
if not tag.getproperty(t, "hide") and filter(t) then
table.insert(tags, t)
end
@ -185,7 +185,7 @@ function taglist.new(screen, filter, buttons, style, update_function, base_widge
end
end
local uc = function (c) return u(c.screen) end
local ut = function (t) return u(tag.getscreen(t)) end
local ut = function (t) return u(t.screen) end
capi.client.connect_signal("focus", uc)
capi.client.connect_signal("unfocus", uc)
tag.attached_connect_signal(nil, "property::selected", ut)

View File

@ -79,7 +79,7 @@ local function tasklist_label(c, args, tb)
else
if c.maximized_horizontal then name = name .. maximized_horizontal end
if c.maximized_vertical then name = name .. maximized_vertical end
if client.floating.get(c) then name = name .. floating end
if c.floating then name = name .. floating end
end
end
@ -88,6 +88,7 @@ local function tasklist_label(c, args, tb)
else
name = name .. (util.escape(c.name) or util.escape("<untitled>"))
end
local focused = capi.client.focus == c
-- Handle transient_for: the first parent that does not skip the taskbar
-- is considered to be focused, if the real client has skip_taskbar.
@ -98,6 +99,7 @@ local function tasklist_label(c, args, tb)
end) == c then
focused = true
end
if focused then
bg = bg_focus
text = text .. "<span color='"..fg_focus.."'>"..name.."</span>"
@ -274,7 +276,7 @@ function tasklist.filter.currenttags(c, screen)
if get_screen(c.screen) ~= screen then return false end
-- Include sticky client too
if c.sticky then return true end
local tags = tag.gettags(screen)
local tags = screen.tags
for _, t in ipairs(tags) do
if t.selected then
local ctags = c:tags()
@ -300,7 +302,7 @@ function tasklist.filter.minimizedcurrenttags(c, screen)
if not c.minimized then return false end
-- Include sticky client
if c.sticky then return true end
local tags = tag.gettags(screen)
local tags = screen.tags
for _, t in ipairs(tags) do
-- Select only minimized clients
if t.selected then

View File

@ -53,13 +53,14 @@ function object.capi_index_fallback(class, args)
-- Look for a getter method
if args.getter_class and args.getter_class[getter_prefix..prop] then
return args.getter_class[getter_prefix..prop](cobj)
elseif args.getter_class and args.getter_class["is_"..prop] then
return args.getter_class["is_"..prop](cobj)
end
-- Make sure something like c:a_mutator() works
if args.getter_class and args.getter_class[prop] then
return args.getter_class[prop]
end
-- In case there is already a "dumb" getter like `awful.tag.getproperty'
if args.getter_fallback then
return args.getter_fallback(cobj, prop)

View File

@ -20,6 +20,9 @@
*/
/** awesome mouse API
*
* See also `mousegrabber`
*
* @author Julien Danjou &lt;julien@danjou.info&gt;
* @copyright 2008-2009 Julien Danjou
* @release @AWESOME_VERSION@
@ -35,10 +38,14 @@
/** Mouse library.
*
* @field screen Mouse screen.
* @table mouse
*/
/**
* The `screen` under the cursor
* @field screen
*/
/** A table with X and Y coordinates.
* @field x X coordinate.
* @field y Y coordinate.

View File

@ -1,4 +1,4 @@
/*
/*
* client.c - client management
*
* Copyright © 2007-2009 Julien Danjou <julien@danjou.info>
@ -19,7 +19,21 @@
*
*/
/** awesome client API
/** A process window.
*
* Clients are the name used by Awesome (and X11) to refer to a window. An
* application can have multiple clients (like for dialogs) or none at all
* (like command line applications). Clients are usually grouped by classes. A
* class is the name used by X11 to help window manager distinguish between
* window and write rules for them. See the `xprop` command line application. A
* client also have a `type` and `size_hints` used to define its behavior.
*
* ![Client geometry](../images/client_geo.svg)
*
* The client `:geometry()` return a table with *x*, *y*, *width* and *height*.
* The area returned **exclude the border width**. All clients also have a
* `shape_bounding` and `shape_clip` used to "crop" the client content. Finally,
* each clients can have titlebars (see `awful.titlebar`).
*
* Furthermore to the classes described here, one can also use signals as
* described in @{signals} and X properties as described in @{xproperties}.
@ -28,6 +42,43 @@
* the documentation generation, you get the real signal name by
* removing the starting dot.
*
* Accessing client objects can be done in multiple ways depending on the
* context. To get the current focused client, use:
*
* local c = client.focus
*
* if c then
* -- do something
* end
*
* To get a list of all clients, use `client:get`
*
* for _, c in ipairs(client.get()) do
* -- do something
* end
*
* To get a callback when a new client is added, use the `manage` signal:
*
* client.connect_signal("manage", function(c)
* -- do something
* end
*
* To be notified a property changed in a client, use:
*
* client.connect_signal("property::name", function(c)
* -- do something
* end
*
* To be notified when a property change for a specific client (assuming it is
* stored in the variable `c`), use:
*
* c:connect_signal("property::name", function()
* -- do something
* end
*
* To get all the clients for a screen, use either `screen.clients` or
* `screen.tiled_clients`
*
* @author Julien Danjou &lt;julien@danjou.info&gt;
* @copyright 2008-2009 Julien Danjou
* @release @AWESOME_VERSION@
@ -53,57 +104,529 @@
/** Client class.
*
* @table class
* @field focus The focused `client.object`.
* @table object
*/
/** Client object.
/**
* The focused `client` or nil (in case there is none).
*
* @field window The X window id.
* @field name The client title.
* @field skip_taskbar True if the client does not want to be in taskbar.
* @field type The window type (desktop, normal, dock, ).
* @field class The client class.
* @field instance The client instance.
* @field pid The client PID, if available.
* @field role The window role, if available.
* @field machine The machine client is running on.
* @field icon_name The client name when iconified.
* @field icon The client icon.
* @field screen Client screen.
* @field hidden Define if the client must be hidden, i.e. never mapped,
* @tfield client focus
*/
/**
* The X window id.
*
* **Signal:**
*
* * *property::window*
*
* @property window
* @param string
*/
/**
* The client title.
*
* **Signal:**
*
* * *property::name*
*
* @property name
* @param string
*/
/**
* True if the client does not want to be in taskbar.
*
* **Signal:**
*
* * *property::skip\_taskbar*
*
* @property skip_taskbar
* @param boolean
*/
/**
* The window type.
*
* Valid types are:
*
* * **desktop**: The root client, it cannot be moved or resized.
* * **dock**: A client attached to the side of the screen.
* * **splash**: A client, usually without titlebar shown when an application starts.
* * **dialog**: A dialog, see `transient_for`.
* * **menu**: A context menu.
* * **toolbar**: A floating toolbar.
* * **utility**:
* * **dropdown_menu**: A context menu attached to a parent position.
* * **popup_menu**: A context menu.
* * **notification**: A notification popup.
* * **combo**: A combobox list menu.
* * **dnd**: A drag and drop indicator.
* * **normal**: A normal application main window.
*
* More information can be found [here](https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472629520)
*
* **Signal:**
*
* * *property::type*
*
* @property type
* @param string
*/
/**
* The client class.
*
* If the client has multiple classes, the first one is used.
*
* To get a client class from the command line, use te `xprop` command.
*
* **Signal:**
*
* * *property::class*
*
* @property class
* @param string
*/
/**
* The client instance.
*
* **Signal:**
*
* * *property::instance*
*
* @property instance
* @param string
*/
/**
* The client PID, if available.
*
* **Signal:**
*
* * *property::pid*
*
* @property pid
* @param number
*/
/**
* The window role, if available.
*
* **Signal:**
*
* * *property::role*
*
* @property role
* @param string
*/
/**
* The machine client is running on.
*
* **Signal:**
*
* * *property::machine*
*
* @property machine
* @param string
*/
/**
* The client name when iconified.
*
* **Signal:**
*
* * *property::icon\_name*
*
* @property icon_name
* @param string
*/
/**
* The client icon.
*
* **Signal:**
*
* * *property::icon*
*
* @property icon
* @param surface
*/
/**
* Client screen.
*
* **Signal:**
*
* * *property::screen*
*
* @property screen
* @param screen
*/
/**
* Define if the client must be hidden, i.e. never mapped,
* invisible in taskbar.
* @field minimized Define it the client must be iconify, i.e. only visible in
*
* **Signal:**
*
* * *property::hidden*
*
* @property hidden
* @param boolean
*/
/**
* Define it the client must be iconify, i.e. only visible in
* taskbar.
* @field size_hints_honor Honor size hints, i.e. respect size ratio.
* @field border_width The client border width.
* @field border_color The client border color.
* @field urgent The client urgent state.
* @field content An image representing the client window content (screenshot).
* @field opacity The client opacity between 0 and 1.
* @field ontop The client is on top of every other windows.
* @field above The client is above normal windows.
* @field below The client is below normal windows.
* @field fullscreen The client is fullscreen or not.
* @field maximized The client is maximized (horizontally and vertically) or not.
* @field maximized_horizontal The client is maximized horizontally or not.
* @field maximized_vertical The client is maximized vertically or not.
* @field transient_for The client the window is transient for.
* @field group_window Window identification unique to a group of windows.
* @field leader_window Identification unique to windows spawned by the same command.
* @field size_hints A table with size hints of the client: `user_position`,
* `user_size`, `program_position`, `program_size`, etc.
* @field sticky Set the client sticky, i.e. available on all tags.
* @field modal Indicate if the client is modal.
* @field focusable True if the client can receive the input focus.
* @field shape_bounding The client's bounding shape as set by awesome as a (native) cairo surface.
* @field shape_clip The client's clip shape as set by awesome as a (native) cairo surface.
* @field shape_client_bounding The client's bounding shape as set by the program as a (native) cairo surface.
* @field shape_client_clip The client's clip shape as set by the program as a (native) cairo surface.
* @field startup_id The FreeDesktop StartId.
* @field valid If the client that this object refers to is still managed by awesome.
* @field first_tag The first tag of the client. Optimized form of `c:tags()[1]`.
* @table object
*
* **Signal:**
*
* * *property::minimized*
*
* @property minimized
* @param boolean
*/
/**
* Honor size hints, e.g. respect size ratio.
*
* For example, a terminal such as `xterm` require the client size to be a
* multiple of the character size. Honoring size hints will cause the terminal
* window to have a small gap at the bottom.
*
* This is enabled by default. To disable it by default, see `awful.rules`.
*
* **Signal:**
*
* * *property::size\_hints\_honor*
*
* @property size_hints_honor
* @param boolean
* @see size_hints
*/
/**
* The client border width.
* @property border_width
* @param integer
*/
/**
* The client border color.
*
* **Signal:**
*
* * *property::border\_color*
*
* @see gears.color
*
* @property border_color
* @param pattern Any string, gradients and patterns will be converted to a
* cairo pattern.
*/
/**
* The client urgent state.
*
* **Signal:**
*
* * *property::urgent*
*
* @property urgent
* @param boolean
*/
/**
* A cairo surface for the client window content.
*
* To get the screenshot, use:
*
* gears.surface(c.content)
*
* To save it, use:
*
* gears.surface(c.content):write_to_png(path)
*
* @property content
* @param surface
*/
/**
* The client opacity.
*
* **Signal:**
*
* * *property::opacity*
*
* @property opacity
* @param number Between 0 (transparent) to 1 (opaque)
*/
/**
* The client is on top of every other windows.
* @property ontop
* @param boolean
*/
/**
* The client is above normal windows.
*
* **Signal:**
*
* * *property::above*
*
* @property above
* @param boolean
*/
/**
* The client is below normal windows.
*
* **Signal:**
*
* * *property::below*
*
* @property below
* @param boolean
*/
/**
* The client is fullscreen or not.
*
* **Signal:**
*
* * *property::fullscreen*
*
* @property fullscreen
* @param boolean
*/
/**
* The client is maximized (horizontally and vertically) or not.
*
* **Signal:**
*
* * *property::maximized*
*
* @property maximized
* @param boolean
*/
/**
* The client is maximized horizontally or not.
*
* **Signal:**
*
* * *property::maximized\_horizontal*
*
* @property maximized_horizontal
* @param boolean
*/
/**
* The client is maximized vertically or not.
*
* **Signal:**
*
* * *property::maximized\_vertical*
*
* @property maximized_vertical
* @param boolean
*/
/**
* The client the window is transient for.
*
* **Signal:**
*
* * *property::transient\_for*
*
* @property transient_for
* @param client
*/
/**
* Window identification unique to a group of windows.
*
* **Signal:**
*
* * *property::group\_window*
*
* @property group_window
* @param client
*/
/**
* Identification unique to windows spawned by the same command.
* @property leader_window
* @param client
*/
/**
* A table with size hints of the client.
*
* **Signal:**
*
* * *property::size\_hints*
*
* @property size_hints
* @param table
* @tfield integer table.user_position
* @tfield integer table.user_size
* @tfield integer table.program_position
* @tfield integer table.program_size
* @tfield integer table.max_width
* @tfield integer table.max_height
* @tfield integer table.min_width
* @tfield integer table.min_height
* @tfield integer table.width_inc
* @tfield integer table.height_inc
* @see size_hints_honor
*/
/**
* Set the client sticky, i.e. available on all tags.
*
* **Signal:**
*
* * *property::sticky*
*
* @property sticky
* @param boolean
*/
/**
* Indicate if the client is modal.
*
* **Signal:**
*
* * *property::modal*
*
* @property modal
* @param boolean
*/
/**
* True if the client can receive the input focus.
*
* **Signal:**
*
* * *property::focusable*
*
* @property focusable
* @param boolean
*/
/**
* The client's bounding shape as set by awesome as a (native) cairo surface.
*
* **Signal:**
*
* * *property::shape\_bounding*
*
* @see gears.surface.apply_shape_bounding
* @property shape_bounding
* @param surface
*/
/**
* The client's clip shape as set by awesome as a (native) cairo surface.
*
* **Signal:**
*
* * *property::shape\_clip*
*
* @property shape_clip
* @param surface
*/
/**
* The client's bounding shape as set by the program as a (native) cairo surface.
*
* **Signal:**
*
* * *property::shape\_client\_bounding*
*
* @property shape_client_bounding
* @param surface
*/
/**
* The client's clip shape as set by the program as a (native) cairo surface.
*
* **Signal:**
*
* * *property::shape\_client\_clip*
*
* @property shape_client_clip
* @param surface
*/
/**
* The FreeDesktop StartId.
*
* When a client is spawned (like using a terminal or `awful.spawn`, a startup
* notification identifier is created. When the client is created, this
* identifier remain the same. This allow to match a spawn event to an actual
* client.
*
* **Signal:**
*
* * *property::startup\_id*
*
* @property startup_id
* @param string
*/
/**
* If the client that this object refers to is still managed by awesome.
*
* To avoid errors, use:
*
* local is_valid = pcall(function() return c.valid end) and c.valid
*
* **Signal:**
*
* * *property::valid*
*
* @property valid
* @param boolean
*/
/**
* The first tag of the client. Optimized form of `c:tags()[1]`.
*
* **Signal:**
*
* * *property::first\_tag*
*
* @property first_tag
* @param tag
*/
/**
* The border color when the client is focused.
*
* @beautiful beautiful.border_focus
* @param string
*/
/**
* The border color when the client is not focused.
*
* @beautiful beautiful.border_normal
* @param string
*/
/**
* The client border width.
*
* @beautiful beautiful.border_width
* @param integer
*/
/** Return client struts (reserved space at the edge of the screen).
@ -126,12 +649,12 @@
* @function instances
*/
/** Set a __index metamethod for all client instances.
/* Set a __index metamethod for all client instances.
* @tparam function cb The meta-method
* @function set_index_miss_handler
*/
/** Set a __newindex metamethod for all client instances.
/* Set a __newindex metamethod for all client instances.
* @tparam function cb The meta-method
* @function set_newindex_miss_handler
*/
@ -2854,161 +3377,46 @@ client_class_setup(lua_State *L)
* @signal mouse::move
*/
signal_add(&client_class.signals, "mouse::move");
/**
* @signal property::above
*/
/* Those signals are documented elsewhere */
signal_add(&client_class.signals, "property::above");
/**
* @signal property::below
*/
signal_add(&client_class.signals, "property::below");
/**
* @signal property::class
*/
signal_add(&client_class.signals, "property::class");
/**
* @signal property::focusable
*/
signal_add(&client_class.signals, "property::focusable");
/**
* @signal property::fullscreen
*/
signal_add(&client_class.signals, "property::fullscreen");
/**
* @signal property::geometry
*/
signal_add(&client_class.signals, "property::geometry");
/**
* @signal property::group_window
*/
signal_add(&client_class.signals, "property::group_window");
/**
* @signal property::height
*/
signal_add(&client_class.signals, "property::height");
/**
* @signal property::hidden
*/
signal_add(&client_class.signals, "property::hidden");
/**
* @signal property::icon
*/
signal_add(&client_class.signals, "property::icon");
/**
* @signal property::icon_name
*/
signal_add(&client_class.signals, "property::icon_name");
/**
* @signal property::instance
*/
signal_add(&client_class.signals, "property::instance");
/**
* @signal property::keys
*/
signal_add(&client_class.signals, "property::keys");
/**
* @signal property::machine
*/
signal_add(&client_class.signals, "property::machine");
/**
* @signal property::maximized
*/
signal_add(&client_class.signals, "property::maximized");
/**
* @signal property::maximized_horizontal
*/
signal_add(&client_class.signals, "property::maximized_horizontal");
/**
* @signal property::maximized_vertical
*/
signal_add(&client_class.signals, "property::maximized_vertical");
/**
* @signal property::minimized
*/
signal_add(&client_class.signals, "property::minimized");
/**
* @signal property::modal
*/
signal_add(&client_class.signals, "property::modal");
/**
* @signal property::name
*/
signal_add(&client_class.signals, "property::name");
/**
* @signal property::ontop
*/
signal_add(&client_class.signals, "property::ontop");
/**
* @signal property::pid
*/
signal_add(&client_class.signals, "property::pid");
/**
* @signal property::role
*/
signal_add(&client_class.signals, "property::role");
/**
* @signal property::screen
*/
signal_add(&client_class.signals, "property::screen");
/**
* @signal property::shape_bounding
*/
signal_add(&client_class.signals, "property::shape_bounding");
/**
* @signal property::shape_client_bounding
*/
signal_add(&client_class.signals, "property::shape_client_bounding");
/**
* @signal property::shape_client_clip
*/
signal_add(&client_class.signals, "property::shape_client_clip");
/**
* @signal property::shape_clip
*/
signal_add(&client_class.signals, "property::shape_clip");
/**
* @signal property::size_hints_honor
*/
signal_add(&client_class.signals, "property::size_hints_honor");
/**
* @signal property::skip_taskbar
*/
signal_add(&client_class.signals, "property::skip_taskbar");
/**
* @signal property::sticky
*/
signal_add(&client_class.signals, "property::sticky");
/**
* @signal property::struts
*/
signal_add(&client_class.signals, "property::struts");
/**
* @signal property::titlebar_bottom
*/
signal_add(&client_class.signals, "property::titlebar_bottom");
/**
* @signal property::titlebar_left
*/
signal_add(&client_class.signals, "property::titlebar_left");
/**
* @signal property::titlebar_right
*/
signal_add(&client_class.signals, "property::titlebar_right");
/**
* @signal property::titlebar_top
*/
signal_add(&client_class.signals, "property::titlebar_top");
/**
* @signal property::transient_for
*/
signal_add(&client_class.signals, "property::transient_for");
/**
* @signal property::type
*/
signal_add(&client_class.signals, "property::type");
/**
* @signal property::urgent
*/
signal_add(&client_class.signals, "property::urgent");
/**
* @signal property::width

View File

@ -20,6 +20,22 @@
*/
/** awesome screen API
*
* Screen objects can be added and removed over time. To get a callback for all
* current and future screens, use `awful.screen.connect_for_each_screen`:
*
* awful.screen.connect_for_each_screen(function(s)
* -- do something
* end)
*
* It is also possible loop over all current screens using:
*
* for s, screen do
* -- do something
* end
*
* Most basic Awesome objects also have a screen property, see `mouse.screen`
* `client.screen`, `wibox.screen` and `tag.screen`.
*
* Furthermore to the classes described here, one can also use signals as
* described in @{signals}.
@ -47,26 +63,91 @@
* The primary screen can be accessed as `screen.primary`.
* Each screen has a set of properties.
*
* @tfield table geometry The screen coordinates. Immutable.
* @tfield table workarea The screen workarea.
* @tfield int index The screen number.
* @tfield table outputs If RANDR information is available, a list of outputs
* for this screen and their size in mm.
* @table screen
*/
/**
* The primary screen.
*
* @tfield screen primary
*/
/**
* The screen coordinates.
*
* **Immutable:** true
* @property geometry
* @param table
* @tfield integer table.x The horizontal position
* @tfield integer table.y The vertical position
* @tfield integer table.width The width
* @tfield integer table.height The height
*/
/**
* The screen number.
*
* An integer greater than 1 and smaller than `screen.count()`. Please note that
* the screen order isn't always mirroring the screen logical position.
*
* **Immutable:** true
* @property index
* @param integer
*/
/**
* If RANDR information is available, a list of outputs
* for this screen and their size in mm.
*
* Please note that the table content may vary.
*
* **Signal:**
*
* * *property::outputs*
*
* **Immutable:** true
* @property outputs
* @param table
* @tfield table table.name A table with the screen name as key (like `eDP1` on a laptop)
* @tfield integer table.name.mm_width The screen physical width
* @tfield integer table.name.mm_height The screen physical height
*/
/**
* The screen workarea.
*
* The workarea is a subsection of the screen where clients can be placed. It
* usually excludes the toolbars (see `awful.wibox`) and dockable clients
* (see `client.dockable`) like WindowMaker DockAPP.
*
* It can be modified be altering the `wibox` or `client` struts.
*
* **Signal:**
*
* * *property::workarea*
*
* @property workarea
* @see client.struts
* @see drawin.struts
* @param table
* @tfield integer table.x The horizontal position
* @tfield integer table.y The vertical position
* @tfield integer table.width The width
* @tfield integer table.height The height
*/
/** Get the number of instances.
*
* @return The number of screen objects alive.
* @function instances
*/
/** Set a __index metamethod for all screen instances.
/* Set a __index metamethod for all screen instances.
* @tparam function cb The meta-method
* @function set_index_miss_handler
*/
/** Set a __newindex metamethod for all screen instances.
/* Set a __newindex metamethod for all screen instances.
* @tparam function cb The meta-method
* @function set_newindex_miss_handler
*/
@ -752,17 +833,15 @@ screen_class_setup(lua_State *L)
NULL,
(lua_class_propfunc_t) luaA_screen_get_workarea,
NULL);
/**
* @signal property::workarea
*/
signal_add(&screen_class.signals, "property::workarea");
/**
* @signal primary_changed
* @signal .primary_changed
*/
signal_add(&screen_class.signals, "primary_changed");
/**
* This signal is emitted when a new screen is added to the current setup.
* @signal added
* @signal .added
*/
signal_add(&screen_class.signals, "added");
}

View File

@ -24,6 +24,8 @@
* Furthermore to the classes described here, one can also use signals as
* described in @{signals}.
*
* ![Client geometry](../images/tag_props.svg)
*
* Some signal names are starting with a dot. These dots are artefacts from
* the documentation generation, you get the real signal name by
* removing the starting dot.
@ -40,12 +42,37 @@
#include "ewmh.h"
#include "luaa.h"
/** Tag object.
/**
* Tag name.
*
* @field name Tag name.
* @field selected True if the tag is selected to be viewed.
* @field activated True if the tag is active and can be used.
* @table tag
* **Signal:**
*
* * *property::name*
*
* @property name
* @param string
*/
/**
* True if the tag is selected to be viewed
*
* **Signal:**
*
* * *property::selected*
*
* @property selected
* @param boolean
*/
/**
* True if the tag is active and can be used.
*
* **Signal:**
*
* * *property::activated*
*
* @property activated
* @param boolean
*/
/** Get the number of instances.
@ -54,12 +81,12 @@
* @function instances
*/
/** Set a __index metamethod for all tag instances.
/* Set a __index metamethod for all tag instances.
* @tparam function cb The meta-method
* @function set_index_miss_handler
*/
/** Set a __newindex metamethod for all tag instances.
/* Set a __newindex metamethod for all tag instances.
* @tparam function cb The meta-method
* @function set_newindex_miss_handler
*/
@ -389,17 +416,8 @@ tag_class_setup(lua_State *L)
(lua_class_propfunc_t) luaA_tag_get_activated,
(lua_class_propfunc_t) luaA_tag_set_activated);
/**
* @signal property::name
*/
signal_add(&tag_class.signals, "property::name");
/**
* @signal property::selected
*/
signal_add(&tag_class.signals, "property::selected");
/**
* @signal property::activated
*/
signal_add(&tag_class.signals, "property::activated");
/**
* @signal request::select

View File

@ -8,7 +8,7 @@ local function _shim_fake_class()
local meta = {
__index = function()end,
__new_index = function()end,
__newindex = function()end,
}
obj._connect_signal = obj.connect_signal
@ -28,7 +28,7 @@ local function _shim_fake_class()
end
function obj.set_newindex_miss_handler(handler)
meta.__new_index = handler
meta.__newindex = handler
end
function obj.emit_signal(name, c, ...)

View File

@ -2,7 +2,7 @@ local gears_obj = require("gears.object")
local clients = {}
local client = awesome._shim_fake_class()
local client, meta = awesome._shim_fake_class()
local function add_signals(c)
c:add_signal("property::width")
@ -119,7 +119,10 @@ function client.gen_fake(args)
client.emit_signal("manage", ret)
assert(not args.screen or (args.screen == ret.screen))
return ret
return setmetatable(ret, {
__index = function(...) return meta.__index(...) end,
__newindex = function(...) return meta.__newindex(...) end
})
end
function client.get(s)

View File

@ -1,6 +1,6 @@
local gears_obj = require("gears.object")
local screen = awesome._shim_fake_class()
local screen, meta = awesome._shim_fake_class()
screen.count = 1
@ -8,6 +8,7 @@ local function create_screen(args)
local s = gears_obj()
s:add_signal("property::workarea")
s:add_signal("property::index")
s:add_signal("padding")
-- Copy the geo in case the args are mutated
@ -42,8 +43,11 @@ local function create_screen(args)
width = geo.width - 2*wa,
height = geo.height - 2*wa,
}
else
return meta.__index(_, key)
end
end,
__newindex = function(...) return meta.__newindex(...) end
})
end

View File

@ -9,8 +9,11 @@ local function new_tag(_, args)
ret:add_signal("property::name")
ret:add_signal("property::geometry")
ret:add_signal("property::screen")
ret:add_signal("property::master_width_factor")
ret:add_signal("property::mwfact")
ret:add_signal("property::ncol")
ret:add_signal("property::column_count")
ret:add_signal("property::master_count")
ret:add_signal("property::nmaster")
ret:add_signal("property::index")
ret:add_signal("property::useless_gap")
@ -35,7 +38,7 @@ local function new_tag(_, args)
return setmetatable(ret, {
__index = function(...) return meta.__index(...) end,
__new_index = function(...) return meta.__new_index(...) end
__newindex = function(...) return meta.__newindex(...) end
})
end

236
tests/test-awesomerc.lua Normal file
View File

@ -0,0 +1,236 @@
local awful = require("awful")
-- luacheck: globals modkey
local old_c = nil
local function get_callback(mod, key)
local inf = {}
awful.key(mod, key, nil, nil, inf)
return inf.execute
end
-- Get a tag and a client
local function get_c_and_t()
client.focus = old_c or client.get()[1]
local c = client.focus
local t = c.screen.selected_tag
return c, t
end
-- display deprecated warnings
--awful.util.deprecate = function() end
local has_spawned = false
local steps = {
function(count)
if count <= 1 and not has_spawned and #client.get() < 2 then
for _=1, 5 do awful.spawn("xterm") end
has_spawned = true
elseif #client.get() >= 5 then
local c, _ = get_c_and_t()
old_c = c
return true
end
end,
-- Wait for the focus to change
function()
if has_spawned then
has_spawned = false
return nil
end
assert(old_c)
-- Test layout
-- local cb = get_callback({modkey}, " ")
-- assert(cb)
--TODO use the key once the bug is fixed
local l = old_c.screen.selected_tag.layout
assert(l)
-- cb()
awful.layout.inc(1)
assert(old_c.screen.selected_tag.layout ~= l)
-- Test ontop
assert(not old_c.ontop)
get_callback({modkey}, "t")()
return true
end,
-- Ok, no now ontop should be true
function()
local _, t = get_c_and_t()
-- Give awesome some time
if not old_c.ontop then return nil end
assert(old_c.ontop)
-- Now, test the master_width_factor
assert(t.master_width_factor == 0.5)
get_callback({modkey}, "l")()
return true
end,
-- The master width factor should now be bigger
function()
local _, t = get_c_and_t()
assert(t.master_width_factor == 0.55)
-- Now, test the master_count
assert(t.master_count == 1)
get_callback({modkey, "Shift"}, "h")()
return true
end,
-- The number of master client should now be 2
function()
local _, t = get_c_and_t()
assert(t.master_count == 2)
-- Now, test the column_count
assert(t.column_count == 1)
get_callback({modkey, "Control"}, "h")()
get_callback({modkey, "Shift" }, "l")()
return true
end,
-- The number of columns should now be 2
function()
local _, t = get_c_and_t()
assert(t.column_count == 2)
-- Now, test the switching tag
assert(t.index == 1)
get_callback({modkey, }, "Right")()
return true
end,
-- The tag index should now be 2
function()
local tags = mouse.screen.tags
-- local t = awful.screen.focused().selected_tag
-- assert(t.index == 2)--FIXME
assert(tags[1].index == 1)
tags[1]:view_only()
return true
end,
-- Before testing tags, lets make sure everything is still right
function()
local tags = mouse.screen.tags
assert(tags[1].selected)
local clients = mouse.screen.clients
-- Make sure the clients are all on the same screen, they should be
local c_scr = client.get()[1].screen
for _, c in ipairs(client.get()) do
assert(c_scr == c.screen)
end
-- Then this should be true
assert(#clients == #client.get())
assert(#mouse.screen.all_clients == #clients)
assert(#mouse.screen.all_clients - #mouse.screen.hidden_clients == #clients)
return true
end,
-- Now, test switching tags
function()
local tags = mouse.screen.tags
local clients = mouse.screen.all_clients
assert(#tags == 9)
assert(#clients == 5)
assert(mouse.screen.selected_tag == tags[1])
for i=1, 9 do
-- Check that assertion, because if it's false, the other assert()
-- wont make any sense.
assert(tags[i].index == i)
end
for i=1, 9 do
tags[i]:view_only()
assert(tags[i].selected)
assert(#mouse.screen.selected_tags == 1)
end
tags[1]:view_only()
return true
end,
-- Lets shift some clients around
function()
local tags = mouse.screen.tags
-- Given all tags have been selected, the selection should be back on
-- tags[1] and the client history should be kept
assert(client.focus == old_c)
--get_callback({modkey, "Shift" }, "#"..(9+i))() --FIXME
client.focus:move_to_tag(tags[2])
assert(not client.focus)
return true
end,
-- The client should be on tag 5
function()
-- Confirm the move did happen
local tags = mouse.screen.tags
assert(tags[1].selected)
assert(#old_c:tags() == 1)
assert(old_c:tags()[1] ~= tags[1])
assert(not old_c:tags()[1].selected)
-- The focus should have changed by now, as the tag isn't visible
assert(client.focus ~= old_c)
assert(old_c:tags()[1] == tags[2])
assert(#tags[2]:clients() == 1)
assert(#tags[1]:clients() == 4)
return true
end
}
require("_runner").run_steps(steps)

View File

@ -0,0 +1,83 @@
local awful = require("awful")
awful.util.deprecate = function() end
local has_spawned = false
local steps = {
function(count)
if count <= 1 and not has_spawned and #client.get() < 2 then
awful.spawn("xterm")
awful.spawn("xterm")
has_spawned = true
elseif #client.get() >= 2 then
-- Test properties
client.focus = client.get()[1]
local c = client.focus
-- local c2 = client.get()[2]
client.add_signal("property::foo")
c.foo = "bar"
-- Check if the property system works
assert(c.foo == "bar")
assert(c.foo == awful.client.property.get(c, "foo"))
-- Test jumpto
--FIXME doesn't work
-- c2:jump_to()
-- assert(client.focus == c2)
-- awful.client.jumpto(c)
-- assert(client.focus == c)
-- Test moveresize
c.size_hints_honor = false
c:geometry {x=0,y=0,width=50,height=50}
c:relative_move( 100, 100, 50, 50 )
for _,v in pairs(c:geometry()) do
assert(v == 100)
end
awful.client.moveresize(-25, -25, -25, -25, c )
for _,v in pairs(c:geometry()) do
assert(v == 75)
end
-- Test movetotag
local t = tags[mouse.screen][1]
local t2 = tags[mouse.screen][2]
c:tags{t}
assert(c:tags()[1] == t)
c:move_to_tag(t2)
assert(c:tags()[1] == t2)
awful.client.movetotag(t, c)
assert(c:tags()[1] == t)
-- Test toggletag
c:tags{t}
c:toggle_tag(t2)
assert(c:tags()[1] == t2 or c:tags()[2] == t2)
awful.client.toggletag(t2, c)
assert(c:tags()[1] == t and c:tags()[1] ~= t2 and c:tags()[2] == nil)
-- Test movetoscreen
--FIXME I don't have the hardware to test
-- Test floating
assert(c.floating ~= nil and type(c.floating) == "boolean")
c.floating = true
assert(awful.client.floating.get(c))
awful.client.floating.set(c, false)
assert(not c.floating)
return true
end
end
}
require("_runner").run_steps(steps)

View File

@ -0,0 +1,89 @@
local awful = require("awful")
awful.util.deprecate = function() end
local has_spawned = false
local steps = {
function(count)
if count <= 1 and not has_spawned and #client.get() < 2 then
awful.spawn("xterm")
awful.spawn("xterm")
has_spawned = true
elseif #client.get() >= 2 then
-- Test properties
client.focus = client.get()[1]
local s = mouse.screen
assert(s)
assert(s == screen[s])
-- Test padding
s.padding = 42
local counter = 0
for _, v in pairs(s.padding) do
assert(v == 42)
counter = counter + 1
end
assert(counter == 4)
awful.screen.padding(s, {
left = 1337,
right = 1337,
top = 1337,
bottom = 1337,
})
counter = 0
for _, v in pairs(s.padding) do
assert(v == 1337)
counter = counter + 1
end
assert(counter == 4)
counter = 0
for _, v in pairs(awful.screen.padding(s)) do
assert(v == 1337)
counter = counter + 1
end
assert(counter == 4)
-- Test square distance
assert(s:get_square_distance(9999, 9999))
assert(s:get_square_distance(9999, 9999)
== awful.screen.getdistance_sq(s, 9999, 9999))
-- Test count
counter = 0
for _ in screen do
counter = counter + 1
end
assert(screen.count() == counter)
counter = 0
awful.screen.connect_for_each_screen(function()
counter = counter + 1
end)
assert(screen.count() == counter)
return true
end
end
}
require("_runner").run_steps(steps)

111
tests/test-awful-tag.lua Normal file
View File

@ -0,0 +1,111 @@
local awful = require("awful")
local beautiful = require("beautiful")
awful.util.deprecate = function() end
local has_spawned = false
local steps = {
function(count)
if count <= 1 and not has_spawned and #client.get() < 2 then
awful.spawn("xterm")
awful.spawn("xterm")
has_spawned = true
elseif #client.get() >= 2 then
-- Test move, swap and index
local tags = mouse.screen.tags
assert(#mouse.screen.tags == 9)
for k, v in ipairs(tags) do
assert(k == v.index)
end
tags[7].index = 9
assert(tags[7].index == 9)
tags[7].index = 4
assert(tags[7].index == 4)
awful.tag.move(5, tags[7])
assert(tags[7].index == 5)
tags[1]:swap(tags[3])
assert(tags[1].index == 3)
assert(tags[3].index == 1)
awful.tag.swap(tags[1], tags[3])
assert(tags[3].index == 3)
assert(tags[1].index == 1)
-- Test add, icon and delete
client.focus = client.get()[1]
local c = client.focus
assert(c and client.focus == c)
assert(beautiful.awesome_icon)
local t = awful.tag.add("Test", {clients={c}, icon = beautiful.awesome_icon})
local found = false
tags = mouse.screen.tags
assert(#tags == 10)
for _, v in ipairs(tags) do
if t == v then
found = true
break
end
end
assert(found)
assert(t:clients()[1] == c)
assert(c:tags()[2] == t)
assert(t.icon == beautiful.awesome_icon)
t:delete()
tags = mouse.screen.tags
assert(#tags == 9)
found = false
for _, v in ipairs(tags) do
if t == v then
found = true
break
end
end
assert(not found)
-- Test selected tags, view only and selected()
t = tags[2]
assert(not t.selected)
assert(t.screen.selected_tag == tags[1])
t:view_only()
assert(t.selected)
assert(not tags[1].selected)
assert(#t.screen.selected_tags == 1)
return true
end
end
}
require("_runner").run_steps(steps)

View File

@ -32,7 +32,7 @@ local steps = {
if count == 1 then -- Setup.
urgent_cb_done = false
-- Select first tag.
awful.tag.viewonly(tags[awful.screen.focused()][1])
tags[awful.screen.focused()][1]:view_only()
runner.add_to_default_rules({ rule = { class = "XTerm" },
properties = { tag = tags[awful.screen.focused()][2], focus = true } })
@ -72,7 +72,7 @@ local steps = {
urgent_cb_done = false
-- Select first tag.
awful.tag.viewonly(tags[awful.screen.focused()][1])
tags[awful.screen.focused()][1]:view_only()
runner.add_to_default_rules({ rule = { class = "XTerm" },
properties = { tag = tags[awful.screen.focused()][2], focus = true, switchtotag = true }})