How can I create an X window/client that is on top of all other windows, not under WM control and has no input? (overlay, OSD) - linux

I want to write applications (or use existing ones, that would be even more convenient) that behave like a hardware screens OSD (on screen display), only without input.
That is: A graphical output (e.g. from a GUI toolkit like Qt or Gtk) is placed on a layer where it is above even fullscreen-windows like Firefox F11 mode or a video player in fullscreen mode. That includes "above" the mouse cursor as well, so technically and graphically the mouse cursor would move below this widget.
I don't know about real fullscreen applications with SDL or OpenGL though, but this is not the requirement. If you know this as well please include it in your answer.
Real world applications are read-only overlays like a little webcam window, a TV-station like logo or premade annotations. So all in all this is meant for live presentations, streaming and recording of screencasts and tutorials with minimal post processing.
My own hacked, unsuccesful, experiments showed at least that removing this window from the WM control ( I did this by choosing a GTK popup dialog instead of a real main window) lets you position in absolute coordinates and it will ignore things like virtual desktops and workspaces, which is good, so you can switch between those and the overlay/HUD will stay in place.
Of course this cannot be done in software with the same Z-value (top/bottom windows) as the hardware screen. So technically I am talking above all other windows but below the screensaver or lock-screen layer.
+1 internet for linking to docs and giving the right keywords.
+2 internet for a working code example, language, gui-toolkit etc. doesn't matter.

You probably need composite overlay window from Composite extension - see section 3.2 "Composite Overlay Window" extension docs. (cursor is above this window)
Version 0.3 of the protocol adds the Composite Overlay Window, which
provides compositing managers with a surface on which to draw without
interference. This window is always above normal windows and is always
below the screen saver window. It is an InputOutput window whose width
and height are the screen dimensions. Its visual is the root visual
and its border width is zero. Attempts to redirect it using the
composite extension are ignored. This window does not appear in the
reply of the QueryTree request. It is also an override redirect
window. These last two features make it invisible to window managers
and other X11 clients. The only way to access the XID of this window
is via the CompositeGetOverlayWindow request. Initially, the Composite
Overlay Window is unmapped.
Example using node-x11:
var x11 = require('x11');
x11.createClient(function(err, display) {
var X = display.client;
var root = display.screen[0].root;
X.require('composite', function(err, Composite) {
Composite.GetOverlayWindow(root, function(err, overlay) {
// already automatically mapped here:
//
// CompositeGetOverlayWindow returns the XID of the Composite Overlay
// Window. If the window has not yet been mapped, it is mapped by this
// request. When all clients who have called this request have terminated
// their X11 connections the window is unmapped.
});
});
});

Related

Window manager for linux, supporting focusless windows

On my arm embedded device with a touchscreen, I have a 3rd party program (program A), that creates a window which handle keyboard presses. Because of that, this window always has to have focus. This is a closed source, and I do not have options to modify it.
I need to create a window in linux, that never grabs focus. It just shows an image, some times full screen. However, I have options not to make it full screen (1 pixel less, so window below is visible.).
Right now, I am using only X server, but I can install (almost) any window manager.
Is there a way to create a window in X, that never gets focus? If I understand X correctly, a window bellow mouse will get focus.
Is there a window manager, which supports such feature?
Is this possible to do with with xcb or wayland?
On Wayland, it's up to the compositor to tell the client whether it has focus or not, and which surface(s) to send key events to. So it would depend on the compositor or compositor toolkit you're using if it's possible.
KWin has an option that sounds like it does what you want. Right click the window title bar and choose more actions -> special window settings -> accept focus
Of the compositor toolkits, I only know the Qt Wayland Compositor API, and with that it should be possible (assuming your application can run as a Wayland client). The easiest thing would be to just show the image in the compositor using the QML APIs, or you could set enabled: false on the WaylandQuickItem or ShellSurfaceItem that you don't want to grab input focus.

How to make an overlay which capture no events

