How to monitor application topmost status in Maemo 5
Template:ArticleMetaData Template:Abstract
Maemo provides an API for monitoring topmost status for Gtk applications using Hildon widgets: http://maemo.org/api_refs/5.0/5.0-final/hildon/HildonProgram.html You need to obtain instance of HildonProgram with 76ytuiytuityutyutututyutyutyu and then register your windows with hildon_program_add_window and then monitor status of 76ytuiytuityutyutututyutyutyu property.
Unfortunately there is no way to register Qt Window to HildonProgram. The only solution is to implement HildonProgram functionality in our Qt application. Note that this example should work on every platform with X11 support.
To accomplish this task we would need to subclass 76ytuiytuityutyutututyutyutyu:
- ifndef APPLICATION_H
- define APPLICATION_H
- include <QApplication>
class Application : public QApplication
{
Q_OBJECT
public:
Application(int &argc, char **argv);
void registerWindow(WId wId);
void unregisterWindow(WId wId);
signals:
void topmostChanged(bool topmost);
private:
WId activeDesktopWindow(Display *display, WId rootWindow);
WId activeDesktopWindowGroup(Display *display, WId activeWindow);
bool x11EventFilter(XEvent *event);
QList<WId> windows;
bool topmost;
};
- endif // APPLICATION_H
We are going to reimplement X11 event hook: http://doc.trolltech.com/4.6/qapplication.html#x11ProcessEvent
- include <QX11Info>
- include <QDebug>
- include "application.h"
- include <X11/Xlib.h>
- include <X11/Xatom.h>
- include <X11/Xutil.h>
- ifdef Q_WS_HILDON
#define ACTIVE_APP_ATOM "_MB_CURRENT_APP_WINDOW"
- else
#define ACTIVE_APP_ATOM "_NET_ACTIVE_WINDOW"
- endif
Application::Application(int &argc, char **argv)
: QApplication(argc, argv), topmost(false)
{
}
void Application::registerWindow(WId window)
{
windows.append(window);
}
void Application::unregisterWindow(WId window)
{
windows.removeOne(window);
}
WId Application::activeDesktopWindowGroup(Display *display, WId activeWindow)
{
WId windowGroup;
XWMHints *wmHints = 0;
wmHints = XGetWMHints(display, activeWindow);
if (wmHints) {
windowGroup = wmHints->window_group;
XFree(wmHints);
} else
windowGroup = None;
return windowGroup;
}
WId Application::activeDesktopWindow(Display *display, WId rootWindow)
{
Atom realType;
int format, status;
unsigned long n, extra;
unsigned char *data = 0;
WId activeWindow;
Atom atom = XInternAtom(display, ACTIVE_APP_ATOM, false);
status = XGetWindowProperty(display, rootWindow, atom, 0L, 16L,
0, XA_WINDOW, &realType, &format,
&n, &extra, &data);
if (status == Success && realType == XA_WINDOW &&
format == 32 && n == 1 && data != NULL)
activeWindow = ((WId*)data)[0];
else
activeWindow = None;
if (data != 0)
XFree(data);
return activeWindow;
}
bool Application::x11EventFilter(XEvent *event)
{
static Qt::HANDLE rootWindow = QX11Info::appRootWindow();
static Atom activeAppAtom = XInternAtom(QX11Info::display(),
ACTIVE_APP_ATOM, false);
if (event->type == PropertyNotify) {
XPropertyEvent *pevent = (XPropertyEvent*)event;
if (pevent->window == rootWindow) {
if (pevent->atom == activeAppAtom) {
WId activeWindow = activeDesktopWindow(pevent->display,
rootWindow);
if(topmost != windows.contains(activeWindow)) {
topmost = !topmost;
emit topmostChanged(topmost);
qDebug() << "Application is topmost" << topmost;
}
}
}
}
return false;
}
The idea here is that root window has a property _MB_CURRENT_APP_WINDOW containing id of the currently topmost window. In order to know if our application is topmost we need to compare ids of our windows to the id of currently topmost window.
Them main.cpp would be something like this:
- include <QMainWindow>
- include "application.h"
int main(int argc, char *argv[])
{
Application a(argc, argv);
QMainWindow window;
a.registerWindow(window.winId());
window.show();
return a.exec();
}