Skip to content

Commit

Permalink
version 0.0.41: New typed version (fixed type_extensions dependency),…
Browse files Browse the repository at this point in the history
… improved LinuxWindow class to accept window object or window id (int/str), added acceptInput(), added getTopWindowAt(), fixed and improved sendBehind() on Ubuntu 22.04+ and Mint/Cinnamon, improved watchdog, added macOS AppScript alwaysOnTop() and alwaysOnBottom()
  • Loading branch information
Kalmat committed Dec 10, 2022
1 parent cf3ecc6 commit d3008ab
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
0.0.42, 2022/12/09 -- Really fixed typing_extensions dependency and setup.py dependencies
0.0.41, 2022/12/09 -- Fixed requirements.txt with typing_extensions dependency
0.0.40, 2022/12/07 -- New typed version. Improved Window class to accept Window object or window id (int/str), added acceptInput(), added getTopWindowAt(), fixed and improved sendBehind() on Ubuntu 22.04+ and Mint/Cinnamon,
0.0.39, 2022/06/07 -- Improved watchdog, fixed Mint/Cinnamon sendBehind() method, added macOS AppScript alwaysOnTop() and alwaysOnBottom() methods
Expand Down
12 changes: 9 additions & 3 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ Linux:
- Test other combinations (especially for sendBehind()). Tested OK: Ubuntu/GNOME and Mint/Cinnamon

