Beispiel #1
0
    def __init__(self, display, store=None, proj_id=1):
        self.display = display

        # windows will be moved to workspace 0 when switching
        self.init_loaded()
        # previous loaded workspaces
        self.history = AutoList()
        # window focuses for each [display][workspace]
        self.focus = AutoList(AutoList)

        if store:
            self.store = SHM(store, proj_id=proj_id)
            self.store.create()
            self.store.attach()
            self.load()
        else:
            self.store = None
Beispiel #2
0
class Manager(object):
    def __init__(self, display, store=None, proj_id=1):
        self.display = display

        # windows will be moved to workspace 0 when switching
        self.init_loaded()
        # previous loaded workspaces
        self.history = AutoList()
        # window focuses for each [display][workspace]
        self.focus = AutoList(AutoList)

        if store:
            self.store = SHM(store, proj_id=proj_id)
            self.store.create()
            self.store.attach()
            self.load()
        else:
            self.store = None

    def init_loaded(self):
        self.loaded = AutoList(1)

    def save(self):
        if self.store:
            s = '%s\n%s\0' % (str(self.loaded), str(self.focus))
            self.store.write(s)

    def load(self):
        if not self.store:
            return

        state = str(self.store).splitlines()
        if len(state) != 2:
            self.store.write('\0')
            print 'wiping invalid state %s' % state
            return

        print 'loading:\n', state
        try:
            parsed = eval(state[0])
            # copy items
            for i in parsed:
                self.loaded.append(i)
            print 'loaded = ', self.loaded
        except:
            self.store.write('\0')
            raise

        try:
            parsed = eval(state[1])
            # copy items
            for i in xrange(len(parsed)):
                for j in xrange(len(parsed[i])):
                    if parsed[i][j]:
                        self.focus[i][j] = parsed[i][j]

            print 'focus = ', self.focus
        except:
            self.store.write('\0')
            raise

    # load current WM state
    def update(self):
        self.update_screens()
        self.update_workspaces()
        self.update_windows()

    # set arbitrary state for loaded desktop
    def set_loaded(self, loaded):
        self.init_loaded()
        for i in xrange(len(loaded)):
            self.loaded[i] = loaded[i]
        self.save()

    # implemented for horizontal non-overlapping views
    # returns corresponding display for window
    def get_screen(self, x):
        for i in xrange(len(self.screens)):
            # TODO maybe include also 5-10 pixels less than Screen.w?
            if x - self.screens[i].x < self.screens[i].w:
                return i

    # update window list
    def update_windows(self):
        for win in xlib.get_windows(self.display):
            try:
                d = xlib.get_desktop(self.display, win)
            except error.BadWindow:
                # crashes in create_resource_object.get_full_property sometimes
                continue
            if d != 0xffffffff:
                geom = xlib.get_geometry(self.display, win)
                screen = self.get_screen(geom[0])
                # win_id, x, y, w, h, xrel, yrel, display
                self.workspaces[d].append(Window(*((win,) + geom + (screen,))))

    # update workspace list
    def update_workspaces(self):
        self.workspaces = AutoList(AutoList)
        # normally should be 0 (always active workspace)
        self.current = xlib.get_current_desktop(self.display)

    # update displays
    def update_screens(self):
        self.screens = Screen.get_screens(self.display)
        num = len(self.screens)
        if num < len(self.loaded):
            self.loaded.trunc(num)
            self.history.trunc(num)

    # swap whole workspaces
    def swap_workspace(self, a, b):
        self.update()

        for win in self.workspaces[a]:
            xlib.set_desktop(self.display, win.id, b)
        for win in self.workspaces[b]:
            xlib.set_desktop(self.display, win.id, a)

        self.display.sync()

    # swap windows on current displays - implemented for 2 horizontal displays
    def swap(self):
        self.update()

        if len(self.screens) != 2: # unsupported
            return
        if self.screens[0].x == self.screens[1].x: # same offset
            return

        for win in self.workspaces[self.current]:
            i = win.d
            relx = win.x - self.screens[i].x
            rely = win.y - self.screens[i].y
            x = self.screens[(i+1) % 2].x + relx - (2*win.xrel)
            y = self.screens[(i+1) % 2].y + rely - (2*win.yrel)
            xlib.moveresize(self.display, win.id, x, y)

        self.display.sync()

    def clear(self):
        return

    # swap workspace on display i - implemented for 2 horizontal displays
    def switch(self, i, target):
        # we have to be on workspace 0 or else it's confusing to user
        if xlib.get_current_desktop(self.display) != 0:
            # TODO maybe switch to workspace 0?  it might be confusing too
            #xlib.set_current_desktop(self.display, 0)
            return

        self.update()

        if i>0 and len(self.screens) != 2: # unsupported
            return
        elif i>0 and self.screens[0].x == self.screens[1].x: # same offset
            return

        # save focus
        win = xlib.get_active_window(self.display)
        try:
            if xlib.get_desktop(self.display, win) == 0:
                # this rules out 0xffffffff
                self.focus[i][self.loaded[i]] = win
        except error.BadWindow:
            pass

        if target == self.loaded[i]:
            if self.history[i] != None: # swap back to previous workspace
                target = self.history[i]
                self.history[i] = self.loaded[i]
            else: # nowhere to switch, it's already loaded
                return
        else: # just update history
            self.history[i] = self.loaded[i]

        # save active workspace
        for win in self.workspaces[0]:
            if win.d == i:
                xlib.set_desktop(self.display, win.id, self.loaded[i])

        # load target workspace
        for win in self.workspaces[target]:
            if win.d == i:
                xlib.set_desktop(self.display, win.id, 0)

        self.loaded[i] = target
        self.display.sync()

        self.save()

        # load focus
        win = self.focus[i][target]
        if win:
            # we have to wait for the windows to be moved
            sleep(0.01)
            xlib.set_active_window(self.display, win)
            self.display.sync()

    # swap winddows between arbitrary independent workspaces
    def swap_displays(self, d1, w1, d2, w2):
        if d1==d2 and w1==w2:
            return

        self.update()

        for win in self.workspaces[w1]:
            if win.d == d1:
                xlib.set_desktop(self.display, win.id, w2)
                # move window, we changed displays
                if d1 != d2:
                    relx = win.x - self.screens[d1].x
                    rely = win.y - self.screens[d1].y
                    x = self.screens[d2].x + relx - (2*win.xrel)
                    y = self.screens[d2].y + rely - (2*win.yrel)

                    xlib.moveresize(self.display, win.id, x, y)
        for win in self.workspaces[w2]:
            if win.d == d2:
                xlib.set_desktop(self.display, win.id, w1)
                # move window, we changed displays
                if d1 != d2:
                    relx = win.x - self.screens[d2].x
                    rely = win.y - self.screens[d2].y
                    x = self.screens[d1].x + relx - (2*win.xrel)
                    y = self.screens[d1].y + rely - (2*win.yrel)

                    xlib.moveresize(self.display, win.id, x, y)

        self.display.sync()

    def command(self, cmd):
        if cmd[0] == 'switch':
            # switch to workspace cmd[2] on display cmd[1]
            if args.length == 3:
                self.switch(cmd[1].to_i, cmd[2].to_i)
        elif cmd[0] == 'swap':
            # swap current halves
            self.swap()
        elif cmd[0] == 'swap_displays':
            # swap any combination of halves
            if len(cmd) == 5:
                try:
                    d1, w1, d2, w2 = int(cmd[1]),int(cmd[2]), int(cmd[3]), int(cmd[4])
                except ValueError:
                    return

                self.swap_displays(d1, w1, d2, w2)
        elif cmd[0] == 'swap_workspace':
            # swap full workspaces
            if len(cmd) == 3:
                try:
                    a, b = int(cmd[1]),int(cmd[2])
                except ValueError:
                    return
                self.swap_workspace(a, b)
        elif cmd[0] == 'set_loaded':
            if len(cmd) == 3:
                try:
                    a, b = int(cmd[1]),int(cmd[2])
                except ValueError:
                    return
                self.set_loaded(a, b)