#!/usr/bin/python3 import subprocess import json import math def exec(cmd): print('exec: ', cmd) return subprocess.getoutput(cmd) def getSwayInfo(cmd): return json.loads(exec("swaymsg -t "+cmd)) class WpManager(object): """" * Workspace Manager """ def __init__(self,Rows, Cols, monitorCount): w = 0 workspaces = [] r=0 while r < Rows: c = 0 while c < Cols: workspaces.append({ 'left': c != 0 and w - 1, 'right': ( ( c + 1 ) != Cols ) and w + 1, 'up': ( r != 0 ) and ( w - Cols ), 'down': ( ( r + 1 ) != Rows ) and w + Cols }) w=w+1 c=c+1 r=r+1 self.workspaces = workspaces self.Rows = Rows self.Cols = Cols self.monitorCount = monitorCount """" * Workspace grid initialisation command generator. * Currenlty not working because `Workspace` command will not work through `swaymsg`. * it will work only if we put these commands on config file """ def getInitCmd (self): outputs = [ v['name'] for v in getSwayInfo('get_outputs') if v['active']] outputCout = len( outputs ) totalWorkspaces = self.Rows * self.Cols cmd = [] ws=0 while ws < totalWorkspaces: op = 0 while op < outputCout: cmd.append("workspace " + str(ws * outputCout + op + 1) + " output "+outputs[op]) op=op+1 ws=ws+1 return ';\n'.join(cmd) """" * Return the list of target workspaces. * * Given current focused workspace and switching direction. eg: ( 1, down ) * for a 3x3 grid in a dual monitor, it will reutrn [ 7, 8 ]. * for single monitor setup, it will return [ 4 ] * For three monitor setup, it will return [ 10, 11, 12 ] * * @param current - current monitor * @param direction - direction up|down|right|left * @returns {Array} - list of target workspaces """ def getWorkspaces (self,current, direction): monitorCount = self.monitorCount out = [] targetw = self.workspaces[math.ceil(current / monitorCount) - 1][direction] if targetw is not False: targetw = targetw * monitorCount i = monitorCount while i != 0: out.append(targetw + i) i=i-1 return out """" * Get swaymsg command for switching current Workspace to direction * * @param swayWorkspace * @param direction * @param isMove * @returns {String} - swaymsg command """ def getCmd (self,swayWorkspace, direction, isMove): currentWS = swayWorkspace['num'] currentOutput = swayWorkspace['output'] ws = self.getWorkspaces(currentWS, direction) if not ws: return out = ["workspace %d"%v for v in ws ] if isMove: tws = ws[currentWS % self.monitorCount] out.insert(0,"move container to workspace %d"%tws) out.append("focus output "+currentOutput) return '; '.join(out) helpStr = ''' sway-wp-switch Usage: sway-wp-switch [ -m ] Options: -m move current window to new workspace while switching. If currently focused windows in output-2, it will be placed in output-two itself without losing focus ''' def main(): import sys direction = sys.argv[1] isMove = False ROWS = 3 COLS = 3 if direction == '-m': isMove = True direction = sys.argv[2] if direction not in ['up', 'down', 'right', 'left', '-i']: print(helpStr) return outputInfo = getSwayInfo('get_outputs') outputInfo = [v for v in outputInfo if v['active'] ] wm = WpManager(ROWS, COLS, len( outputInfo )) if direction == '-i': cmd = wm.getInitCmd() print(cmd) cmd='' else: workspaceInfo = next(v for v in getSwayInfo('get_workspaces') if v[ 'focused' ] ) cmd = wm.getCmd(workspaceInfo, direction, isMove) if cmd: exec('swaymsg -t command "%s"'% cmd) main()