--- bbkeys-0.8.4/src/grab_defs.hh Sun Jan 13 13:59:39 2002 +++ bbkeys-mouse/src/grab_defs.hh Sun Jul 14 21:15:48 2002 @@ -75,6 +75,19 @@ grabVertDec, grabToggleDecor, + + grabMouseUp, + grabMouseDown, + grabMouseLeft, + grabMouseRight, + + grabMouseButton1, + grabMouseButton2, + grabMouseButton3, + + grabRootMouseButton1, + grabRootMouseButton2, + grabRootMouseButton3, NUM_GRABS }; --- bbkeys-0.8.4/src/bbkeys.hh Sun Jan 13 13:59:39 2002 +++ bbkeys-mouse/src/bbkeys.hh Sat Jul 13 22:41:22 2002 @@ -137,6 +137,10 @@ void saveMenuSearch(Window,Basemenu *); void removeMenuSearch(Window); + // functions for mouse movement and button handling + void moveMouse(const int delta_x,const int delta_y); + void clickMouse(const unsigned int button,const Bool is_press,const Bool sendToRoot = false); + // functions which return information inline int getCurrentDesktopNr(void) { return current_desktop?current_desktop->number:-1; @@ -201,6 +205,8 @@ LinkedList *desktopList; // list of all desktop windows Window focus_window; // window which has the focus + int mouseDeltaX,mouseDeltaY; + WMInterface *wminterface; // interface for communicating with the // window manager --- bbkeys-0.8.4/src/bbkeys.cc Mon Jan 14 22:21:25 2002 +++ bbkeys-mouse/src/bbkeys.cc Sun Jul 14 21:52:57 2002 @@ -618,6 +620,26 @@ if (!strcasecmp(action, "ToggleDecor")) return grabToggleDecor; + if (!strcasecmp(action, "MouseUp")) + return grabMouseUp; + if (!strcasecmp(action, "MouseDown")) + return grabMouseDown; + if (!strcasecmp(action, "MouseLeft")) + return grabMouseLeft; + if (!strcasecmp(action, "MouseRight")) + return grabMouseRight; + if (!strcasecmp(action, "MouseButton1")) + return grabMouseButton1; + if (!strcasecmp(action, "MouseButton2")) + return grabMouseButton2; + if (!strcasecmp(action, "MouseButton3")) + return grabMouseButton3; + if (!strcasecmp(action, "RootMouseButton1")) + return grabRootMouseButton1; + if (!strcasecmp(action, "RootMouseButton2")) + return grabRootMouseButton2; + if (!strcasecmp(action, "RootMouseButton3")) + return grabRootMouseButton3; return 0; } @@ -776,7 +798,8 @@ /* if we're supposed to having an execCommand and we do have * something to put into it */ - if (grabSet.KeyMap[count].action == grabExecute) { + if (grabSet.KeyMap[count].action == grabExecute) + { execCmdBegin = strchr(actionBegin + 1, '('); if (execCmdBegin) { strncpy(execCommand, execCmdBegin + 1, @@ -784,8 +807,43 @@ grabSet.KeyMap[count].execCommand = strdup(execCommand); } - } else { - grabSet.KeyMap[count].execCommand = NULL; + } + + else + { + grabSet.KeyMap[count].execCommand = NULL; + + + // If we are doing a mouse-movement action, the user can specify the deltaX/Y + + if (grabSet.KeyMap[count].action == grabMouseUp || + grabSet.KeyMap[count].action == grabMouseDown || + grabSet.KeyMap[count].action == grabMouseLeft || + grabSet.KeyMap[count].action == grabMouseRight) + { + execCmdBegin = strchr(actionBegin + 1, '('); + + if (execCmdBegin) + { + strncpy(execCommand, execCmdBegin + 1,strcspn(execCmdBegin + 1, ")")); + + int delta = atoi(execCommand); + + if (delta > 0) + { + if (grabSet.KeyMap[count].action == grabMouseLeft || + grabSet.KeyMap[count].action == grabMouseRight) + { + mouseDeltaX = delta; + } + + else + { + mouseDeltaY = delta; + } + } + } + } } #ifdef DEBUG @@ -861,6 +919,11 @@ desktop_count = 0; doingCycling = False; + // hard-code this until someone tells me the elegant way to do this (probably + // from the prefs file or the command line) + mouseDeltaX = 30; + mouseDeltaY = 10; + // make draw the bbkeys window MakeWindow(False); Redraw(); @@ -1762,8 +1825,61 @@ wminterface->decorateToggleWindow(focus_window); } break; + + case grabMouseUp: + moveMouse(0,-mouseDeltaY); + break; + + case grabMouseDown: + moveMouse(0,mouseDeltaY); + break; + + case grabMouseLeft: + moveMouse(-mouseDeltaX,0); + break; + + case grabMouseRight: + moveMouse(mouseDeltaX,0); + break; + + case grabMouseButton1: + clickMouse(1,True,false); + usleep(100000); + clickMouse(1,False,false); + break; + + case grabMouseButton2: + clickMouse(2,True,false); + usleep(100000); + clickMouse(2,False,false); + break; + + case grabMouseButton3: + clickMouse(3,True,false); + usleep(100000); + clickMouse(3,False,false); + break; + + case grabRootMouseButton1: + clickMouse(1,True,true); + usleep(100000); + clickMouse(1,False,true); + break; + + case grabRootMouseButton2: + clickMouse(2,True,true); + usleep(100000); + clickMouse(2,False,true); + break; + + case grabRootMouseButton3: + clickMouse(3,True,true); + usleep(100000); + clickMouse(3,False,true); + break; } } + timer->start(); break; } @@ -2294,3 +2410,218 @@ it.current()->desktop); } + + +/******************************************************************************* + + Mouse Simulation Code + +*******************************************************************************/ + +void ToolWindow::moveMouse(const int delta_x,const int delta_y) +{ +Display *display; +Window root; +Window root_return,child_return; +int root_x, root_y, win_x, win_y; +unsigned int modkey_mask; + + + display = getXDisplay(); + + root = getCurrentScreenInfo()->getRootWindow(); + + XQueryPointer(display, root, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &modkey_mask); + +#ifdef DEBUG + fprintf(stderr,"Current cursor = (%d,%d)\n",root_x,root_y); +#endif + + root_x += delta_x; + root_y += delta_y; + + XWarpPointer(display, None, root, 0, 0, 0, 0, root_x, root_y); + + XFlush(display); +} + + + +void ToolWindow::clickMouse(const unsigned int buttonNum,const Bool is_press,const Bool sendToRoot) +{ +Display *display; +Window root_id,child_id,root_return_id,window_id; +int root_x, root_y, win_x, win_y; +unsigned int modkey_mask; + +XEvent theEvent; + +unsigned int eventType; +unsigned int sendMask; +unsigned int stateMask; + +static unsigned int buttonMasks = { 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask }; +static unsigned int buttonCodes = { 0, Button1, Button2, Button3, Button4, Button5 }; + + + // Sanity check + + if (buttonNum < 1 || buttonNum > 5) + { +#ifdef DEBUG + fprintf(stderr,"ToolWindow::clickMouse: Bad buttonNum = %ud\n",buttonNum); +#endif + + return; + } + + +#ifdef DEBUG + fprintf(stderr,"ToolWindow::clickMouse: Beginning....\n"); +#endif + + // Get the active X display, root window, current cursor info + + display = getXDisplay(); + + root_id = getCurrentScreenInfo()->getRootWindow(); + +#ifdef DEBUG + fprintf(stderr,"root_id = 0x%lX\n",(unsigned long) root_id); +#endif + + + if (XQueryPointer(display, root_id, &root_return_id, &child_id, &root_x, &root_y, &win_x, &win_y, &modkey_mask) == False) + { +#ifdef DEBUG + fprintf(stderr,"ToolWindow::clickMouse: while getting root-level info, XQueryPointer() returned False\n"); +#endif + + return; + } + +#ifdef DEBUG + fprintf(stderr,"root_return_id = 0x%lX\n",(unsigned long) root_return_id); + fprintf(stderr,"child_id = 0x%lX\n",(unsigned long) child_id); +#endif + + + window_id = root_id; + + + // If we are not sending to the root window, then we have to drill down to find the deepest child window + + if (!sendToRoot) + { + while (child_id != None) + { + window_id = child_id; + + if (XQueryPointer(display, window_id, &root_return_id, &child_id, &root_x, &root_y, &win_x, &win_y, &modkey_mask) == False) + { +#ifdef DEBUG + fprintf(stderr,"ToolWindow::clickMouse: while drilling down, XQueryPointer() returned False\n"); +#endif + + return; + } + +#ifdef DEBUG + fprintf(stderr,"after drilling:\n"); + fprintf(stderr,"window_id = 0x%lX\n",(unsigned long) window_id); + fprintf(stderr,"child_id = 0x%lX\n",(unsigned long) child_id); +#endif + } + } + + + // Button press or release? + + if (is_press) + { + eventType = ButtonPress; + stateMask = 0; + + sendMask = ButtonPressMask | buttonMasks[buttonNum]; + } + + else + { + eventType = ButtonRelease; + stateMask = buttonMasks[buttonNum]; + + sendMask = ButtonReleaseMask | buttonMasks[buttonNum]; + } + + +#ifdef DEBUG + fprintf(stderr,"finally:\n"); + fprintf(stderr,"root_id = 0x%lX\n",(unsigned long) root_id); + fprintf(stderr,"window_id = 0x%lX\n",(unsigned long) window_id); + fprintf(stderr,"child_id = 0x%lX\n",(unsigned long) child_id); +#endif + + + // Finally, set up the XEvent we'll be sending + + bzero(&theEvent,sizeof(XEvent)); + + theEvent.type = eventType; + + theEvent.xbutton.type = theEvent.type; + theEvent.xbutton.serial = 0; // X is supposed to fill this in (why 7 in sample?) + theEvent.xbutton.send_event = True; + theEvent.xbutton.display = display; + theEvent.xbutton.window = window_id; + theEvent.xbutton.root = root_id; + theEvent.xbutton.subwindow = child_id; + theEvent.xbutton.time = CurrentTime; + theEvent.xbutton.x = win_x; + theEvent.xbutton.y = win_y; + theEvent.xbutton.x_root = root_x; + theEvent.xbutton.y_root = root_y; + theEvent.xbutton.state = stateMask; + theEvent.xbutton.button = buttonCodes[buttonNum]; + theEvent.xbutton.same_screen = True; + + + // Finally, send the event + + if (XSendEvent(display, window_id, True, sendMask, &theEvent) == 0) + { +#ifdef DEBUG + fprintf(stderr,"ToolWindow::clickMouse: XSendEvent Failed\n"); +#endif + } + + XFlush(display); +}