X11 Wait for and Get Clipboard Text - c

I have to monitor the X11 Clipboard.
For the moment, I request the ClipBoard Selection each 5 seconds, then I hash the text returned from clipboard and I compare it with the hash calculate from the last check. If hash are not the same, I analysis the text content and do some stuff...
I don't like my method. I'm from Windows, and with the winapi, it is the kernel that notify your program when the clipboard has changed, and it's more efficient!
I just want to know if it is possible that X11 can notify your program as winapi when the clipboard has changed ? What is the more efficient way to check clipboard modifications with X11 ?

Use XFixesSelectSelectionInput() from Xfixes extension and wait for XFixesSelectionNotify event.
Example:
// gcc -o xclipwatch xclipwatch.c -lX11 -lXfixes
...
#include <X11/extensions/Xfixes.h>
...
void WatchSelection(Display *display, Window window, const char *bufname)
{
int event_base, error_base;
XEvent event;
Atom bufid = XInternAtom(display, bufname, False);
assert( XFixesQueryExtension(display, &event_base, &error_base) );
XFixesSelectSelectionInput(display, DefaultRootWindow(display), bufid, XFixesSetSelectionOwnerNotifyMask);
while (True)
{
XNextEvent(display, &event);
if (event.type == event_base + XFixesSelectionNotify &&
((XFixesSelectionNotifyEvent*)&event)->selection == bufid)
{
if (!PrintSelection(display, window, bufname, "UTF8_STRING"))
PrintSelection(display, window, bufname, "STRING");
fflush(stdout);
}
}
}
...
This works both for bufname == "CLIPBOARD" and bufname == "PRIMARY" selection.
Also see PrintSelection() function in this answer.

Find window with selection using GetSelectionOwner (PRIMARY and CLIPBOARD)
get copy of selection by sending SelectionRequest, notify your application
watch for SelectionClear event
update window with selection using id from SelectionClear event, goto step 2

The accepted answer from x11user is a good one. But you probably want a non-blocking while loop, and for that you can take that answer, and adapt it like this.
// get the internal X11 event file descriptor
int x11fd = ConnectionNumber(display);
while(!shutdown)
{
if(!XPending(display)) {
// wait on the file descriptor
// you can use poll, epoll, select, eventfd, etc.
}
XNextEvent(display, &event);
// process the event
}

Related

How do I Monitor Mouse Movement Events in All Windows (Not Just One) on X11

