summaryrefslogtreecommitdiff
path: root/workspace.lua
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-06-13 10:30:56 +0200
committerAnton Khirnov <anton@khirnov.net>2020-06-13 10:30:56 +0200
commit0ded3ecd3bb65b37602e2ad06d657b47dd3025e7 (patch)
tree58e00ab1a6d567b9e777a93482e0fd10b9c9d306 /workspace.lua
parent044a445cdc2f25f9f069eb95113812cd19f1c0fe (diff)
workspace: avoid unnecessary page stealing
When switching to a different desktop, the current code would use the last-used tag even if it is currently displayed. Instead, keep a per-desktop stack of free tags and pick the first of those.
Diffstat (limited to 'workspace.lua')
-rw-r--r--workspace.lua129
1 files changed, 65 insertions, 64 deletions
diff --git a/workspace.lua b/workspace.lua
index 768293f..bd16161 100644
--- a/workspace.lua
+++ b/workspace.lua
@@ -2,39 +2,23 @@ local M = {}
local awful = require("awful")
local object = require("gears.object")
+local stack = require("stack")
local Workspace = {}
-local function desktop_show(self, screen, page_idx)
- if page_idx == nil then
- local page_hist = self.page_history[screen]
- if page_hist ~= nil then
- page_idx = page_hist
- else
- page_idx = 1
- end
- end
-
- local page = self.pages[page_idx]
-
- if page then
- self.page_history[screen] = page_idx
- end
- return page_idx
-end
-
function Workspace:add_desktop(idx, name, nb_pages)
local desk = object()
desk.name = name
desk.pages = {}
+ desk.indices_free = stack.Stack:new()
for i = 1, nb_pages do
desk.pages[i] = awful.tag.add(name .. i, { layout = self.layouts[1] })
+ desk.indices_free:push(i)
end
- -- page_history[i] is the last page viewed on screen i
- desk.page_history = {}
+ desk.screen_map = {}
self.desktops[idx] = desk
return idx
@@ -53,17 +37,17 @@ function Workspace:_apply_state()
if self.screen_state[s] then
awful.tag.viewnone(s)
- local desk = self.screen_state[s].desktop
- local page = self.desktops[desk].pages[self.screen_state[s].page]
+ local desk = self.screen_state[s].desktop_idx
+ local page = self.desktops[desk].pages[self.screen_state[s].page_idx]
page.screen = s
end
end
for s in screen do
local state = self.screen_state[s]
if state then
- local desk_idx = state.desktop
+ local desk_idx = state.desktop_idx
local desk = self.desktops[desk_idx]
- local page_idx = state.page
+ local page_idx = state.page_idx
local page = desk.pages[page_idx]
print("workspace displaying: " .. s.index .. " => " .. desk_idx .. "/" .. page_idx)
@@ -76,54 +60,71 @@ function Workspace:_apply_state()
awful.screen.focus(orig_focus)
end
-function Workspace:view(screen, desktop, page_idx)
- if self.desktops[desktop] == nil then
- print("Adding desktop " .. desktop)
- self:add_desktop(desktop, "Desktop " .. desktop, 10)
- end
- print("workspace: " .. screen.index .. ": view " .. desktop .. "/" .. (page_idx or "nil"))
- -- the page currently displayed on the target screen
- local old = {}
- if self.screen_state[screen] then
- old.desk = self.screen_state[screen].desktop
- old.page_idx = self.screen_state[screen].page
- old.page = self.desktops[old.desk].pages[page_old_idx]
- print(screen.index .. " now showing " .. old.desk .. "/" .. old.page_idx)
- end
+function Workspace:view(screen, desktop_idx, page_idx)
+ print("workspace: " .. screen.index .. ": view " .. desktop_idx .. "/" .. (page_idx or "nil"))
- -- the page to display on the target screen
- page_idx = desktop_show(self.desktops[desktop], screen, page_idx)
- local page_new = nil
- if page_idx then
- page_new = self.desktops[desktop].pages[page_idx]
+ if self.desktops[desktop_idx] == nil then
+ print("Adding desktop " .. desktop_idx)
+ self:add_desktop(desktop_idx, "Desktop " .. desktop_idx, 10)
end
+ local desktop = self.desktops[desktop_idx]
+
+ -- the current state of the target screen
+ local state_cur = self.screen_state[screen]
+
-- the screen on which the new page is currently displayed (if any)
- local screen_cur = nil
- if page_new and page_new.selected then
- screen_cur = page_new.screen
- print("page " .. page_idx .. " now displayed on " .. screen_cur.index)
- end
+ local screen_other = nil
- if old.page ~= page_new or page_new == nil then
- self.screen_state[screen] = { page = page_idx, desktop = desktop }
- if desktop ~= old.desk then
- self.signals:emit_signal("desktop:view", screen, desktop)
+ if page_idx == nil then
+ -- the page is not specified
+ if state_cur and state_cur.desktop_idx == desktop_idx then
+ -- requested desktop is already displayed on this screen, nothing to do
+ return
end
- if screen_cur then
- local desk_prev = self.screen_state[screen_cur].desktop
- old.page_idx = desktop_show(self.desktops[old.desk], screen_cur, old.page_idx)
-
- self.screen_state[screen_cur] = { page = old.page_idx, desktop = old.desk }
- if desk_prev ~= old.desk then
- self.signals:emit_signal("desktop:view", screen_cur, old.desk)
- end
+ -- take the topmost free one
+ page_idx = desktop.indices_free:pop()
+ if page_idx == nil then
+ print("No free pages on desktop")
+ return
end
+ else
+ -- check if the page is already displayed somewhere
+ screen_other = desktop.screen_map[page_idx]
+ if screen_other == screen then
+ -- the page is already displayed on this screen, nothing to do
+ return
+ elseif screen_other == nil then
+ desktop.indices_free:remove(page_idx)
+ end
+ end
+ if screen_other then
+ -- the page we want is already shown on some other screen, so we swap
+ -- the contents of the two screens
+ self.screen_state[screen] = self.screen_state[screen_other]
+ self.screen_state[screen_other] = state_cur
+
+ desktop.screen_map[page_idx] = screen
+ self.signals:emit_signal("desktop:view", screen, desktop_idx)
+ if state_cur then
+ self.desktops[state_cur.desktop_idx].screen_map[state_cur.page_idx] = screen_other
+ self.signals:emit_signal("desktop:view", screen_other, state_cur.desktop_idx)
+ end
+ else
+ -- mark previous page as free
+ if state_cur then
+ self.desktops[state_cur.desktop_idx].screen_map[state_cur.page_idx] = nil
+ self.desktops[state_cur.desktop_idx].indices_free:push(state_cur.page_idx)
+ end
- self:_apply_state()
+ desktop.screen_map[page_idx] = screen
+ self.screen_state[screen] = { page_idx = page_idx, desktop_idx = desktop_idx }
+ self.signals:emit_signal("desktop:view", screen, desktop_idx)
end
+
+ self:_apply_state()
end
function Workspace:view_relative(offset, screen)
@@ -132,9 +133,9 @@ function Workspace:view_relative(offset, screen)
local state = self.screen_state[screen]
if state then
- local desk = state.desktop
- print("state " .. state.page .. " res " .. (state.page + offset) % 10)
- local page = 1 + ((state.page - 1 + offset) % #self.desktops[desk].pages)
+ local desk = state.desktop_idx
+ print("state " .. state.page_idx .. " res " .. (state.page_idx + offset) % 10)
+ local page = 1 + ((state.page_idx - 1 + offset) % #self.desktops[desk].pages)
print("desk " .. desk .. " " .. #self.desktops[desk].pages)
print("view relative switch to " .. page)