Skip to content

Commit

Permalink
Merge pull request #102 from dictation-toolbox/feat/x11-window-class
Browse files Browse the repository at this point in the history
Add additional Window classes and change the old one
  • Loading branch information
drmfinlay committed Jul 18, 2019
2 parents 25abd72 + ac2234e commit 5f492d8
Show file tree
Hide file tree
Showing 16 changed files with 1,068 additions and 310 deletions.
21 changes: 21 additions & 0 deletions documentation/window_classes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Window classes
============================================================================

Dragonfly's Window classes are interfaces to the window control and
placement APIs for the current platform. Currently the Windows and X11
(Linux) platforms are supported.

The :class:`FakeWindow` class will be used on unsupported platforms.

.. automodule:: dragonfly.windows.base_window
:members:

.. automodule:: dragonfly.windows.fake_window
:members:

.. automodule:: dragonfly.windows.win32_window
:members:

.. automodule:: dragonfly.windows.x11_window
:members:
1 change: 1 addition & 0 deletions documentation/windows.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ Contents of Dragonfly's windows sub-package:
:maxdepth: 2

clipboard
window_classes
9 changes: 3 additions & 6 deletions dragonfly/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,18 @@
from .action_key import Key
from .action_text import Text
from .action_paste import Paste
from .action_waitwindow import WaitWindow
from .action_focuswindow import FocusWindow
from .action_startapp import StartApp, BringApp

if sys.platform.startswith("win"):
# Import Windows only classes and functions.
from .action_mouse import Mouse
from .action_waitwindow import WaitWindow
from .action_focuswindow import FocusWindow
from .action_startapp import StartApp, BringApp
from .action_playsound import PlaySound
from .sendinput import (KeyboardInput, MouseInput,
HardwareInput, make_input_array,
send_input_array)
else:
# Import mocked classes and functions for other platforms.
from ..os_dependent_mock import Mouse
from ..os_dependent_mock import WaitWindow
from ..os_dependent_mock import FocusWindow
from ..os_dependent_mock import StartApp, BringApp
from ..os_dependent_mock import PlaySound
33 changes: 7 additions & 26 deletions dragonfly/actions/action_focuswindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
"""


import win32con
from .action_base import ActionBase, ActionError
from ..windows.window import Window
from ..windows import Window


#---------------------------------------------------------------------------
Expand Down Expand Up @@ -67,26 +65,9 @@ def _execute(self, data=None):
if executable: executable = (executable % data).lower()
if title: title = (title % data).lower()

windows = Window.get_all_windows()
for window in windows:
if not window.is_visible:
continue
if (window.executable.endswith("natspeak.exe")
and window.classname == "#32770"
and window.get_position().dy < 50):
# If a window matches the above, it is very probably
# the results-box of DNS. We ignore this because
# its title is the words of the last recognition,
# which will often interfere with a search for
# a window with a spoken title.
continue

if executable:
if window.executable.lower().find(executable) == -1:
continue
if title:
if window.title.lower().find(title) == -1:
continue
window.set_foreground()
return
raise ActionError("Failed to find window (%s)." % self._str)
# Get the first matching window and bring it to the foreground.
windows = Window.get_matching_windows(executable, title)
if windows:
windows[0].set_foreground()
else:
raise ActionError("Failed to find window (%s)." % self._str)
4 changes: 2 additions & 2 deletions dragonfly/actions/action_waitwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@


import time
import win32con

from dragonfly.actions.action_base import ActionBase, ActionError
from dragonfly.windows.window import Window
from ..windows import Window


#---------------------------------------------------------------------------
Expand Down
9 changes: 3 additions & 6 deletions dragonfly/actions/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,15 @@
from .action_key import Key
from .action_text import Text
from .action_paste import Paste
from .action_waitwindow import WaitWindow
from .action_focuswindow import FocusWindow
from .action_startapp import StartApp, BringApp

if sys.platform.startswith("win"):
# Import Windows only classes and functions.
from .action_mouse import Mouse
from .action_waitwindow import WaitWindow
from .action_focuswindow import FocusWindow
from .action_startapp import StartApp, BringApp
from .action_playsound import PlaySound
else:
# Import mocked classes and functions for other platforms.
from ..os_dependent_mock import Mouse
from ..os_dependent_mock import WaitWindow
from ..os_dependent_mock import FocusWindow
from ..os_dependent_mock import StartApp, BringApp
from ..os_dependent_mock import PlaySound
15 changes: 8 additions & 7 deletions dragonfly/actions/keyboard/_x11_xdotool.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@ def send_keyboard_events(cls, events):
arguments += ['sleep', '%.3f' % timeout]

# Press/release the keys using xdotool, catching any errors.
command = [cls.xdotool] + arguments
readable_command = ' '.join(command)
cls._log.debug(readable_command)
try:
command = [cls.xdotool] + arguments
cls._log.debug(' '.join(command))
success = subprocess.call(command) > 0
if success:
return_code = subprocess.call(command)
if return_code > 0:
raise RuntimeError("xdotool command exited with non-zero "
"return code %d" % success)
"return code %d" % return_code)
except Exception as e:
cls._log.exception("Failed to execute xdotool command '%s': %s",
arguments, e)
cls._log.exception("Failed to execute xdotool command '%s': "
"%s", readable_command, e)
20 changes: 3 additions & 17 deletions dragonfly/os_dependent_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,9 @@ def __init__(self, spec=None, static=False):
DynStrActionBase.__init__(self, spec, static)


WaitWindow = MockAction
FocusWindow = MockAction
StartApp = MockAction
BringApp = MockAction
PlaySound = MockAction


class _WindowInfo(object):
executable = ""
title = ""
handle = ""


class Window(object):
@staticmethod
def get_foreground():
return _WindowInfo
class PlaySound(ActionBase):
def __init__(self, name=None, file=None):
ActionBase.__init__(self)


monitors = []
Expand Down
6 changes: 1 addition & 5 deletions dragonfly/test/suites.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,14 @@
"test_parser",
"test_rpc",
"test_timer",
"test_window",
"doc:documentation/test_action_base_doctest.txt",
"doc:documentation/test_grammar_elements_basic_doctest.txt",
"doc:documentation/test_grammar_elements_compound_doctest.txt",
"doc:documentation/test_grammar_list_doctest.txt",
"doc:documentation/test_recobs_doctest.txt",
]

# Only include common Windows-only tests on Windows.
if os.name == "nt":
common_names.extend(["test_window"])


# Define spoken language test files. All of them work with the natlink and
# text engines. The English tests should work with sapi5 and sphinx by
# default.
Expand Down
20 changes: 11 additions & 9 deletions dragonfly/windows/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@

import sys

from .rectangle import Rectangle, unit
from .point import Point
# Import classes that work on all platforms.
from .rectangle import Rectangle, unit
from .point import Point
from .window import Window
from .fake_window import FakeWindow

# Windows-specific
if sys.platform.startswith("win"):
from .window import Window
from .monitor import Monitor, monitors
from .clipboard import Clipboard
else: # Mock imports
from ..os_dependent_mock import Window
from ..os_dependent_mock import Monitor, monitors
from ..util import Clipboard
from .monitor import Monitor, monitors
from .clipboard import Clipboard

# Import mock classes.
else:
from ..os_dependent_mock import Monitor, monitors
Loading

0 comments on commit 5f492d8

Please sign in to comment.