mirror of
https://github.com/gryf/wmaker.git
synced 2026-03-19 09:13:33 +01:00
wmaker: add window app icon to the window list
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/19 It is disabled by default, it needs WindowListAppIcons to be set to YES manually in the conf file or "Show app icons in window list." enabled from WPrefs expert panel.
This commit is contained in:
committed by
Carlos R. Mafra
parent
ae6b03e50f
commit
2901b418ad
@@ -78,6 +78,9 @@ static struct expert_option {
|
||||
{ N_("Ignore minimized windows when cycling."),
|
||||
/* default: */ False, OPTION_WMAKER, "CycleIgnoreMinimized" },
|
||||
|
||||
{ N_("Show app icons in window list."),
|
||||
/* default: */ False, OPTION_WMAKER, "WindowListAppIcons" },
|
||||
|
||||
{ N_("Show switch panel when cycling windows."),
|
||||
/* default: */ True, OPTION_WMAKER_ARRAY, "SwitchPanelImages" },
|
||||
|
||||
|
||||
@@ -254,4 +254,5 @@
|
||||
CycleActiveHeadOnly = NO;
|
||||
CycleAllWorkspaces = NO;
|
||||
CycleIgnoreMinimized = NO;
|
||||
WindowListAppIcons = NO;
|
||||
}
|
||||
|
||||
@@ -479,6 +479,7 @@ extern struct WPreferences {
|
||||
int hot_corner_delay; /* Delay after which the hot corner is triggered */
|
||||
int hot_corner_edge; /* Hot corner edge size */
|
||||
char *hot_corner_actions[4]; /* Action of each corner */
|
||||
char window_list_app_icons; /* Show app icons in window list */
|
||||
|
||||
struct {
|
||||
#ifdef USE_ICCCM_WMREPLACE
|
||||
|
||||
@@ -534,6 +534,8 @@ WDefaultEntry optionList[] = {
|
||||
&wPreferences.hot_corner_edge, getInt, NULL, NULL, NULL},
|
||||
{"HotCornerActions", "(\"None\", \"None\", \"None\", \"None\")", &wPreferences,
|
||||
NULL, getPropList, setHotCornerActions, NULL, NULL},
|
||||
{"WindowListAppIcons", "NO", NULL,
|
||||
&wPreferences.window_list_app_icons, getBool, NULL, NULL, NULL},
|
||||
|
||||
/* style options */
|
||||
|
||||
|
||||
31
src/menu.c
31
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 (wPreferences.window_list_app_icons && 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 (wPreferences.window_list_app_icons && 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));
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user