improved algorithm for mapping/unmapping
In previous versions, all the previous current visible menus are unmapped and the new currently visible menus are mapped when the current visible menu changed. Now, using an algorithm that finds the lowest common ancestor between current and current_new menus, only the necessary menus are remapped on the display.
This commit is contained in:
parent
d888f2cae4
commit
d8a7caf2e3
66
xmenu.c
66
xmenu.c
|
@ -9,6 +9,7 @@
|
||||||
/* macros */
|
/* macros */
|
||||||
#define LEN(x) (sizeof (x) / sizeof (x[0]))
|
#define LEN(x) (sizeof (x) / sizeof (x[0]))
|
||||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||||
|
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||||
|
|
||||||
/* color enum */
|
/* color enum */
|
||||||
enum {ColorFG, ColorBG, ColorLast};
|
enum {ColorFG, ColorBG, ColorLast};
|
||||||
|
@ -42,25 +43,25 @@ struct ScreenGeometry {
|
||||||
|
|
||||||
/* menu item structure */
|
/* menu item structure */
|
||||||
struct Item {
|
struct Item {
|
||||||
char *label;
|
char *label; /* string to be drawed on menu */
|
||||||
char *output;
|
char *output; /* string to be outputed when item is clicked */
|
||||||
int y;
|
int y; /* item y position relative to menu */
|
||||||
int h;
|
int h; /* item height */
|
||||||
size_t labellen;
|
size_t labellen; /* strlen(label) */
|
||||||
struct Item *next;
|
struct Item *next; /* next item */
|
||||||
struct Menu *submenu;
|
struct Menu *submenu; /* submenu spawned by clicking on item */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* menu structure */
|
/* menu structure */
|
||||||
struct Menu {
|
struct Menu {
|
||||||
struct Menu *parent;
|
struct Menu *parent; /* parent menu */
|
||||||
struct Item *caller;
|
struct Item *caller; /* item that spawned the menu */
|
||||||
struct Item *list;
|
struct Item *list; /* list of items contained by the menu */
|
||||||
struct Item *selected;
|
struct Item *selected; /* item currently selected in the menu */
|
||||||
int x, y, w, h;
|
int x, y, w, h; /* menu geometry */
|
||||||
unsigned level;
|
unsigned level; /* menu level relative to root */
|
||||||
Drawable pixmap;
|
Drawable pixmap; /* pixmap to draw the menu on */
|
||||||
Window win;
|
Window win; /* menu window to map on the screen */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
|
@ -138,6 +139,10 @@ main(int argc, char *argv[])
|
||||||
calcscreengeom();
|
calcscreengeom();
|
||||||
calcmenu(rootmenu);
|
calcmenu(rootmenu);
|
||||||
|
|
||||||
|
/* map root menu */
|
||||||
|
currmenu = rootmenu;
|
||||||
|
XMapWindow(dpy, rootmenu->win);
|
||||||
|
|
||||||
/* run event loop */
|
/* run event loop */
|
||||||
run();
|
run();
|
||||||
|
|
||||||
|
@ -454,20 +459,45 @@ done:
|
||||||
static void
|
static void
|
||||||
setcurrmenu(struct Menu *currmenu_new)
|
setcurrmenu(struct Menu *currmenu_new)
|
||||||
{
|
{
|
||||||
struct Menu *menu;
|
struct Menu *menu, *menu_;
|
||||||
struct Item *item;
|
struct Item *item;
|
||||||
|
struct Menu *lcamenu; /* lowest common ancestor menu */
|
||||||
|
unsigned minlevel; /* level of the closest to root menu */
|
||||||
|
unsigned maxlevel; /* level of the closest to root menu */
|
||||||
|
|
||||||
if (currmenu_new == currmenu)
|
if (currmenu_new == currmenu)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (menu = currmenu; menu != NULL; menu = menu->parent) {
|
/* find lowest common ancestor menu */
|
||||||
|
lcamenu = rootmenu;
|
||||||
|
if (currmenu != NULL) {
|
||||||
|
minlevel = MIN(currmenu_new->level, currmenu->level);
|
||||||
|
maxlevel = MAX(currmenu_new->level, currmenu->level);
|
||||||
|
if (currmenu_new->level == maxlevel) {
|
||||||
|
menu = currmenu_new;
|
||||||
|
menu_ = currmenu;
|
||||||
|
} else {
|
||||||
|
menu = currmenu;
|
||||||
|
menu_ = currmenu_new;
|
||||||
|
}
|
||||||
|
while (menu->level > minlevel)
|
||||||
|
menu = menu->parent;
|
||||||
|
|
||||||
|
while (menu != menu_) {
|
||||||
|
menu = menu->parent;
|
||||||
|
menu_ = menu_->parent;
|
||||||
|
}
|
||||||
|
lcamenu = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (menu = currmenu; menu != lcamenu; menu = menu->parent) {
|
||||||
XUnmapWindow(dpy, menu->win);
|
XUnmapWindow(dpy, menu->win);
|
||||||
}
|
}
|
||||||
|
|
||||||
currmenu = currmenu_new;
|
currmenu = currmenu_new;
|
||||||
|
|
||||||
item = NULL;
|
item = NULL;
|
||||||
for (menu = currmenu; menu != NULL; menu = menu->parent) {
|
for (menu = currmenu; menu != lcamenu; menu = menu->parent) {
|
||||||
XMapWindow(dpy, menu->win);
|
XMapWindow(dpy, menu->win);
|
||||||
if (item != NULL)
|
if (item != NULL)
|
||||||
menu->selected = item;
|
menu->selected = item;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user