diff --git a/README.md b/README.md
index 7493959..940616e 100644
--- a/README.md
+++ b/README.md
@@ -74,7 +74,7 @@ bindsym $mod+Shift+Up nop layman move up
bindsym $mod+Shift+Right nop layman move right
```
-The `src/mananagers/` directoy contains files that each hold an implementation of a WLM, with `WorkspaceLayoutManager.py`
+The `src/managers/` directory contains files that each hold an implementation of a WLM, with `WorkspaceLayoutManager.py`
containing the parent class from which all WLMs are derived.
### none
diff --git a/config.toml b/config.toml
index 94332a5..ae4e7f3 100644
--- a/config.toml
+++ b/config.toml
@@ -5,12 +5,12 @@
# values for options not set in a [workspace] or [output] section.
[layman]
defaultLayout = "none" # The default WLM to assign to a workspace
-excludedWorkspaces = [] # Numbers of workspaces to be excuded
+excludedWorkspaces = [] # Numbers of workspaces to be excluded
excludedOutputs = [] # Names of outputs to be excuded
debug = false # Enable logging debug messages globaly
depthLimit = 0 # Autotiling: Default depth limit (disabled) for all workspaces
stackLayout = "splitv" # MasterStack: Default stack layout for all workspaces
-stackSidet = "right" # MasterStack: Default stack position for all workspaces
+stackSide = "right" # MasterStack: Default stack position for all workspaces
masterWidth = 50 # MasterStack: Default master width for all workspaces
diff --git a/examle_sway_config b/example_sway_config
similarity index 100%
rename from examle_sway_config
rename to example_sway_config
diff --git a/src/config.py b/src/config.py
index 8002558..843a095 100644
--- a/src/config.py
+++ b/src/config.py
@@ -13,11 +13,11 @@
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-layman. If not, see .
+layman. If not, see .
"""
-import tomli
from logging import exception
+import tomli
CONFIG_PATH = ".config/layman/config.toml"
@@ -73,7 +73,7 @@ def getForWorkspace(self, workspaceNum, key):
except KeyError:
pass
- # If output config doesn't have the key, falback to default
+ # If output config doesn't have the key, fallback to default
try:
value = self.configDict[TABLE_LAYMAN][key]
except KeyError:
diff --git a/src/config.toml b/src/config.toml
deleted file mode 100644
index e3c42d1..0000000
--- a/src/config.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-# This is an example config file that only sets the default values for each value.
-# Configure your own desired options before using
-
-# The `layman` section configures options that apply to the layman daemon, and any fallback
-# values for options not set in a [workspace] or [output] section.
-[layman]
-defaultLayout = "none" # The default WLM to assign to a workspace
-excludedWorkspaces = [] # Numbers of workspaces to be excuded
-excludedOutputs = [] # Names of outputs to be excuded
-debug = false # Enable logging debug messages globaly
-depthLimit = 0 # Autotiling: Default depth limit (disabled) for all workspaces
-stackLayout = "splitv" # MasterStack: Default stack layout for all workspaces
-masterWidth = 50 # MasterStack: Default master width for all workspaces
-
-
-# `output` sections configure options for workspaces created on this output.
-[output.DP-1]
-defaultLayout = "none" # The default WLM to assign to a workspace on this output
-debug = false # Enable debug messages for WLMs on this output
-depthLimit = 0 # Autotiling: Depth limit (disabled) for workspaces on this output
-stackLayout = "splitv" # MasterStack: Default stack layout for workspaces on this output
-masterWidth = 50 # MasterStack: Default master width for workspaces on this output
-
-
-# `workspace` sections configure options for the specified workspace.
-[workspace.1]
-defaultLayout = "none" # The default WLM to assign to this workspace
-debug = false # Enable debug messages for this workspace
-depthLimit = 0 # Autotiling: Depth limit (disabled) for this workspace
-stackLayout = "splitv" # MasterStack: Stack layout for this workspace
-masterWidth = 50 # MasterStack: Master width for this workspaces on this output
-
diff --git a/src/layman.py b/src/layman.py
index 0058e19..1c3b311 100755
--- a/src/layman.py
+++ b/src/layman.py
@@ -16,22 +16,21 @@
You should have received a copy of the GNU General Public License along with
layman. If not, see .
"""
-from i3ipc import Event, Connection
-from importlib.machinery import SourceFileLoader
import inspect
import logging
import os
-from setproctitle import setproctitle
import shutil
+from importlib.machinery import SourceFileLoader
+from typing import cast
-from .server import MessageServer
+from i3ipc import Connection, Event, WindowEvent
+from i3ipc.events import IpcBaseEvent
+from setproctitle import setproctitle
-from . import utils
-from . import config
-from .managers import WorkspaceLayoutManager
-from .managers import MasterStackLayoutManager
-from .managers import AutotilingLayoutManager
-from .managers import GridLayoutManager
+from . import config, utils
+from .managers import (AutotilingLayoutManager, GridLayoutManager,
+ MasterStackLayoutManager, WorkspaceLayoutManager)
+from .server import MessageServer
class Layman:
@@ -49,7 +48,8 @@ def __init__(self):
window::new, window::focus, window::close, window::move, and window::floating.
"""
- def windowCreated(self, _, event):
+ def windowCreated(self, _, event: IpcBaseEvent):
+ event = cast(WindowEvent, event)
window = utils.findFocusedWindow(self.cmdConn)
workspace = utils.findFocusedWorkspace(self.cmdConn)
@@ -62,7 +62,8 @@ def windowCreated(self, _, event):
self.dispatchToManager(event, window, workspace)
- def windowFocused(self, _, event):
+ def windowFocused(self, _, event: IpcBaseEvent):
+ event = cast(WindowEvent, event)
window = utils.findFocusedWindow(self.cmdConn)
workspace = utils.findFocusedWorkspace(self.cmdConn)
@@ -74,7 +75,8 @@ def windowFocused(self, _, event):
# Pass command to the appropriate manager
self.dispatchToManager(event, window, workspace)
- def windowClosed(self, _, event):
+ def windowClosed(self, _, event: IpcBaseEvent):
+ event = cast(WindowEvent, event)
# Try to find workspace by locating where the window is recorded
workspaces = []
for num in self.workspaceWindows:
@@ -97,7 +99,8 @@ def windowClosed(self, _, event):
self.dispatchToManager(event, window, workspace)
- def windowMoved(self, _, event):
+ def windowMoved(self, _, event: IpcBaseEvent):
+ event = cast(WindowEvent, event)
window = utils.findFocusedWindow(self.cmdConn)
workspace = utils.findFocusedWorkspace(self.cmdConn)
@@ -120,7 +123,8 @@ def windowMoved(self, _, event):
self.dispatchToManager(event, window, workspace)
- def windowFloating(self, _, event):
+ def windowFloating(self, _, event: IpcBaseEvent):
+ event = cast(WindowEvent, event)
window = self.cmdConn.get_tree().find_by_id(event.container.id)
workspace = utils.findFocusedWorkspace(self.cmdConn)
diff --git a/src/managers/WorkspaceLayoutManager.py b/src/managers/WorkspaceLayoutManager.py
index cede51f..13ef1ec 100644
--- a/src/managers/WorkspaceLayoutManager.py
+++ b/src/managers/WorkspaceLayoutManager.py
@@ -13,29 +13,40 @@
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-layman. If not, see .
+layman. If not, see .
"""
import inspect
-from ..config import KEY_DEBUG
+import i3ipc
+
+from ..config import KEY_DEBUG, LaymanConfig
+
class WorkspaceLayoutManager:
# These properties should be overriden to configure your WLM as
- # Needed
+ # needed.
shortName = "none"
overridesMoveBinds = False # Should window movement commands be sent as binds
supportsFloating = False # Should windowFloating be used, or treated as Added/Removed
- # These are the functions you should override for to implement a
- # WLM.
- def __init__(self, con, workspace, options):
+ con: i3ipc.Connection
+ workspaceId: int
+ workspaceName: str
+
+ # These are the functions you should override to implement a WLM.
+ #
+ # Parameters:
+ # con (i3ipc.Connection): An i3ipc connection for executing commands.
+ # workspace (i3ipc.WorkspaceReply): The workspace the layout manager is associated with.
+ # options (LaymanConfig): The loaded config file used for option defaults.
+ def __init__(self, con: i3ipc.Connection, workspace: i3ipc.WorkspaceReply, options: LaymanConfig):
self.con = con
self.workspaceId = workspace.ipc_data["id"]
self.workspaceNum = workspace.num
self.debug = options.getForWorkspace(self.workspaceNum, KEY_DEBUG)
- # windowAdded is called when a new window is added to the workpsace,
+ # windowAdded is called when a new window is added to the workspace,
# either by being created on the workspace or moved to it from another.
def windowAdded(self, event, window):
pass
@@ -47,7 +58,7 @@ def windowRemoved(self, event, window):
pass
- # windowFocused is called when a window on the workpsace is focused.
+ # windowFocused is called when a window on the workspace is focused.
def windowFocused(self, event, window):
pass
@@ -57,7 +68,7 @@ def windowFocused(self, event, window):
def windowMoved(self, event, window):
pass
- # windowFloating is called when a windows floating state is toggled.
+ # windowFloating is called when a window's floating state is toggled.
def windowFloating(self, event, window):
pass
@@ -92,7 +103,7 @@ def log(self, msg):
print(("%s %d: %s: %s" % (self.shortName, self.workspaceNum, inspect.stack()[1][3], msg)))
- # This log function includes the class name, workspace number, and the
+ # This log function includes the class name, workspace number, and the
# name of the function 2 calls up. This makes it useful for helper
# functions that get called by event handlers
def logCaller(self, msg):
diff --git a/src/server.py b/src/server.py
index 877a9fe..ae487ed 100644
--- a/src/server.py
+++ b/src/server.py
@@ -13,36 +13,17 @@
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-layman. If not, see .
+layman. If not, see .
"""
-from os import unlink, mkfifo
-from queue import Queue
+from os import mkfifo, unlink
from threading import Thread
PIPE = "/tmp/layman.pipe"
-class MessageQueue(Queue):
- def __init__(self, maxsize=0):
- super().__init__(maxsize=0)
- self.on_change_listeners = []
-
- def _put(self, msg):
- # Add to queue
- super()._put(msg)
-
- # Run any listeners on a separate thread
- for listener in self.on_change_listeners:
- listener(msg)
-
- def registerListener(self, listener):
- self.on_change_listeners.append(listener)
-
class MessageServer():
def __init__(self, callback):
self.callback = callback
- self.queue = MessageQueue()
- self.queue.registerListener(callback)
try:
unlink(PIPE)
@@ -56,5 +37,4 @@ def __init__(self, callback):
def readPipe(self):
while True:
with open(PIPE) as fifo:
- self.queue.put(fifo.read())
-
+ self.callback(fifo.read())