void emulate_click(int x, int y) { menuwin_ungrab_mouse(0); xcb_test_fake_input(conn,XCB_BUTTON_PRESS,1,XCB_CURRENT_TIME,XCB_NONE,x,y,0); xcb_test_fake_input(conn,XCB_BUTTON_RELEASE,1,XCB_CURRENT_TIME,XCB_NONE,x,y,0); menuwin_grab_mouse(); }
/** Send fake events. Usually the current focused client will get it. * \param L The Lua VM state. * \return The number of element pushed on stack. * \luastack * \lparam The event type: key_press, key_release, button_press, button_release * or motion_notify. * \lparam The detail: in case of a key event, this is the keycode to send, in * case of a button event this is the number of the button. In case of a motion * event, this is a boolean value which if true make the coordinates relatives. * \lparam In case of a motion event, this is the X coordinate. * \lparam In case of a motion event, this is the Y coordinate. * If not specified, the current one is used. */ static int luaA_root_fake_input(lua_State *L) { if(!globalconf.have_xtest) { luaA_warn(L, "XTest extension is not available, cannot fake input."); return 0; } const char *stype = luaL_checkstring(L, 1); uint8_t type, detail; int x = 0, y = 0; if (A_STREQ(stype, "key_press")) { type = XCB_KEY_PRESS; if(lua_type(L, 2) == LUA_TSTRING) { detail = _string_to_key_code(lua_tostring(L, 2)); /* keysym */ } else { detail = luaL_checknumber(L, 2); /* keycode */ } } else if(A_STREQ(stype, "key_release")) { type = XCB_KEY_RELEASE; if(lua_type(L, 2) == LUA_TSTRING) { detail = _string_to_key_code(lua_tostring(L, 2)); /* keysym */ } else { detail = luaL_checknumber(L, 2); /* keycode */ } } else if(A_STREQ(stype, "button_press")) { type = XCB_BUTTON_PRESS; detail = luaL_checknumber(L, 2); /* button number */ } else if(A_STREQ(stype, "button_release")) { type = XCB_BUTTON_RELEASE; detail = luaL_checknumber(L, 2); /* button number */ } else if(A_STREQ(stype, "motion_notify")) { type = XCB_MOTION_NOTIFY; detail = luaA_checkboolean(L, 2); /* relative to the current position or not */ x = luaL_checknumber(L, 3); y = luaL_checknumber(L, 4); } else return 0; xcb_test_fake_input(globalconf.connection, type, detail, XCB_CURRENT_TIME, XCB_NONE, x, y, 0); return 0; }
/** Send fake events. Usually the current focused client will get it. * \param L The Lua VM state. * \return The number of element pushed on stack. * \luastack * \lparam The event type: key_press, key_release, button_press, button_release * or motion_notify. * \lparam The detail: in case of a key event, this is the keycode to send, in * case of a button event this is the number of the button. In case of a motion * event, this is a boolean value which if true make the coordinates relatives. * \lparam In case of a motion event, this is the X coordinate. * \lparam In case of a motion event, this is the Y coordinate. * \lparam In case of a motion event, this is the screen number to move on. * If not specified, the current one is used. */ static int luaA_root_fake_input(lua_State *L) { if(!globalconf.have_xtest) { luaA_warn(L, "XTest extension is not available, cannot fake input."); return 0; } size_t tlen; const char *stype = luaL_checklstring(L, 1, &tlen); uint8_t type, detail; int x = 0, y = 0; xcb_window_t root = XCB_NONE; switch(a_tokenize(stype, tlen)) { case A_TK_KEY_PRESS: type = XCB_KEY_PRESS; detail = luaL_checknumber(L, 2); /* keycode */ break; case A_TK_KEY_RELEASE: type = XCB_KEY_RELEASE; detail = luaL_checknumber(L, 2); /* keycode */ break; case A_TK_BUTTON_PRESS: type = XCB_BUTTON_PRESS; detail = luaL_checknumber(L, 2); /* button number */ break; case A_TK_BUTTON_RELEASE: type = XCB_BUTTON_RELEASE; detail = luaL_checknumber(L, 2); /* button number */ break; case A_TK_MOTION_NOTIFY: type = XCB_MOTION_NOTIFY; detail = luaA_checkboolean(L, 2); /* relative to the current position or not */ x = luaL_checknumber(L, 3); y = luaL_checknumber(L, 4); if(lua_gettop(L) == 5 && !globalconf.xinerama_is_active) { int screen = luaL_checknumber(L, 5) - 1; luaA_checkscreen(screen); root = xutil_screen_get(globalconf.connection, screen)->root; } break; default: return 0; } xcb_test_fake_input(globalconf.connection, type, detail, XCB_CURRENT_TIME, root, x, y, 0); return 0; }
void menuwin_press_key_at(int x, int y) { if (y<0) { emulate_click(x,y+height); return; } if (y>key_win.height) { emulate_click(x,y); return; } x=(x*KEYS_PER_ROW)/width; y=((key_win.height-y)*KEYS_H_DIVISOR)/height; if (y==0) { // main buttons row switch(x) { case 0: support_close_window(); break; case 5: if (key_win.has_keyboard&0x01) { key_win.has_keyboard^=0x02; menuwin_set_window(); } break; case 6: case 7: key_win.wait_for=1; support_next_window(1); break; case 8: case 9: key_win.wait_for=1; support_next_window(0); break; case 10: case 11: support_launch_manager(); break; } return; } int lx,ly,i; i=4*KEYS_PER_ROW*keyboard_current_block; for(ly=4;ly>0;ly--) { for(lx=0;lx<KEYS_PER_ROW;lx++) { if (keyboard_lowercase[i].type!=KEY_BLANK) { if ((x>=lx)&&(x<(lx+keyboard_lowercase[i].w))&&(y<=ly)&&(y>(ly-keyboard_lowercase[i].h))) { if (keyboard_lowercase[i].type==KEY_JUMPTO) { keyboard_current_block=keyboard_lowercase[i].keycode; menuwin_expose(NULL); } else { xcb_keycode_t keycode=keyboard_lowercase[i].keycode; xcb_keycode_t keymod =keyboard_lowercase[i].modifier; if (keycode!=0) { printf("Emiting keycode %d with modifier %d\n",keycode,keymod); if (keymod!=0) { xcb_test_fake_input(conn,XCB_KEY_PRESS,keymod,XCB_CURRENT_TIME,XCB_NONE,0,0,0); xcb_flush(conn); } xcb_test_fake_input(conn,XCB_KEY_PRESS,keycode,XCB_CURRENT_TIME,XCB_NONE,0,0,0); xcb_flush(conn); xcb_test_fake_input(conn,XCB_KEY_RELEASE,keycode,XCB_CURRENT_TIME,XCB_NONE,0,0,0); xcb_flush(conn); if (keymod!=0) { xcb_test_fake_input(conn,XCB_KEY_RELEASE,keymod,XCB_CURRENT_TIME,XCB_NONE,0,0,0); xcb_flush(conn); } } } goto key_end; } } i++; } } key_end: return; }