summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
authorScott Moynes <smoynes@nexus.carleton.ca>2003-05-09 23:15:28 +0000
committerScott Moynes <smoynes@nexus.carleton.ca>2003-05-09 23:15:28 +0000
commita8a4a2cca30602b66b7a7f68bb9f3fffd34e92c9 (patch)
treefddb23143b63c703c73886be2d1e45765ec0bad5 /openbox
parentd5eacc5642ad8f5611f7c946d734863bc8898513 (diff)
Menu uber patch
Since we have no menu parser see menu_startup() to customize
Diffstat (limited to 'openbox')
-rw-r--r--openbox/event.c12
-rw-r--r--openbox/menu.c160
-rw-r--r--openbox/menu.h29
-rw-r--r--openbox/menu_render.c116
-rw-r--r--openbox/plugin.c74
-rw-r--r--openbox/plugin.h8
-rw-r--r--openbox/timer.c4
7 files changed, 319 insertions, 84 deletions
diff --git a/openbox/event.c b/openbox/event.c
index 2e2d5c0c..5dd1f705 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -378,6 +378,7 @@ static void event_process(XEvent *e)
window = event_get_window(e);
if (!(client = g_hash_table_lookup(client_map, &window)))
menu = g_hash_table_lookup(menu_map, &window);
+
event_set_lasttime(e);
event_hack_mods(e);
if (event_ignore(e, client))
@@ -858,10 +859,12 @@ static void event_handle_menu(Menu *menu, XEvent *e)
g_message("EVENT %d", e->type);
switch (e->type) {
case ButtonPress:
+ g_message("BUTTON PRESS");
if (e->xbutton.button == 3)
menu_hide(menu);
break;
case ButtonRelease:
+ g_message("BUTTON RELEASED");
if (!menu->shown) break;
/* grab_pointer_window(FALSE, None, menu->frame);*/
@@ -879,16 +882,21 @@ static void event_handle_menu(Menu *menu, XEvent *e)
e->xbutton.y < (signed)(h+b)) {
menu_entry_fire(entry);
}
- }
+
break;
case EnterNotify:
case LeaveNotify:
g_message("enter/leave");
entry = menu_find_entry(menu, e->xcrossing.window);
if (entry) {
- entry->hilite = e->type == EnterNotify;
+ if (menu->mouseover)
+ menu->mouseover(entry, e->type == EnterNotify);
+ else
+ menu_control_mouseover(entry, e->type == EnterNotify);
+
menu_entry_render(entry);
}
break;
+ }
}
}
diff --git a/openbox/menu.c b/openbox/menu.c
index 88eef9c5..b271cf31 100644
--- a/openbox/menu.c
+++ b/openbox/menu.c
@@ -3,11 +3,15 @@
#include "stacking.h"
#include "grab.h"
#include "render/theme.h"
+#include "screen.h"
+#include "geom.h"
+#include "plugin.h"
static GHashTable *menu_hash = NULL;
GHashTable *menu_map = NULL;
-#define FRAME_EVENTMASK (ButtonMotionMask | EnterWindowMask | LeaveWindowMask)
+#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \
+ LeaveWindowMask)
#define TITLE_EVENTMASK (ButtonPressMask | ButtonMotionMask)
#define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
ButtonPressMask | ButtonReleaseMask)
@@ -60,6 +64,8 @@ void menu_entry_free(MenuEntry *self)
void menu_startup()
{
Menu *m;
+ Menu *s;
+ Menu *t;
Action *a;
menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -67,15 +73,50 @@ void menu_startup()
(GDestroyNotify)menu_destroy_hash_value);
menu_map = g_hash_table_new(g_int_hash, g_int_equal);
- m = menu_new("sex menu", "root", NULL);
+ m = menu_new(NULL, "root", NULL);
+
a = action_from_string("execute");
a->data.execute.path = g_strdup("xterm");
menu_add_entry(m, menu_entry_new("xterm", a));
a = action_from_string("restart");
menu_add_entry(m, menu_entry_new("restart", a));
- menu_add_entry(m, menu_entry_new("--", NULL));
+ menu_add_entry(m, menu_entry_new_separator("--"));
a = action_from_string("exit");
menu_add_entry(m, menu_entry_new("exit", a));
+ s = menu_new("subsex menu", "submenu", m);
+ a = action_from_string("execute");
+ a->data.execute.path = g_strdup("xclock");
+ menu_add_entry(s, menu_entry_new("xclock", a));
+
+ menu_add_entry(m, menu_entry_new_submenu("subz", s));
+
+ /*
+ t = (Menu *)plugin_create("timed_menu");
+ a = action_from_string("execute");
+ a->data.execute.path = g_strdup("xeyes");
+ menu_add_entry(t, menu_entry_new("xeyes", a));*/
+
+ s = menu_new("empty", "chub", m);
+ menu_add_entry(m, menu_entry_new_submenu("empty", s));
+
+ s = menu_new("", "s-club", m);
+ menu_add_entry(m, menu_entry_new_submenu("empty", s));
+
+ s = menu_new(NULL, "h-club", m);
+ menu_add_entry(m, menu_entry_new_submenu("empty", s));
+
+ s = menu_new(NULL, "g-club", m);
+
+ a = action_from_string("execute");
+ a->data.execute.path = g_strdup("xterm");
+ menu_add_entry(s, menu_entry_new("xterm", a));
+ a = action_from_string("restart");
+ menu_add_entry(s, menu_entry_new("restart", a));
+ menu_add_entry(s, menu_entry_new_separator("--"));
+ a = action_from_string("exit");
+ menu_add_entry(s, menu_entry_new("exit", a));
+
+ menu_add_entry(m, menu_entry_new_submenu("long", s));
m = menu_new("client menu", "client", NULL);
a = action_from_string("iconify");
@@ -86,6 +127,7 @@ void menu_startup()
menu_add_entry(m, menu_entry_new("(un)maximize", a));
a = action_from_string("close");
menu_add_entry(m, menu_entry_new("close", a));
+
}
void menu_shutdown()
@@ -113,18 +155,22 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
self->label = g_strdup(label);
self->name = g_strdup(name);
self->parent = parent;
+ self->open_submenu = NULL;
self->entries = NULL;
self->shown = FALSE;
- self->invalid = FALSE;
- /* default controllers? */
-
+ self->invalid = TRUE;
+
+ /* default controllers */
self->show = show;
self->hide = NULL;
self->update = update;
self->mouseover = NULL;
self->selected = NULL;
+ self->plugin = NULL;
+ self->plugin_data = NULL;
+
attrib.override_redirect = TRUE;
attrib.event_mask = FRAME_EVENTMASK;
self->frame = createWindow(ob_root, CWOverrideRedirect|CWEventMask, &attrib);
@@ -133,6 +179,7 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
self->items = createWindow(self->frame, 0, &attrib);
XSetWindowBorderWidth(ob_display, self->frame, theme_bwidth);
+ XSetWindowBackground(ob_display, self->frame, theme_b_color->pixel);
XSetWindowBorderWidth(ob_display, self->title, theme_bwidth);
XSetWindowBorder(ob_display, self->frame, theme_b_color->pixel);
XSetWindowBorder(ob_display, self->title, theme_b_color->pixel);
@@ -207,35 +254,42 @@ void menu_add_entry(Menu *menu, MenuEntry *entry)
void menu_show(char *name, int x, int y, Client *client)
{
Menu *self;
-
+
self = g_hash_table_lookup(menu_hash, name);
if (!self) {
g_warning("Attempted to show menu '%s' but it does not exist.",
name);
return;
}
+
+ menu_show_full(self, x, y, client);
+}
- if (self->invalid) {
- if (self->update) {
- self->update(self);
- } else {
- menu_render(self);
- }
- }
+void menu_show_full(Menu *self, int x, int y, Client *client)
+{
+ g_assert(self != NULL);
+
+ menu_render(self);
self->client = client;
if (self->show) {
- self->show(self, x, y, client);
+ self->show(self, x, y, client);
} else {
menu_control_show(self, x, y, client);
}
}
+
void menu_hide(Menu *self) {
if (self->shown) {
XUnmapWindow(ob_display, self->frame);
self->shown = FALSE;
+ if (self->open_submenu)
+ menu_hide(self->open_submenu);
+ if (self->parent && self->parent->open_submenu == self)
+ self->parent->open_submenu = NULL;
+
}
}
@@ -251,29 +305,6 @@ MenuEntry *menu_find_entry(Menu *menu, Window win)
return NULL;
}
-void menu_entry_render(MenuEntry *self)
-{
- Menu *menu = self->parent;
- Appearance *a;
-
- a = !self->enabled ? self->a_disabled :
- (self->hilite && self->action ? self->a_hilite : self->a_item);
-
- RECT_SET(a->area, 0, 0, menu->width,
- menu->item_h);
- RECT_SET(a->texture[0].position, menu->bullet_w,
- 0, menu->width - 2 * menu->bullet_w,
- menu->item_h);
-
- XMoveResizeWindow(ob_display, self->item, 0, self->y,
- menu->width, menu->item_h);
- a->surface.data.planar.parent = menu->a_items;
- a->surface.data.planar.parentx = 0;
- a->surface.data.planar.parenty = self->y;
-
- paint(self->item, a);
-}
-
void menu_entry_fire(MenuEntry *self)
{
Menu *m;
@@ -294,11 +325,52 @@ void menu_entry_fire(MenuEntry *self)
*/
void menu_control_show(Menu *self, int x, int y, Client *client) {
- XMoveWindow(ob_display, self->frame, x, y);
+ 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));
+
+ if (!self->shown) {
+ stacking_raise_internal(self->frame);
+ XMapWindow(ob_display, self->frame);
+ self->shown = TRUE;
+ } else if (self->shown && self->open_submenu) {
+ menu_hide(self->open_submenu);
+ }
+}
- if (!self->shown) {
- stacking_raise_internal(self->frame);
- XMapWindow(ob_display, self->frame);
- self->shown = TRUE;
- }
+void menu_control_mouseover(MenuEntry *self, gboolean enter) {
+ int x;
+ self->hilite = enter;
+
+ if (enter) {
+ if (self->parent->open_submenu && self->submenu
+ != self->parent->open_submenu)
+ menu_hide(self->parent->open_submenu);
+
+ if (self->submenu) {
+ self->parent->open_submenu = self->submenu;
+
+ /* shouldn't be invalid since it must be displayed */
+ g_assert(!self->parent->invalid);
+ /* TODO: I don't understand why these bevels should be here.
+ Something must be wrong in the width calculation */
+ x = self->parent->location.x + self->parent->size.width +
+ theme_bevel;
+
+ /* need to get the width. is this bad?*/
+ menu_render(self->submenu);
+
+ if (self->submenu->size.width + x > screen_physical_size.width)
+ x = self->parent->location.x - self->submenu->size.width -
+ theme_bevel;
+
+ menu_show_full(self->submenu, x,
+ self->parent->location.y + self->y, NULL);
+ }
+ }
}
diff --git a/openbox/menu.h b/openbox/menu.h
index 1a3f002a..081b3528 100644
--- a/openbox/menu.h
+++ b/openbox/menu.h
@@ -3,15 +3,19 @@
#include "action.h"
#include "render/render.h"
+#include "geom.h"
#include <glib.h>
extern GHashTable *menu_map;
struct Menu;
+struct MenuEntry;
typedef void(*menu_controller_show)(struct Menu *self, int x, int y, Client *);
typedef void(*menu_controller_update)(struct Menu *self);
+typedef void(*menu_controller_mouseover)(struct MenuEntry *self,
+ gboolean enter);
typedef struct Menu {
char *label;
@@ -23,6 +27,8 @@ typedef struct Menu {
gboolean invalid;
struct Menu *parent;
+
+ struct Menu *open_submenu;
/* place a menu on screen */
menu_controller_show show;
@@ -30,7 +36,7 @@ typedef struct Menu {
/* render a menu */
menu_controller_update update;
- void (*mouseover)( /* some bummu */);
+ menu_controller_mouseover mouseover;
void (*selected)( /* some bummu */);
@@ -44,7 +50,12 @@ typedef struct Menu {
Appearance *a_items;
int bullet_w;
int item_h;
- int width;
+ Point location;
+ Size size;
+
+ /* plugin stuff */
+ char *plugin;
+ void *plugin_data;
} Menu;
typedef enum MenuEntryRenderType {
@@ -89,6 +100,8 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
void menu_free(char *name);
void menu_show(char *name, int x, int y, Client *client);
+void menu_show_full(Menu *menu, int x, int y, Client *client);
+
void menu_hide(Menu *self);
MenuEntry *menu_entry_new_full(char *label, Action *action,
@@ -96,7 +109,16 @@ MenuEntry *menu_entry_new_full(char *label, Action *action,
gpointer submenu);
#define menu_entry_new(label, action) \
- menu_entry_new_full(label, action, MenuEntryRenderType_None, NULL)
+menu_entry_new_full(label, action, MenuEntryRenderType_None, NULL)
+
+#define menu_entry_new_separator(label) \
+menu_entry_new_full(label, NULL, MenuEntryRenderType_Separator, NULL)
+
+#define menu_entry_new_submenu(label, submenu) \
+menu_entry_new_full(label, NULL, MenuEntryRenderType_Submenu, submenu)
+
+#define menu_entry_new_boolean(label, action) \
+menu_entry_new_full(label, action, MenuEntryRenderType_Boolean, NULL)
void menu_entry_free(MenuEntry *entry);
@@ -112,4 +134,5 @@ void menu_entry_fire(MenuEntry *self);
void menu_render(Menu *self);
+void menu_control_mouseover(MenuEntry *entry, gboolean enter);
#endif
diff --git a/openbox/menu_render.c b/openbox/menu_render.c
index cf961f24..6a95fcbb 100644
--- a/openbox/menu_render.c
+++ b/openbox/menu_render.c
@@ -4,21 +4,36 @@
#include "openbox.h"
#include "render/theme.h"
+void menu_render_full(Menu *self);
+
void menu_render(Menu *self) {
+ if (self->invalid) {
+ if (self->update) {
+ self->update(self);
+ } else {
+ menu_render_full(self);
+ }
+ }
+}
+
+
+void menu_render_full(Menu *self) {
GList *it;
- int items_h;
+ int items_h = 0;
int nitems = 0; /* each item, only one is used */
int item_y;
- self->width = 1;
- self->item_h = 0;
+ self->size.width = 1;
+ self->item_h = 1;
/* set texture data and size them mofos out */
- self->a_title->texture[0].data.text.string = self->label;
- appearance_minsize(self->a_title, &self->title_min_w, &self->title_h);
- self->title_min_w += theme_bevel * 2;
- self->title_h += theme_bevel * 2;
- self->width = MAX(self->width, self->title_min_w);
+ if (self->label) {
+ self->a_title->texture[0].data.text.string = self->label;
+ appearance_minsize(self->a_title, &self->title_min_w, &self->title_h);
+ self->title_min_w += theme_bevel * 2;
+ self->title_h += theme_bevel * 2;
+ self->size.width = MAX(self->size.width, self->title_min_w);
+ }
for (it = self->entries; it; it = it->next) {
MenuEntry *e = it->data;
@@ -26,39 +41,44 @@ void menu_render(Menu *self) {
e->a_item->texture[0].data.text.string = e->label;
appearance_minsize(e->a_item, &e->min_w, &self->item_h);
- self->width = MAX(self->width, e->min_w);
+ self->size.width = MAX(self->size.width, e->min_w);
e->a_disabled->texture[0].data.text.string = e->label;
appearance_minsize(e->a_disabled, &e->min_w, &h);
self->item_h = MAX(self->item_h, h);
- self->width = MAX(self->width, e->min_w);
-
+ self->size.width = MAX(self->size.width, e->min_w);
+
e->a_hilite->texture[0].data.text.string = e->label;
appearance_minsize(e->a_hilite, &e->min_w, &h);
self->item_h = MAX(self->item_h, h);
- self->width = MAX(self->width, e->min_w);
+ self->size.width = MAX(self->size.width, e->min_w);
e->min_w += theme_bevel * 2;
++nitems;
}
self->bullet_w = self->item_h + theme_bevel;
- self->width += 2 * self->bullet_w;
+ self->size.width += 2 * self->bullet_w + 2 * theme_bevel;
self->item_h += theme_bevel * 2;
- items_h = self->item_h * nitems;
+ items_h = self->item_h * MAX(nitems, 1);
+
+ if (self->label) {
+ RECT_SET(self->a_title->area, 0, 0, self->size.width, self->title_h);
+ RECT_SET(self->a_title->texture[0].position, 0, 0, self->size.width,
+ self->title_h);
+ }
- RECT_SET(self->a_title->area, 0, 0, self->width, self->title_h);
- RECT_SET(self->a_title->texture[0].position, 0, 0, self->width,
- self->title_h);
- RECT_SET(self->a_items->area, 0, 0, self->width, items_h);
+ RECT_SET(self->a_items->area, 0, 0, self->size.width, items_h);
- XResizeWindow(ob_display, self->frame, self->width,
- self->title_h + items_h);
- XMoveResizeWindow(ob_display, self->title, -theme_bwidth, -theme_bwidth,
- self->width, self->title_h);
+ XResizeWindow(ob_display, self->frame, self->size.width,
+ MAX(self->title_h + items_h, 1));
+ if (self->label)
+ XMoveResizeWindow(ob_display, self->title, -theme_bwidth,
+ -theme_bwidth, self->size.width, self->title_h);
XMoveResizeWindow(ob_display, self->items, 0, self->title_h + theme_bwidth,
- self->width, items_h);
+ self->size.width, items_h);
- paint(self->title, self->a_title);
+ if (self->label)
+ paint(self->title, self->a_title);
paint(self->items, self->a_items);
item_y = 0;
@@ -67,6 +87,52 @@ void menu_render(Menu *self) {
menu_entry_render(it->data);
item_y += self->item_h;
}
-
+
+ self->size.height = item_y;
self->invalid = FALSE;
}
+
+void menu_entry_render(MenuEntry *self)
+{
+ Menu *menu = self->parent;
+ Appearance *a;
+
+ switch (self->render_type) {
+ case MenuEntryRenderType_Submenu:
+ /* TODO: submenu mask */
+ case MenuEntryRenderType_Boolean:
+ /* TODO: boolean check */
+ a = self->enabled ? (self->hilite ? self->a_hilite : self->a_item)
+ : self->a_disabled;
+ break;
+ case MenuEntryRenderType_None:
+ a = self->enabled ? (self->hilite ? self->a_hilite : self->a_item )
+ : self->a_disabled;
+ break;
+ case MenuEntryRenderType_Separator:
+ a = self->a_item;
+ break;
+
+ default:
+ g_message("unhandled render_type");
+ a = !self->enabled ? self->a_disabled :
+ (self->hilite &&
+ (self->action || self->render_type == MenuEntryRenderType_Submenu) ?
+ self->a_hilite : self->a_item);
+ break;
+ }
+
+ RECT_SET(a->area, 0, 0, menu->size.width,
+ menu->item_h);
+ RECT_SET(a->texture[0].position, menu->bullet_w,
+ 0, menu->size.width - 2 * menu->bullet_w,
+ menu->item_h);
+
+ XMoveResizeWindow(ob_display, self->item, 0, self->y,
+ menu->size.width, menu->item_h);
+ a->surface.data.planar.parent = menu->a_items;
+ a->surface.data.planar.parentx = 0;
+ a->surface.data.planar.parenty = self->y;
+
+ paint(self->item, a);
+}
diff --git a/openbox/plugin.c b/openbox/plugin.c
index c3e21ec4..a5055de9 100644
--- a/openbox/plugin.c
+++ b/openbox/plugin.c
@@ -4,6 +4,8 @@
typedef void (*PluginSetupConfig)();
typedef void (*PluginStartup)();
typedef void (*PluginShutdown)();
+typedef void *(*PluginCreate)(/* TODO */);
+typedef void (*PluginDestroy)(void *);
typedef struct {
GModule *module;
@@ -12,14 +14,18 @@ typedef struct {
PluginSetupConfig config;
PluginStartup startup;
PluginShutdown shutdown;
+ PluginCreate create;
+ PluginDestroy destroy;
} Plugin;
-static gpointer load_sym(GModule *module, char *name, char *symbol)
+static gpointer load_sym(GModule *module, char *name, char *symbol,
+ gboolean allow_fail)
{
gpointer var;
if (!g_module_symbol(module, symbol, &var)) {
- g_warning("Failed to load symbol '%s' from plugin '%s'",
- symbol, name);
+ if (!allow_fail)
+ g_warning("Failed to load symbol '%s' from plugin '%s'",
+ symbol, name);
var = NULL;
}
return var;
@@ -50,9 +56,14 @@ static Plugin *plugin_new(char *name)
}
p->config = (PluginSetupConfig)load_sym(p->module, name,
- "plugin_setup_config");
- p->startup = (PluginStartup)load_sym(p->module, name, "plugin_startup");
- p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown");
+ "plugin_setup_config", FALSE);
+ p->startup = (PluginStartup)load_sym(p->module, name, "plugin_startup",
+ FALSE);
+ p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown",
+ FALSE);
+ p->create = (PluginCreate)load_sym(p->module, name, "plugin_create", TRUE);
+ p->destroy = (PluginDestroy)load_sym(p->module, name, "plugin_destroy",
+ TRUE);
if (p->config == NULL || p->startup == NULL || p->shutdown == NULL) {
g_module_close(p->module);
@@ -85,12 +96,13 @@ void plugin_shutdown()
g_datalist_clear(&plugins);
}
-gboolean plugin_open(char *name)
+gboolean plugin_open_full(char *name, gboolean reopen)
{
Plugin *p;
if (g_datalist_get_data(&plugins, name) != NULL) {
- g_warning("plugin '%s' already loaded, can't load again", name);
+ if (!reopen)
+ g_warning("plugin '%s' already loaded, can't load again", name);
return TRUE;
}
@@ -105,6 +117,14 @@ gboolean plugin_open(char *name)
return TRUE;
}
+gboolean plugin_open(char *name) {
+ return plugin_open_full(name, FALSE);
+}
+
+gboolean plugin_open_reopen(char *name) {
+ return plugin_open_full(name, TRUE);
+}
+
void plugin_close(char *name)
{
g_datalist_remove_data(&plugins, name);
@@ -156,3 +176,41 @@ void plugin_loadall()
g_io_channel_unref(io);
}
}
+
+void *plugin_create(char *name /* TODO */)
+{
+ Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name);
+
+ if (p == NULL) {
+ g_warning("Unable to find plugin for create: %s", name);
+ return NULL;
+ }
+
+ if (p->create == NULL || p->destroy == NULL) {
+ g_critical("Unsupported create/destroy: %s", name);
+ return NULL;
+ }
+
+ return p->create();
+}
+
+void plugin_destroy(char *name, void *data)
+{
+ Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name);
+
+ if (p == NULL) {
+ g_critical("Unable to find plugin for destroy: %s", name);
+ /* really shouldn't happen, but attempt to free something anyway? */
+ g_free(data);
+ return;
+ }
+
+ if (p->destroy == NULL || p->create == NULL) {
+ g_critical("Unsupported create/destroy: %s", name);
+ /* really, really shouldn't happen, but attempt to free anyway? */
+ g_free(data);
+ return;
+ }
+
+ p->destroy(data);
+}
diff --git a/openbox/plugin.h b/openbox/plugin.h
index 8595fbac..733f564b 100644
--- a/openbox/plugin.h
+++ b/openbox/plugin.h
@@ -7,7 +7,15 @@ void plugin_shutdown();
void plugin_loadall();
void plugin_startall();
+/* default plugin */
gboolean plugin_open(char *name);
+/* load a plugin, but don't warn about reopens. for menus */
+gboolean plugin_open_reopen(char *name);
void plugin_close(char *name);
+/* call plugin's generic constructor */
+void *plugin_create(char *name /* TODO */);
+/* free memory allocated by plugin_create() */
+void plugin_destroy(char *name, void *object);
+
#endif
diff --git a/openbox/timer.c b/openbox/timer.c
index b6a82cd3..e4591544 100644
--- a/openbox/timer.c
+++ b/openbox/timer.c
@@ -15,7 +15,7 @@ static long timecompare(GTimeVal *a, GTimeVal *b)
long r;
if ((r = b->tv_sec - a->tv_sec)) return r;
- return b->tv_usec - a->tv_sec;
+ return b->tv_usec - a->tv_usec;
}
@@ -108,7 +108,7 @@ void timer_dispatch(GTimeVal **wait)
/* the queue is sorted, so if this timer shouldn't fire, none are
ready */
- if (timecompare(&now, &NEAREST_TIMEOUT) <= 0)
+ if (timecompare(&NEAREST_TIMEOUT, &now) <= 0)
break;
/* we set the last fired time to delay msec after the previous firing,