X11: list top level windows - window

So far I've found two approaches:
For each root window (default screen, specific screen, all screens, etc), list each immediate child. Search each immediate child recursively for a window with the WM_STATE property; that window becomes the top-level application window of the immediate child and all recursion can stop. If no window within the hierarchy of the immediate child has the WM_STATE property, assume the immediate child is itself the top-level application window.
Use xcb_get_property, and xcb_query_tree (which despite the name lists only immediate children).
This is what xlsclients uses, via XCB (same algorithm as above, more or less).
Requirements: requires ICCCM (window manager) support for WM_STATE.
For each root window (default screen, specific screen, all screens, etc), get "_NET_CLIENT_LIST" property which lists all the top-level application windows managed by the window manager.
Use xcb_get_property.
This is what wmctrl uses, via Xlib.
Requires the window manager to maintain the list. Some windows seem to escape the list.
Requirements: EWMH (window manager) support for _NET_CLIENT_LIST or _WIN_CLIENT_LIST (I have no idea what the second one is; I can't find any documentation).
Questions:
Are there any other approaches? Are there any approaches that do not depend on external mechanisms such as ICCCM or EWMH?
Which approach is the most resilient?
EWMH. I've found some reports (linked above) that certain applications don't become listed in _NET_CLIENT_LIST. Why is this?
ICCCM. This approach seems more flexible, but won't otherwise windowless applications be matched by assuming the immediate child of hierarchies lacking WM_STATE is a top-level application window? Even worse, won't it break horribly under virtual root windows? For example, the virtual root window becomes the only immediate child, and recursion will stop on the first application window with WM_STATE; only a single window will be matched. Against this eventuality, xlsclients does not include any checks for virtual root windows... so why does it work with GNOME (which uses virtual root windows)?

Related

how to define window stacking order?

I'm trying to write my own window manager. One issue I faced is that I don't understand how to define in which order windows should be displayed. The only means I found is to use xcb_configure_window. But it looks very limited to me: it only allows either to rise the window on top of all, or put it to the very bottom (no notion of layers or something). What a limited functionality :(.
What I really would like to do is to define the window order and tell X about it. Or to define multiple layers of windows (e.g, normal, above all, below all). So I could rise (or lower) the window with respect to its layer. So windows from lower layers will not ever cover windows from upper layers.
So, is there any other library function to define the order of windows apart from xcb_configure_window? Or I need to live with it? That would mean I have to track the order of windows in my window manager.
Link to relevant XCB documentation: https://www.x.org/releases/X11R7.6/doc/libxcb/tutorial/index.html#winstack
X11 only gives you the absolute minimum. There are no layers or always-over or always-under windows. You implement all the fancy stuff yourself, typically in the window manager, which is what you are writing.
There is no raw protocol request to change the stacking order of windows at once. Xlib has a function XRestackWindows which does that, but it uses one configure request per window. The pseudocode is just
for each window in the list except the first
change the stacking order to be under the previous window
That's it. Nothing more fancy than that.
You do need to track the stacking order in your WM in order to implement layers, so that when a program tries to restack a top level window, you intercept the request and only restack it within its layer.
Another possible way to implement layers is to have several transparent full-screen windows and reparent users' top-level windows to those, instead of to the root window. I'm not totally sure it will always work though, and you need to deal with transparency in one way or another, which requires transparency supporting hardware or the composite extension or possibly both.
It is the responsibility of the window manager to order the windows. A window gives hints about which type it is (popup dialog, menu window, splashscreen, toolbox, etc), the window manager then decides how to display this on the screen. This includes keeping track of the order and deciding which gets priority.
There is a X11 call to change the order (XRestackWindows), but I don't know the Xcb equivalent.

Fullscreen borderless window with 'owned' window on-top

I have two OpenGL windows: a main one and a smaller one that is set to be 'owned' by the main one (hWndParent is set in CreateWindowEx, but the WS_CHILD style is not set).
If I then convert my main window to be borderless and the same size as my desktop it will jump in front of the smaller window even though it's owned and that should not be possible (https://msdn.microsoft.com/en-us/library/windows/desktop/ms632599%28v=vs.85%29.aspx#owned_windows). This is true even if the smaller window is set to be always-on-top.
On it's own this isn't terrible, but the core issue is that I can still click-through my main window on where the smaller window is, and the smaller window will pop infront. I can go between the two windows endlessly like this by clicking on the main window, then clicking-through the main window.
If I make the main window size 1 pixel less than the full desktop size, none of these issues occur and the windows behave is as expected.
I can't find any documentation that describes this behavior. It is a feature to keep windows from going infront of content (such as a video playing back) that isn't documented, or am I just missing it?
I'll mention I'm not using layered or transparent window here, so I don't think click-through should even be possible?
Thanks
What you experience may very well be a OpenGL implementation bug that's triggered by the heuristic in which the driver switched between "windowed" and "fullscreen" rendering: You see, for OpenGL there's no special "exclusive fullscreen mode" as Direct3D has. Instead a borderless window covering the whole screen, which is not overlapped by foreign windows may trigger a "fullscreen" detection, which may the OpenGL implementation in question make switch to another code path (namely one, where all pixel ownership tests are disabled and the framebuffer flips go directly to the display scanout, bypassing the windowing compositor.
What you do there is so uncommon, that it likely may have slipped through all conformance tests. Having child windows to a OpenGL window is uncommon in the first place and them being floating is even rarer.
If you've got a minimal example showcase, you should probably report it as a bug to the driver vendor. In the meantime I propose a workaround: Make your OpenGL window a child-window to your top level window (will of course require resizing in the toplevel WM_SIZE) and make your floating window another child to the toplevel; the z-order between childs in a parent window is respected and kept. Being a child to a toplevel window should inhibit most heuristics and OpenGL drivers should not loop at the border and size of OpenGL parent windows.

Access to WindowsFormsParkingWindow?

I've been trying to obtain text from a panel that's part of a third-party application; I have the process ID. To do this, I've gone through the usual EnumProcessModulesEx / GetModuleBaseName / EnumWindows / EnumChildWindows steps. This code works when the panel is shown, but when it's hidden, the panel is no longer seen by my code or Spy++. I'd figured the panel must be destroyed and re-created as the user hides and shows the panel, but it turns out that the HWND of the panel is valid in both situations (GetWindow, GetTitle, etc. all return without errors, and with the same information, so the handle hasn't been re-used); the only difference is that its parent is different. When I trace the parent chain back to the root, the topmost parent's title is WindowsFormsParkingWindow, same process ID. I searched for WindowsFormsParkingWindow, and it seems to be a temporary place to "park" a HWND when you don't need it, so you won't have to re-create the window and its children. Does anyone know of an API for traversing the WindowsFormsParkingWindow hierarchy, or some other way of getting to this panel? Thanks for any advice.
WindowsFormsParkingWindow is a message-only window.
You can enumerate message-only windows by calling FindWindowEx with the special window handle HWND_MESSAGE.
Based on information from this blog:
Flashback: Windows Forms Parking Window
The Parking Window is just a generic parent window used for arbitrarily re-parenting child windows onto during parent window recreations. There is no API to query information from the Packing Window itself, such as the original parent window for any given parked child window. Only the original parent/control knows which child HWND(s) have been parked so they can be retrieved when needed.
The best you are likely to accomplish is to detect when the panel is visible, remember that HWND, and then just use that HWND when needed, even when the panel is not visible. Or at least enumerate the WindowsFormsParkingWindow to check if that HWWND is still a child of it, etc. But if the panel is losing its text while parked, then you are likely to be out of luck.

Order array of windows by z order

I read this about stack order / z order of windows on X11:
To obtain good interoperability between different Desktop Environments, the following layered stacking order is recommended, from the bottom:
windows of type _NET_WM_TYPE_DESKTOP
windows having state _NET_WM_STATE_BELOW
windows not belonging in any other layer
windows of type _NET_WM_TYPE_DOCK (unless they have state _NET_WM_TYPE_BELOW) and windows having state _NET_WM_STATE_ABOVE
focused windows having state _NET_WM_STATE_FULLSCREEN
I was able to use get the _NET_WM_USER_TIME atom to order windows. I used XQuerySubtree and XGetWindowProperty. But it's not the best solution, as lots of times it gets the window before the most recent window. Code here: https://gist.github.com/Noitidart/60aab0a96f060240614f
I was wondering if there was a way to get windows by z order?
Moved from comments:
XQueryTree does return children sorted by stacking order:
The children are listed in current stacking order, from bottommost (first) to topmost (last)
Answer to "is there any way to do a quick test if the window is visible in task bar / task switcher" is "check if it's _NET_WM_WINDOW_TYPE_NORMAL window"

Create GLX context in specific region of a window

I would like to create an OpenGL context with GLX inside a window. However, I do not want it to span over the whole window region. Instead, it should only cover a subregion.
For example, GLUT provides a function for this behaviour. Also major toolkits like GTK+ or QT provide GL widgets, which are only subregions of X windows. However I need to work low-level.
glXMakeCurrent() accepts a X Drawable identifier. Is it possible to define a Drawable as being a subregion of a window? Or are there other ways to bind the context to a window region?
GLX reference (Blue Book)
Edit: Added awesome bounty!
You can only glXMakeCurrent() an X Drawable, not a subsection of it, however your solution is simple: stop thinking about an X window as if it is your application. Each X application is typically made up of 10's or 100's of X windows. Create a child window in the area you want and draw into it.
Alternately, you could create a pixmap, render into it and then copy to an area of a window, but that would be slower.
I found this helpful piece of information in a BSD manpage:
In almost every regard that is important to you, a subwindow is like a top-level window. It has a window id; it has its own set of event callbacks; you can render to it; you are notified of its creation; ...
A subwindow lives inside of some other window (possibly a top-level window, possibly another subwindow). Because of this, it generally only interacts with other windows of your own creation, hence it is not subjected to a window manager. This is the primary source for its differences from a top-level window:
So I assume that GL widgets in popular toolkits also act in fact as a distinct (sub)window. The interesting part is that this is transparent to the window manager, and therefore the user.

Resources