Skip to content

Commit

Permalink
LINUX: Added experimental Wayland support (only if unsafe mode enable…
Browse files Browse the repository at this point in the history
…d and only for some apps). Fixed ewmhlib freezing in Wayland when connecting to display ":1", and added some performance improvements
  • Loading branch information
Kalmat committed Sep 19, 2023
1 parent d011545 commit caa98e1
Show file tree
Hide file tree
Showing 23 changed files with 583 additions and 438 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/type-checking.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "docs/requirements.txt"
- run: pip install -r "docs/requirements.txt"
cache-dependency-path: "requirements.txt"
- run: pip install -r "requirements.txt"
- run: mypy . --python-version=${{ matrix.python-version }}
22 changes: 4 additions & 18 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PyWinCtl authors, contributors and maintainers:
PyWinCtl authors, contributors and issues or bugs raisers:

Kalmat https://github.com/Kalmat
Rodrigo Silva (MestreLion) https://github.com/MestreLion
Expand All @@ -11,21 +11,7 @@ holychowders https://github.com/holychowders
Anthony Molinaro (djnym) https://github.com/djnym
Kyle King https://github.com/KyleKing
Leonard Bruns https://github.com/roym899
In general, all those who so generously share their work and knowledge on Internet (stackoverflow, github, ...) so I could find a solution or a string to pull!
ReaperMantis https://github.com/ReaperMantis

PyGetWindow (original module): Here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --
people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made PyGetWindow that much better:

Al Sweigart https://github.com/asweigart/
arkulinskis https://github.com/arkulinskis
aweffr https://github.com/aweffr
Demonthos https://github.com/Demonthos
Duxxi https://github.com/sjhhh3
EMOholcicka https://github.com/EMOholcicka
Kudria https://github.com/Kudria
lexxish https://github.com/lexxish
李宏杰 https://github.com/lihongjie0209
Randall White
Ronald Oussoren
Steve Newell https://github.com/newellista
In general, all those who so generously share their work and knowledge on Internet (stackoverflow, github, ...)
so I could find a solution or a string to pull!
5 changes: 3 additions & 2 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
0.1, 2023/02/03 -- LINUX: Added experimental Wayland support (only if unsafe mode enabled and only for some apps).
0.2, 2023/09/09 -- LINUX: Added experimental Wayland support (only if unsafe mode enabled and only for some apps).
Fixed ewmhlib freezing in Wayland when connecting to display ":1", and added some performance improvements
0.1, 2023/09/06 -- LINUX: Fixed all title-related methods (title, getAllTitles, getAllAppsWindowTitles, etc.) returning empty values when using Xlib's get_wm_name()
MACOS: Tested OK in multi-monitor setups (based on PyWinBox and PyMonCtl features).
ALL: getDisplay() method returns a list of monitors.
0.0.50, 2023/02/03 -- ALL: Added PyMonCtl module to improve multi-monitor capabilities, added setParent() method. Reorganized to avoid IDEs showing external and / or private elements
WINDOWS: Simplified alwaysOnBottom(), found a smarter way to refresh window after bringing it back with sendBehind()
MACOS: Tested in multi-monitor setups (based on PyWinBox and PyMonCtl features)
MACOSNSWINDOW: Added experimental acceptInput() method (not possible in AppleScript version)
0.0.45, 2023/08/21 -- ALL: Included PyWinBox module which hopefully better handles multi-monitor setups (macOS tests pending)
LINUX: Fixed geometry calculations (thanks to roym899), removed ewmh and pynput dependencies
Expand Down
11 changes: 6 additions & 5 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Original module (Windows support) Copyright (c) 2015, Al Sweigart
Copyright (c) 2021, Kalmat <palookjones@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand All @@ -11,7 +11,7 @@ modification, are permitted provided that the following conditions are met:
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the PyAutoGUI nor the names of its
* Neither the name of the PyWinCtl nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

Expand All @@ -26,9 +26,9 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

--------------------------------------------------------------------------------
------------------------------------------------------------------------------

This fork (Linux and macOS support) Copyright (c) 2021, Kalmat (aka alef) <palookjones@gmail.com>
Original module (PyGetWindow, Windows support only) Copyright (c) 2015, Al Sweigart
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand All @@ -54,4 +54,5 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

20 changes: 8 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Cross-Platform module to get info on and control windows on screen.

With PyWinCtl you can retrieve info or control windows from other open applications, as well as use it as a cross-platform toolkit to manipulate your own application windows.

