PDA

View Full Version : [Solved] Need help with GDK/X/libwnck events ...


RYX
January 10th, 2007, 03:31 PM
Hi everybody! I am trying to create a tasklist for open windows in Python. What I try to do is catching MAP/UNMAP/FOCUS_CHANGE events for all open windows ... SInce the xlib-bindings for python are totally outdated, I am trying to whole thing using gtk.gdk. I would use libwnck but I couldn't find any way to handle events in libwnck.

I first tried to add a filter function to the root window and check its events, but I only get GtkEvent.NOTHING as type. I then tried using gtk.gdk.event_handler_set to hook into all events. Now I get ALL events (that's what I wanted), but I don't know how to pass the ones I don't need back to GDK to not make other apps totally unresponsive ... returning False/true/event apparently does not work ...

Any hints? Thanks in advance ...

:)

mikedee
January 10th, 2007, 04:28 PM
I dont think this really answers your question, but you sound like you are trying to build a list of open windows by watching for create/destroy notifications.

All of the current windows are held as a property of the root window. _NET_CLIENT_LIST is the property you need to read. I am trying to work out a dbus netwm interface so in future you will be able to read this via dbus rather than xlib.

RYX
January 10th, 2007, 04:43 PM
Thanks for your reply. :)

Retrieving the opened windows is possible using gtk.gdk, the real challenge seems to be getting the right events for ANY window to handle minimize, maximize, close and open of windows. A dbus-interface would offer a different, but apparently easier way of achieving what I want. But does dbus send messages about opening/closing windows?

I am just surprised that libwnck doesn't offer any kind of event-handling - I'd expected at least some notification about minimize/maximize and open/close ... (that's all I need).

mikedee
January 10th, 2007, 05:10 PM
Retrieving the opened windows is possible using gtk.gdk, the real challenge seems to be getting the right events for ANY window to handle minimize, maximize, close and open of windows. A dbus-interface would offer a different, but apparently easier way of achieving what I want. But does dbus send messages about opening/closing windows?

The main problem is that X does not really send signals that we understand (as teh humans). It does not send easy signals like window created, window minimized etc. It sends x signals like map/unmap. You have to piece them together, eg. create + map = new window. Just a map means that possibly the window was just unminimized/unshaded (you would have to use other information like the state to work out what happened).

David will be adding these events to compiz so it will be easy to get a dbus signal when a window is closed/minimized etc. I personally would wait for that as it will be much simpler (hopefully the work will be finished soon :))

RYX
January 10th, 2007, 05:38 PM
Generally, I understand those X-related stuff like display/screen/... and have no problem with digging through refs/specs. But for the python-xlib bindings (which are only available for python2.5 on Ubuntu Edgy) there is nothing but help(Xlib), help(Xlib.xobject), ...

So I don't know how to get events from the X-window system to handle them in Python. If I would know how to listen to events from X without creating my own Xevent-loop I would know what to do ... Do you know of any example code for that?

I am testing the possibilites for writing a window-decorator in python, so the X-bindings are most likely on my list (no matter if I want to or not :)).

(btw: Now I begin to understand what you mean with Python's "poor" documentation ... everything that's not part of pygtk/gnome or "official" python is very rarely documented)

:)

mikedee
January 10th, 2007, 06:11 PM
So I don't know how to get events from the X-window system to handle them in Python. If I would know how to listen to events from X without creating my own Xevent-loop I would know what to do ... Do you know of any example code for that?

AFAIK this would not be possible, you cannot listen for any signals without a loop (thats why you have gtk_main, it listens for mouse click events etc).

Look at my scripting plugin for how to do that easily. Hopefully everything you need will be in there already so you would only need to pull out the buts you want. Start with the official dbus plugin and then wrap the handleEvent function and send a signal for each one.

I am not sure how decorators actually work, but it could be possible to communicate all this information internally to the decorator plugin which could forward everything via the dbus plugin to your app. g/kwd use dbus to communicate to the decorator plugin now anyway, so what I am suggesting is not totally unheard of :)

Doing everything with the python xlib bindings should be possible, but it maybe harder (to code and distribute) than writing c code for it and forwarding it via dbus. Doing it in python would be an interesting use of technology and it would mean that we could do much more interesting things more quickly.

RYX
January 11th, 2007, 01:16 AM
After reading through the source of gtk-window-decorator and libwnck I found the solution. The signals I was looking for are emitted by the wnck.WnckScreen object. But in the devhelp-section for libwnck were no signals listed - otherwise I would have noticed earlier ... :)

And in the end it is very simple and similar to common gtk-event-handling:
#!/usr/bin/env python

# A little example for handling window events
# emitted by the WnckScreen-object. Can be
# used for things like pagers, taskbars, decorators, ...
#
# written by RYX (aka Rico Pfaus)

import gtk, wnck

# define event-handlers
def active_window_changed(screen):
print "Active window changed on screen: " + str(screen)
pass

def window_opened(screen, window):
print "Window opened: " + str(window)
pass

def window_closed(screen, window):
print "Window closed: " + str(window)
pass

# init screen and hook into WnckSceen's events
screen = wnck.screen_get_default()
screen.connect("active_window_changed", active_window_changed)
screen.connect("window_opened", window_opened)
screen.connect("window_closed", window_closed)

# only for demonstration
win = gtk.Window()
def destroy_event(widget, data=None):
gtk.main_quit()
win.connect("destroy", destroy_event)
win.show()

# start gtk's main-loop
gtk.main()

Start from a console and watch the output when opening/closing/switching windows ...

And here are all signals that are emitted by the WnckScreen, in case someone (like myself :)) needs them somewhen and is too lazy to look into the sourcecode:
active_window_changed (screen)
active_workspace_changed (screen)
window_stacking_changed (screen)
window_opened (screen, window)
window_closed (screen, window)
workspace_created (screen, workspace)
workspace_destroyed (screen, workspace)
application_opened (screen, application)
application_closed (screen, application)
class_group_opened(screen, class_group)
class_group_closed (screen, class_group)
background_changed (screen)
showing_desktop_changed (screen)
viewports_changed

Some more interesting signals - this time emitted by WnckApplication (especially useful when building a tasklist):
name_changed (application)()
icon_changed (application)

:)