Windows:
- alwaysOnTop(): Working with GDI, not with windows using DirectDraw exclusive mode (is it possible with Python, or combining C++ and Python???)
https://stackoverflow.com/questions/7009080/detecting-full-screen-mode-in-windows
https://stackoverflow.com/questions/7928308/displaying-another-application-on-top-of-a-directdraw-full-screen-application
https://www.codeproject.com/articles/730/apihijack-a-library-for-easy-dll-function-hooking?fid=1267&df=90&mpp=25&sort=Position&view=Normal&spc=Relaxed&select=116946&fr=73&prof=True
https://guidedhacking.com/threads/d3d9-hooking.8481/
https://stackoverflow.com/questions/25601362/transparent-window-on-top-of-immersive-full-screen-mode
- sendBehind(False): Find a smarter way to update window (now it's minimize/restore)
- SendBottom(): Find a way to filter user vs. system apps. It should be doable like in Task Manager!!!
- alwaysOnBottom(): Try to find other smarter methods to keep window at the bottom (now it's a thread)

macOS / AppleScript:
- In general, find a way to optimize all appScript calls in terms of time and resources
https://discussions.apple.com/thread/1877444
https://discussions.apple.com/thread/2189505
https://discussions.apple.com/thread/1877444
https://discussions.apple.com/thread/2189505
- getAllWindows()/getAllTitles(): Find a way to return windows in same stack order than on screen
- alwaysOnTop(): Try to find other smarter methods to keep window at the top (now it's a thread)
- alwaysOnBottom(): Try to find other smarter methods to keep window at the bottom (now it's a thread)
- sendBehind(): Is it even possible???
- acceptInput(): Is it even possible???

General:
- Create type stubs or add to base library
- PyRect: Create type stubs or add to base library
Binary file removed dist/PyWinCtl-0.0.41-py3-none-any.whl
Binary file not shown.
Binary file added dist/PyWinCtl-0.0.42-py3-none-any.whl
Binary file not shown.
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@
package_data={"pywinctl": ["src/pywinctl/py.typed"]},
test_suite='tests',
install_requires=[
"PyRect>=0.1",
"PyRect>=0.2",
"pywin32>=302; sys_platform == 'win32'",
"xlib>=0.21; sys_platform == 'linux'",
"ewmh>=0.1; sys_platform == 'linux'",
"pynput>=1.6.0; sys_platform == 'linux'",
"pyobjc>=8.1; sys_platform == 'darwin'"
],
keywords="gui window control menu title name geometry size position move resize minimize maximize restore "
Expand Down
2 changes: 1 addition & 1 deletion src/pywinctl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
if sys.platform == "darwin":
__all__ += ["NSWindow"]

__version__ = "0.0.41"
__version__ = "0.0.42"

class Box(NamedTuple):
left: int
Expand Down
16 changes: 13 additions & 3 deletions src/pywinctl/_pywinctl_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
import time
import tkinter as tk
from collections.abc import Callable
from typing import Iterable
from typing import Iterable, TYPE_CHECKING
if TYPE_CHECKING:
from typing_extensions import TypedDict
else:
# Only needed if the import from typing_extensions is used outside of annotations
from typing import TypedDict

import ewmh
import Xlib.display
Expand All @@ -22,14 +27,13 @@
import Xlib.X
import Xlib.Xatom
import Xlib.Xutil
from typing_extensions import TypedDict
from Xlib.xobject.drawable import Window

from pywinctl import BaseWindow, Point, Re, Rect, Size, _WinWatchDog, pointInRect

DISP = Xlib.display.Display()
SCREEN = DISP.screen()
ROOT = SCREEN.root
ROOT: Window = SCREEN.root
EWMH = ewmh.EWMH(_display=DISP, root=ROOT)

# WARNING: Changes are not immediately applied, specially for hide/show (unmap/map)
Expand Down Expand Up @@ -93,6 +97,10 @@ def getActiveWindow():
win_id = EWMH.getActiveWindow()
if win_id:
return LinuxWindow(win_id)
# ret = ROOT.get_full_property(DISP.get_atom('_NET_ACTIVE_WINDOW', False), Xlib.X.AnyPropertyType)
# if ret and ret.value:
# win_id = ret.value[0]
# return LinuxWindow(win_id)
return None


Expand Down Expand Up @@ -128,6 +136,7 @@ def getAllWindows():
"""
windows = EWMH.getClientListStacking()
return [window for window in __remove_bad_windows(windows)]
# return [window for window in __remove_bad_windows(ROOT.get_full_property(DISP.get_atom('_NET_CLIENT_LIST_STACKING', False), Xlib.X.AnyPropertyType).value)]


def getAllTitles() -> list[str]:
Expand Down Expand Up @@ -424,6 +433,7 @@ def _rect(self):

def __init__(self, hWnd: Window | int | str):
super().__init__()
print(type(hWnd))
if isinstance(hWnd, int):
self._hWnd = DISP.create_resource_object('window', hWnd)
elif isinstance(hWnd, str):
Expand Down
11 changes: 9 additions & 2 deletions src/pywinctl/_pywinctl_macos.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@
import threading
import time
from collections.abc import Callable, Iterable
from typing import Any, overload, cast, Sequence
from typing_extensions import TypeAlias, TypedDict, Literal
from typing import Any, AnyStr, overload, cast, Sequence, TYPE_CHECKING

if TYPE_CHECKING:
from typing_extensions import TypeAlias, TypedDict, Literal
else:
# Only needed if the import from typing_extensions is used outside of annotations
TypeAlias = Any
from typing import TypedDict
Literal = AnyStr

import AppKit
import Quartz
Expand Down
14 changes: 9 additions & 5 deletions src/pywinctl/_pywinctl_win.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,25 @@
import time
from collections.abc import Callable, Sequence
from ctypes import wintypes
from typing import TYPE_CHECKING, cast, overload
from typing import cast, overload, AnyStr, TYPE_CHECKING
if TYPE_CHECKING:
from typing_extensions import Literal, NotRequired, TypedDict
from win32.lib.win32gui_struct import _MENUITEMINFO
else:
# Only needed if the import from typing_extensions is used outside of annotations
Literal = AnyStr
NotRequired = dict
from typing import TypedDict

import win32api
import win32con
import win32gui
import win32gui_struct
import win32process
from typing_extensions import Literal, NotRequired, TypedDict
from win32com.client import GetObject

from pywinctl import BaseWindow, Point, Re, Rect, Size, _WinWatchDog, pointInRect

if TYPE_CHECKING:
from win32.lib.win32gui_struct import _MENUITEMINFO

# WARNING: Changes are not immediately applied, specially for hide/show (unmap/map)
# You may set wait to True in case you need to effectively know if/when change has been applied.
WAIT_ATTEMPTS = 10
Expand Down

0 comments on commit d3008ab

Please sign in to comment.