]> Dogcows Code - chaz/openbox/commitdiff
menus grab the keyboard and pointer, thus making only one menu visible at a time...
authorDana Jansens <danakj@orodu.net>
Wed, 25 Jun 2003 18:43:42 +0000 (18:43 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 25 Jun 2003 18:43:42 +0000 (18:43 +0000)
openbox/event.c
openbox/menu.c
openbox/menu.h
openbox/menu_render.c

index 52747d3fb8adffd0461c611255f4bf0ca2afa552..e9e85f0be2c3ef7efbc576f9955573aba888aa57 100644 (file)
@@ -41,7 +41,7 @@ static void event_handle_root(XEvent *e);
 static void event_handle_dock(Dock *s, XEvent *e);
 static void event_handle_dockapp(DockApp *app, XEvent *e);
 static void event_handle_client(Client *c, XEvent *e);
-static void event_handle_menu(Menu *menu, Client *c, XEvent *e);
+static void event_handle_menu(Client *c, XEvent *e);
 static void fd_event_handle();
 #ifdef USE_SM
 static void ice_watch(IceConn conn, IcePointer data, Bool opening,
@@ -501,10 +501,7 @@ static void event_process(XEvent *e)
         return;
 
     /* deal with it in the kernel */
-    if (menu) {
-        event_handle_menu(menu, client, e);
-        return;
-    } else if (client)
+    if (client)
        event_handle_client(client, e);
     else if (dockapp)
        event_handle_dockapp(dockapp, e);
@@ -535,6 +532,15 @@ static void event_process(XEvent *e)
        xerror_set_ignore(FALSE);
     }
 
+    if (menu_visible)
+        if (e->type == MotionNotify || e->type == ButtonRelease ||
+            e->type == ButtonPress ||
+            e->type == KeyPress || e->type == KeyRelease) {
+            event_handle_menu(client, e);
+
+            return; /* no dispatch! */
+        }
+
     if (moveresize_in_progress)
         if (e->type == MotionNotify || e->type == ButtonRelease ||
             e->type == ButtonPress ||
@@ -977,57 +983,110 @@ static void event_handle_client(Client *client, XEvent *e)
     }
 }
 
