Skip to content

Commit

Permalink
Merge pull request #193 from dictation-toolbox/feat/set-focus
Browse files Browse the repository at this point in the history
Support focusing windows without raising them on X11
  • Loading branch information
drmfinlay authored Jan 11, 2020
2 parents 81ddedc + 9886fef commit 5540b2d
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 4 deletions.
17 changes: 14 additions & 3 deletions dragonfly/actions/action_focuswindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,33 @@ class FocusWindow(ActionBase):
(the window object), and should return ``True`` for your
target windows; example:
``lambda window: window.get_position().dy > 100``.
- *focus_only* (*bool*, default *False*) -- if *True*, then
attempt to focus the window without raising it by using the
*Window.set_focus()* method instead of *set_foreground()*.
This argument may do nothing depending on the platform.
This action searches all visible windows for a window which
matches the given parameters.
"""

def __init__(self, executable=None, title=None, index=None,
filter_func=None):
filter_func=None, focus_only=False):
if executable: self.executable = executable.lower()
else: self.executable = None
if title: self.title = title.lower()
else: self.title = None
self.index = index
self.filter_func = filter_func
self.focus_only = focus_only
ActionBase.__init__(self)

arguments = []
if executable: arguments.append("executable=%r" % executable)
if title: arguments.append("title=%r" % title)
if index: arguments.append("index=%r" % index)
if filter_func: arguments.append("filter_func=%r" % filter_func)
if focus_only: arguments.append("focus_only=%r" % focus_only)
self._str = ", ".join(arguments)

def _execute(self, data=None):
Expand All @@ -84,8 +90,13 @@ def _execute(self, data=None):
# Get the first matching window and bring it to the foreground.
windows = Window.get_matching_windows(executable, title)
if self.filter_func:
windows = [window for window in windows if self.filter_func(window)]
windows = [window for window in windows
if self.filter_func(window)]
if windows and (index < len(windows)):
windows[index].set_foreground()
window = windows[index]
if self.focus_only:
window.set_focus()
else:
window.set_foreground()
else:
raise ActionError("Failed to find window (%s)." % self._str)
9 changes: 8 additions & 1 deletion dragonfly/actions/action_startapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,16 @@ def __init__(self, *args, **kwargs):
if *True*, then attempt to bring the window to the foreground
after starting the application. Does nothing if the
application is already running.
- *focus_only* (*bool*, default *False*) -- if *True*, then
attempt to focus a matching window without raising it by
using the *set_focus()* method instead of *set_foreground()*.
This argument may do nothing depending on the platform.
"""
self._title = kwargs.pop("title", None)
self._index = kwargs.pop("index", None)
self._filter_func = kwargs.pop("filter_func", None)
self._focus_only = kwargs.pop("focus_only", False)
StartApp.__init__(self, *args, **kwargs)

def _execute(self, data=None):
Expand All @@ -203,8 +208,10 @@ def _execute(self, data=None):
title = self._title
index = self._index
filter_func = self._filter_func
focus_only = self._focus_only
focus_action = FocusWindow(executable=target, title=title,
index=index, filter_func=filter_func)
index=index, filter_func=filter_func,
focus_only=focus_only)
# Attempt to focus on an existing window.
if not focus_action.execute():
# Failed to focus on an existing window, so start
Expand Down
9 changes: 9 additions & 0 deletions dragonfly/windows/base_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,15 @@ def set_foreground(self):
""" Set the window as the foreground (active) window. """
raise NotImplementedError()

def set_focus(self):
"""
Set the window as the active window without raising it.
*Note*: this method will behave like :meth:`set_foreground()` in
environments where this isn't possible.
"""
raise NotImplementedError()

def move(self, rectangle, animate=None):
"""
Move the window, optionally animating its movement.
Expand Down
5 changes: 5 additions & 0 deletions dragonfly/windows/darwin_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,8 @@ def set_foreground(self):
end tell
''' % self._id
applescript.AppleScript(script).run()

def set_focus(self):
# Setting window focus without raising the window doesn't appear to
# be possible in macOS, so fallback on set_foreground().
self.set_foreground()
3 changes: 3 additions & 0 deletions dragonfly/windows/fake_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,6 @@ def close(self):

def set_foreground(self):
pass

def set_focus(self):
pass
5 changes: 5 additions & 0 deletions dragonfly/windows/win32_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,8 @@ def set_foreground(self):

# Set the foreground window.
self._set_foreground()

def set_focus(self):
# Setting window focus without raising the window doesn't appear to
# be possible in Windows, so fallback on set_foreground().
self.set_foreground()

0 comments on commit 5540b2d

Please sign in to comment.