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:
parent
32c51bb443
commit
7af1c6a9c3
4 changed files with 134 additions and 48 deletions
137
openbox/event.c
137
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_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,
|
||||||
|
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
|
else
|
||||||
menu_control_mouseover(entry, e->type == EnterNotify);
|
menu_control_mouseover(over, FALSE);
|
||||||
|
menu_entry_render(over);
|
||||||
menu_entry_render(entry);
|
over = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue