From 6e54661e7fd900cb0ec6763ccfca923e9582035e Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Thu, 31 Jul 2008 22:33:18 +0200 Subject: [PATCH] awful: implement focus history Signed-off-by: Julien Danjou --- awesomerc.lua.in | 17 +++++++----- lib/awful.lua.in | 71 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/awesomerc.lua.in b/awesomerc.lua.in index 0a65cf4e..05cd3249 100644 --- a/awesomerc.lua.in +++ b/awesomerc.lua.in @@ -92,8 +92,8 @@ function mytaglist.label(t) return awful.widget.taglist.label.all(t, bg_focus, f -- Create a tasklist widget mytasklist = widget({ type = "tasklist", name = "mytasklist" }) mytasklist:mouse_add(mouse({ }, 1, function (object, c) c:focus_set(); c:raise() end)) -mytasklist:mouse_add(mouse({ }, 4, function () awful.client.focus(1) end)) -mytasklist:mouse_add(mouse({ }, 5, function () awful.client.focus(-1) end)) +mytasklist:mouse_add(mouse({ }, 4, function () awful.client.focusbyidx(1) end)) +mytasklist:mouse_add(mouse({ }, 5, function () awful.client.focusbyidx(-1) end)) function mytasklist.label(c, screen) return awful.widget.tasklist.label.currenttags(c, screen, bg_focus, fg_focus) end -- Create a textbox widget @@ -201,8 +201,8 @@ keybinding({ modkey, "Shift" }, "q", awesome.quit):add() -- Client manipulation keybinding({ modkey }, "m", awful.client.maximize):add() keybinding({ modkey, "Shift" }, "c", function () client.focus_get():kill() end):add() -keybinding({ modkey }, "j", function () awful.client.focus(1); client.focus_get():raise() end):add() -keybinding({ modkey }, "k", function () awful.client.focus(-1); client.focus_get():raise() end):add() +keybinding({ modkey }, "j", function () awful.client.focusbyidx(1); client.focus_get():raise() end):add() +keybinding({ modkey }, "k", function () awful.client.focusbyidx(-1); client.focus_get():raise() end):add() keybinding({ modkey, "Shift" }, "j", function () awful.client.swap(1) end):add() keybinding({ modkey, "Shift" }, "k", function () awful.client.swap(-1) end):add() keybinding({ modkey, "Control" }, "j", function () awful.screen.focus(1) end):add() @@ -210,6 +210,7 @@ keybinding({ modkey, "Control" }, "k", function () awful.screen.focus(-1) end):a keybinding({ modkey, "Control" }, "space", awful.client.togglefloating):add() keybinding({ modkey, "Control" }, "Return", function () client.focus_get():swap(awful.client.master()) end):add() keybinding({ modkey }, "o", awful.client.movetoscreen):add() +keybinding({ modkey }, "Tab", awful.client.focus.history.previous):add() -- Layout manipulation keybinding({ modkey }, "l", function () awful.tag.incmwfact(0.05) end):add() @@ -362,10 +363,10 @@ function hook_arrange(screen) -- Update tag history awful.tag.history.update(screen) - -- If no window has focus, give focus to the first one + -- If no window has focus, give focus to the latest in history if not client.focus_get() then - local vc = client.visible_get(screen) - if #vc > 0 then vc[1]:focus_set() end + local c = awful.client.focus.history.get(screen, 0) + if c then c:focus_set() end end -- Uncomment if you want mouse warping @@ -402,10 +403,12 @@ end -- Set up some hooks awful.hooks.focus(hook_focus) +awful.hooks.focus(awful.client.focus.history.add) awful.hooks.unfocus(hook_unfocus) awful.hooks.marked(hook_marked) awful.hooks.unmarked(hook_unmarked) awful.hooks.manage(hook_manage) +awful.hooks.unmanage(awful.client.focus.history.delete) awful.hooks.mouseover(hook_mouseover) awful.hooks.arrange(hook_arrange) awful.hooks.timer(1, hook_timer) diff --git a/lib/awful.lua.in b/lib/awful.lua.in index 977d9e1d..151a4c66 100644 --- a/lib/awful.lua.in +++ b/lib/awful.lua.in @@ -44,6 +44,9 @@ P.completion = {} P.screen = {} P.layout = {} P.client = {} +P.client.focus = {} +P.client.focus.history = {} +P.client.focus.history.data = {} P.tag = {} P.tag.history = {} P.tag.history.data = {} @@ -83,6 +86,68 @@ local function cycle(t, i) return i end +--- Remove a client from the focus history +-- @param c The client that must be removed. +function P.client.focus.history.delete(c) + for k, v in ipairs(P.client.focus.history.data) do + if v == c then + table.remove(P.client.focus.history.data, k) + break + end + end +end + +--- Update client focus history. +-- @param c The client that has been focused. +function P.client.focus.history.add(c) + -- Remove the client if its in stack + P.client.focus.history.delete(c) + -- Record the client has latest focused + table.insert(P.client.focus.history.data, 1, c) +end + +--- Get the latest focused client for a screen in history. +-- @param screen The screen number to look for. +-- @param idx The index: 0 will return first candidate, +-- 1 will return second, etc. +-- @return A client. +function P.client.focus.history.get(screen, idx) + -- When this counter is equal to idx, we return the client + local counter = 0 + local vc = client.visible_get(screen) + for k, c in ipairs(P.client.focus.history.data) do + if c.screen == screen then + for j, 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 + -- Argh nobody found in history, give the first one visible if there is one + if counter == 0 then + return vc[1] + end +end + +--- Focus the previous client in history. +function P.client.focus.history.previous() + local sel = client.focus_get() + local s + if sel then + s = sel.screen + else + s = mouse.screen + end + local c = P.client.focus.history.get(s, 1) + if c then c:focus_set() end +end + --- Get a client by its relative index to the focused window. -- @usage Set i to 1 to get next, -1 to get previous. -- @param i The index. @@ -107,7 +172,7 @@ end --- Focus a client by its relative index. -- @param i The index. -- @param c Optional client. -function P.client.focus(i, c) +function P.client.focusbyidx(i, c) local target = P.client.next(i, c) if target then target:focus_set() @@ -173,8 +238,8 @@ function P.screen.focus(i) s = mouse.screen end s = cycle(screen.count(), s + i) - local vc = client.visible_get(s) - if #vc > 0 then vc[1]:focus_set() end + local c = P.client.focus.history.get(s, 0) + if c then c:focus_set() end -- Move the mouse on the screen mouse.coords = screen.coords_get(s) end