diff --git a/CHANGES.txt b/CHANGES.txt index c802ebf..6b1fedd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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 diff --git a/TODO.txt b/TODO.txt index 27f462f..b7fe75c 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,14 +2,20 @@ 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) @@ -17,4 +23,4 @@ https://discussions.apple.com/thread/2189505 - acceptInput(): Is it even possible??? General: -- Create type stubs or add to base library +- PyRect: Create type stubs or add to base library diff --git a/dist/PyWinCtl-0.0.41-py3-none-any.whl b/dist/PyWinCtl-0.0.41-py3-none-any.whl deleted file mode 100644 index 6428920..0000000 Binary files a/dist/PyWinCtl-0.0.41-py3-none-any.whl and /dev/null differ diff --git a/dist/PyWinCtl-0.0.42-py3-none-any.whl b/dist/PyWinCtl-0.0.42-py3-none-any.whl new file mode 100644 index 0000000..c0c2958 Binary files /dev/null and b/dist/PyWinCtl-0.0.42-py3-none-any.whl differ diff --git a/setup.py b/setup.py index 28ba7ae..4690085 100644 --- a/setup.py +++ b/setup.py @@ -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 " diff --git a/src/pywinctl/__init__.py b/src/pywinctl/__init__.py index 00a3c32..63fb66a 100644 --- a/src/pywinctl/__init__.py +++ b/src/pywinctl/__init__.py @@ -25,7 +25,7 @@ if sys.platform == "darwin": __all__ += ["NSWindow"] -__version__ = "0.0.41" +__version__ = "0.0.42" class Box(NamedTuple): left: int diff --git a/src/pywinctl/_pywinctl_linux.py b/src/pywinctl/_pywinctl_linux.py index 79b6f40..40cadc6 100644 --- a/src/pywinctl/_pywinctl_linux.py +++ b/src/pywinctl/_pywinctl_linux.py @@ -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 @@ -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) @@ -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 @@ -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]: @@ -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): diff --git a/src/pywinctl/_pywinctl_macos.py b/src/pywinctl/_pywinctl_macos.py index 1847da1..e7481f8 100644 --- a/src/pywinctl/_pywinctl_macos.py +++ b/src/pywinctl/_pywinctl_macos.py @@ -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 diff --git a/src/pywinctl/_pywinctl_win.py b/src/pywinctl/_pywinctl_win.py index c019645..e3d07b6 100644 --- a/src/pywinctl/_pywinctl_win.py +++ b/src/pywinctl/_pywinctl_win.py @@ -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