Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Gnome Extension Window interface, left-right modifier distinction changes #844

Draft
wants to merge 20 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8c1809b
Add documentation, clipboard macro
sebastiansam55 Apr 13, 2023
2ad3ee2
Update documentation to work with sphinx better
sebastiansam55 Apr 20, 2023
462518f
Refactor interface, split out windowInterface, gnomeextension window …
sebastiansam55 Apr 22, 2023
dba3345
Add distinction between left and right modifiers
sebastiansam55 Apr 22, 2023
579c71d
Use XWindowInterface by default
sebastiansam55 Apr 22, 2023
995cdcf
Add left/right modifiers to Qt interface
sebastiansam55 Apr 22, 2023
7926b86
pull out gnome extension interfaces
sebastiansam55 Apr 26, 2023
ca48438
Add universal toggle (left or right modifier)
sebastiansam55 Apr 26, 2023
a05b5b3
Fix usage count, add some usage statistics
sebastiansam55 Apr 27, 2023
7b8aef6
API and macro usage statistics
sebastiansam55 Apr 28, 2023
12bb5dc
Update checking to be display server specific
sebastiansam55 Apr 28, 2023
20376e1
UInput Interface
sebastiansam55 May 21, 2023
7935b6a
update statistics to make them more anonymous
sebastiansam55 Aug 26, 2023
22f7f8e
Add mouse/keyboard to preferences interface
sebastiansam55 Aug 26, 2023
2c521ec
Add version check and method to get screen size
sebastiansam55 Aug 26, 2023
09d218c
Add mouse and keyboard to config file
sebastiansam55 Aug 26, 2023
2ed3278
Update error dialog methods
sebastiansam55 Aug 26, 2023
ecfdc8b
update where interfaces are created
sebastiansam55 Aug 26, 2023
d67d5b3
add mouse methods to interface. error popups
sebastiansam55 Aug 26, 2023
ae672d1
update to allow mouse events to be used as hotkeys
sebastiansam55 Aug 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 49 additions & 33 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,27 @@ Important misc changes
- Update action versions in build.yaml to latest.
- Update Qt/GTK "Run" button in interface to run on F5
- Update two links in the **README.rst** file.
- Adds GNOME Window Extension for interacting with Windows on x11/wayland

Features
---------
Create a GUI-free headless entrypoint to autokey, which can be run without GUI libraries and controlled purely via scripting API

Allows the distinction between left and right modifier keys for ``[Key.CONTROL, Key.ALT, Key.SUPER, Key.SHIFT, Key.HYPER, Key.META]``.

At this time you cannot "mix and match", IE if you have a ``Key.CONTROL`` and ``Key.ALT`` as the hotkeys it will check for;
``Key.LEFTCONTROL, Key.LEFTALT``
and
``Key.RIGHTCONTROL, Key.RIGHTALT``

But not for;
``Key.LEFTCONTROL, Key.RIGHTALT``
``Key.RIGHTCONTROL, Key.RIGHTALT``

This is considered a breaking change, prior it would, in effect, check for all of those scenarios.

Currently the left/right modifiers GUI option is only accessible via the GTK interface, but they should be respected if you manually update your config files.

Bug fixes
---------

Expand Down Expand Up @@ -88,7 +104,7 @@ Scripting API