-static void event_handle_menu(Menu *menu, Client *client, XEvent *e)
+static void event_handle_menu(Client *client, XEvent *e)
 {
+    static MenuEntry *over = NULL;
     MenuEntry *entry;
+    Menu *top;
+    GSList *it;
+
+    top = g_slist_nth_data(menu_visible, 0);
 
     g_message("EVENT %d", e->type);
     switch (e->type) {
+    case KeyPress:
+        if (over) {
+            if (over->parent->mouseover)
+                over->parent->mouseover(over, FALSE);
+            else
+                menu_control_mouseover(over, FALSE);
+            menu_entry_render(over);
+        }
+/*
+        if (top->hide)
+            top->hide(top);
+        else
+*/
+            menu_hide(top);
+        break;
     case ButtonPress:
+        if (e->xbutton.button > 3) break;
+
        g_message("BUTTON PRESS");
-        if (e->xbutton.button == 3)
-            menu_hide(menu);
-        else if (e->xbutton.button == 1) {
-            entry = menu_find_entry(menu, e->xbutton.window);
-            if (!entry)
-                stacking_raise(MENU_AS_WINDOW(menu));
-        }
         break;
     case ButtonRelease:
+        if (e->xbutton.button > 3) break;
+
        g_message("BUTTON RELEASED");
-        if (!menu->shown) break;
-
-/*        grab_pointer_window(FALSE, None, menu->frame);*/
-
-        if (e->xbutton.button == 1) {
-            entry = menu_find_entry(menu, e->xbutton.window);
-            if (entry) {
-                int junk;
-                Window wjunk;
-                guint ujunk, b, w, h;
-                XGetGeometry(ob_display, e->xbutton.window,
-                             &wjunk, &junk, &junk, &w, &h, &b, &ujunk);
-                if (e->xbutton.x >= (signed)-b &&
-                    e->xbutton.y >= (signed)-b &&
-                    e->xbutton.x < (signed)(w+b) &&
-                    e->xbutton.y < (signed)(h+b)) {
+
+        for (it = menu_visible; it; it = g_slist_next(it)) {
+            Menu *m = it->data;
+            if (e->xbutton.x_root >= m->location.x - ob_rr_theme->bwidth &&
+                e->xbutton.y_root >= m->location.y - ob_rr_theme->bwidth &&
+                e->xbutton.x_root < m->location.x + m->size.width +
+                ob_rr_theme->bwidth &&
+                e->xbutton.y_root < m->location.y + m->size.height +
+                ob_rr_theme->bwidth) {
+                if ((entry = menu_find_entry_by_pos(it->data,
+                                                    e->xbutton.x_root -
+                                                    m->location.x,
+                                                    e->xbutton.y_root -
+                                                    m->location.y))) {
                     menu_entry_fire(entry);
                 }
+                break;
             }
         }
+        if (!it) {
+            if (over) {
+                if (over->parent->mouseover)
+                    over->parent->mouseover(over, FALSE);
+                else
+                    menu_control_mouseover(over, FALSE);
+            }
+            menu_entry_render(over);
+/*
+            if (top->hide)
+                top->hide(top);
+            else
+*/
+                menu_hide(top);
+        }
        
         break;
-    case EnterNotify:
-    case LeaveNotify:
-        g_message("enter/leave");
-        entry = menu_find_entry(menu, e->xcrossing.window);
-        if (entry) {
-            if (menu->mouseover)
-                menu->mouseover(entry, e->type == EnterNotify);
+    case MotionNotify:
+        g_message("motion");
+        for (it = menu_visible; it; it = g_slist_next(it)) {
+            Menu *m = it->data;
+            if ((entry = menu_find_entry_by_pos(it->data,
+                                                e->xmotion.x_root -
+                                                m->location.x,
+                                                e->xmotion.y_root -
+                                                m->location.y))) {
+                if (over && entry != over) {
+                    if (over->parent->mouseover)
+                        over->parent->mouseover(over, FALSE);
+                    else
+                        menu_control_mouseover(over, FALSE);
+                    menu_entry_render(over);
+                }
+
+                over = entry;
+                if (over->parent->mouseover)
+                    over->parent->mouseover(over, TRUE);
+                else
+                    menu_control_mouseover(over, TRUE);
+                menu_entry_render(over);
+                break;
+            }
+        }
+        if (!it && over) {
+            if (over->parent->mouseover)
+                over->parent->mouseover(over, FALSE);
             else
-                menu_control_mouseover(entry, e->type == EnterNotify);
-           
-            menu_entry_render(entry);
+                menu_control_mouseover(over, FALSE);
+            menu_entry_render(over);
+            over = NULL;
         }
         break;
     }
index b67b76a6b3c64c52b916567848ea05295d061ff3..8f7c8b6cb301277a81c96e31806a67c3da57ca63 100644 (file)
@@ -2,12 +2,12 @@
 #include "openbox.h"
 #include "stacking.h"
 #include "grab.h"
-#include "render/theme.h"
 #include "screen.h"
 #include "geom.h"
 #include "plugin.h"
 
 GHashTable *menu_hash = NULL;
+GSList *menu_visible = NULL;
 
 #define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \
                         LeaveWindowMask)
@@ -310,6 +310,16 @@ void menu_show_full(Menu *self, int x, int y, Client *client)
     
     self->client = client;
 
+    if (!self->shown) {
+        GSList *it;
+
+        if (!self->parent) {
+            grab_pointer(TRUE, None);
+            grab_keyboard(TRUE);
+        }
+        menu_visible = g_slist_append(menu_visible, self);
+    }
+
     if (self->show) {
        self->show(self, x, y, client);
     } else {
@@ -326,6 +336,11 @@ void menu_hide(Menu *self) {
        if (self->parent && self->parent->open_submenu == self)
            self->parent->open_submenu = NULL;
 
+        if (!self->parent) {
+            grab_keyboard(FALSE);
+            grab_pointer(FALSE, None);
+        }
+        menu_visible = g_slist_remove(menu_visible, self);
     }
 }
 
@@ -353,6 +368,18 @@ MenuEntry *menu_find_entry(Menu *menu, Window win)
     return NULL;
 }
 
+MenuEntry *menu_find_entry_by_pos(Menu *menu, int x, int y)
+{
+    if (x < 0 || x >= menu->size.width || y < 0 || y >= menu->size.height)
+        return NULL;
+
+    y -= menu->title_h + ob_rr_theme->bwidth;
+    if (y < 0) return NULL;
+    
+    g_message ("%d %p", y/menu->item_h, g_list_nth_data(menu->entries, y / menu->item_h));
+    return g_list_nth_data(menu->entries, y / menu->item_h);
+}
+
 void menu_entry_fire(MenuEntry *self)
 {
     Menu *m;
@@ -375,12 +402,10 @@ void menu_entry_fire(MenuEntry *self)
 void menu_control_show(Menu *self, int x, int y, Client *client) {
     g_assert(!self->invalid);
     
-    XMoveWindow(ob_display, self->frame, 
-               MIN(x, screen_physical_size.width - self->size.width), 
-               MIN(y, screen_physical_size.height - self->size.height));
     POINT_SET(self->location, 
              MIN(x, screen_physical_size.width - self->size.width), 
              MIN(y, screen_physical_size.height - self->size.height));
+    XMoveWindow(ob_display, self->frame, self->location.x, self->location.y);
 
     if (!self->shown) {
        XMapWindow(ob_display, self->frame);
@@ -413,9 +438,9 @@ void menu_control_mouseover(MenuEntry *self, gboolean enter) {
            /* need to get the width. is this bad?*/
            menu_render(self->submenu);
 
-           if (self->submenu->size.width + x > screen_physical_size.width)
+           if (self->submenu->size.width + x >= screen_physical_size.width)
                x = self->parent->location.x - self->submenu->size.width - 
-                   ob_rr_theme->bevel;
+                   ob_rr_theme->bwidth;
            
            menu_show_full(self->submenu, x,
                           self->parent->location.y + self->y,
index 6cb76a5e67dcceda758287e8dd6e6b8c501254e8..ea5d7454e714c1631daaaf5d3ca58cf33039cb1a 100644 (file)
@@ -16,6 +16,7 @@ typedef void(*menu_controller_mouseover)(struct MenuEntry *self,
                                          gboolean enter);
 
 extern GHashTable *menu_hash;
+extern GSList *menu_visible;
 
 typedef struct Menu {
     ObWindow obwin;
@@ -131,6 +132,7 @@ void menu_entry_set_submenu(MenuEntry *entry, Menu *submenu);
 void menu_add_entry(Menu *menu, MenuEntry *entry);
 
 MenuEntry *menu_find_entry(Menu *menu, Window win);
+MenuEntry *menu_find_entry_by_pos(Menu *menu, int x, int y);
 
 void menu_entry_render(MenuEntry *self);
 
index 87ffa9136061e44e86c47700a475df452cf0d70a..d3b0e0169fac3d976c4df7950accd82b3114aad1 100644 (file)
@@ -79,8 +79,8 @@ void menu_render_full(Menu *self) {
     self->item_h += ob_rr_theme->bevel * 2;
     items_h = self->item_h * MAX(nitems, 1);
 
-    XResizeWindow(ob_display, self->frame, self->size.width,
-                 MAX(self->title_h + items_h + ob_rr_theme->bwidth, 1));
+    self->size.height = MAX(self->title_h + items_h + ob_rr_theme->bwidth, 1);
+    XResizeWindow(ob_display, self->frame, self->size.width,self->size.height);
     if (self->label)
        XMoveResizeWindow(ob_display, self->title, -ob_rr_theme->bwidth,
                          -ob_rr_theme->bwidth,
@@ -101,7 +101,6 @@ void menu_render_full(Menu *self) {
         item_y += self->item_h;
     }
     
-    self->size.height = item_y;
     self->invalid = FALSE;
 }
 
@@ -134,6 +133,7 @@ void menu_entry_render(MenuEntry *self)
          self->a_hilite : self->a_item);
        break;
     }
+    g_message ("%s %d", self->label, self->hilite);
 
     XMoveResizeWindow(ob_display, self->item, 0, self->y,
                       menu->size.width, menu->item_h);
This page took 0.034449 seconds and 4 git commands to generate.