I'm trying write an X11 program to monitor all mouse movements on the desktop. The program should be able to receive a notification whenever the mouse is moved by the human user, or moved programmatically via XWarpPointer() by a robotic application. I know it should be possible by setting a PointerMotionMask via XSelectInput() and monitor MotionNotify, but I'm having troubles receiving mouse events from all windows, not just one.
Initially, I just tried to receive pointer motion events from the root window, in the following demo.
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
XSelectInput(display, root_window, PointerMotionMask);
while (1) {
XNextEvent(display, &event);
switch(event.type) {
case MotionNotify:
printf("x: %d y: %d\n", event.xmotion.x, event.xmotion.y );
break;
}
}
return 0;
}
But it doesn't receive any events, unless the mouse pointer is on an empty desktop background. It's clear that merely receiving events from the root window won't work. Then I tried a workaround: first, set SubstructureNotifyMask on the root window to monitor all CreateNotify events to catch all newly created windows, then call XSelectInput() to enable the PointerMotionMask on these windows.
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
XSelectInput(display, root_window, SubstructureNotifyMask);
while (1) {
XNextEvent(display, &event);
switch(event.type) {
case CreateNotify:
XSelectInput(display, event.xcreatewindow.window, PointerMotionMask);
break;
case MotionNotify:
printf("x: %d y: %d\n", event.xmotion.x, event.xmotion.y);
break;
}
}
return 0;
}
This approach is more successful, I started to receive some mouse events from new windows. Unfortunately, it still doesn't work in all portions inside a window - for example, it cannot receive mouse events from the console area in terminal emulators, but can receive events when the mouse is located around the title bar. It appears that a window can create more subwindows, so the mouse events won't be recorded.
Then I tried another workaround - set both SubstructureNotifyMask and PointerMotionMask in CreateNotify, so when a window creates a child window, SubstructureNotifyMask ensures more CreateNotify events will be received in a recursive manner, so all child windows will get PointerMotionMask as well.
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
XSelectInput(display, root_window, SubstructureNotifyMask);
while (1) {
XNextEvent(display, &event);
switch(event.type) {
case CreateNotify:
XSelectInput(display, event.xcreatewindow.window, SubstructureNotifyMask | PointerMotionMask);
break;
case MotionNotify:
printf("x: %d y: %d\n", event.xmotion.x, event.xmotion.y);
break;
}
}
return 0;
}
It works a bit better than the second example, but it's not reliable:
X is fully asynchronous, is it possible that the child window got created before we had a chance to XSelectInput()?
Sometimes it just reports a BadWindow error and crashes.
X event handling becomes messy - if the program already handles a lot of different X events, enabling SubstructureNotifyMask recursively will make many unrelated events delivered to other handlers, and it's a pain to add extra code to discriminate between wanted and unwanted events.
So, how do I monitor mouse movement events in all windows on X11?
After doing some research, especially reading the source code of Xeyes (I always fell the demo is stupid, but it helps a lot here!), I found:
Calling XSelectInput() on all the windows and subwindows is a futile attempt, you have to set a mask on every single window and child window ever created, it's not a robust solution, and not recommended.
Instead, it's better to just continuously pulling the mouse pointer from the X server explicitly via XQueryPointer(), rather than asking the X server to push MotionEvent to us.
One naive solution is simply setting up a timer by XtAppAddTimeOut() and calling XQueryPointer() periodically, it works, and indeed, it was what Xeyes did in the past! But it unnecessarily wastes CPU time. Nowadays, the best practice is to take advantage of XInputExtention 2.0. The workflow is:
Initialize XInput v2.0
Enable various masks via XISetMask() and XIEventMask() to receive XI_RawMotion events (or XI_Motion, see notes below) from XIAllMasterDevices (or XIAllDevices).
When a XI_RawMotion (or XI_Motion) event has been received, call XQueryPointer().
XQueryPointer() returns:
Mouse coordinates with respect to the root window.
The active window under the mouse cursor, if any.
Perform a XTranslateCoordinates() if we want relative coordinates with respect to the active window under the mouse cursor.
Demo
Here's a demo (save as mouse.c, compile with gcc mouse.c -o mouse -lX11 -lXi). However, it cannot detect XWarpPointer(), see notes below.
#include <stdio.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
/* Initialize (FIXME: no error checking). */
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
/* check XInput */
int xi_opcode, event, error;
if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
fprintf(stderr, "Error: XInput extension is not supported!\n");
return 1;
}
/* Check XInput 2.0 */
int major = 2;
int minor = 0;
int retval = XIQueryVersion(display, &major, &minor);
if (retval != Success) {
fprintf(stderr, "Error: XInput 2.0 is not supported (ancient X11?)\n");
return 1;
}
/*
* Set mask to receive XI_RawMotion events. Because it's raw,
* XWarpPointer() events are not included, you can use XI_Motion
* instead.
*/
unsigned char mask_bytes[(XI_LASTEVENT + 7) / 8] = {0}; /* must be zeroed! */
XISetMask(mask_bytes, XI_RawMotion);
/* Set mask to receive events from all master devices */
XIEventMask evmasks[1];
/* You can use XIAllDevices for XWarpPointer() */
evmasks[0].deviceid = XIAllMasterDevices;
evmasks[0].mask_len = sizeof(mask_bytes);
evmasks[0].mask = mask_bytes;
XISelectEvents(display, root_window, evmasks, 1);
XEvent xevent;
while (1) {
XNextEvent(display, &xevent);
if (xevent.xcookie.type != GenericEvent || xevent.xcookie.extension != xi_opcode) {
/* not an XInput event */
continue;
}
XGetEventData(display, &xevent.xcookie);
if (xevent.xcookie.evtype != XI_RawMotion) {
/*
* Not an XI_RawMotion event (you may want to detect
* XI_Motion as well, see comments above).
*/
XFreeEventData(display, &xevent.xcookie);
continue;
}
XFreeEventData(display, &xevent.xcookie);
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
/*
* We need:
* child_return - the active window under the cursor
* win_{x,y}_return - pointer coordinate with respect to root window
*/
int retval = XQueryPointer(display, root_window, &root_return, &child_return,
&root_x_return, &root_y_return,
&win_x_return, &win_y_return,
&mask_return);
if (!retval) {
/* pointer is not in the same screen, ignore */
continue;
}
/* We used root window as its reference, so both should be the same */
assert(root_x_return == win_x_return);
assert(root_y_return == win_y_return);
printf("root: x %d y %d\n", root_x_return, root_y_return);
if (child_return) {
int local_x, local_y;
XTranslateCoordinates(display, root_window, child_return,
root_x_return, root_y_return,
&local_x, &local_y, &child_return);
printf("local: x %d y %d\n\n", local_x, local_y);
}
}
XCloseDisplay(display);
return 0;
}
Sample Output
root: x 631 y 334
local: x 140 y 251
root: x 628 y 338
local: x 137 y 255
root: x 619 y 343
local: x 128 y 260
XWarpPointer() Troubles
The demo above doesn't work if the pointer is moved via XWarpPointer() by a robotic application on newer systems after X.Org 1.10.4. This is intentional, see Bug 30068 on FreeDesktop.
In order to receive mouse events triggered by all mouse movements, including XWarpPointer(), change XI_RawMotion to XI_Motion, and change XIAllMasterDevices to XIAllDevices.
References
This demo lacks error checking and may contain bugs. If in doubts, please check the following authoritative references.
Tracking Cursor Position by Keith Packard, a real X expert, has been heavily involved in the development of X since the late 1980s, and responsible for many X extensions and technical papers.
Xeyes source code from X.Org.