This module is a Python 3 evolution from [asweigart's PyGetWindow module](https://github.com/asweigart/PyGetWindow), which adds Linux/X11 and macOS support to the MS Windows-only original module, experimental multi-monitor support, and many additional features; in the hope others can use it, test it or contribute.
This module is a Python 3 evolution from [asweigart's PyGetWindow module](https://github.com/asweigart/PyGetWindow), which adds Linux/X11 and macOS support to the MS Windows-only original module, multi-monitor support, and many additional features; in the hope others can use it, test it or contribute.

My most sincere thanks and acknowledgement to [MestreLion](https://github.com/MestreLion), [super-ibby](https://github.com/super-ibby), [Avasam](https://github.com/Avasam), [macdeport](https://github.com/macdeport) and [holychowders](https://github.com/holychowders) for their help and moral boost.
My most sincere thanks and acknowledgement. amongst many others (see AUTHORS.txt), to [MestreLion](https://github.com/MestreLion), [super-ibby](https://github.com/super-ibby), [Avasam](https://github.com/Avasam), [macdeport](https://github.com/macdeport) and [holychowders](https://github.com/holychowders) for their help and moral boost.

1. [Window Features](#window-features)
1. [Important macOS notice](#macos-notice)
Expand Down Expand Up @@ -61,7 +61,7 @@ These functions are available at the moment, in all three platforms (Windows, Li
***Important macOS notice <a name="macos-notice"></a>***

macOS doesn't "like" controlling windows from other apps, so there are two separate classes you can use:
- To control your own application's windows: MacOSNSWindow() is based on NSWindow Objects (you have to pass the NSApp() Object reference).
- To control your own application's windows: MacOSNSWindow() is based on NSWindow Objects (you have to pass the NSApp() and the NSWindow() objects reference).
- To control other applications' windows: MacOSWindow() is based on Apple Script, so it is non-standard, slower and, in some cases, tricky (uses window name as reference, which may change or be duplicate), but it's working fine in most cases. You will likely need to grant permissions on Settings -> Security&Privacy -> Accessibility. ***Notice some applications will have limited Apple Script support or no support at all, so some or even all methods may fail!***

***Important Linux notice <a name="linux-notice"></a>***
Expand All @@ -70,7 +70,7 @@ The enormous variety of Linux distributions, Desktop Environments, Window Manage

This module has been tested OK in some X11 setups: Ubuntu/Gnome, Ubuntu/KDE, Ubuntu/Unity, Mint/Cinnamon and Raspbian/LXDE. Except for Mint/Cinnamon and Ubuntu 22.04+, `sendBehind()` method doesn't properly work!

In Wayland (the new GNOME compositor for Ubuntu 22.04+), it is not possible to retrieve the active window nor the list
In Wayland (the new GNOME protocol for Ubuntu 22.04+), it is not possible to retrieve the active window nor the list
of open windows, so `getActiveWindow()` and `getAllWindows()` will not work even though unsafe-mode is
enabled (built-in and "official" applications do not populate their XID nor their X-Window object, so it may work for
other applications like Chrome or your own application windows)
Expand All @@ -79,7 +79,7 @@ In case you find problems in other configs, please [open an issue](https://githu

## Window Change Notifications <a name="watchdog"></a>

Window watchdog sub-class, running in a separate Thread, will allow you to define hooks and its callbacks to be notified when some window states change. Accessible through 'watchdog' submodule.
Window watchdog sub-class, running in a separate Thread, will allow to define hooks and its callbacks to be notified when some window states change. Accessible through 'watchdog' submodule.

The watchdog will automatically stop when window doesn't exist anymore or main program quits.

Expand Down Expand Up @@ -217,7 +217,7 @@ Note not all windows/applications will have a menu accessible by these methods.

To install this module on your system, you can use pip:

pip install pywinctl
pip3 install pywinctl

or

Expand All @@ -244,17 +244,13 @@ If you want to use this code or contribute, you can either:
* Create a fork of the [repository](https://github.com/Kalmat/PyWinCtl), or
* [Download the repository](https://github.com/Kalmat/PyWinCtl/archive/refs/heads/master.zip), uncompress, and open it on your IDE of choice (e.g. PyCharm)

Be sure you install all dependencies described on "docs/requirements.txt" by using pip
Be sure you install all dependencies described on "requirements.txt" by using pip

## TEST <a name="test"></a>

To test this module on your own system, cd to "tests" folder and run:

pytest -vv test_pywinctl.py

or, in case you get an import error, try this:

python3 -m pytest -vv test_pywinctl.py
python3 test_pywinctl.py

MacOSNSWindow class and methods can be tested by running this, also on "tests" folder:

Expand Down
Binary file removed dist/PyWinCtl-0.1-py3-none-any.whl
Binary file not shown.
Binary file added dist/PyWinCtl-0.2-py3-none-any.whl
Binary file not shown.
27 changes: 0 additions & 27 deletions pyrightconfig.json

This file was deleted.

4 changes: 2 additions & 2 deletions docs/requirements.txt → requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Requirements needed for development
# Run: `pip install -r docs/requirements.txt`
# Build/Production requirements are found in ../setup.py
# Run: `pip install -r requirements.txt`
# Build/Production requirements are found in setup.py
# Run: `pip install -e .`
#
# installs dependencies from setup.py, and the package itself,
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
"pywin32>=302; sys_platform == 'win32'",
"python-xlib>=0.21; sys_platform == 'linux'",
"pyobjc>=8.1; sys_platform == 'darwin'",
"pywinbox>=0.5",
"pymonctl>=0.5"
"typing_extensions>=4.4.0",
"pywinbox>=0.6",
"pymonctl>=0.6"
],
extras_require={
'dev': [
"types-setuptools>=65.5",
"mypy>=0.990",
"typing_extensions>=4.4.0",
"types-pywin32>=305.0.0.3",
"types-python-xlib>=0.32"
]
Expand Down
5 changes: 5 additions & 0 deletions src/ewmhlib/Props/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

from ._props import (Root, DesktopLayout, Window, WindowType, State, StateAction,
MoveResize, DataFormat, Mode, StackMode, HintAction)
4 changes: 4 additions & 0 deletions src/ewmhlib/Props.py → src/ewmhlib/Props/_props.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

from enum import IntEnum
import Xlib.X

Expand Down Expand Up @@ -40,6 +43,7 @@ class DesktopLayout(IntEnum):

class Window:
NAME = "_NET_WM_NAME"
LEGACY_NAME = "WM_NAME"
VISIBLE_NAME = "_NET_WM_VISIBLE_NAME"
ICON_NAME = "_NET_WM_ICON_NAME"
VISIBLE_ICON_NAME = "_NET_WM_VISIBLE_ICON_NAME"
Expand Down
4 changes: 4 additions & 0 deletions src/ewmhlib/Structs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

from ._structs import (ScreensInfo, DisplaysInfo, WmHints, Aspect, WmNormalHints)
5 changes: 4 additions & 1 deletion src/ewmhlib/Structs.py → src/ewmhlib/Structs/_structs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import List
#!/usr/bin/python
# -*- coding: utf-8 -*-#from typing import List

from typing_extensions import TypedDict
from typing import List

from ctypes import Structure, c_int32, c_ulong, c_uint32
import Xlib.xobject
Expand Down Expand Up @@ -31,6 +33,7 @@ class DisplaysInfo(TypedDict):
- is_default: ''True'' if the display is the default display
- screens: list of ScreensInfo structs belonging to display
"""
display: Xlib.display.Display
name: str
is_default: bool
screens: List[ScreensInfo]
Expand Down
15 changes: 11 additions & 4 deletions src/ewmhlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-


__all__ = [
"version", "displaysCount", "getDisplaysNames", "getDisplaysInfo", "getDisplayFromRoot", "getDisplayFromWindow",
"version", "displaysCount", "getDisplays", "getDisplaysInfo", "getRoots", "getRootsInfo",
"defaultDisplay", "defaultScreen", "defaultRoot", "defaultEwmhRoot",
"getDisplayFromRoot", "getScreenFromRoot",
"getDisplayFromWindow", "getScreenFromWindow", "getRootFromWindow",
"getProperty", "getPropertyValue", "changeProperty", "sendMessage",
"defaultDisplay", "defaultScreen", "defaultRoot", "defaultRootWindow", "RootWindow", "EwmhWindow",
"EwmhRoot", "EwmhWindow",
"Props", "Structs"
]

Expand All @@ -16,8 +20,11 @@ def version(numberOnly: bool = True):
return ("" if numberOnly else "EWMHlib-")+__version__


from ._main import (displaysCount, getDisplaysNames, getDisplaysInfo, getDisplayFromRoot, getDisplayFromWindow,
from ._main import (displaysCount, getDisplays, getDisplaysInfo, getRoots, getRootsInfo,
defaultDisplay, defaultScreen, defaultRoot, defaultEwmhRoot,
getDisplayFromRoot, getScreenFromRoot,
getDisplayFromWindow, getScreenFromWindow, getRootFromWindow,
getProperty, getPropertyValue, changeProperty, sendMessage,
defaultDisplay, defaultScreen, defaultRoot, RootWindow, defaultRootWindow, EwmhWindow,
EwmhRoot, EwmhWindow,
Props, Structs
)
Loading

0 comments on commit caa98e1

Please sign in to comment.