Click through transparent xlib windows
Asked Answered
A

5

14

I have a transparent, watermark like application that is written with XLib in C. Currently if you click anywhere on the application nothing happens but I would like it to pass mouse input to whatever is below it. e.g. If you click the X to close a window that is below the application it should close the application, not do nothing.

Attainable answered 6/5, 2013 at 14:30 Comment(0)
M
4

Well this is what I found.

Note that this feature was added in the last decade so if you have an old version of X11, this may or may not work.

First include these into your project as they would be needed:

#include <X11/extensions/shape.h>
#include <X11/extensions/Xfixes.h>

And to change the input geometry (that is the place where you can interact with the window), in this case we'll set it to 0 by 0 pixels which would mean none. This is an example:

XRectangle rect;
XserverRegion region = XFixesCreateRegion(display, &rect, 1);
XFixesSetWindowShapeRegion(display, window, ShapeInput, 0, 0, region);
XFixesDestroyRegion(display, region);

And add this to the project linker -lXfixes

Moynihan answered 11/6, 2018 at 21:56 Comment(0)
D
2

If you don't want your "watermark" window to receive any input, and instead have the input go to the window below it, then I would look into the implementation behind gtk_widget_input_shape_combine_region. I previously used its predecessor gtk_widget_input_shape_combine_mask to cause all parts of a popup window not to receive any events.

I'm out of my comfort zone here, but it looks like XShapeCombineRectangles is the relevant call (the linked do_shape_combine_region is called with shape = ShapeInput for this case).

Dostie answered 7/1, 2015 at 18:42 Comment(2)
I tried it with an GDK Window, but this didn't work.Agustinaah
When I tried it for an xlib window, it worked (even the requirement that you can click on "X" to close an underlying window is fulfilled).Agustinaah
A
1

I think XQueryTree could be of help. Execute it onto the root window and get the list of child windows, find their locations and pass the mouse/keyboard's XEvent to the appropriate window.

Note: You have to take care of active/inactive windows, active/inactive area of window, child of another window, size and x/y location of other windows. Code is going to be messy for this.

Affianced answered 7/5, 2013 at 8:2 Comment(5)
So I would use XQueryTree to get the window id's then XGetWindowAttributes and check for an overlap, if there is an over lap I send the mouse event to that window? Also how do I send, or pass, the mouse event to the window?Attainable
Have a look onto this as well '#14657115' and this also 'semicomplete.com/blog/geekery/…'Affianced
I am able to pick the correct window with XQueryTree however I am having trouble sending the proper events to the window. I assume I want to send FocusChangeEvent and possibly ButtonPressEvent but I haven't been able to successfully do either. Any one have a good XSendEvent example?Attainable
Please ask this as a new question for thisAffianced
Don't use XQueryTree, it should work, but some WMs (Openbox) insert a whole bunch of window nodes so you'll likely hit one of your own and end up processing the same event in a loop. Use _NET_CLIENT_LIST_STACKING atom on root to get the windows in stacking order instead, it's cheaper and works better.Edroi
G
0
  1. You need to implement small window manager which will listen all events on default root indow using XSelectInput.

  2. Then do polling on fd = connectionNember(display).

  3. Whenever you receive event. Check if this is Mouse event, it will give you x,y. You can find the correct window by traversing the window stack.

  4. Then use XGrabPinter to report event to the underlying window.

Graticule answered 12/1, 2015 at 16:0 Comment(0)
L
0

Some additional notes:

  • If you want to do this in xcb, make sure you query xfixes version 5.0 first otherwise you will get a nebulous BadRequest error
  • Here is an alternate method (stolen from picom source, who in turn stole it from compiz source ☺)
xcb_shape_mask(conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, window, 0, 0, 0);
xcb_shape_rectangles(conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, window, 0, 0, 0, NULL);

As for how that works, I do not have a clue. XShape is notoriously undocumented. However the outcome seems to be the same.

Lookin answered 4/8, 2021 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.