As mentioned in a previous posting to the blackbox mailing list, I offer 
up a patch for bbkeys to support keyboard-mouse support.  My patch is the 
code only at this point.  If it is acceptable, then some other stuff 
needs to be tweaked (man pages, Perl config script, bbconf, etc.).

The basic idea is as described before:

>I added the following actions to bbkeys:
>
>     MouseUp - move cursor up
>     MouseDown - move cursor down
>     MouseLeft - move cursor left
>     MouseRight - move cursor right
>
>     MouseButton1 - send button 1 click to front window
>     MouseButton2 - send button 2 click to front window
>     MouseButton3 - send button 3 click to front window
>
>     RootMouseButton1 - send button 1 click to root window
>     RootMouseButton2 - send button 1 click to root window
>     RootMouseButton3 - send button 1 click to root window

Adding these things to the .bbkeysrc is easy.  For example:

     KeyToGrab(KP_0), WithModifier(None), WithAction(RootMouseButton3)
     KeyToGrab(KP_Equal), WithModifier(None), WithAction(MouseButton1)
     KeyToGrab(KP_Divide), WithModifier(None), WithAction(MouseButton2)
     KeyToGrab(KP_Multiply), WithModifier(None), WithAction(MouseButton3)

The only tricky ones are the mouse motion actions, since they allow you 
to specify a movement distance:

     KeyToGrab(KP_8), WithModifier(None), WithAction(MouseUp), Delta(10)
     KeyToGrab(KP_2), WithModifier(None), WithAction(MouseDown)
     KeyToGrab(KP_6), WithModifier(None), WithAction(MouseRight), 
Delta(30)
     KeyToGrab(KP_4), WithModifier(None), WithAction(MouseLeft)

As mentioned before, the "Delta" value is crude at present, allowing you 
to only specify vertical and horizontal movement deltas that apply to all 
Mouse* actions.  It is not possible (at the moment) to specify something 
like alt+KP_8 moves up 10 pixels while control+KP_8 moves 20 pixels.  It 
is possible to have different horizontal and vertical motion amounts 
though.


And the patches to grab_defs.hh, bbkeys.hh, and bbkeys.cc are as follows. 
 (This is small, so please excuse the inclusion here.)

Oh-- be sure to make clean before changing grab_defs.hh.  The bbkeys 
Makefile doesn't seem to track that file.


--- 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> *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;
+    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);
+}

Reply via email to