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.

Kevin Dong
  • 5,001
  • 9
  • 29
  • 62
Corey
  • 161
  • 1
  • 7

5 Answers5

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

nik123
  • 113
  • 1
  • 2
  • 11
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).

Michael Urman
  • 15,737
  • 2
  • 28
  • 44
  • I tried it with an GDK Window, but this didn't work. – u_Ltd. Jul 10 '17 at 07:20
  • 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). – u_Ltd. Jul 10 '17 at 07:21
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.

gvlasov
  • 18,638
  • 21
  • 74
  • 110
bikram990
  • 1,085
  • 1
  • 14
  • 36
  • 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? – Corey May 07 '13 at 17:37
  • 1
    Have a look onto this as well 'http://stackoverflow.com/questions/14656615/xlib-xsendevent-click-event-do-not-work-inside-of-some-windows-on-ubuntu-12-04?rq=1' and this also 'http://www.semicomplete.com/blog/geekery/xsendevent-xdotool-and-ld_preload.html' – bikram990 May 08 '13 at 04:38
  • 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? – Corey May 30 '13 at 18:28
  • Please ask this as a new question for this – bikram990 May 31 '13 at 05:54
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.

Pointer
  • 627
  • 2
  • 8
  • 19
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.

Asad-ullah Khan
  • 1,573
  • 18
  • 22