Introduction
The OpenTk.NativeWindow
class provides the property WindowInfo
, which returns an IWindowInfo
interface.
On X11, there are more properties than those, defined by the IWindowInfo
interface. These properties are visible within the debugger and accessible via reflection.
int screen = 0;
PropertyInfo piScreen = nativeWindow.WindowInfo.GetType().GetProperty("Screen");
if (piScreen != null)
screen = (System.Int32)piScreen.GetValue(nativeWindow.WindowInfo, null);
On X11, the WindowInfo
property contains the client window ID within the WindowInfo.WindowHandle
property. To investigate the details of this relationship, and especially the window manager's shell window ID, the code shown below can be used.
Background
The libX11 provides the XQueryTree()
method, that can be used to traverse the windows tree. Assumed, the OpenTK window to investigate is an independent application window (not a child window), the search depth is just one (otherwise the code has to be adopted).
Using the Code
Under the circumstances mentioned above, the following code is ready to use:
public static bool TryFindX11WindowOnScreen(NativeWindow nativeWindow, out IntPtr x11window,
bool checkTitle)
{
x11window = IntPtr.Zero;
if (nativeWindow == null)
return false;
IntPtr display = X11lib.XOpenDisplay ("");
if (display != IntPtr.Zero)
{
int screen = 0;
PropertyInfo piScreen = nativeWindow.WindowInfo.GetType().GetProperty("Screen");
if (piScreen != null)
screen = (System.Int32)piScreen.GetValue(nativeWindow.WindowInfo, null);
IntPtr rootWindow = X11lib.XRootWindow (display, (X11lib.TInt)screen);
System.Collections.Generic.List<IntPtr> children = X11lib.XQueryTree(display, rootWindow);
for (int countChild = 0; countChild < children.Count; countChild++)
{
X11lib.XWindowAttributes attributes = new X11lib.XWindowAttributes();
if ((int)X11lib.XGetWindowAttributes(display, children[countChild], ref attributes) != 0)
{
if ((int)attributes.x == nativeWindow.Bounds.X &&
(int)attributes.y == nativeWindow.Bounds.Y &&
(int)attributes.width == nativeWindow.Bounds.Width &&
(int)attributes.height == nativeWindow.Bounds.Height)
{
x11window = children[countChild];
" Y=" + attributes.y +
" W=" + attributes.width +
" H=" + attributes.height);
break;
}
}
}
children.Clear();
if (x11window != IntPtr.Zero && checkTitle)
{
bool match = false;
if (x11window != IntPtr.Zero)
{
string childName = X11lib.XGetWMName(display, x11window);
if (nativeWindow.Title == childName)
{
match = true;
}
else
{
children = X11lib.XQueryTree(display, x11window);
for (int countChild = 0; countChild < children.Count; countChild++)
{
X11lib.XWindowAttributes attributes = new X11lib.XWindowAttributes();
if ((int)X11lib.XGetWindowAttributes(display, children[countChild],
ref attributes) != 0)
{
childName = X11lib.XGetWMName(display, children[countChild]);
if (nativeWindow.Title == childName)
{
match = true;
break;
}
}
}
}
}
if (match == false)
x11window = IntPtr.Zero;
}
X11lib.XCloseDisplay(display);
}
return (x11window != IntPtr.Zero);
}
The prototypes of the methods within the X11lib
helper class are provieded with the download above.
The investigation shows that the window manager's shell window has plenty of child windows, the requested OpenTK surface among them.
The image shows an exploded view of the shell window to demonstrate the child windows of the window manager's shell window.
Points of Interest
It is possible to investigate a OpenTK/OpenGL window's window manager's shell window to manipulate the shell window's property?
History
- 11th July, 2016: First version