Open recluzegeek opened 5 months ago
Hi! Thanks A LOT for your feedback!!!
Sorry I've been extremely busy, so I had no time to finish and fully test next version of all involved modules (PyWinBox, PyMonCtl and PyWinCtl)... I hope to be able to test everything soon, so I can eventually upload all these new versions which fix tones of issues and improves some other features.
In your case, this is how that part of the code looks now:
# Thanks to odknt (https://github.com/odknt) for his HELP!!!
if isinstance(wa, list) and len(wa) >= 4:
wx, wy, wr, wb = wa[0], wa[1], wa[2], wa[3]
else:
wx, wy, wr, wb = x, y, w, h
Linux and all possible combinations is particularly complex (well, it's sort of a nightmare, to be hones), so testing everything takes a lot. I hope you can wait!!!!
In the meantime, do not hesitate to arise any comment, issue or suggestion you may have. Thanks again!!!
EDIT: Did you fix the other issue regarding DWM? Is awesome
an alternative you may consider? Just curious
Thanks for the quick reply. I'll look into your provided code snippet and come back to you once I test it. Shifting to awesome
from dwm
doesn't seem feasible at the moment because dwm
is deeply integrated into my daily workflow. I rely heavily on it, and my muscle memory is attuned to its shortcuts, minimizing my use of the mouse.
EDIT: I tested these lines of code in windows, linux mint and arch running dwm and all of them passed, except on arch empty list and dictionary were returned
import pywinctl
print(pywinctl.getAllTitles())
print(pywinctl.getAllAppsWindowsTitles())
# ------------------------
# RESULT ON ARCH
[]
{}
Process finished with exit code 0
HAHAHAHA! Sorry. SInce it says awesome
is a fork of dwm
I thought it would be more straightforward.
I guess you mean that you have tested Mint and Arch together with dwm
, right? If so, since PyWinCtl requires EMWH, it is likely not properly working. In case it is not dwm, please let me know which desktop/window managers you are using in those cases.
Thanks!
No worries, I too was confused in my early linux days. It happens and IMO its normal :) I've tested arch with dwm
and used Linux Mint 21.3 x86_64 with Cinnamon 6.0.4 as desktop environment.
Ah, ok! That's why Mint works, whilst Arch doesn't... Arch with other desktop/window managers works if those managers are EWMH-compliant. I already have actual installs of Ubuntu/GNOME (Wayland is not working since it's not EMWH-compliant, Linux Mint/Cinnamon and Manjaro/KDE; but not Arch yet, sorry.
Manjaro actually is derived from Arch, as Mint is derived of Ubuntu. If it works on Manjaro, then it also should be working in arch. Issue itself is not in the arch, rather in the desktop/windows manager. In this case, dwm doesn't seems to be EWMH-compliant.
I created this git issue for mint on this issue, AttributeError: module 'Xlib.ext.randr' has no attribute 'get_monitors'
, since Xlib should be performing well across linux distros. Surprisingly, this issue arose during my Mint testing and not on Arch :)
Arch with dwm
is my main development machine, yet I think I've to work in mint for sometime till new release.
Yes, that's correct. EMWH-compliance depends on the Desktop/Windows Manager, not the OS. E.g. in "standard" Ubuntu, GNOME is EWMH-compliant, but Wayland is not (furthermore, there is no way in Wayland to get the list of windows nor the active one... I mean, that feature is not supported at all, even using any other protocol to communicate with it)
I hope to be able to start all tests soon, which include Mint/Cinnamon amongst many other combinations. I will keep you posted on any progress. Hopefully I will have a complete new version ready to be uploaded so all these issues are fixed.
Please, bear in mind that non-EWMH window managers (like dwm) will still not work with the new version, since it will inevitably continue to rely on EWMH to handle windows.
Back to the initial issue, and just if you are curious, this is a snippet of the new version, which includes a workaround specifically for Cinnamon:
def _getMonitorsData(handle: Optional[int] = None) -> (
List[Tuple[Xlib.display.Display, Struct, XWindow, randr.GetScreenResourcesCurrent,
randr.MonitorInfo, str, int, randr.GetOutputInfo, int, randr.GetCrtcInfo]]):
monitors: List[Tuple[Xlib.display.Display, Struct, XWindow, randr.GetScreenResourcesCurrent,
randr.MonitorInfo, str, int, randr.GetOutputInfo, int, randr.GetCrtcInfo]] = []
stopSearching = False
for rootData in getRoots():
display, screen, root = rootData
try:
mons = randr.get_monitors(root).monitors
except:
# In Cinnamon randr extension has no get_monitors() method (?!?!?!?)
mons = _RgetAllMonitors()
stopSearching = True
for monitor in mons:
if isinstance(monitor.name, int):
monitor.name = display.get_atom_name(monitor.name)
res = randr.get_screen_resources_current(root)
output = monitor.crtcs[0]
outputInfo = randr.get_output_info(display, output, res.config_timestamp)
if outputInfo.crtc:
if handle:
if handle == output:
crtcInfo = randr.get_crtc_info(display, outputInfo.crtc, res.config_timestamp)
return [(display, screen, root, res, monitor, monitor.name, output, outputInfo, outputInfo.crtc, crtcInfo)]
else:
crtcInfo = randr.get_crtc_info(display, outputInfo.crtc, res.config_timestamp)
monitors.append((display, screen, root, res, monitor, monitor.name, output, outputInfo, outputInfo.crtc, crtcInfo))
if stopSearching:
break
return monitors
def _RgetAllMonitors():
# Check if this works in actual Cinnamon
monitors: List[_Monitor] = []
outputDict = {}
for outputData in _XgetAllOutputs():
display, screen, root, output, outputInfo = outputData
outputDict[outputInfo.name] = {"outputData": outputData}
namesData = _RgetMonitorsInfo()
for item in namesData:
monName, primary, x, y, w, h = item
if monName in outputDict.keys():
display, screen, root, output, outputInfo = outputDict[monName]["outputData"]
wm, hm = outputInfo.mm_width, outputInfo.mm_height
crtcs = [output]
monitors.append(_Monitor(monName, primary, x, y, w, h, wm, hm, crtcs))
return monitors
Hi there again. This time I'm not creating a new issue, 😄 just for clarification and enhancements. Does pywinctl
provides any interface or method to return the currently running app name along with its windows title.
Like the new_window = pywinctl.getActiveWindow()
returns the currently focused windows title,
Error with pymonctl.getAllMonitorsDict()
on Linux Mint and Arch Linux · Issue #86 · Kalmat/PyWinCtl — Mozilla Firefox
I want a method to return Mozilla Firefox or firefox.exe (container in which its running) or something like that. Maybe the method exists, I'm unaware of it.
Also the docs didn't provided any help either, there are just bunch of methods name, we should be documenting them properly, what they returns or what they do along with some code examples.
Hi again! I will try to clarify and summarize.
PYWINCTL: PyWinCtl returns the active window and the name of the app it belongs to, by using:
new_window = pywinctl.getActiveWindow()
if new_window is not None:
app_name = new_window.getAppName()
print(app_name)
else:
print("NOT FOUND")
But ONLY IF the desktop/window manager is EWMH-compliant (e.g. GNOME, Cinnamon, KDE, awesome, ...). PyWinCtl will not work with non-EWMH environments (e.g. DWM, Wayland, ...)
PYMONCTL
In short, you can use PyWinCtl to get the active app name, but not together with DWM. If you also need PyMonCtl, I can provide you with a wheel that fixes the Cinnamon issue so you can work with it whilst I finish all tests and upload the new version.
I hope this helps to clarify.
Thanks for the clarification. I'm now working on mint in virtual box and was asking a general question about getting app name. It was my bad for not understanding the method naming convention. Again thanks for the clarification. 😶🌫️
No worries at all! Happy to hear this has been helpful. Thank you so much for your feedback. As you suggested, I have improved the module documentation (again, it will be available in next version).
Just let me know if you need anything else, you find any other issue or you have any suggestion!
Currently, I'm playing with this wonderful cross-platform library to track my application usage across systems and encountered the errors on the way described below:
The following error occurs when running the
test_pywinctl.py
under test directory on Linux Mint with Python 3.10. Works fine in window 10 under virtualbox.Similar kind of issue appeared on the Arch Linux with Python 3.11.8. This time was the deprecation warning
DeprecationWarning: getAllScreens() is deprecated. Use getAllMonitorsDict() from PyMonCtl module instead monitors = pywinctl.getAllScreens()
Following the warning, refactored the code to use
pymonctl.getAllMonitorsDict()
and got this error,From what I've read in the pymonctl README.md, properties may be None if can't be read/obtained. Also the key thing to note is that it doesn't work on Linux Mint with XLib installed
I'm using dual monitor and managing them using ARandR — Screen Layout Editor for Linux.