Skip to content

Commit

Permalink
Switch to a proper solution for trackng cycle position in cycle_dimen…
Browse files Browse the repository at this point in the history
…sions

Fixes #20
Fixes #25
Fixes #86
  • Loading branch information
Stephan Sokolow authored and Stephan Sokolow committed Aug 23, 2017
1 parent a40f4b7 commit ba72039
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 7 deletions.
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
- Allow `ModMask` to be empty/None to enable bindings without a common prefix
- Add `monitor-prev-all`, `monitor-next-all`, and `monitor-switch-all` commands
- Add gtkexcepthook for more convenient handling of unexpected errors
- Fix window cycling when windows impose constraints on their dimensions
- Work around PyGTK's incompatibilty with tox
- Make install.sh a bit more robust
- Do a ton of refactoring to ease reusing existing code in new commands.

0.2.2:
- Added move-to{,-top,-bottom}{,-left,-right} (David Stygstra)
Expand Down
26 changes: 19 additions & 7 deletions quicktile/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

import gtk.gdk, wnck # pylint: disable=import-error

from .layout import (check_tolerance, closest_geom_match,
resolve_fractional_geom)
from .layout import resolve_fractional_geom
from .wm import GRAVITY
from .util import clamp_idx, fmt_table

Expand Down Expand Up @@ -110,6 +109,12 @@ def wrapper(winman, # type: WindowManager
})

args, kwargs = p_args + args, dict(p_kwargs, **kwargs)

# TODO: Factor out this hack
if 'cmd_idx' in kwargs:
state['cmd_idx'] = kwargs['cmd_idx']
del kwargs['cmd_idx']

func(winman, window, state, *args, **kwargs)

if name in self.commands:
Expand Down Expand Up @@ -140,8 +145,8 @@ def add_many(self, command_map):
# TODO: Refactor and redesign for better maintainability
def decorate(func):
"""Closure used to allow decorator to take arguments"""
for cmd, arglist in command_map.items():
self.add(cmd, *arglist)(func)
for pos, (cmd, arglist) in enumerate(command_map.items()):
self.add(cmd, cmd_idx=pos, *arglist)(func)
return func
return decorate

Expand Down Expand Up @@ -203,11 +208,18 @@ def cycle_dimensions(winman, # type: WindowManager
logging.debug("Selected preset sequence resolves to these monitor-relative"
" pixel dimensions:\n\t%r", dims)

closest_distance, closest_idx = closest_geom_match(win_geom, dims)
if check_tolerance(closest_distance, clip_box):
pos = (closest_idx + 1) % len(dims)
try:
cmd_idx, pos = winman.get_property('_QUICKTILE_CYCLE_POS', win)[2]
except TypeError:
cmd_idx, pos = None, -1

if cmd_idx == state.get('cmd_idx', 0):
pos = (pos + 1) % len(dims)
else:
pos = 0

winman.set_property('_QUICKTILE_CYCLE_POS',
(state.get('cmd_idx', 0), pos), win)
result = gtk.gdk.Rectangle(*dims[pos])

logging.debug("Target preset is %s relative to monitor %s",
Expand Down
42 changes: 42 additions & 0 deletions quicktile/wm.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,48 @@ def _get_win_for_prop(self, window=None):
return gtk.gdk.window_foreign_new(window.get_xid())
else:
return self.gdk_screen.get_root_window()

def get_property(self, key, window=None):
# type: (str, Optional[wnck.Window]) -> Any
"""Retrieve the value of a property on the given window.
@param window: If unset, the root window will be queried.
@type window: C{wnck.Window} or C{None}
"""
return self._get_win_for_prop(window).property_get(key)

def set_property(self, key, # type: str
value, # type: Union[Sequence[int], int, str]
window=None # type: Optional[wnck.Window]
): # type: (...) -> None
"""Set the value of a property on the given window.
@param window: If unset, the root window will be queried.
@type window: C{wnck.Window} or C{None}
"""

if isinstance(value, basestring):
prop_format = 8
prop_type = "STRING"
else:
prop_format = 32
prop_type = "CARDINAL"
if isinstance(value, int):
value = [value]

self._get_win_for_prop(window).property_change(
key, prop_type,
prop_format, gtk.gdk.PROP_MODE_REPLACE, value)

def del_property(self, key, window=None):
# type: (str, Optional[wnck.Window]) -> None
"""Unset a property on the given window.
@param window: If unset, the root window will be queried.
@type window: C{wnck.Window} or C{None}
"""
self._get_win_for_prop(window).property_delete(key)

def get_relevant_windows(self, workspace):
"""C{wnck.Screen.get_windows} without WINDOW_DESKTOP/DOCK windows."""

Expand Down
2 changes: 2 additions & 0 deletions test_quicktile.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
__author__ = "Stephan Sokolow (deitarion/SSokolow)"
__license__ = "GNU GPL 2.0 or later"

# TODO: I need a functional test to make sure issue #25 doesn't regress

try:
import pygtk
pygtk.require('2.0')
Expand Down

0 comments on commit ba72039

Please sign in to comment.