summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-06-25 18:43:42 +0000
committerDana Jansens <danakj@orodu.net>2003-06-25 18:43:42 +0000
commit7af1c6a9c3a57f3ded34fad3f9f4a30fe377a65e (patch)
treeb05a5534c89253ad2685ee73723abb9132078942
parent32c51bb4435f2f3c68616e26e7ee64dfcfb6a38d (diff)
menus grab the keyboard and pointer, thus making only one menu visible at a time, and making them act like gtk menus and * menus do, where you can click and drag and release to select something as well as click-release to elave it open while you search around the menu
-rw-r--r--openbox/event.c137
-rw-r--r--openbox/menu.c37
-rw-r--r--openbox/menu.h2
-rw-r--r--openbox/menu_render.c6
4 files changed, 134 insertions, 48 deletions
diff --git a/openbox/event.c b/openbox/event.c
index 52747d3f..e9e85f0b 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -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;
}
diff --git a/openbox/menu.c b/openbox/menu.c
index b67b76a6..8f7c8b6c 100644
--- a/openbox/menu.c
+++ b/openbox/menu.c
@@ -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,
diff --git a/openbox/menu.h b/openbox/menu.h
index 6cb76a5e..ea5d7454 100644
--- a/openbox/menu.h
+++ b/openbox/menu.h
@@ -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);
diff --git a/openbox/menu_render.c b/openbox/menu_render.c
index 87ffa913..d3b0e016 100644
--- a/openbox/menu_render.c
+++ b/openbox/menu_render.c
@@ -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);