Wednesday, February 3, 2016

Closing Chrome's download shelf

Was playing with XWarpPointer and XQueryPoint Monday evening and came up with a way to close Chrome's download shelf without having to run XWarpPointer 4 times. Hint: it requires declaring the Window to avoid having to employ relative positions. See the man page for an explanation.

Basically, what the below does is fake a mouse click at a specific location on the screen. Coupling it with a function key or Gleebox (I use both), I can close the annoying download shelf without having to touch the mouse.

// compile with: gcc -lX11 -o cdl cdl.c

#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>

int main() {

 // determine the location of the close button by running
 // xdotool getmouselocation
 // following values are for my display

 int button_x = 1661;
 int button_y = 1005;

 //create a field in which mouse can operate

 Display *mousefield = XOpenDisplay(NULL);
 //return error if above didn't work
 if (mousefield == NULL) {
  return -1;

 // find the proper window

 Window root_window;

 //determine current location of mouse

 XEvent event;
 XQueryPointer(mousefield, DefaultRootWindow(mousefield), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
 int original_x=event.xbutton.x;
 int original_y=event.xbutton.y;

 // move the pointer to the location of the close button
 // assumes window is full screen
 // see for explanation

 // move pointer to xbutton

 XWarpPointer(mousefield, None, root_window, 0, 0, 0, 0, button_x, button_y);

 // click & release the button

 XEvent event2;
 memset (&event2, 0, sizeof(event2));
 event2.xbutton.button = Button1;
 event2.xbutton.same_screen = True;
 event2.xbutton.subwindow = DefaultRootWindow(mousefield);
 while(event2.xbutton.subwindow) {
  XQueryPointer(mousefield, event2.xbutton.window, &event2.xbutton.root, &event2.xbutton.subwindow, &event2.xbutton.x_root, &event2.xbutton.y_root, &event2.xbutton.x, &event2.xbutton.y, &event2.xbutton.state);
 // put the mouse back where you found it

 XWarpPointer(mousefield, None, root_window, 0, 0, 0, 0, original_x, original_y);

 // kill the field created above

 return 0;