XGrabKeyboard() is not taking keyboard inout for a particular window in x11

I ran a simple C code that at first prints all the active windows and asks the user to choose a window to which the keyboard input should be conveyed.
I cam across the XGrabKeyboard() function in which I can specify the window which can grab the keyboard. It is functioning properly.
For example I set the focus to the text editor and when I run the code, the caret starts blinking in the text editor. But the problem is that it receives o input and behaves as if the keyboard is frozen.
My question is what exactly is XGrabKeyboard() doing? Is it used to just grab the control of the keyboard, or can it be used to associate the keyboard completely with a window and start doing any keyboard activities in that window ? Or should always the DefaultRootWindow() be grabbed?
I came across many questions, but they are not explaining what I actually need.
About XGrabKeyboard() : https://tronche.com/gui/x/xlib/input/XGrabKeyboard.html
// list holds window IDs received from a winlist function
list = (Window*)winlist(d,&len);
printf("And the window indices and names are...\n");
for (i=0;i<(int)len;i++) {
name = winame(d,list[i]);
printf("-->index = %d\t%s<--\n",i, name);
free(name);
}
int x;
printf("Select the window for which Keyboard should be grabbed (0 indexed) ");
scanf("%d",&x);
if(XGrabKeyboard(d, list[x], False, GrabModeAsync, GrabModeAsync, CurrentTime)!=0)//GrabSuccess)
printf("Keyboard grab failed for window = %s", winame(d, list[x]));
else
{
printf("Keyboard Grab Successful\n");
sleep(10);
}

xlib drawing lines dont appear outside event loop

i am following an example in a book and i have a drawing function that draws lines. when i place it just before the event loop before XFlush() no lines are drawn but if i place it in the eventloop like below the lines are drawn.
while(1)
{
XNextEvent(display, &report);
if (report.type == Expose)
{
draw_lines(win1, gca, 300, 200);
}
}
can anyone explain to me why this is happening? thanks much. why does it matter whether i place the function in the event loop or not?
Something seems to have changed in xlib. Look at my answer to this question and the others it references.
You can do the draws and flush first, then wait for the expose event with:
/* catch expose events */
XSelectInput(display, win, ExposureMask);
/* wait for the expose event */
XEvent ev;
XNextEvent(display, &ev);

XCB: window will not unmap after being mapped once

