make client-list-menu work too

more menu cleanups
This commit is contained in:
Dana Jansens 2003-08-28 07:34:03 +00:00
parent ffba11aeb0
commit f7eb47dba4
12 changed files with 190 additions and 145 deletions

View file

@ -27,11 +27,11 @@ bin_PROGRAMS = \
plugin_LTLIBRARIES = \ plugin_LTLIBRARIES = \
plugins/placement/placement.la \ plugins/placement/placement.la \
plugins/menu/client_menu.la plugins/menu/client_menu.la \
plugins/menu/client_list_menu.la
# plugins/menu/timed_menu.la \ # plugins/menu/timed_menu.la \
# plugins/menu/fifo_menu.la \ # plugins/menu/fifo_menu.la \
# plugins/menu/include_menu.la \ # plugins/menu/include_menu.la \
# plugins/menu/client_list_menu.la
if OBCONF if OBCONF
bin_PROGRAMS += \ bin_PROGRAMS += \

View file

@ -28,6 +28,7 @@
</menu> </menu>
<menu id="client-menu" plugin="client_menu" /> <menu id="client-menu" plugin="client_menu" />
<menu id="client-list-menu" plugin="client_list_menu" />
<menu id="root-menu" label="Openbox 3"> <menu id="root-menu" label="Openbox 3">
<menu id="apps-menu" /> <menu id="apps-menu" />
@ -35,6 +36,8 @@
<separator /> <separator />
<menu id="client-menu" plugin="client_menu" /> <menu id="client-menu" plugin="client_menu" />
<separator /> <separator />
<menu id="client-list-menu" plugin="client_list_menu" />
<separator />
<item label="Restart"> <item label="Restart">
<action name="restart" /> <action name="restart" />
</item> </item>

View file

@ -693,7 +693,7 @@ ObAction *action_from_string(char *name)
return a; return a;
} }
ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node) ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
{ {
char *actname; char *actname;
ObAction *act = NULL; ObAction *act = NULL;
@ -705,8 +705,13 @@ ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node)
if ((n = parse_find_node("execute", node->xmlChildrenNode))) if ((n = parse_find_node("execute", node->xmlChildrenNode)))
act->data.execute.path = parse_string(doc, n); act->data.execute.path = parse_string(doc, n);
} else if (act->func == action_showmenu) { } else if (act->func == action_showmenu) {
if ((n = parse_find_node("menu", node->xmlChildrenNode))) if ((n = parse_find_node("menu", node->xmlChildrenNode))) {
gchar *plugin;
act->data.showmenu.name = parse_string(doc, n); act->data.showmenu.name = parse_string(doc, n);
if (parse_attr_string("plugin", n, &plugin))
menu_open_plugin(i, act->data.showmenu.name, plugin);
}
} else if (act->func == action_desktop) { } else if (act->func == action_desktop) {
if ((n = parse_find_node("desktop", node->xmlChildrenNode))) if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
act->data.desktop.desk = parse_int(doc, n); act->data.desktop.desk = parse_int(doc, n);

View file

@ -137,7 +137,7 @@ ObAction *action_new(void (*func)(union ActionData *data));
*/ */
ObAction *action_from_string(char *name); ObAction *action_from_string(char *name);
ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node); ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
void action_free(ObAction *a); void action_free(ObAction *a);
/* Execute */ /* Execute */

View file

