diff --git a/dragonfly/actions/action_focuswindow.py b/dragonfly/actions/action_focuswindow.py index 64c7a69a..e614ad00 100644 --- a/dragonfly/actions/action_focuswindow.py +++ b/dragonfly/actions/action_focuswindow.py @@ -47,6 +47,10 @@ 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. @@ -54,13 +58,14 @@ class FocusWindow(ActionBase): """ 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 = [] @@ -68,6 +73,7 @@ def __init__(self, executable=None, title=None, index=None, 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): @@ -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) diff --git a/dragonfly/actions/action_startapp.py b/dragonfly/actions/action_startapp.py index ca4926d4..92b52cf6 100644 --- a/dragonfly/actions/action_startapp.py +++ b/dragonfly/actions/action_startapp.py @@ -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): @@ -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 diff --git a/dragonfly/windows/base_window.py b/dragonfly/windows/base_window.py index 51a3fb95..5dcc8b2b 100644 --- a/dragonfly/windows/base_window.py +++ b/dragonfly/windows/base_window.py @@ -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. diff --git a/dragonfly/windows/darwin_window.py b/dragonfly/windows/darwin_window.py index 22e802b3..31b5ddfd 100644 --- a/dragonfly/windows/darwin_window.py +++ b/dragonfly/windows/darwin_window.py @@ -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() diff --git a/dragonfly/windows/fake_window.py b/dragonfly/windows/fake_window.py index d40b1d0c..afb13b72 100644 --- a/dragonfly/windows/fake_window.py +++ b/dragonfly/windows/fake_window.py @@ -99,3 +99,6 @@ def close(self): def set_foreground(self): pass + + def set_focus(self): + pass diff --git a/dragonfly/windows/win32_window.py b/dragonfly/windows/win32_window.py index 0442f3ea..c281eea4 100644 --- a/dragonfly/windows/win32_window.py +++ b/dragonfly/windows/win32_window.py @@ -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()