I have a small example program written in C that opens a window using the XCB API.
Strictly AFTER I have created and shown the window, I would (at a later time) like to hide the window.
(Obviously in this specific example, I could remove the call to xcb_map_window, and the window would be hidden, but I want to do it at a later point in my larger application, like a toggle to show/hide the window, NOTE: I do NOT want to minimize it).
Here is the sample code (NOTE: this code now works thanks to the answer):
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <xcb/xcb.h>
void set_window_visible(xcb_connection_t* c, xcb_window_t win, bool visible) {
xcb_generic_event_t *event;
if(visible) {
// Map the window on the screen
xcb_map_window (c, win);
// Make sure the map window command is sent
xcb_flush(c);
// Wait for EXPOSE event.
//
// TODO: add timeout in-case X server does not ever send the expose event.
while(event = xcb_wait_for_event(c)) {
bool gotExpose = false;
switch(event->response_type & ~0x80) {
case XCB_EXPOSE:
gotExpose = true;
break;
default:
break; // We don't know the event type, then.
}
free(event);
if(gotExpose) {
break;
}
}
} else {
// Hide the window
xcb_unmap_window(c, win);
// Make sure the unmap window command is sent
xcb_flush(c);
}
}
int main() {
xcb_connection_t *c;
xcb_screen_t *screen;
xcb_window_t win;
xcb_generic_event_t *event;
// Open the connection to the X server
c = xcb_connect (NULL, NULL);
// Get the first screen
screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
// Ask for our window's Id
win = xcb_generate_id(c);
// Create the window
uint32_t mask = XCB_CW_EVENT_MASK;
uint32_t valwin[] = {XCB_EVENT_MASK_EXPOSURE | XCB_BUTTON_PRESS};
xcb_create_window(
c, // Connection
XCB_COPY_FROM_PARENT, // depth (same as root)
win, // window Id
screen->root, // parent window
0, 0, // x, y
150, 150, // width, height
10, // border_width
XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
screen->root_visual, // visual
mask, valwin // masks
);
bool visible = true;
set_window_visible(c, win, true);
while(1) {
sleep(2);
// Toggle visibility
visible = !visible;
set_window_visible(c, win, visible);
printf("Window visible: ");
if(visible) {
printf("true.\n");
} else {
printf("false.\n");
}
}
// pause until Ctrl-C
pause();
return 0;
}
Which I compile and run with:
gcc xcbwindow.c -o xcbwindow -lxcb
./xcbwindow
From anything I can find on Google or here, I am doing everything correctly. So for clarification I am using Unity and Ubuntu 12.04 LTS:
unity --version reports:
unity 5.20.0
uname -a reports:
Linux [redacted] 3.2.0-32-generic #51-Ubuntu SMP Wed Sep 26 21:33:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
Can anyone explain where I've gone wrong in this code?
EDIT: updated code with a flush() at the end after xcb_unmap_window(); still doesn't work.
EDIT2: Tried code with cinnamon WM; still doesn't work (It's not a Unity bug).
EDIT3: Code updated in this post now works.
Your program simply goes too fast.
It maps the window and then immediately unmaps it. The window is top level, which means the requests are redirected to the window manager. But the window manager receives the unmap request when the window is not mapped yet, so it simply discards the request. Insert sleep(3) between the map and unmap calls and observe.
In real code, your window needs to get at least one expose event before sending out the unmap request. This guarantees it's actually mapped by the window manager.

C++/CLI Timer freezes applications

I am using a timer in a c++ windows form app. To handle receiving messages sent from a server using WinSock2. The current code for my timer is,
private: System::Void tmrMessages_Tick(System::Object^ sender, System::EventArgs^ e) {
int ID;
char* cID = new char[64];
char* message = new char[256];
ZeroMemory(cID, 64);
ZeroMemory(message, 256);
if(recv(sConnect, message, 256, NULL) != SOCKET_ERROR && recv(sConnect, cID, 64, NULL) != SOCKET_ERROR)
{
ID = atoi(cID);
if (ID == 1)
{
lbxMessages->Items->Add("hello");
}
}
}
I didn't have it add the variables to the listbox because I wanted to test and make sure it worked first. It DOES work but, it makes the app so slow that it doesn't allow any user input at all. It does show the listbox being updated but, like I said doesn't allow me to move the window, click textboxes or anything. If you have any idea why this is happening please let me know.
thanks.
If those are blocking reads, they'll freeze the UI thread until you get data.
What you should do is set non-blocking mode and read until you fill your buffer, which may take multiple recv calls, the process it.
I really like WSAAsyncSelect for this... it automatically puts the socket into non-blocking mode and sends your window a message whenever data is available. You can easily handle that message by overriding WndProc.
It should be pretty straightforward:
#include <winsock2.h>
#include <windows.h>
const unsigned WM_SOCKETREADY = WM_USER + 100;
...
when you open the socket (assuming that's a member function of the form), call
WSAAsyncSelect(sConnect, HWND(Handle.ToPointer()), WM_SOCKETREADY, FD_READ);
and then WndProc (which you should override) will have the message delivered to it
virtual void WndProc( Message% m ) override
{
switch (m.Msg) {
case WM_SOCKETREADY:
ReadSocketHandler();
return;
default:
Form::WndProc(m);
return;
}
}

Resources