add support for mouse scrolling (#26)
authorphillbush <phillbush@cock.li>
Sat, 13 Feb 2021 23:36:55 +0000 (20:36 -0300)
committerphillbush <phillbush@cock.li>
Sat, 13 Feb 2021 23:36:55 +0000 (20:36 -0300)
xmenu.1
xmenu.c
xmenu.h

diff --git a/xmenu.1 b/xmenu.1
index 82a6ebb..7b14eea 100644 (file)
--- a/xmenu.1
+++ b/xmenu.1
@@ -190,7 +190,6 @@ or
 .BR "\(dqright\(dq" ,
 text is aligned to the left, center, or right of the menu, respectively.
 By default, text is aligned to the left.
 .BR "\(dqright\(dq" ,
 text is aligned to the left, center, or right of the menu, respectively.
 By default, text is aligned to the left.
-
 .SH EXAMPLES
 The following script illustrates the use of
 .BR xmenu .
 .SH EXAMPLES
 The following script illustrates the use of
 .BR xmenu .
diff --git a/xmenu.c b/xmenu.c
index 8658a9d..afb4301 100644 (file)
--- a/xmenu.c
+++ b/xmenu.c
@@ -1129,17 +1129,37 @@ itemcycle(struct Menu *currmenu, int direction)
        return item;
 }
 
        return item;
 }
 
+/* check if button is used to scroll */
+static int
+isscrollbutton(unsigned int button)
+{
+       if (button == Button4 || button == Button5)
+               return 1;
+       return 0;
+}
+
 /* check if button is used to open a item on click */
 static int
 isclickbutton(unsigned int button)
 {
 /* check if button is used to open a item on click */
 static int
 isclickbutton(unsigned int button)
 {
-       if (button == Button1)
+       if (button == Button1 || button == Button2)
                return 1;
        if (!rflag && button == Button3)
                return 1;
        return 0;
 }
 
                return 1;
        if (!rflag && button == Button3)
                return 1;
        return 0;
 }
 
+/* warp pointer to center of selected item */
+static void
+warppointer(struct Menu *menu, struct Item *item)
+{
+       if (menu == NULL || item == NULL)
+               return;
+       if (menu->selected) {
+               XWarpPointer(dpy, None, menu->win, 0, 0, 0, 0, menu->w / 2, item->y + item->h / 2);
+       }
+}
+
 /* append buf into text */
 static int
 append(char *text, char *buf, size_t textsize, size_t buflen)
 /* append buf into text */
 static int
 append(char *text, char *buf, size_t textsize, size_t buflen)
@@ -1240,6 +1260,7 @@ run(struct Menu *currmenu)
        KeySym ksym;
        Status status;
        XEvent ev;
        KeySym ksym;
        Status status;
        XEvent ev;
+       int warped = 0;
        int action;
        int len;
        int i;
        int action;
        int len;
        int i;
@@ -1256,38 +1277,50 @@ run(struct Menu *currmenu)
                                action = ACTION_DRAW;
                        break;
                case MotionNotify:
                                action = ACTION_DRAW;
                        break;
                case MotionNotify:
-                       menu = getmenu(currmenu, ev.xbutton.window);
-                       item = getitem(menu, ev.xbutton.y);
-                       if (menu == NULL || item == NULL || previtem == item)
-                               break;
-                       previtem = item;
-                       select = menu->selected = item;
-                       if (item->submenu != NULL) {
-                               currmenu = item->submenu;
-                               select = NULL;
-                       } else {
-                               currmenu = menu;
+                       if (!warped) {
+                               menu = getmenu(currmenu, ev.xbutton.window);
+                               item = getitem(menu, ev.xbutton.y);
+                               if (menu == NULL || item == NULL || previtem == item)
+                                       break;
+                               previtem = item;
+                               select = menu->selected = item;
+                               if (item->submenu != NULL) {
+                                       currmenu = item->submenu;
+                                       select = NULL;
+                               } else {
+                                       currmenu = menu;
+                               }
+                               action = ACTION_CLEAR | ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
                        }
                        }
-                       action = ACTION_CLEAR | ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
+                       warped = 0;
                        break;
                case ButtonRelease:
                        break;
                case ButtonRelease:
-                       if (!isclickbutton(ev.xbutton.button))
-                               break;
-                       menu = getmenu(currmenu, ev.xbutton.window);
-                       item = getitem(menu, ev.xbutton.y);
-                       if (menu == NULL || item == NULL)
-                               break;
+                       if (isscrollbutton(ev.xbutton.button)) {
+                               if (ev.xbutton.button == Button4)
+                                       select = itemcycle(currmenu, ITEMPREV);
+                               else
+                                       select = itemcycle(currmenu, ITEMNEXT);
+                               action = ACTION_CLEAR | ACTION_SELECT | ACTION_DRAW | ACTION_WARP;
+                       } else if (isclickbutton(ev.xbutton.button)) {
+                               menu = getmenu(currmenu, ev.xbutton.window);
+                               item = getitem(menu, ev.xbutton.y);
+                               if (menu == NULL || item == NULL)
+                                       break;
 enteritem:
 enteritem:
-                       if (item->label == NULL)
-                               break;  /* ignore separators */
-                       if (item->submenu != NULL) {
-                               currmenu = item->submenu;
-                       } else {
-                               printf("%s\n", item->output);
-                               return;
+                               if (item->label == NULL)
+                                       break;  /* ignore separators */
+                               if (item->submenu != NULL) {
+                                       currmenu = item->submenu;
+                               } else {
+                                       printf("%s\n", item->output);
+                                       return;
+                               }
+                               select = currmenu->list;
+                               action = ACTION_CLEAR | ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
+                               if (ev.xbutton.button == Button2) {
+                                       action |= ACTION_WARP;
+                               }
                        }
                        }
-                       select = currmenu->list;
-                       action = ACTION_CLEAR | ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
                        break;
                case ButtonPress:
                        menu = getmenu(currmenu, ev.xbutton.window);
                        break;
                case ButtonPress:
                        menu = getmenu(currmenu, ev.xbutton.window);
@@ -1419,6 +1452,10 @@ append:
                        mapmenu(currmenu);
                if (action & ACTION_DRAW)
                        drawmenus(currmenu);
                        mapmenu(currmenu);
                if (action & ACTION_DRAW)
                        drawmenus(currmenu);
+               if (action & ACTION_WARP) {
+                       warppointer(currmenu, select);
+                       warped = 1;
+               }
        }
 }
 
        }
 }
 
diff --git a/xmenu.h b/xmenu.h
index b5f1556..5e369a2 100644 (file)
--- a/xmenu.h
+++ b/xmenu.h
@@ -6,6 +6,7 @@
 #define ACTION_SELECT 1<<1      /* select item */
 #define ACTION_MAP    1<<2      /* remap menu windows */
 #define ACTION_DRAW   1<<3      /* redraw menu windows */
 #define ACTION_SELECT 1<<1      /* select item */
 #define ACTION_MAP    1<<2      /* remap menu windows */
 #define ACTION_DRAW   1<<3      /* redraw menu windows */
+#define ACTION_WARP   1<<4      /* warp the pointer */
 
 /* enum for keyboard menu navigation */
 enum { ITEMPREV, ITEMNEXT, ITEMFIRST, ITEMLAST };
 
 /* enum for keyboard menu navigation */
 enum { ITEMPREV, ITEMNEXT, ITEMFIRST, ITEMLAST };