0

I wrote the following code to detect when a window is created on the screen by another application (not by my code):

Display* display = XOpenDisplay(":0");
XSetWindowAttributes attributes;
attributes.event_mask = SubstructureNotifyMask | StructureNotifyMask;
Window win = XDefaultRootWindow(display);
XChangeWindowAttributes(display, win, CWEventMask, &attributes);

while (1) {
   XEvent event;
   XNextEvent(display, &event);
   if (event.type == CreateNotify)
      puts("create Notify event occured\n");
}

The code basically works, however, I noticed that, when I start an application (e.g. terminal) the CreateNotify event seems to be fired multiple times. Can anybody explain why? I would have expected that CreateNotify will only be fired once for every started application/window. How do I have to modify the code to achieve this?

cxw
  • 16,685
  • 2
  • 45
  • 81
Moonlit
  • 5,171
  • 14
  • 57
  • 95

1 Answers1

0

The events are for child windows. Per the Xlib Programming Manual, "Creating any children ... generates an event." A typical X application includes numerous child windows, and you're seeing each of them.

When you get the event, check event.xcreatewindow.parent (XEvent is a union per the reference). If that is win, the root window, you have a top-level window. Otherwise, you have a child window. Try:

if ( (event.type == CreateNotify) && (event.xcreatewindow.parent == win) )
    puts("top-level create Notify event occured\n");
cxw
  • 16,685
  • 2
  • 45
  • 81
  • thank you for your suggestion. tried it but it seems that `event` has no member called `parent`: `‘XEvent {aka union _XEvent}’ has no member named ‘parent’` – Moonlit Oct 26 '16 at 19:20
  • ah ok, thank you i's now compilable, but unfortunately the behavior is the same. – Moonlit Oct 26 '16 at 19:39
  • @Moonlit maybe the other windows are the chrome added by the window manager, then. Use [XFetchName](https://tronche.com/gui/x/xlib/ICC/client-to-window-manager/XFetchName.html) (see [this question](http://stackoverflow.com/q/27910906/2877364)) to look at the window names and see if that gives you any ideas. Since every application will have a different configuration of windows, this might be a tricky one. – cxw Oct 26 '16 at 19:51
  • alright, I'll investigate this and post my solution as soon I've got it working. In the end I just want to get notified when an application gets started/displayed, and then put it to a specified location on the screen with a specified size. Do you think I am on the right track with this approach above, or do you think there might be an easier solution? – Moonlit Oct 26 '16 at 20:18
  • @Moonlit [this](https://www.freedesktop.org/wiki/Specifications/startup-notification-spec/)? Logging off for the day. Good luck! – cxw Oct 26 '16 at 20:24
  • 1
    Top-level windows are created right and left by as much as moving your mouse (e.g. tooltips are top-level windows). You are on a wrong track. It looks like you are trying to replicate or amend window manager functionality. It is not going to work. You need to write a window manager, or interface with your existing window manager (via dbus or whatever). – n. m. could be an AI Oct 28 '16 at 11:05