0

I am trying to get the XEvents, and then decide whether it should continue like normal or be blocked.

Basically what gdk_window_add_filter is doing: https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-add-filter

I attempted it with the code below but am having these issues:

  • XGrabPointer is not working if done after startup, but if i do it along with startup it works.
  • If I get XGrabPointer to work, by doing it along with startup, XUngrabPointer is not working, it always returns 1.
  • If I get XGrabPointer to working, by doing it along with startup, XAllowEvents is not letting the events go through.

This is my full code it is in ctypes:

var win = ostypes.TYPE.Window();
var revert_to = ostypes.TYPE.int();
var rez_XGetFocus = ostypes.API('XGetInputFocus')(ostypes.HELPER.cachedXOpenDisplay(), win.address(), revert_to.address());
console.log('rez_XGetFocus:', rez_XGetFocus);

var rez_XSelectInput = ostypes.API('XSelectInput')(ostypes.HELPER.cachedXOpenDisplay(), win, ostypes.CONST.ButtonPressMask | ostypes.CONST.ButtonReleaseMask);
console.log('rez_XSelectInput:', rez_XSelectInput);

var rez_XGrab = ostypes.API('XGrabPointer')(ostypes.HELPER.cachedXOpenDisplay(), win, true, ostypes.CONST.ButtonPressMask | ostypes.CONST.ButtonReleaseMask, ostypes.CONST.GrabModeSync, ostypes.CONST.GrabModeAsync, ostypes.CONST.None, ostypes.CONST.None, ostypes.CONST.CurrentTime);
console.log('rez_XGrab:', rez_XGrab);
var rez_XGrab = 0;
if (!cutils.jscEqual(rez_XGrab, ostypes.CONST.GrabSuccess)) {
    if (cutils.jscEqual(rez_XGrab, ostypes.CONST.AlreadyGrabbed)) {
        console.log('already grabbed so will ungrab then regrab');

        var rez_XUngrab = ostypes.API('XUngrabPointer')(ostypes.HELPER.cachedXOpenDisplay(), ostypes.CONST.CurrentTime);
        console.log('rez_XUngrab:', rez_XUngrab);

        var rez_XFlush = ostypes.API('XFlush')(ostypes.HELPER.cachedXOpenDisplay());
        console.log('rez_XFlush:', rez_XFlush);

        var rez_XGrab2 = ostypes.API('XGrabPointer')(ostypes.HELPER.cachedXOpenDisplay(), win, false, ostypes.CONST.ButtonPressMask | ostypes.CONST.ButtonReleaseMask, ostypes.CONST.GrabModeSync, ostypes.CONST.GrabModeAsync, ostypes.CONST.None, ostypes.CONST.None, ostypes.CONST.CurrentTime);
        console.log('rez_XGrab2:', rez_XGrab2);

        if (!cutils.jscEqual(rez_XGrab2, ostypes.CONST.GrabSuccess)) {
            console.error('failed to XGrabPointer a SECOND time with value:', rez_XGrab);
            throw new Error('failed to XGrabPointer a SECOND time with value: ' + rez_XGrab);
        }
    } else {
        console.error('failed to XGrabPointer with value:', rez_XGrab);
        throw new Error('failed to XGrabPointer with value: ' + rez_XGrab);
    }
}
// 
// // var rez_XChangeGrab = ostypes.API('XChangeActivePointerGrab')(ostypes.HELPER.cachedXOpenDisplay(), ostypes.HELPER.cachedDefaultRootWindow(), ostypes.CONST.ButtonPressMask | ostypes.CONST.ButtonReleaseMask, ostypes.CONST.CurrentTime);
// // console.log('rez_XChangeGrab:', rez_XChangeGrab);
// 
// // throw new Error('ok?');
// // var rez_XSelectInput = ostypes.API('XSelectInput')(ostypes.HELPER.cachedXOpenDisplay(), ostypes.HELPER.cachedDefaultRootWindow(), ostypes.CONST.ButtonPressMask | ostypes.CONST.ButtonReleaseMask);
// // console.log('rez_XSelectInput:', rez_XSelectInput);
// 
var ev = ostypes.TYPE.XEvent();

var st = new Date().getTime();
var runFor = 10000; // ms
while (true) {

    var rez_XAllow = ostypes.API('XAllowEvents')(ostypes.HELPER.cachedXOpenDisplay(), ostypes.CONST.SyncPointer, ostypes.CONST.CurrentTime);
    console.log('rez_XAllow:', rez_XAllow);

    var rez_XNextEvent = ostypes.API('XNextEvent')(ostypes.HELPER.cachedXOpenDisplay(), ev.address());
    console.log('rez_XNextEvent:', rez_XNextEvent);
    console.info('ev:', ev.xbutton);

    // :debug:
    if (new Date().getTime() - st > runFor) {
        console.log('time up');
        break;
    }
}


