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

This commit is contained in:
Dana Jansens 2003-06-25 18:43:42 +00:00
parent 32c51bb443
commit 7af1c6a9c3
4 changed files with 134 additions and 48 deletions

View 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_dock(Dock *s, XEvent *e);
static void event_handle_dockapp(DockApp *app, XEvent *e); static void event_handle_dockapp(DockApp *app, XEvent *e);
static void event_handle_client(Client *c, 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(); static void fd_event_handle();
#ifdef USE_SM #ifdef USE_SM
static void ice_watch(IceConn conn, IcePointer data, Bool opening, static void ice_watch(IceConn conn, IcePointer data, Bool opening,
@ -501,10 +501,7 @@ static void event_process(XEvent *e)
return; return;
/* deal with it in the kernel */ /* deal with it in the kernel */
if (menu) { if (client)
event_handle_menu(menu, client, e);
return;
} else if (client)
event_handle_client(client, e); event_handle_client(client, e);
else if (dockapp) else if (dockapp)
event_handle_dockapp(dockapp, e); event_handle_dockapp(dockapp, e);
@ -535,6 +532,15 @@ static void event_process(XEvent *e)
xerror_set_ignore(FALSE); 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 (moveresize_in_progress)
if (e->type == MotionNotify || e->type == ButtonRelease || if (e->type == MotionNotify || e->type == ButtonRelease ||
e->type == ButtonPress || 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; MenuEntry *entry;
Menu *top;
GSList *it;
top = g_slist_nth_data(menu_visible, 0);
g_message("EVENT %d", e->type); g_message("EVENT %d", e->type);
switch (e->type) { switch (e->type) {
case ButtonPress: case KeyPress:
g_message("BUTTON PRESS"); if (over) {
if (e->xbutton.button == 3) if (over->parent->mouseover)
menu_hide(menu); over->parent->mouseover(over, FALSE);
else if (e->xbutton.button == 1) { else
entry = menu_find_entry(menu, e->xbutton.window); menu_control_mouseover(over, FALSE);
if (!entry) menu_entry_render(over);
stacking_raise(MENU_AS_WINDOW(menu));
} }
/*
if (top->hide)
top->hide(top);
else
*/
menu_hide(top);
break;
case ButtonPress:
if (e->xbutton.button > 3) break;
g_message("BUTTON PRESS");
break; break;
case ButtonRelease: case ButtonRelease:
if (e->xbutton.button > 3) break;
g_message("BUTTON RELEASED"); g_message("BUTTON RELEASED");
if (!menu->shown) break;
/* grab_pointer_window(FALSE, None, menu->frame);*/ for (it = menu_visible; it; it = g_slist_next(it)) {
Menu *m = it->data;
if (e->xbutton.button == 1) { if (e->xbutton.x_root >= m->location.x - ob_rr_theme->bwidth &&
entry = menu_find_entry(menu, e->xbutton.window); e->xbutton.y_root >= m->location.y - ob_rr_theme->bwidth &&
if (entry) { e->xbutton.x_root < m->location.x + m->size.width +
int junk; ob_rr_theme->bwidth &&
Window wjunk; e->xbutton.y_root < m->location.y + m->size.height +
guint ujunk, b, w, h; ob_rr_theme->bwidth) {
XGetGeometry(ob_display, e->xbutton.window, if ((entry = menu_find_entry_by_pos(it->data,
&wjunk, &junk, &junk, &w, &h, &b, &ujunk); e->xbutton.x_root -
if (e->xbutton.x >= (signed)-b && m->location.x,
e->xbutton.y >= (signed)-b && e->xbutton.y_root -
e->xbutton.x < (signed)(w+b) && m->location.y))) {
e->xbutton.y < (signed)(h+b)) {
menu_entry_fire(entry); 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; break;
case EnterNotify: case MotionNotify:
case LeaveNotify: g_message("motion");
g_message("enter/leave"); for (it = menu_visible; it; it = g_slist_next(it)) {
entry = menu_find_entry(menu, e->xcrossing.window); Menu *m = it->data;
if (entry) { if ((entry = menu_find_entry_by_pos(it->data,
if (menu->mouseover) e->xmotion.x_root -
menu->mouseover(entry, e->type == EnterNotify); m->location.x,
else e->xmotion.y_root -
menu_control_mouseover(entry, e->type == EnterNotify); 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);
}
menu_entry_render(entry); 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(over, FALSE);
menu_entry_render(over);
over = NULL;
} }
break; break;
} }

View file

@ -2,12 +2,12 @@
#include "openbox.h" #include "openbox.h"
#include "stacking.h" #include "stacking.h"
#include "grab.h" #include "grab.h"
#include "render/theme.h"
#include "screen.h" #include "screen.h"
#include "geom.h" #include "geom.h"
#include "plugin.h" #include "plugin.h"
GHashTable *menu_hash = NULL; GHashTable *menu_hash = NULL;
GSList *menu_visible = NULL;
#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \ #define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \
LeaveWindowMask) LeaveWindowMask)
@ -310,6 +310,16 @@ void menu_show_full(Menu *self, int x, int y, Client *client)
self->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) { if (self->show) {
self->show(self, x, y, client); self->show(self, x, y, client);
} else { } else {
@ -326,6 +336,11 @@ void menu_hide(Menu *self) {
if (self->parent && self->parent->open_submenu == self) if (self->parent && self->parent->open_submenu == self)
self->parent->open_submenu = NULL; 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; 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) void menu_entry_fire(MenuEntry *self)
{ {
Menu *m; Menu *m;
@ -375,12 +402,10 @@ void menu_entry_fire(MenuEntry *self)
void menu_control_show(Menu *self, int x, int y, Client *client) { void menu_control_show(Menu *self, int x, int y, Client *client) {
g_assert(!self->invalid); 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, POINT_SET(self->location,
MIN(x, screen_physical_size.width - self->size.width), MIN(x, screen_physical_size.width - self->size.width),
MIN(y, screen_physical_size.height - self->size.height)); MIN(y, screen_physical_size.height - self->size.height));
XMoveWindow(ob_display, self->frame, self->location.x, self->location.y);
if (!self->shown) { if (!self->shown) {
XMapWindow(ob_display, self->frame); 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?*/ /* need to get the width. is this bad?*/
menu_render(self->submenu); 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 - x = self->parent->location.x - self->submenu->size.width -
ob_rr_theme->bevel; ob_rr_theme->bwidth;
menu_show_full(self->submenu, x, menu_show_full(self->submenu, x,
self->parent->location.y + self->y, self->parent->location.y + self->y,

View file

@ -16,6 +16,7 @@ typedef void(*menu_controller_mouseover)(struct MenuEntry *self,
gboolean enter); gboolean enter);
extern GHashTable *menu_hash; extern GHashTable *menu_hash;
extern GSList *menu_visible;
typedef struct Menu { typedef struct Menu {
ObWindow obwin; ObWindow obwin;
@ -131,6 +132,7 @@ void menu_entry_set_submenu(MenuEntry *entry, Menu *submenu);
void menu_add_entry(Menu *menu, MenuEntry *entry); void menu_add_entry(Menu *menu, MenuEntry *entry);
MenuEntry *menu_find_entry(Menu *menu, Window win); 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); void menu_entry_render(MenuEntry *self);

View file

@ -79,8 +79,8 @@ void menu_render_full(Menu *self) {
self->item_h += ob_rr_theme->bevel * 2; self->item_h += ob_rr_theme->bevel * 2;
items_h = self->item_h * MAX(nitems, 1); items_h = self->item_h * MAX(nitems, 1);
XResizeWindow(ob_display, self->frame, self->size.width, self->size.height = MAX(self->title_h + items_h + ob_rr_theme->bwidth, 1);
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) if (self->label)
XMoveResizeWindow(ob_display, self->title, -ob_rr_theme->bwidth, XMoveResizeWindow(ob_display, self->title, -ob_rr_theme->bwidth,
-ob_rr_theme->bwidth, -ob_rr_theme->bwidth,
@ -101,7 +101,6 @@ void menu_render_full(Menu *self) {
item_y += self->item_h; item_y += self->item_h;
} }
self->size.height = item_y;
self->invalid = FALSE; self->invalid = FALSE;
} }
@ -134,6 +133,7 @@ void menu_entry_render(MenuEntry *self)
self->a_hilite : self->a_item); self->a_hilite : self->a_item);
break; break;
} }
g_message ("%s %d", self->label, self->hilite);
XMoveResizeWindow(ob_display, self->item, 0, self->y, XMoveResizeWindow(ob_display, self->item, 0, self->y,
menu->size.width, menu->item_h); menu->size.width, menu->item_h);