diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..d0e6a2a
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+pi3-smart-workspace
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 1cbbf47..734b730 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/PyOutputHandler.iml b/.idea/pi3-smart-workspace.iml
similarity index 100%
rename from .idea/PyOutputHandler.iml
rename to .idea/pi3-smart-workspace.iml
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..582da73
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,64 @@
+About
+-----
+
+Simple program that looks through the i3 config and finds the bound workspaces for each output, and then opening that workspace on the output, that the mouse is currently on.
+
+Allowing for a more seameless interaction with how workspaces are openend.
+
+Usage
+-----
+
+::
+
+ usage: pi3-smar-switch [-h] [-f] [-p | -m | -s] WORKSPACE_NAME
+
+ Moves selected i3 workspace to the current output (by default determined by
+ cursor location) and focuses it.
+
+ positional arguments:
+ workspace name of the i3 workspace
+
+ optional arguments:
+ -h, --help show this help message and exit
+ -f, --focus use focused window instead of cursor position to determine the
+ current output
+ -p, --push moves replaced workspace to the second output (works only if
+ there are two outputs, ignored otherwise)
+ -m, --master same as 'push' but will only move from primary output to the
+ secondary
+ -s, --swap (NOT IMPLEMENTED YET) behaves like xmonad, swaps workspaces if
+ they are on a different output
+
+Installation
+------------
+
+Install using `pipsi`_ (recommended) or pip:
+
+::
+
+ pipsi install pi3-switch
+
+Add keybindings to ~/.config/i3/config and reload i3 (remember to modify flags to your liking):
+
+::
+
+ bindsym $mod+1 exec pi3-switch -p 1
+ bindsym $mod+2 exec pi3-switch -p 2
+ bindsym $mod+3 exec pi3-switch -p 3
+ bindsym $mod+4 exec pi3-switch -p 4
+ bindsym $mod+5 exec pi3-switch -p 5
+ bindsym $mod+6 exec pi3-switch -p 6
+ bindsym $mod+7 exec pi3-switch -p 7
+ bindsym $mod+8 exec pi3-switch -p 8
+ bindsym $mod+9 exec pi3-switch -p 9
+ bindsym $mod+0 exec pi3-switch -p 10
+
+Credits
+-------
+
+Thanks to Travis Finkenauer for an inspiration (`i3-wk-switch`_) and
+Tony Crisci for an easy-to-use i3 python library (`i3ipc-python`_).
+
+.. _pipsi: https://github.com/mitsuhiko/pipsi
+.. _i3-wk-switch: https://github.com/tmfink/i3-wk-switch
+.. _i3ipc-python: https://github.com/acrisci/i3ipc-python
diff --git a/pi3/__init__.py b/pi3/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/main.py b/pi3/smart-workspace.py
similarity index 56%
rename from main.py
rename to pi3/smart-workspace.py
index 1c8eac1..ef06ea3 100644
--- a/main.py
+++ b/pi3/smart-workspace.py
@@ -1,15 +1,9 @@
-from i3ipc import connection, Connection
-import logging
+from i3ipc import Connection
import sys
from pprint import pprint
import pynput
import re
-import asyncio
-
-"""import argparse
-"""
-
-logger = logging.getLogger(__name__)
+import argparse
class WorkSpacer:
@@ -17,32 +11,48 @@ class WorkSpacer:
def __init__(self, args):
self.i3 = None
self.args = args
- self.workspaces_on_outputs = None
+ self.workspaces_on_outputs = {}
self.workspaces = None
self.outputs = None
-
+ self.config = None
self.mouse = pynput.mouse.Controller()
-
self.mouse_position = None
self.current_output_name = None
def _connect(self):
try:
self.i3 = Connection()
- re.compile(r'')
- self.workspaces_on_outputs = [ws for ws in self.i3.get_config().__dict__['config'].split('\n') if ws]
+ self.config = self.i3.get_config().__dict__['config']
+ config_outputs = {}
+ for matchNo, match in enumerate(
+ re.finditer(r'set (\$[a-zA-Z]+) ((HDMI|DP|VGA)-\d)', self.config, re.MULTILINE), start=1
+ ):
+ config_outputs[match.group(1)] = match.group(2)
+ pprint(config_outputs)
+ config_workspace_names = {}
+ for matchNum, match in enumerate(
+ re.finditer(r'set (\$.*) (\d.*)', self.config, re.MULTILINE)
+ ):
+ config_workspace_names[match.group(1)] = match.group(2)
+ pprint(config_workspace_names)
+ for matchNum, match in enumerate(
+ re.finditer(r'workspace (\$.*) output (\$.*)', self.config, re.MULTILINE)
+ ):
+ if not self.workspaces_on_outputs.keys().__contains__(config_outputs[match.group(2)]):
+ self.workspaces_on_outputs[config_outputs[match.group(2)]] = []
+ self.workspaces_on_outputs[config_outputs[match.group(2)]].append(config_workspace_names[match.group(1)])
+
except Exception as exc:
- logger.error(f"Could not load i3: {exc}", exc_info=exc)
sys.exit(1)
self.workspaces = [workspaces for workspaces in self.i3.get_workspaces()]
- outputs = self.i3.get_outputs()
- #pprint(outputs[1].__dict__)
+ outputs = self.i3.get_outputs()
self.outputs = [output for output in outputs if output.__dict__["active"] is True]
def run(self):
self._connect()
self.mouse_position = self.mouse.position
self.current_output_name = self._get_workspace_from_courser_position()
+ self.i3.command(f'workspace {self.workspaces_on_outputs[self.current_output_name][self.args]}')
def _get_workspace_from_courser_position(self):
for output in self.outputs:
@@ -68,12 +78,18 @@ class WorkSpacer:
return [workspace for workspace in self.workspaces if workspace.__dict__['output'] == output]
-def tst():
- ws = WorkSpacer('')
+def main():
+ parser = argparse.ArgumentParser(
+ description="Dynamic changes the workspace, based on what output your cursoer is on."
+ )
+ parser.add_argument("-i", "--index", type=int,
+ help="the number index of the workspace that should be openend. 1 = workspace 1 etc.")
+ ws = WorkSpacer(parser.parse_args())
ws.run()
+
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
- tst()
+ main()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..57eb532
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+evdev==1.3.0
+i3ipc==2.2.1
+pynput==1.7.1
+python-xlib==0.27
+six==1.15.0
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..e2e78d3
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,32 @@
+from setuptools import setup
+
+with open('README.rst', 'r') as fh:
+ long_description = fh.read()
+with open('requirements.txt', 'r') as file:
+ required = []
+ for x in file.readline():
+ required.append(x)
+
+
+setup(
+ name="pi3-smart-workspace",
+ description="A smart switcher for multiple workspaces.",
+ long_description=long_description,
+ version="0.0.1",
+ license="Apache License",
+ author="Asger Geel Weirsøe",
+ author_email="asger@weirsoe.dk",
+ url="https://github.com/GeneralDenmark/PyOutputHandler",
+ install_requires=required,
+ packages=["pi3"],
+ zip_safe=True,
+ entry_points={"console_scripts": ["pi3-smart-workspace = pi3.smart-workspace:main"]},
+ scripts=["pi3/smart-workspace.py"],
+ classifiers=[
+ "Development Status :: 2 - Pre-Alpha",
+ "License :: OSI Approved :: Apache Software License",
+ "Operating System :: POSIX :: Linux",
+ "Programming Language :: Python :: 3",
+ "Topic :: Desktop Environment :: Window Managers",
+ ],
+)
\ No newline at end of file