- Deprecated: Confusingly named engine.create_abbreviation() and engine.create_hotkey() are deprecated and will be removed in the future. Use engine.create_phrase() with appropriate arguments instead.
- Extended: engine.create_phrase() now supports multiple new optional arguments, allowing to fully configure the created phrase. It can set everything the GUI can do.
- New: Scripts can use engine.get_triggered_abbreviation() to read which abbreviation triggered its execution.
- New: Scripts can use engine.get_triggered_abbreviation() to read which abbreviation triggered it's execution.
The function returns a tuple containing the abbreviation and the trigger character (the character that 'completed' or 'confirmed' the abbreviation. Both tuple elements are None if the script was not triggered by an abbreviation. The trigger character is None if the script was configured to 'trigger immediately'. The function always returns a tuple, so direct tuple unpacking like abbreviation, trigger = engine.get_triggered_abbreviation() will always work.
- Allow creation of 'temporary' hotkeys and whole folders (which do not persist between sessions).
- Allow overriding existing hotkeys when creating phrases with hotkeys.
Expand All @@ -97,7 +113,7 @@ Scripting API
**keyboard API object**

- keyboard.send_keys() got a new optional parameter send_mode, allowing to specify how the given text is sent. It basically offers the same pasting options as are available to AutoKey Phrases.
- keyboard.send_keys() now raises a TypeError instead of a generic AssertionError, if parameters dont match the expected types.
- keyboard.send_keys() now raises a TypeError instead of a generic AssertionError, if parameters don't match the expected types.

**New clipboard API method**
- Change the default phrase send mode to `ctrl+v` (paste using clipboard) rather than sending keys one at a time.
Expand All @@ -115,12 +131,12 @@ Scripting API


Command line interface
++++++++++++++++++++++
^^^^^^^^^^^^^^^^^^^^^^

- Added a --version command line switch. It prints the current AutoKey version on the standard output and then exits.

Graphical user interfaces
+++++++++++++++++++++++++
^^^^^^^^^^^^^^^^^^^^^^^^^

- (GTK) Warn user about missing required and optional programs on startup.
- (GTK) UI will now update when changes are detected to watched files.
Expand All @@ -129,7 +145,7 @@ Graphical user interfaces
- Add setting to change GtkSourceView theme, (defaults to classic).

Other
+++++
^^^^^

- Add `wait_for_keyevent` scripting function.
- Rewrote script error logging system, with a neat Script Error Dialog to go with it.
Expand All @@ -149,20 +165,20 @@ Bug fixes
- Both QT and GTK versions will reload hotkeys after a keymap change event.
- Fix locking issue
- Expose Alt_GR as a hotkey modifier on GTK.
- (GTK) Fixed GUI lock-up, if multiple script error notifications are posted in quick succession. The notifications are now rate-limited and wont post more than one notification per second. Fixes issue #383
- (GTK) Fixed GUI lock-up, if multiple script error notifications are posted in quick succession. The notifications are now rate-limited and won't post more than one notification per second. Fixes issue #383

Scripting API
+++++++++++++
^^^^^^^^^^^^^

- Fixed API call `system.exec_command()` crashing, if output capturing is active, but the executed command has empty output. Fixes issue #379

Packaging
+++++++++
^^^^^^^^^

- Fixed AutoKey PNG icon size. Now, the icon size is 96x96 pixels, fixing Lintian warnings on Debian. Fixes issue #369

Other changes
---------
-------------

- Add CI for testing
- Update pip installation requirements
Expand Down Expand Up @@ -277,7 +293,7 @@ Bug fixes
- Force AutoKey to exit, if the X server connection closes, most probably at logout or session end. Fixes issue #198

Qt tray icon fixes and improvements
+++++++++++++++++++++++++++++++++++
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Added »View script error« entry to the Tray icon context menu, like in the GTK GUI. Part of issue #158
- Tray icon turns red, when scripts raise an error, like in the GTK GUI. Part of issue #158
Expand Down Expand Up @@ -384,40 +400,40 @@ Resurrected, re-written and cleaned up the `autokey-qt` Qt GUI. `autokey-qt` is
dependent on currently supported libraries.

Added improvements
++++++++++++++++++
^^^^^^^^^^^^^^^^^^
- The main window now keeps its complete state when closed and re-opened (excluding complete application restarts). This includes the currently selected item(s) in the tree view on the left of the main window, selected text and cursor position in the editor on the right if currently editing a script or phrase.
- The entries in the popup menu, that is shown when a hotkey assigned to a folder is pressed, now show icons based on their type (folder, phrase or script). This also works when items are configured to be shown in the system tray icon context menu.
- The *A* autokey application icons are now always displayed correctly, both in the main window and the system tray icon.
- Various menu actions now have system dependent keyboard shortcuts, that should adjust to the expected default of the users current platform/desktop environment.
- Various menu actions now have system dependent keyboard shortcuts, that should adjust to the expected default of the user's current platform/desktop environment.
- Added icons and descriptive tooltip texts to various buttons.
- The `enable monitoring` checkboxes (both in the `Settings` menu and the tray icon context menu) now properly react to pressing the global hotkey for this action and thus stay in sync. (Even if the hotkey is used while the menu is shown.)

Regressions
+++++++++++
^^^^^^^^^^^
- Customizing the main window toolbar entries and keyboard shortcuts to trigger various UI actions is no longer possible. This feature was provided by the KDE4 libraries and is currently dropped.
- The previous, KDE4-based About dialogue is replaced with a very minimalistic one.
- The settings dialogue heavily used the KDE4 functionalities. During the port to Qt5, the dialogue lost some visual style, but all core functionality is kept.

Runtime dependencies
++++++++++++++++++++
^^^^^^^^^^^^^^^^^^^^
- Removed dependencies on deprecated and unmaintained PyQt4 and PyKDE4 libraries.
- Removed dependency on `dbus.mainloop.qt`, instead use the DBus support built into Qt5.
- Now depend on PyQt5, the Qt5 SVG module and the Qt5 QScintilla2 module.

Build-time dependencies
+++++++++++++++++++++++
^^^^^^^^^^^^^^^^^^^^^^^
Optionally depend on `pyrcc5` command line tool to compile Qt resources into a Python module.

Qt UI files are no longer compiled using `pykdeuic4`, Removed the old compiler wrapper script in commit 6eeeb92f_.

.. _6eeeb92f: https://github.com/autokey/autokey/commit/6eeeb92f14c694979c1367d51350c1e6509329b1

Known bugs
++++++++++
^^^^^^^^^^
The system tray icon is shown, but non-functional, after enabling it in the settings dialogue. AutoKey Qt has to be restarted for the tray icon to start working. This should have no impact on the normal daily use.

Changed features
++++++++++++++++
^^^^^^^^^^^^^^^^
The `hide tray icon` entry in the tray icon context menu now hides the icon for the current session only. The entry does not permanently disable the tray icon any more without any confirmation. Now, the only way to permanently disable the tray icon is through using the appropriate setting in the settings dialogue.

Fixed the broken `Clipboard` and `Mouse selection` phrase paste modes
Expand All @@ -431,20 +447,20 @@ Scripting API Changes
---------------------

Additions
+++++++++
^^^^^^^^^

- Added a colour picker dialogue to the GTK dialog class, because the used `zenity` now supports it.
- The picked colour is returned as three integers using the ColourData NamedTuple, providing both index based access and attribute access, using the channel names (`r`, `g`, `b`). Additionally, ColourData provides some conversion methods.

Breaking changes
++++++++++++++++
^^^^^^^^^^^^^^^^
- See Pull request `#148`_. The `dialog` classes for user input in scripts now return typed NamedTuple tuples instead of plain tuples. This change is safe as long as users do not perform needlessly restrictive type checks in their scripts (e.g. `if type(returned_data) == type(tuple()): ...`). User scripts doing so will break.
- The KDialog based colour picker now also returns a ColourData instance instead of a HTML style hex string, thus making this portable between both GTK and Qt GUIs. AutoKey users previously using the old KDE GUI and using the colour picker dialogue have to port their scripts. A simple fix is using the `html_code` property of the returned ColourData instance.

.. _`#148`: https://github.com/autokey/autokey/pull/148

Fixes
+++++
^^^^^
- Re-introduce the newline trimming for system.exec_command() function. During the porting to Python 3, the newline trimming was removed, causing users various issues with unexpected newline characters at end of output. Now properly remove the _last_ newline at end of command output. (See issues `#75`_, `#92`_, `#145`_)
- Applied various code style improvements to the scripting module.

Expand Down Expand Up @@ -537,18 +553,18 @@ Internal changes: Changed the data structure of the input stack.
Version 0.93.0 <2014-02-27 Thu>
===============================

Added functions acknowledge_gnome_notification and move_to_pat, more details `here`_.
Added functions "acknowledge_gnome_notification" and "move_to_pat", more details `here`_.

.. _here: https://github.com/autokey/autokey/blob/master/new_features.rst

Version 0.92.0 <2014-02-21 Fri>
===============================
Added an interactive shell launcher, autokey-shell”. “autokey-shell allows you to run some AutoKey functions interactively. Read `this`_ for more details.
Added an interactive shell launcher, "autokey-shell". "autokey-shell" allows you to run some AutoKey functions interactively. Read `this`_ for more details.


Version 0.91.0 <2014-02-14 Fri>
===============================
Added a new function click_on_pat for use in user scripts. See `this`_ for more details.
Added a new function "click_on_pat" for use in user scripts. See `this`_ for more details.

.. _this: https://github.com/autokey/autokey/blob/master/new_features.rst

Expand All @@ -562,29 +578,29 @@ Python 3 related changes
Python 3 is less tolerant of circular imports so some files were split into several files. Those pieces of the original have their file names prefixed with the original's.

Bug fixes
+++++++++
^^^^^^^^^
Eliminate possible deadlock.
Changed

.. code-block:: python

p = subprocess.Popen([], stdout=subprocess.PIPE)
p = subprocess.Popen([...], stdout=subprocess.PIPE)
retCode = p.wait()
output = p.stdout.read()[:-1] # Drop trailing newline

to

.. code:: python
.. code-block:: python

p = subprocess.Popen([], stdout=subprocess.PIPE)
p = subprocess.Popen([...], stdout=subprocess.PIPE)
output = p.communicate()[0].decode()[:-1] # Drop trailing newline
retCode = p.returncode

The former may cause a deadlock, for more information, see `Python docs`_. This pattern appears several times in the source codes.

.. _Python docs: http://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait

For a gi.repository.Notify.Notification object, test if method attach_to_status_icon exists before calling. After this fix, errors in user scripts will trigger a notification.
For a "gi.repository.Notify.Notification" object, test if method "attach_to_status_icon" exists before calling. After this fix, errors in user scripts will trigger a notification.

Respect XDG standard. Details `here`__.

Expand All @@ -595,13 +611,13 @@ Corrected a typo in manpage of autokey-run.
For the GTK GUI, after script error is viewed, tray icon is reverted back to original.

Other changes
+++++++++++++
In setup.py, the /usr/ prefix to the directory names in the data_files argument were removed to allow for non-root install.
^^^^^^^^^^^^^
In setup.py, the "/usr/" prefix to the directory names in the data_files argument were removed to allow for non-root install.

Removed the WINDOWID environment variable so that zenity is not tied to the window from which it was launched.
Removed the "WINDOWID" environment variable so that zenity is not tied to the window from which it was launched.

Modified the launcher and other files to allow for editable installs (pip install -e).
Modified the launcher and other files to allow for editable installs ("pip install -e").

Added an about dialog for the Python 3 port.
Added an "about" dialog for the Python 3 port.

Changed hyperlink for bug reports.
1 change: 1 addition & 0 deletions CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Please add a line to CHANGELOG.rst when creating PRs
Please make sure tests pass before you submit PRs. To ensure this happens automatically, I recommend adding the following lines to the file `.git/hooks/pre-push`:

.. code:: sh

remote="$1"
url="$2"

Expand Down
51 changes: 49 additions & 2 deletions lib/autokey/UI_common_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import subprocess
import sys
import time
import os

from . import common
import autokey.model.helpers
Expand All @@ -24,13 +25,52 @@
qt_modules = ['PyQt5', 'PyQt5.QtGui', 'PyQt5.QtWidgets', 'PyQt5.QtCore',
'PyQt5.Qsci']

common_programs = ['wmctrl', 'ps', 'xrandr']
# wmctrl, xrandr are x11 specific programs.
x11_programs = ['wmctrl', 'xrandr']
common_programs = ['ps']
# Checking some of these appears to be redundant as some are provided by the same packages on my system but
# better safe than sorry.
optional_programs = ['visgrep', 'import', 'png2pat', 'xte', 'xmousepos']
x11_optional_programs = ['xte', 'xmousepos']
optional_programs = ['visgrep', 'import', 'png2pat']
gtk_programs = ['zenity']
qt_programs = ['kdialog']

def checkGnomeAutokeyExtension():
bus_name = "org.gnome.Shell"
object_path = "/org/gnome/Shell/Extensions/AutoKey"
interface_name = "org.gnome.Shell.Extensions.AutoKey"
check_dbus_object_exists(bus_name, object_path, interface_name)
pass


def check_dbus_object_exists(bus_name, object_path, interface_name):
#keep dbus import here
import dbus
try:
# Connect to the D-Bus session bus
bus = dbus.SessionBus()

# Get a reference to the service and object
obj = bus.get_object(bus_name, object_path)

# Get a reference to the desired interface
interface = dbus.Interface(obj, interface_name)

# Call a method on the object (e.g., 'Get') and check if it returns a valid result
interface.List() # Replace 'property_name' with an actual property name

# If the method call was successful, the object exists
return True

except dbus.exceptions.DBusException as e:
# Handle the exception and return False if the object does not exist
if e.get_dbus_name() == 'org.freedesktop.DBus.Error.UnknownObject':
return False
else:
# If the exception is not related to the unknown object, re-raise it
raise


def checkModuleImports(modules):
missing_modules = []
for module in modules:
Expand All @@ -57,6 +97,9 @@ def checkProgramImports(programs, optional=False):
return missing_programs

def checkOptionalPrograms():
if os.environ.get("XDG_SESSION_TYPE") == "x11":
checkProgramImports(x11_optional_programs, optional=True)

if common.USED_UI_TYPE == "QT":
checkProgramImports(optional_programs, optional=True)
elif common.USED_UI_TYPE == "GTK":
Expand All @@ -74,6 +117,10 @@ def getErrorMessage(item_type, missing_items):

def checkRequirements():
errorMessage = ""

if os.environ.get("XDG_SESSION_TYPE") == "x11":
missing_programs = checkProgramImports(x11_programs)

if common.USED_UI_TYPE == "QT":
missing_programs = checkProgramImports(common_programs+qt_programs)
missing_modules = checkModuleImports(common_modules+qt_modules)
Expand Down