This patch is adding the app icon in between the flags icon and
the window name from the window list.
Feature request from
https://github.com/window-maker/wmaker/issues/19and reddit.
---
src/menu.c | 31 ++++++++++++++++++++++++++++++
src/menu.h | 1 +
src/switchmenu.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+)
diff --git a/src/menu.c b/src/menu.c
index e84b1caa..7806372a 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -267,6 +267,7 @@ WMenuEntry *wMenuInsertCallback(WMenu *menu, int index, const char *text,
entry = wmalloc(sizeof(WMenuEntry));
entry->flags.enabled = 1;
entry->text = wstrdup(text);
+
entry->icon = NULL;
entry->cascade = -1;
entry->clientdata = clientdata;
entry->callback = callback;
@@ -369,6 +370,9 @@ void wMenuRemoveItem(WMenu * menu, int index)
if (menu->entries[index]->text)
wfree(menu->entries[index]->text);
+
if (menu->entries[index]->icon)
+
wPixmapDestroy(menu->entries[index]->icon);
+
if (menu->entries[index]->rtext)
wfree(menu->entries[index]->rtext);
@@ -499,6 +503,10 @@ void wMenuRealize(WMenu * menu)
text = menu->entries[i]->text;
width = WMWidthOfString(scr->menu_entry_font, text, strlen(text)) + 10;
+
if (menu->entries[i]->icon) {
+
width += menu->entries[i]->icon->width + 4;
+
}
+
if (menu->entries[i]->flags.indicator) {
width += MENU_INDICATOR_SPACE;
}
@@ -562,6 +570,9 @@ void wMenuDestroy(WMenu * menu, int recurse)
wfree(menu->entries[i]->text);
+
if (menu->entries[i]->icon)
+
wPixmapDestroy(menu->entries[i]->icon);
+
if (menu->entries[i]->rtext)
wfree(menu->entries[i]->rtext);
#ifdef USER_MENU
@@ -711,6 +722,26 @@ static void paintEntry(WMenu * menu, int index, int selected)
if (entry->flags.indicator)
x += MENU_INDICATOR_SPACE + 2;
+
if (entry->icon && entry->icon->image != None) {
+
int ix = x;
+
int iy = y + (h - entry->icon->height) / 2;
+
+
if (entry->icon->mask != None) {
+
XSetClipMask(dpy, scr->copy_gc, entry->icon->mask);
+
XSetClipOrigin(dpy, scr->copy_gc, ix, iy);
+
} else {
+
XSetClipMask(dpy, scr->copy_gc, None);
+
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
+
}
+
+
XCopyArea(dpy, entry->icon->image, win, scr->copy_gc,
+
0, 0, entry->icon->width, entry->icon->height, ix, iy);
+
XSetClipMask(dpy, scr->copy_gc, None);
+
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
+
+
x += entry->icon->width + 4;
+
}
+
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font,
x, 3 + y + wPreferences.menu_text_clearance, entry->text, strlen(entry->text));
diff --git a/src/menu.h b/src/menu.h
index 60ff9555..036403bd 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -46,6 +46,7 @@ typedef struct WMenuEntry {
int order;
char *text;
/* entry text */
char *rtext;
/* text to show in the right part */
+
struct WPixmap *icon;
/* optional icon displayed before the text */
void (*callback)(struct WMenu *menu, struct WMenuEntry *entry);
void (*free_cdata)(void *data); /* proc to be used to free clientdata */
void *clientdata;
/* data to pass to callback */
diff --git a/src/switchmenu.c b/src/switchmenu.c
index 551b4e58..a8c3937f 100644
--- a/src/switchmenu.c
+++ b/src/switchmenu.c
@@ -48,6 +48,50 @@ static int initialized = 0;
static void observer(void *self, WMNotification * notif);
static void wsobserver(void *self, WMNotification * notif);
+static WPixmap *switchMenuIconForWindow(WScreen *scr, WWindow *wwin)
+{
+
RImage *image = NULL;
+
WPixmap *pix;
+
WApplication *wapp;
+
int max_size;
+
+
if (!scr || !wwin)
+
return NULL;
+
+
max_size = WMFontHeight(scr->menu_entry_font) + 2;
+
if (max_size < 12)
+
max_size = 12;
+
+
/* Prefer the actual appicon image when available */
+
wapp = wApplicationOf(wwin->main_window);
+
if (wapp && wapp->app_icon && wapp->app_icon->icon && wapp->app_icon->icon->file_image) {
+
image = RRetainImage(wapp->app_icon->icon->file_image);
+
}
+
+
/* Fall back to _NET_WM_ICON, then the default icon */
+
if (!image && !WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
+
image = RRetainImage(wwin->net_icon_image);
+
if (!image)
+
image = get_icon_image(scr, wwin->wm_instance, wwin->wm_class, max_size);
+
+
if (!image)
+
return NULL;
+
+
image = wIconValidateIconSize(image, max_size);
+
if (!image)
+
return NULL;
+
+
pix = wmalloc(sizeof(WPixmap));
+
memset(pix, 0, sizeof(WPixmap));
+
RConvertImageMask(scr->rcontext, image, &pix->image, &pix->mask, 128);
+
pix->width = image->width;
+
pix->height = image->height;
+
pix->depth = scr->w_depth;
+
+
RReleaseImage(image);
+
return pix;
+}
+
/*
* FocusWindow
*
@@ -216,6 +260,8 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
wfree(t);
+
entry->icon = switchMenuIconForWindow(scr, wwin);
+
entry->flags.indicator = 1;
entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH + 8);
if (IS_OMNIPRESENT(wwin))
@@ -273,6 +319,7 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
if (entry->rtext) {
int idx = -1;
char *t, *rt;
+
WPixmap *ipix;
int it, ion;
if (IS_OMNIPRESENT(wwin)) {
@@ -285,6 +332,8 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
rt = entry->rtext;
entry->rtext = NULL;
+
ipix = entry->icon;
+
entry->icon = NULL;
t = entry->text;
entry->text = NULL;
@@ -300,6 +349,7 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
wfree(t);
entry->rtext = rt;
+
entry->icon = ipix;
entry->flags.indicator = 1;
entry->flags.indicator_type = it;
entry->flags.indicator_on = ion;
--
2.43.0