From dc28cdcd211c6f7923829ff3b76b28d9d740b77d Mon Sep 17 00:00:00 2001 From: Peter Palfrader Date: Fri, 28 Sep 2012 13:44:44 +0000 Subject: Add wss git-svn-id: svn+ssh://asteria.noreply.org/svn/weaselutils/trunk@551 bc3d92e2-beff-0310-a7cd-cc87d7ac0ede --- wss | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100755 wss diff --git a/wss b/wss new file mode 100755 index 0000000..7bce0eb --- /dev/null +++ b/wss @@ -0,0 +1,209 @@ +#!/usr/bin/python + +# workspace switcher status +# +# display the workspaces of e.g. an xfce desktop during workspaces switches, +# including a sketch of all windows + +# Copyright (c) 2012 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + + +import pygtk, gtk, glib +import wnck + +SCALE=50 +BORDER=3 +DELAY=500 + +class WSS: + def cb_hide(self, data=None): + self.window.hide() + return False + + def cb_update(self, widget, data=None): + workspace = self.screen.get_active_workspace() + if self.previous is not None: + self.label.set_markup("%s"%(workspace.get_name())) + + if not self.timerid is None: + glib.source_remove(self.timerid) + self.timerid = glib.timeout_add(DELAY, self.cb_hide) + + self.paint() + self.window.queue_draw() + self.window.show() + self.previous = workspace + + def get_layout(self): + wsposmap = {} + if self.layout is None: + wss = self.screen.get_workspaces() + maxrow = 0 + maxcol = 0 + for ws in wss: + r = ws.get_layout_row() + c = ws.get_layout_column() + if r > maxrow: maxrow = r + if c > maxcol: maxcol = c + wsposmap[ws.get_number()] = (r,c) + w = self.screen.get_width() + h = self.screen.get_height() + + self.layout = (w, h, maxrow+1, maxcol+1) + self.wsposmap = wsposmap + return self.layout + + def setup_table(self): + if self.table is not None: return + width, height, rows, cols = self.get_layout() + + table = gtk.Table(rows, cols, True) + table.set_col_spacings(BORDER) + table.set_row_spacings(BORDER) + cells = [] + areainfo = {} + + for r in xrange(0,rows): + cells.append([]) + for c in xrange(0,cols): + area = gtk.DrawingArea() + area.set_size_request(width/SCALE+2, height/SCALE+2) + area.connect("expose-event", self.area_expose_cb) + table.attach(area, c, c+1, r, r+1, xpadding=0, ypadding=0) + + i = {} + i['w'] = [] + + cells[r].append(i) + areainfo[area] = i + + + table.show_all() + self.box.add(table) + self.table = table + self.cells = cells + self.areainfo = areainfo + + def area_expose_cb(self, area, event): + width, height, rows, cols = self.get_layout() + + style = area.get_style() + defgc = style.fg_gc[gtk.STATE_NORMAL] + + active_window = self.screen.get_active_window() + + i = self.areainfo[area] + if 'gc' not in i: + c = area.window.get_colormap().alloc_color(gtk.gdk.Color('#666666'), writeable=False, best_match=True) + i['gc'] = area.window.new_gc(foreground=c) + c = area.window.get_colormap().alloc_color(gtk.gdk.Color('#bbbbff'), writeable=False, best_match=True) + i['gc-focus'] = area.window.new_gc(foreground=c) + c = area.window.get_colormap().alloc_color(gtk.gdk.Color('#0000FF'), writeable=False, best_match=True) + i['gc-border'] = area.window.new_gc(foreground=c, line_width=3) + + for w in i['w']: + geom = w.get_geometry() + if w == active_window: + area.window.draw_rectangle(i['gc-focus'], True, geom[0]/SCALE+1, geom[1]/SCALE+1, geom[2]/SCALE, geom[3]/SCALE) + area.window.draw_rectangle(defgc, False, geom[0]/SCALE+1, geom[1]/SCALE+1, geom[2]/SCALE, geom[3]/SCALE) + else: + area.window.draw_rectangle(i['gc'], True, geom[0]/SCALE+1, geom[1]/SCALE+1, geom[2]/SCALE, geom[3]/SCALE) + area.window.draw_rectangle(defgc, False, geom[0]/SCALE+1, geom[1]/SCALE+1, geom[2]/SCALE, geom[3]/SCALE) + + if i['active']: + area.window.draw_rectangle(i['gc-border'], False, 0, 0, width/SCALE+1, height/SCALE+1) + else: + area.window.draw_rectangle(defgc, False, 0, 0, width/SCALE+1, height/SCALE+1) + + return True + + def cell_info_from_workspace(self, ws): + wsn = ws.get_number() + wspos = self.wsposmap[wsn] + row, col = wspos + cell = self.cells[row][col] + + return cell + + def paint(self): + width, height, mr, mc = self.get_layout() + self.setup_table() + + window_list = self.screen.get_windows() + for a in self.areainfo: + del self.areainfo[a]['w'][:] + self.areainfo[a]['active'] = False + + for w in window_list: + ws = w.get_workspace() + if ws is not None: + cell = self.cell_info_from_workspace(ws) + cell['w'].append(w) + + active = self.screen.get_active_workspace() + cell = self.cell_info_from_workspace(active) + cell['active'] = True + + + def __init__(self): + window = gtk.Window(gtk.WINDOW_POPUP) + + label = gtk.Label() + + box = gtk.VBox() + box.set_border_width(20) + + box.add(label) + window.add(box) + + window.set_position(gtk.WIN_POS_CENTER) + + box.show_all() + + screen = wnck.screen_get_default() + screen.connect('active-workspace-changed', self.cb_update) + + self.window = window + self.label = label + self.box = box + self.screen = screen + self.previous = None + self.table = None + self.cells = None + self.layout = None + self.areainfo = None + self.timerid = None + + def main(self): + # All PyGTK applications must have a gtk.main(). Control ends here + # and waits for an event to occur (like a key press or mouse event). + gtk.main() + +if __name__ == "__main__": + wss = WSS() + wss.main() + +# vim:set et: +# vim:set ts=4: +# vim:set shiftwidth=4: -- cgit v1.2.3