@ -92,7 +92,7 @@ static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
if (keylist) { if (keylist) {
nact = parse_find_node("action", node); nact = parse_find_node("action", node);
while (nact) { while (nact) {
if ((action = action_parse(doc, nact))) { if ((action = action_parse(i, doc, nact))) {
/* validate that its okay for a key binding */ /* validate that its okay for a key binding */
if (action->func == action_moveresize && if (action->func == action_moveresize &&
action->data.moveresize.corner != action->data.moveresize.corner !=
@ -165,7 +165,7 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
goto next_nbut; goto next_nbut;
nact = parse_find_node("action", nbut->xmlChildrenNode); nact = parse_find_node("action", nbut->xmlChildrenNode);
while (nact) { while (nact) {
if ((action = action_parse(doc, nact))) { if ((action = action_parse(i, doc, nact))) {
/* validate that its okay for a mouse binding*/ /* validate that its okay for a mouse binding*/
if (mact == OB_MOUSE_ACTION_MOTION) { if (mact == OB_MOUSE_ACTION_MOTION) {
if (action->func != action_moveresize || if (action->func != action_moveresize ||

View file

@ -1170,13 +1170,14 @@ static void event_handle_menu(XEvent *ev)
switch (ev->type) { switch (ev->type) {
case ButtonRelease: case ButtonRelease:
if (!(f = menu_frame_under(ev->xmotion.x_root, if (!(f = menu_frame_under(ev->xbutton.x_root,
ev->xmotion.y_root))) ev->xbutton.y_root)))
menu_frame_hide_all(); menu_frame_hide_all();
else { else {
if ((e = menu_entry_frame_under(ev->xmotion.x_root, if ((e = menu_entry_frame_under(ev->xbutton.x_root,
ev->xmotion.y_root))) ev->xbutton.y_root)))
menu_entry_frame_execute(e); menu_entry_frame_execute(e,
!(ev->xbutton.state & ControlMask));
} }
break; break;
case MotionNotify: case MotionNotify:

View file

@ -47,7 +47,7 @@ static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
for (node = node->xmlChildrenNode; node; node = node->next) for (node = node->xmlChildrenNode; node; node = node->next)
if (!xmlStrcasecmp(node->name, (const xmlChar*) "action")) if (!xmlStrcasecmp(node->name, (const xmlChar*) "action"))
acts = g_slist_append(acts, action_parse(doc, node)); acts = g_slist_append(acts, action_parse(i, doc, node));
menu_add_normal(state->menus->data, 0, label, acts); menu_add_normal(state->menus->data, 0, label, acts);
g_free(label); g_free(label);
} }
@ -64,6 +64,21 @@ static void parse_menu_separator(ObParseInst *i,
menu_add_separator(state->menus->data, 0); menu_add_separator(state->menus->data, 0);
} }
gboolean menu_open_plugin(ObParseInst *i, gchar *name, gchar *plugin)
{
gboolean ret = FALSE;
if (plugin_open(plugin, i)) {
plugin_start(plugin);
if (g_hash_table_lookup(menu_hash, name))
ret = TRUE;
else
g_warning("Specified plugin '%s' did not provide the "
"menu '%s'", plugin, name);
}
return ret;
}
static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
gpointer data) gpointer data)
{ {
@ -75,13 +90,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
if (!g_hash_table_lookup(menu_hash, name)) { if (!g_hash_table_lookup(menu_hash, name)) {
if (parse_attr_string("plugin", node, &plugin)) { if (parse_attr_string("plugin", node, &plugin)) {
if (!plugin_open(plugin, i)) menu_open_plugin(i, name, plugin);
goto parse_menu_fail;
plugin_start(plugin);
if (!g_hash_table_lookup(menu_hash, name))
g_warning("Specified plugin '%s' did not provide the "
"menu '%s'", plugin, name);
goto parse_menu_fail;
} else { } else {
if (!parse_attr_string("label", node, &title)) if (!parse_attr_string("label", node, &title))
goto parse_menu_fail; goto parse_menu_fail;
@ -107,6 +116,10 @@ parse_menu_fail:
void menu_destroy_hash_value(ObMenu *self) void menu_destroy_hash_value(ObMenu *self)
{ {
/* XXX make sure its not visible */ /* XXX make sure its not visible */
if (self->destroy_func)
self->destroy_func(self, self->data);
menu_clear_entries_internal(self); menu_clear_entries_internal(self);
g_free(self->name); g_free(self->name);
g_free(self->title); g_free(self->title);
@ -315,6 +328,22 @@ void menu_set_update_func(gchar *name, ObMenuUpdateFunc func)
self->update_func = func; self->update_func = func;
} }
void menu_set_execute_func(gchar *name, ObMenuExecuteFunc func)
{
ObMenu *self;
if (!(self = menu_from_name(name))) return;
self->execute_func = func;
}
void menu_set_destroy_func(gchar *name, ObMenuDestroyFunc func)
{
ObMenu *self;
if (!(self = menu_from_name(name))) return;
self->destroy_func = func;
}
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id) ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id)
{ {
ObMenuEntry *ret = NULL; ObMenuEntry *ret = NULL;

View file

@ -3,13 +3,15 @@
#include "action.h" #include "action.h"
#include "window.h" #include "window.h"
#include "render/render.h"
#include "geom.h" #include "geom.h"
#include "render/render.h"
#include "parser/parse.h"
#include <glib.h> #include <glib.h>
struct _ObClient; struct _ObClient;
struct _ObMenuFrame; struct _ObMenuFrame;
struct _ObMenuEntryFrame;
typedef struct _ObMenu ObMenu; typedef struct _ObMenu ObMenu;
typedef struct _ObMenuEntry ObMenuEntry; typedef struct _ObMenuEntry ObMenuEntry;
@ -18,6 +20,9 @@ typedef struct _ObSubmenuMenuEntry ObSubmenuMenuEntry;
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry; typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data); typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data);
typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntryFrame *frame,
gpointer data);
typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data);
extern GList *menu_visible; extern GList *menu_visible;
@ -35,6 +40,8 @@ struct _ObMenu
gpointer data; gpointer data;
ObMenuUpdateFunc update_func; ObMenuUpdateFunc update_func;
ObMenuExecuteFunc execute_func;
ObMenuDestroyFunc destroy_func;
}; };
typedef enum typedef enum
@ -84,7 +91,11 @@ void menu_parse();
gboolean menu_new(gchar *name, gchar *title, gpointer data); gboolean menu_new(gchar *name, gchar *title, gpointer data);
void menu_free(gchar *name); void menu_free(gchar *name);
gboolean menu_open_plugin(ObParseInst *i, gchar *name, gchar *plugin);
void menu_set_update_func(gchar *name, ObMenuUpdateFunc func); void menu_set_update_func(gchar *name, ObMenuUpdateFunc func);
void menu_set_execute_func(gchar *name, ObMenuExecuteFunc func);
void menu_set_destroy_func(gchar *name, ObMenuDestroyFunc func);
void menu_show(gchar *name, gint x, gint y, struct _ObClient *client); void menu_show(gchar *name, gint x, gint y, struct _ObClient *client);

View file

@ -344,8 +344,10 @@ static void menu_frame_render(ObMenuFrame *self)
} }
if (!w) w = 10; if (!w) w = 10;
if (!allitems_h) allitems_h = 3; if (!allitems_h) {
if (!h) h = 3; allitems_h = 3;
h += 3;
}
XResizeWindow(ob_display, self->window, w, h); XResizeWindow(ob_display, self->window, w, h);
XResizeWindow(ob_display, self->items, w, allitems_h); XResizeWindow(ob_display, self->items, w, allitems_h);
@ -546,20 +548,24 @@ void menu_entry_frame_show_submenu(ObMenuEntryFrame *self)
menu_frame_show(f, self->frame); menu_frame_show(f, self->frame);
} }
void menu_entry_frame_execute(ObMenuEntryFrame *self) void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide)
{ {
if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) { if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
GSList *it;
/* release grabs before executing the shit */ /* release grabs before executing the shit */
menu_frame_hide_all(); menu_frame_hide_all();
for (it = self->entry->data.normal.actions; it; if (self->frame->menu->execute_func)
it = g_slist_next(it)) self->frame->menu->execute_func(self, self->frame->menu->data);
{ else {
ObAction *act = it->data; GSList *it;
act->data.any.c = self->frame->client;
act->func(&act->data); for (it = self->entry->data.normal.actions; it;
it = g_slist_next(it))
{
ObAction *act = it->data;
act->data.any.c = self->frame->client;
act->func(&act->data);
}
} }
} }
} }

View file

@ -94,6 +94,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y);
void menu_entry_frame_show_submenu(ObMenuEntryFrame *self); void menu_entry_frame_show_submenu(ObMenuEntryFrame *self);
void menu_entry_frame_execute(ObMenuEntryFrame *self); void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide);
#endif #endif

View file

@ -1,142 +1,123 @@
#include "kernel/openbox.h" #include "kernel/openbox.h"
#include "kernel/menu.h" #include "kernel/menu.h"
#include "kernel/menuframe.h"
#include "kernel/action.h" #include "kernel/action.h"
#include "kernel/screen.h" #include "kernel/screen.h"
#include "kernel/client.h" #include "kernel/client.h"
#include "kernel/focus.h" #include "kernel/focus.h"
#include "gettext.h"
#include "render/theme.h" #include "render/theme.h"
#include <glib.h> #include <glib.h>
static char *PLUGIN_NAME = "client_list_menu"; #define MENU_NAME "client-list-menu"
typedef struct { typedef struct {
GSList *submenus; /* how many desktop menus we've made */
} Client_List_Menu_Data; guint desktops;
} MenuData;
typedef struct { typedef struct {
guint desktop; guint desktop;
} Client_List_Desktop_Menu_Data; } DesktopData;
#define CLIENT_LIST_MENU(m) ((ObMenu *)m)
#define CLIENT_LIST_MENU_DATA(m) ((Client_List_Menu_Data *)((ObMenu *)m)->plugin_data)
#define CLIENT_LIST_DESKTOP_MENU(m) ((ObMenu *)m)
#define CLIENT_LIST_DESKTOP_MENU_DATA(m) ((Client_List_Desktop_Menu_Data *)((ObMenu *)m)->plugin_data)
static void self_update(ObMenu *self);
static void self_destroy(ObMenu *self);
void plugin_setup_config() { } void plugin_setup_config() { }
void plugin_shutdown() { }
void plugin_destroy (ObMenu *m) { }
void *plugin_create() static void desk_menu_update(ObMenuFrame *frame, gpointer data)
{ {
ObMenu *menu = menu_new_full("Desktops", "client-list-menu", NULL, ObMenu *menu = frame->menu;
NULL, self_update, NULL, DesktopData *d = data;
NULL, NULL, self_destroy); GList *it;
menu->plugin = PLUGIN_NAME; menu_clear_entries(menu->name);
menu->plugin_data = g_new(Client_List_Menu_Data, 1);
CLIENT_LIST_MENU_DATA(menu)->submenus = NULL;
return (void *)menu; for (it = focus_order[d->desktop]; it; it = g_list_next(it)) {
ObClient *c = it->data;
if (client_normal(c)) {
GSList *acts;
ObAction* act;
act = action_from_string("activate");
act->data.activate.c = c;
acts = g_slist_prepend(NULL, act);
menu_add_normal(menu->name, 0,
(c->iconic ? c->icon_title : c->title), acts);
}
}
}
/* executes it without changing the client in the actions, since we set that
when we make the actions! */
static void desk_menu_execute(ObMenuEntryFrame *self, gpointer data)
{
GSList *it;
for (it = self->entry->data.normal.actions; it; it = g_slist_next(it))
{
ObAction *act = it->data;
act->func(&act->data);
}
}
static void desk_menu_destroy(ObMenu *menu, gpointer data)
{
DesktopData *d = data;
g_free(d);
}
static void self_update(ObMenuFrame *frame, gpointer data)
{
guint i;
MenuData *d = data;
menu_clear_entries(MENU_NAME);
for (i = 0; i < screen_num_desktops; ++i) {
gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i);
DesktopData *data = g_new(DesktopData, 1);
data->desktop = i;
menu_new(name, screen_desktop_names[i], data);
menu_set_update_func(name, desk_menu_update);
menu_set_execute_func(name, desk_menu_execute);
menu_set_destroy_func(name, desk_menu_destroy);
menu_add_submenu(MENU_NAME, 0, name);
g_free(name);
}
d->desktops = MAX(d->desktops, screen_num_desktops);
}
static void self_destroy(ObMenu *menu, gpointer data)
{
MenuData *d = data;
guint i;
for (i = 0; i < d->desktops; ++i) {
gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i);
menu_free(name);
g_free(name);
}
g_free(d);
} }
void plugin_startup() void plugin_startup()
{ {
plugin_create("client_list_menu"); MenuData *data;
data = g_new(MenuData, 1);
data->desktops = 0;
menu_new(MENU_NAME, _("Desktops"), data);
menu_set_update_func(MENU_NAME, self_update);
menu_set_destroy_func(MENU_NAME, self_destroy);
} }
void plugin_shutdown()
static void desk_update(ObMenu *self)
{ {
GList *it; menu_free(MENU_NAME);
guint desk;
menu_clear(self);
desk = CLIENT_LIST_DESKTOP_MENU_DATA(self)->desktop;
for (it = focus_order[desk]; it; it = g_list_next(it)) {
ObClient *c = (ObClient *)it->data;
if (client_normal(c)) {
ObAction* a = action_from_string("activate");
a->data.activate.c = c;
menu_add_entry(self, menu_entry_new((c->iconic ?
c->icon_title :
c->title), a));
}
}
menu_render(self);
}
static void desk_selected(ObMenuEntry *entry,
unsigned int button, unsigned int x, unsigned int y)
{
entry->action->data.activate.here = (button == 2);
entry->parent->client = entry->action->data.activate.c;
menu_entry_fire(entry, button, x, y);
}
static void desk_destroy(ObMenu *self)
{
g_free(self->plugin_data);
}
static void self_update(ObMenu *self)
{
guint i, n;
ObMenu *deskmenu;
gchar *s;
GList *eit, *enext;
GSList *sit, *snext;
n = g_slist_length(CLIENT_LIST_MENU_DATA(self)->submenus);
for (i = 0; i < screen_num_desktops; ++i) {
if (i >= n) {
s = g_strdup_printf("client-list-menu-desktop-%d", i);
deskmenu = menu_new_full(screen_desktop_names[i], s, self,
NULL,
desk_update, desk_selected, NULL, NULL,
desk_destroy);
g_free(s);
deskmenu->plugin = PLUGIN_NAME;
deskmenu->plugin_data = g_new(Client_List_Desktop_Menu_Data, 1);
CLIENT_LIST_DESKTOP_MENU_DATA(deskmenu)->desktop = i;
CLIENT_LIST_MENU_DATA(self)->submenus =
g_slist_append(CLIENT_LIST_MENU_DATA(self)->submenus,
deskmenu);
}
menu_add_entry(self, menu_entry_new_submenu(screen_desktop_names[i],
deskmenu));
}
for (eit = g_list_nth(self->entries, i); eit; eit = enext) {
enext = g_list_next(eit);
menu_entry_free(eit->data);
self->entries = g_list_delete_link(self->entries, eit);
}
for (sit = g_slist_nth(CLIENT_LIST_MENU_DATA(self)->submenus, i);
sit; sit = snext) {
snext = g_slist_next(sit);
menu_free(sit->data);
CLIENT_LIST_MENU_DATA(self)->submenus =
g_slist_delete_link(CLIENT_LIST_MENU_DATA(self)->submenus, sit);
}
menu_render(self);
}
static void self_destroy(ObMenu *self)
{
g_free(self->plugin_data);
} }

View file

@ -82,6 +82,15 @@ static void layer_update(ObMenuFrame *frame, gpointer data)
if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
e->data.normal.enabled = !!frame->client; e->data.normal.enabled = !!frame->client;
} }
e = menu_find_entry_id(menu, LAYER_TOP);
e->data.normal.enabled = !frame->client->above;
e = menu_find_entry_id(menu, LAYER_NORMAL);
e->data.normal.enabled = !(frame->client->above || frame->client->below);
e = menu_find_entry_id(menu, LAYER_BOTTOM);
e->data.normal.enabled = !frame->client->below;
} }
static void send_to_update(ObMenuFrame *frame, gpointer data) static void send_to_update(ObMenuFrame *frame, gpointer data)