How would I get a handle to the active gtk.Window in python? (not a window I created, but the currently focused window).
The answer is actually not OS-specific -- you can do it within GTK. You can get a list of all the toplevel windows from the application using gtk.window_list_toplevels(), then iterate through it until you find one where window.is_active() returns True.
If you want to consider other windows than the ones from your application, then you could try gtk.gdk.screen_get_default().get_toplevel_windows() but this will only get you GDK windows and not GTK windows, because you have no way of knowing whether those GDK windows are actually associated with GTK windows.
[Note: This answers the question as the OP originally phrased it, which other readers will probably be searching for - not the very different question that they changed it to in comments on the other answer.]
If you have a GtkApplication and have added your GtkWindows to it - which you should probably do, because GtkApplication can do lots of really cool stuff! - then you can use GtkApplication's much simpler API dedicated to this purpose:
Gtk.Application.get_active_window():
Gets the “active” window for the application.
The active window is the one that was most recently focused (within the application). This window may not have the focus at the moment if another application has it — this is just the most recently-focused window within this application.
Related
I'm trying, ultimately, to create "oddly-shaped windows" with Python using the Tkinter module. But for now I will settle for being able to make the background transparent while keeping child widgets fully-visible.
I'm aware this is done with wxPython and some other modules, but I'm inquiring as to the limits of Tkinter.
Can Tkinter create a clear Canvas or Frame? Can it pack UI elements without a canvas or frame? Can individual UI elements be transparent?
Can it pass mouse-click locations back to the system for processing any windows below it in the Z stack?
The option root.attributes('-alpha', 0.1) can be used to make a transparent window
from Tkinter import *
root = Tk()
root.attributes('-alpha', 0.3)
root.mainloop()
However in this case even the widgets on the root will inherit the transparency.
Update for Linux (Tested on Ubuntu)
The above code does not work on Linux machines. Here's an update that works on Linux.
from tkinter import Tk # or(from Tkinter import Tk) on Python 2.x
root = Tk()
root.wait_visibility(root)
root.wm_attributes('-alpha',0.3)
root.mainloop()
Not sure if this works on Windows.
Summary as of late 2019:
As of TCL/TK version 8.6, the alpha, fullscreen and topmost window attributes work on ALL platforms (Windows, Mac and Linux):
https://www.tcl.tk/man/tcl8.6/TkCmd/wm.htm#M9
Previous versions of the manual noted that there PREVIOUSLY WERE platform differences (only some platforms supported those 3 attributes). But as long as you use the latest TCL/TK, you're guaranteed that all of those attributes will work on ALL platforms!
There are still platform quirks on LINUX, since each window attribute feature relies on the operating system's underlying window manager (on Mac and Windows they're always capable, but on Linux there are tons of different window managers/compositors, and NOT all support transparent windows, etc). It says that in case transparency is not supported, the alpha property will stay at 1.0 if you try to read it again later. However the page also notes that on Linux (X11), the attributes are updated asynchronously which means that you can't trust the value you read (if you change alpha and then immediately try to read it, you'll still read the old value, so you can't use that method to check if alpha was successfully changed on Linux).
As for the other answers saying that you first need to use root.wait_visibility(root) on Linux to make sure the window is visible on screen before setting the alpha attribute... I don't know, since I don't have a Linux machine to check. But I heavily doubt that it's needed anymore, since the official manual says that alpha is supported and says nothing about that command being necessary. Either way, it doesn't hurt to add the wait_visibility trick too... It is simply a command that runs a very brief event loop that waits until the actual window has appeared on the user's screen. So it's probably still a good idea to add that command before all of your attribute-setting. Especially since it's proven to help the alpha work on Linux on old TCL/TK versions! PS: You don't need the (root) argument, and should type root.wait_visibility() instead, which means "wait for self (root in this case since we called the command on the root object)".
Update:
Daniel in the comments below has let me know that root.wait_visibility() is still necessary on Ubuntu 19.10. Although he didn't specify his Python, TCL/TK or TkInter versions so maybe they're outdated on his system. Either way, sounds like it's a safer bet to always include that command for backwards compatibility!
I am thinking of writing a python program that runs in the background and can inspect user's GUI events.
My requirements is very simple:
1) When user right click the mouse, it can show an option; and when this option is chosen, my program should know this event.
2) When user select a file and click some predefined key combination, my program should know this event.
What should I do? Is this a GUI program? I am also thinking that, this program maybe a daemon on the machine and can inspect the user's GUI event, but I am not sure how can I do this.
Thanks.
If you're talking about doing this stuff inside of a wxPython program, then it's all pretty simple. There's a PopupMenu widget for the first one and an AcceratorTable for the second one. If you're wanting to catch mouse and keyboard events outside of a wxPython program, then you have to go very low-level and hook into the OS itself, which means that there really isn't any good way to do it cross-platform. You'll probably want to look at ctypes and similar libraries for that sort of thing.
I've been researching this problem a bit and while I don't have a definite answer, I thought it would be good to share what I found.
First, according to the answers for this question, wxPython cannot track nor control the mouse position outside of the area controlled by the wxPython app. However, as we can see in the answers to this question, under certain circumstances it may be possible to create system-wide hot keys that wxPython can see (although we can also see that this is probably not the optimal solution).
So what will work for the OP? Well, build a cross platform application that does what the OP wants seems almost impossible so I will assume the OP is developing for MS Windows. Following the suggestions in those previous two questions, I looked into the PyWin32 API. It's a little hard to find documentation for it but this question offers some helpful links. A little more digging and I found this tutorial for system-wide hotkeys as well as the win32event.WaitForMultipleObjects and win32event.WaitForSingleObject methods which, if the OP can figure out the proper event, may be what the OP needs to catch menu clicks.
I know it's far from a complete answer but hopefully this can serve as a good jumping-off point for further research.
I'm a bit confused with some gtk and gnome concepts. I'm trying to get list of non minimized windows on my gnome2 desktop, but after reading the pygtk documentation and inspecting the results, I can't understand the results.
Neither of the two snippets below appears to work.
First I tried this..
>>> gtk.gdk.window_get_toplevels()
[<gtk.gdk.Window object at 0xb74339b4 (GdkWindow at 0x8a4c170)>]
>>> gtk.gdk.window_get_toplevels()[0].get_children()
[]
then this
>>> d = gtk.gdk.DisplayManager()
>>> d.get_default_display().get_screen(0).get_root_window().get_children()
[<gtk.gdk.Window object at 0x89dcc84 (GdkWindow at 0x8a4c170)>, <gtk.gdk.Window object at 0x89dccac (GdkWindow at 0x8a4c0c0)>]
As seen in the console output, the second option returns two windows. But I haven't been able to figure out what they are. None of them has any children and I allways get those two windows regardless how many windows I have on my desktop.
Could anybody explain the hierarchy of objects of the typical gtk based desktop environment?
I can't understand why the above code doesn't work.
Please refrain from posting alternative solutions that resource to wnck, xlib, qt, etc. I'm more interested in understanding what I am doing wrong than in getting advice such us checking other libraries.
Your constraint is like saying "I want to build a CD player using only a banana. Please refrain from posting alternative solutions that resort to lasers." GTK can't do that, you're using the wrong tool for the job.
Here's an explanation of what a "window" actually means and why your code doesn't work:
First off, you need to understand the difference between a gtk.Window and a gtk.gdk.Window. A GTK window is a top level GTK widget that can contain other widgets. It is usually linked to a window on your desktop, but doesn't have to be - in GTK 3 there is an OffscreenWindow.
A GDK window, on the other hand, is platform-dependent. On an X desktop it is a thin wrapper around an X window, which is not necessarily a toplevel desktop window. On other systems it exists to abstract away the windowing system. A GDK window receives events, so some GTK non-window widgets have their own GDK windows. "Window" is really a terrible name for these objects, but it was inherited from X and it's probably not going to change.
Each GTK process only knows about its own windows. You can get a list of the toplevel GTK windows of your own application using gtk.window_list_toplevels(). Getting the children of these windows should return you the GTK widgets that they contain. However, you can't descend into the widget hierarchy of other processes' windows. For example, what if another process has a window with a child widget that is a custom widget that your process doesn't know about? What should it report as the type of that widget?
Getting a list of the toplevel GDK windows with gtk.gdk.window_get_toplevels() is basically the same as getting a list of the toplevel X windows, as far as I understand it. You have no way of knowing what kind of windows they are - they might be the Gnome Panel, or they might be Qt windows, or they might be something else altogether that doesn't correspond with a desktop window.
Libwnck (link to the overview of what it does) can get you a list of non-minimized windows, and their titles, but it won't allow you to see inside them. There's no way to do that. Libwnck uses GDK internally, so technically you could do it using GDK, but why would you bother if there's already a library that does that for you? If you really want to do it yourself, look at the libwnck source code.
The windows you get are the windows that were created within your process. To get the list of windows, you need to query the properties of the root window, like this:
import gtk.gdk
root = gtk.gdk.get_default_root_window()
for id in root.property_get('_NET_CLIENT_LIST')[2]:
w = gtk.gdk.window_foreign_new(id)
if w:
print(w.property_get('WM_NAME')[2])
Please note that GDK is a thin layer over underlying OS graphics engine (X11/Quartz/Aqua/GDI etc) and result may differ on different NIX devices.
I am planning to do the folliwing:
Create a PyGtk GUI (hardcoded, no Glade) with some widgets, and at the bottom of the screen put some sort of VTE (Virtual Terminal Emulator) from where I could manipulate the widgets, for example changing their attributes and calling their methods from the commandline.
The result would be similar to using AutoCAD's commands, only that I would be acting upon the GUI objects.
I have already found very few things about gtk.VteTerminal widget, but not only could not find a working example or make one myself, it also seem to be a system terminal, not a "current session" python terminal where I could run python commands and access GUI objects.
Any suggestion?
Thanks for reading
What you want exists already: GtkParasite. It's meant for debugging, but I'm sure if you wanted it to actually be a part of your application, you could adapt it.
I'm late to the party, but I had a similar problem.
Look here
Virtual Terminal Question
It's an option if you decide to do something different than what you might have already done.
I've got a Python/GTK project I've been working on for a while, and some of the functionality I want already exists in Gnome panel applets. Based on my reading, panel applets are already in a subclass of the standard GTK Bin, so I would think there'd be a way that I can use the C-based GTK objects in my Python-based application.
For instance, I've got the fish applet in /usr/lib/gnome-panel/fish-applet-2 as a binary
Can I do some GTK magic to get that object so it can be embedded into my Python/GTK gui?
I'm not expecting a step-by-step walkthrough, but if anyone can point me in the right direction, I'd appreciate it.
The code for applets in gnome panel is quite complex. It's based on the gnome Bonobo framework (which in turn is based on CORBA). But now the whole thing is in a bit of a flux because gnome is moving away from Bonobo to a new dbus-based design. So if it's loading existing gnome panel applets you want you should absolutely use the code from gnome panel to do it. There is (or at least was) an example program included that does nothing but load an applet into a window.
If you want to display a widget from one of your own programs (a custom applet) inside another of your programs it's much easier. There are a set of widgets called GtkSocket and GtkPlug for this purpose. Of course the to programs doesn't need to run on the same machine. But there is always the delicate problem of getting them together in the first place.