I would like to draw some sort of window on top of all the other windows. For example, to display some debugging infos (like conky) or things like a timer.
The main thing is that I would like to able to continue using the other windows while using it (the events go through transparently).
I've tried doing it with pygtk, pyqt and others but can't find a way to make it a real overlay with no event capture.
Is there some low-level x11 solution?
I think the Composite-extension-approach will not work when a compositing manager is running (and thus Composite's overlay window is already used).
Since you explicitly mention "no event capture":
The SHAPE extension allows to set some different shapes for a window. Version 1.1 of this extension added the "input" shape. Just setting this to an empty region should pretty much do what you want.
Some concrete example of exactly what I think you ask for can be found in Conky's source code: http://sources.debian.net/src/conky/1.10.3-1/src/x11.cc/?hl=769#L764-L781
Edit: Since you said that you didn't find anything in Gtk (well, PyGtk), here is the function that you need in Gtk: https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-input-shape-combine-region
You might need Composite extension + GetOverlayWindow request:
Version 0.3 of the protocol adds the Composite Overlay Window, which
provides compositing managers with a surface on which to draw without
interference. This window is always above normal windows and is always
below the screen saver window. It is an InputOutput window whose width
and height are the screen dimensions. Its visual is the root visual
and its border width is zero. Attempts to redirect it using the
composite extension are ignored. This window does not appear in the
reply of the QueryTree request. It is also an override redirect
window. These last two features make it invisible to window managers
and other X11 clients. The only way to access the XID of this window
is via the CompositeGetOverlayWindow request. Initially, the Composite
Overlay Window is unmapped.
CompositeGetOverlayWindow returns the XID of the Composite Overlay
Window. If the window has not yet been mapped, it is mapped by this
request. When all clients who have called this request have terminated
their X11 connections the window is unmapped.
Composite managers may render directly to the Composite Overlay
Window, or they may reparent other windows to be children of this
window and render to these. Multiple clients may render to the
Composite Overlay Window, create child windows of it, reshape it, and
redefine its input region, but the specific arbitration rules followed
by these clients is not defined by this specification; these policies
should be defined by the clients themselves.
C api : XCompositeGetOverlayWindow
PyGTK Solution:
I think the composite and shapes X extensions are sufficiently ubiquitous and shall assume here that they are active on your system. Here's PyGtk code for this:
# avoid title bar and standard window minimize, maximize, close buttons
win.set_decorated(False)
# make the window stick above all others (super button will still override it in the z-order, which is fine)
win.set_keep_above(True)
# make events pass through
region = cairo.Region(cairo.RectangleInt(0, 0, 0, 0))
my_window.input_shape_combine_region(region)
win.show_all()
# set the entire window to be semi-transparent, if we like
win.set_opacity(0.2)
Basically what this does is tell Gtk that other than pixel (0,0) the entire window my_window should not be considered part of itself in terms of event propagation. That in turn, according to my current understanding means that when the pointer moves and clicks, the events go to the underlying window under the pointer position, as if my_window was not there.
Caveat:
This does allow your overlay window being the focus window (due to user-solicited window switching or just because it pops up and gets the focus when your application starts). Which means that for example, keyboard events will still undesirably go to it up until the user has clicked through it to make it lose focus in favor of whatever window is under the cursor. I would likely use the approach described here to iron out this aspect.
If there's a different and proper approach for making a portion of the screen "display stuff but not receive events", without building an oddball window like above over it, I'm happy to learn about it.
I assume that one's particular desktop environment (gnome, unity, etc. on linux) may interfere with this solution depending on version and configuration, on some occasions.

How to grab the pointer on Wayland like Gnome does?

It specifically says in the Wayland TODO text file that Wayland doesn't have active grabs for the pointer yet. But if I run Gnome on Wayland, try clicking a menu open and then clicking outside it, the outside click is swallowed as if the pointer was grabbed by the menu window. How does Gnome manage that?
What you are talking about can be done very easily by creating a transparent overlay over the entire screen. In that case, the click events on the transparent region will not propagate to the underlying elements. You can see this in Telegram's image viewer, where it creates a full-screen gray overlay under the image.
But on the compositor side this effect can be achieved in a different way-- by disabling all input events outside the popup rectangle.

How do I write directly to the screen?

Specifically, I want to display text and images on the monitor, on top of all other windows, but without being clickable or in any way possible to interact with - clicks on it should go straight through to whatever window is underneath.
So far, my research has led me to try and read the X documentation regarding the composite overlay window, but unfortunately I have not been able to get anywhere with it. The only resource I found that was of any help is a small nodejs library (node-x11) which unfortunately appears to have been abandoned while still incomplete, and which I was not able to get to work. Apparently there is also a python library, but that seemed to be even less complete than the nodejs on.
node-x11 author here (and it's not abandoned, I just only add functionality I need or users request, so if you missing something please fill an issue!)
You can use GetOverlayWindow from composite extension:
Version 0.3 of the protocol adds the Composite Overlay Window, which
provides compositing managers with a surface on which to draw without
interference. This window is always above normal windows and is always
below the screen saver window. It is an InputOutput window whose width
and height are the screen dimensions. Its visual is the root visual
and its border width is zero. Attempts to redirect it using the
composite extension are ignored. This window does not appear in the
reply of the QueryTree request. It is also an override redirect window.
These last two features make it invisible to window managers and other X11
clients. The only way to access the XID of this window is via the
CompositeGetOverlayWindow request. Initially, the Composite Overlay
Window is unmapped.
CompositeGetOverlayWindow returns the XID of the Composite Overlay
Window. If the window has not yet been mapped, it is mapped by this
request. When all clients who have called this request have terminated
their X11 connections the window is unmapped.
Composite managers may render directly to the Composite Overlay
Window, or they may reparent other windows to be children of this
window and render to these. Multiple clients may render to the
Composite Overlay Window, create child windows of it, reshape it, and
redefine its input region, but the specific arbitration rules followed
by these clients is not defined by this specification; these policies
should be defined by the clients themselves.
node-x11 example:
var x11 = require('x11');
x11.createClient(function(err, display) {
var X = display.client;
var root = display.screen[0].root;
X.require('composite', function(err, Composite) {
Composite.GetOverlayWindow(root, function(err, overlayId) {
// now you can draw on overlayId window here.
});
});
});

Three.js First Person Controls moves the camera all the time

The game I'm designing currently requires a first person controller and luckily Three.js offers that class as well.
However I can't stop the camera from flying around. I know that the mouse movement causes the fly because it happens as soon as I move the mouse. But reading the js code,I cant find the attribue which causes this movement. Here is how I initiate the controls:
controls = new THREE.FirstPersonControls(camera);
controls.movementSpeed = 0.1;
controls.lookSpeed = 0.001;
controls.lookVertical = true;
I do not want the view direction to change when I am not moving the mouse.
any idea ?
Keep in mind that the FPS style mouse movement in webGL is usable rather only in a full screen mode. If an application runs in a standard windowed mode, the cursor is visible, and the application can not detect cursor movements that cross the edge of the window. This makes it impossible to look around in the FPS style (look movement stops when the cursors reaches the window edge).
This is probably the main reason why a PointerLockControls demo asks you to switch to the full screen mode.
With FirstPersonControls the look movement continues when the mouse reaches the edge. Such approach works well in the windowed mode.
You might want to use the PointerLockControls instead
See an example here:
https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_pointerlock.html

Resources