#!/usr/bin/env python # cycle-workspace-multiscreen # Moves the currently active workspace to the left/right/top/bottom active # display. # Depends on i3ipc (`pip install i3ipc`) # Because workspace name are fixed to a display, just rename workspace can # change workspace to another display. # So for the moment this script is tested and work if workspaces are fixed # to a display. import asyncio import sys from i3ipc.aio import Connection async def cycle(): i3 = await Connection().connect() # figure out what is on, and what is currently on your screen. workspace_origin = list(filter(lambda w: w.focused, await i3.get_workspaces()))[0] outputs = list(filter(lambda o: o.active, await i3.get_outputs())) output_origin = "" for output in outputs: if output.current_workspace == workspace_origin.name: output_origin = output output_destination = workspace_origin if sys.argv[1] == "right": output_origin_x = output_origin.rect.x output_origin_width = output_origin.rect.width next_workspace_start = output_origin_x + output_origin_width for output in outputs: if next_workspace_start == output.rect.x: output_destination = output if sys.argv[1] == "left": output_origin_x = output_origin.rect.x output_origin_width = output_origin.rect.width next_workspace_start = output_origin_x - output_origin_width for output in outputs: next_workspace_start = output_origin_x - output.rect.width if next_workspace_start == output.rect.x: output_destination = output if sys.argv[1] == "bottom": output_origin_y = output_origin.rect.y output_origin_height = output_origin.rect.height next_workspace_start = output_origin_y + output_origin_height output_origin_x = output_origin.rect.x for output in outputs: output_end = output.rect.x + output.rect.width # FIXME: screen must have the same start x position and screen with not # the same resolution can by buggy if (next_workspace_start == output.rect.y and output.rect.x <= output_origin_x <= output_end): output_destination = output if sys.argv[1] == "top": output_origin_y = output_origin.rect.y output_origin_height = output_origin.rect.height next_workspace_start = output_origin_y - output_origin_height output_origin_x = output_origin.rect.x for output in outputs: next_workspace_start = output_origin_y - output.rect.height output_end = output.rect.x + output.rect.width # FIXME: screen must have the same start x position and screen with not # the same resolution can by buggy if (next_workspace_start == output.rect.y and output.rect.x <= output_origin_x <= output_end): output_destination = output if (output_destination != workspace_origin): wrksp_orig = workspace_origin.name wkrsp_dest = output_destination.current_workspace # Move origin workspace to the correct screen await i3.command(f'move workspace to output {output_destination.name}') # Rename origin workspace to temporary workspace of the screen destination await i3.command(f'rename workspace {wrksp_orig} to a_fucking_workspace') # Change focus to the workspace destination await i3.command(f'workspace {wkrsp_dest}') # Move destination workspace to the correct screen await i3.command(f'move workspace to output {workspace_origin.output}') # Rename workspace destination to the origin workspace await i3.command(f'rename workspace {wkrsp_dest} to {workspace_origin.name}') # Rename temporary workspace to workspace destination await i3.command(f'rename workspace a_fucking_workspace to {wkrsp_dest}') # Change focus the workspace destination await i3.command(f'workspace {wkrsp_dest}') loop = asyncio.get_event_loop() loop.run_until_complete(cycle()) loop.close()