local M = {} local awful = require("awful") local beautiful = require("beautiful") local gstring = require("gears.string") local wibox = require("wibox") local Page = {} function Page:set_visible(visible, this_screen) local border_color = nil if visible then if this_screen then border_color = beautiful.border_focus or '#ffffff' else border_color = beautiful.border_marked or '#d00000' end else border_color = beautiful.border_normal or '#000000' end self.border:set_color(border_color) end function Page:client_remove(client) local wgt = self._widgets[client] if wgt then self.client_container:remove_widgets(wgt) end self._widgets[client] = nil end function Page:client_add(c) local font = beautiful.small_text_font or "sans 7" local bg_normal = beautiful.bg_normal or "#000000" local fg_normal = beautiful.fg_normal or "#ffffff" local bg_focus = beautiful.bg_focus or "#ffffff" local fg_focus = beautiful.fg_focus or "#000000" local bg_urgent = beautiful.bg_urgent or "#ffffff" local fg_urgent = beautiful.fg_urgent or "#d00000" local tb = wibox.widget.textbox("", false) local bg = wibox.container.background(tb, bg) tb:set_font(font) local function update_text(c) local text = gstring.xml_escape(c.name) or "" -- add markers for window state (maximized, floating) if c.maximized then text = '+' .. text else if c.maximized_horizontal then text = '⬌' .. text end if c.maximized_vertical then text = '⬍' .. text end if c.floating then text = '✈' .. text end end tb:set_markup(text) end c:connect_signal("property::name", update_text) c:connect_signal("property::floating", update_text) c:connect_signal("property::maximized", update_text) c:connect_signal("property::maximized_horizontal", update_text) c:connect_signal("property::maximized_vertical", update_text) c:connect_signal("focus", function(c) if c.screen == self.screen then bg:set_bg(bg_focus) bg:set_fg(fg_focus) end end) c:connect_signal("unfocus", function(c) if c.screen == self.screen then bg:set_bg(bg_normal) bg:set_fg(fg_normal) end end) c:connect_signal("property::urgent", function(c) if c.urgent then bg:set_bg(bg_urgent) bg:set_fg(fg_urgent) else if c == client.focus and c.screen == self.screen then bg:set_bg(bg_focus) bg:set_fg(fg_focus) else bg:set_bg(bg_normal) bg:set_fg(fg_normal) end end end) update_text(c) self.client_container:add(bg) self._widgets[c] = bg end function Page:new(tag, screen, index) local ret = setmetatable({}, self) self.__index = self local client_container = wibox.layout.flex.vertical() local border_width = beautiful.border_width or 1 local margin = wibox.container.margin(client_container) margin.margins = border_width local page_number = wibox.widget.textbox(tostring(index)) page_number:set_font('mono 32') page_number:set_align ('center') page_number:set_valign('center') page_number:set_opacity(0.2) local stack = wibox.layout.stack() stack:add(page_number, margin) ret.client_container = client_container ret.border = margin ret.tag = tag ret.screen = screen -- a table of mapping clients to their widgets ret._widgets = {} -- top-level widget containing the page ret.widget = stack ret:set_visible(tag.selected, tag.screen == screen) -- add initial clients for i, client in pairs(tag:clients()) do ret:client_add(client) end tag:connect_signal('tagged', function (t, c) ret:client_add(c) end) tag:connect_signal('untagged', function (t, c) ret:client_remove(c) end) return ret end local PagerDesk = {} function PagerDesk:new(desktop, screen) local ret = setmetatable({}, self) self.__index = self local title_desk = wibox.widget.textbox() local function set_title(desktop) title_desk:set_text(string.format("[%d] %s", desktop.idx, desktop.name)) end desktop:connect_signal("desktop:name", set_title) set_title(desktop) local title_page = wibox.widget.textbox() local title_bar = wibox.layout.ratio.horizontal() title_bar:set_spacing(10) title_bar:set_spacing_widget(wibox.widget.separator()) title_bar:add(title_desk, title_page) title_bar:set_ratio(1, 0.75) local title_normal_bg = beautiful.bg_normal or "#ffffff" local title_normal_fg = beautiful.fg_normal or "#000000" local title_focus_bg = beautiful.bg_focus or "#ff0000" local title_focus_fg = beautiful.fg_focus or "#000000" local title_container = wibox.container.background(title_bar, title_normal_bg) title_container:set_fg(title_normal_fg) local pages_container = wibox.layout.flex.vertical() ret.pages = {} for i = 1, #desktop.pages do ret.pages[i] = Page:new(desktop.pages[i], screen, i) pages_container:add(ret.pages[i].widget) end -- top-level widget containing the desktop ret.widget = wibox.layout.align.vertical(title_container, pages_container) desktop:connect_signal("page:view", function(desktop, s, page_idx) if s == ret.screen then title_page:set_text(string.format("%d", page_idx)) end ret.pages[page_idx]:set_visible(true, s == ret.screen) end) desktop:connect_signal("page:hide", function(desktop, page_idx) ret.pages[page_idx]:set_visible(false, false) end) client.connect_signal("focus", function(c) if c.screen == ret.screen then title_container:set_fg(title_focus_fg) title_container:set_bg(title_focus_bg) else title_container:set_fg(title_normal_fg) title_container:set_bg(title_normal_bg) end end) ret.desktop = desktop ret.screen = screen return ret end local Pager = {} function Pager:set_desktop(desktop) if self._desktops[desktop] == nil then self._desktops[desktop] = PagerDesk:new(desktop, self.screen) end self.widget:set_widget(self._desktops[desktop].widget) end function Pager:new(workspace, screen) local ret = setmetatable({}, self) self.__index = self -- this is merely a placeholder for switching between -- PagerDesk widgets ret.widget = wibox.container.constraint() ret._desktops = {} ret.screen = screen workspace.signals:connect_signal("desktop:view", function(signals, view_screen, desktop) if view_screen == ret.screen then ret:set_desktop(desktop) end end) return ret end M.Pager = Pager return M