var rez_XUngrab2 = ostypes.API('XUngrabPointer')(ostypes.HELPER.cachedXOpenDisplay(), ostypes.CONST.CurrentTime);
console.log('rez_XUngrab2:', rez_XUngrab2);
Noitidart
  • 35,443
  • 37
  • 154
  • 323
  • 1
    Perhaps it *is* grabbed. Are you calling this from a menu or something? – n. m. could be an AI Oct 25 '15 at 00:42
  • Thanks @n.m. nah I'm calling it from a brand new thread i spawned from which I already called `XInitThreads` for thread safety. If it is already grabbed, then shouldn't `XUngrabPointer` not return 1? – Noitidart Oct 25 '15 at 01:52
  • 1
    The spec tells nothing about what XUngrabPointer might return. It seems to always return 1 no matter what. It doesn't matter whether you are calling it from a new thread or not. I'm asking if it's called in response for some user action. – n. m. could be an AI Oct 25 '15 at 05:05
  • Thanks @n.m. oh no I'm just trying to monitor the mouse buttons/wheel and if the user matches a combination then I want to block the mouse from getting to the window, and then trigger a custom function. – Noitidart Oct 25 '15 at 05:47
  • 1
    You say "this works if done at startup, and doesn't work if done not at startup". I'm trying to understand what are those non-startup conditions that prevent the code from working. Since you can do an infinite number of things before calling your function, you ought to be a bit more specific regarding this non-startup thing. If it is called while a mouse button is pressed, you probably will get the already-grabbed error. – n. m. could be an AI Oct 25 '15 at 08:02
  • 1
    It is also not very clear how you plan to propagate the events, and how other clients that require pointer grabs for various things are supposed to work together with your program. – n. m. could be an AI Oct 25 '15 at 08:07
  • Thanks @n.m. I'm very experimental here :( Not sure if I'm going about it right. But the startup clairfication: This is a firefox addon that is restartless, so when I install it, firefox has already been running for sometime, so XGrabPointer fails. But now I restart firefox, with addon already installed, XGrab works in that its blocking all mouse events. I found that `gdk_window_add_filter` does exactly what I want, reports each mouse button/wheel event and I can allow to continue to window or block it. However I want to do it with X so I'm just trying out codes I find :( Can you guide plz – Noitidart Oct 25 '15 at 14:56
  • 1
    It is safe to assume that when extension is being installed, the pointer is grabbed. You can just do a few attempts with an interval of a second or so. However grabbing the pointer for an extended period of time is VERY likely to break other programs. – n. m. could be an AI Oct 25 '15 at 15:46
  • Thanks @n.m. is there any alternative to acheiving what `gdk_window_add_filter` does without using `XGrabPointer`. Is there anyway to grab the pointer even if a context menu is shown, because on addon install there is a top level panel that is visible which I think is grabbing it, I thought XGrabPointer should override any existing grabs? – Noitidart Oct 25 '15 at 21:51
  • 1
    I don't know. What is your extension supposed to do? – n. m. could be an AI Oct 26 '15 at 05:34
  • Thanks @n.m.! My extension allows users to set mouse cominbations. For example, the user will set "on mouse down of right button, while it is held, scroll wheel up" will move tab focus right. So i will block the wheel up events so it doesnt scroll the page up. Very basic example. Reason I am moving to C api from javascript, is because javascript has issues when context menus and some other situations. So basically i need to listen for all mouse events and be able to allow them through to the or block them. – Noitidart Oct 26 '15 at 08:22
  • 1
    You want to write a *global event hook*. Google it. You will find lots of questions. Good luck finding one working answer, AFAIK it is impossible. – n. m. could be an AI Oct 26 '15 at 08:30
  • Thanks @n.m. but I dont need a global hook i just need to hook and block in my app :( Anything possible here? :( – Noitidart Oct 26 '15 at 12:18
  • 1
    But XGrabPointer *is* global. There's nothing like that in the application scope, – n. m. could be an AI Oct 29 '15 at 14:01
  • Ooo thanks @n.m. my goal is to do exactly what `gtk_window_add_filter` does, it has to do it via x no? Shouldnt that be possible? – Noitidart Oct 29 '15 at 20:22
  • 1
    If a context menu is open (typically after a rigth click) XGrabPointer() returns AlreadyGrabbed and I have no idea how recover the possiblitiy of grab the mouse. Can you give me any tip? – ezain Jun 21 '19 at 10:59
  • Hi @ezain - I'm not sure what's causing that. I worked with this a bit ago, not sure what I ended up with, but my code is here in js-ctypes - https://github.com/Noitidart/MouseControl/tree/master/modules/workers – Noitidart Jun 21 '19 at 17:06

0 Answers0