icon works

This commit is contained in:
Nishi 2025-12-30 00:49:56 +09:00
commit 16e1bd9c89
Signed by: nishi
GPG key ID: 27EF69B208EB9343
5 changed files with 141 additions and 10 deletions

View file

@ -49,6 +49,8 @@ int wm_content_width(int entire);
int wm_content_height(int entire);
int wm_content_x(void);
int wm_content_y(void);
int wm_set_icon_by_name(MwWidget widget, const char* cat, const char* name);
void wm_set_icon(MwWidget widget, unsigned char* data, int width, int height);
/* config.c */
extern xemil_t* wm_config;

View file

@ -7,7 +7,7 @@
<Button>
<Left>
<!-- Ordered from left to right -->
<Close />
<Menu />
</Left>
<Right>
<!-- Ordered from right to left -->

View file

@ -14,6 +14,8 @@ typedef struct wmframe {
MwWidget* left;
MwWidget* right;
MwWidget menu_button;
MwLLPixmap maximize;
MwLLPixmap restore;
MwLLPixmap iconify;
@ -200,6 +202,8 @@ static void apply_button(MwWidget widget, const char* str) {
MwAddUserHandler(widget, MwNactivateHandler, maximize, w);
} else if(strcmp(str, "Iconify") == 0) {
px = f->iconify;
} else if(strcmp(str, "Menu") == 0) {
f->menu_button = widget;
}
if(px != NULL) {
@ -321,6 +325,8 @@ MwWidget wm_frame(int w, int h) {
f->maximized = 0;
f->dragging = 0;
f->menu_button = NULL;
icon = malloc(10 * 6 * 4);
memset(icon, 0, 10 * 6 * 4);
@ -414,6 +420,8 @@ MwWidget wm_frame(int w, int h) {
pthread_mutex_unlock(&xmutex);
wm_set_icon_by_name(wnd, NULL, "unknown");
return wnd;
}
@ -443,6 +451,54 @@ void wm_set_name(MwWidget widget, const char* name) {
pthread_mutex_unlock(&xmutex);
}
int wm_set_icon_by_name(MwWidget widget, const char* cat, const char* name) {
wmframe_t* f = widget->opaque;
MwLLPixmap px = NULL;
int st = 0;
pthread_mutex_lock(&xmutex);
if(f->menu_button != NULL) {
char* p;
if((px = MwGetVoid(f->menu_button, MwNpixmap)) != NULL) {
MwLLDestroyPixmap(px);
px = NULL;
}
if((p = MDEIconLookUp(cat == NULL ? "Applications" : cat, name, 16)) != NULL) {
px = MwLoadImage(f->menu_button, p);
free(p);
}
MwSetVoid(f->menu_button, MwNpixmap, px);
}
pthread_mutex_unlock(&xmutex);
if(px != NULL) st = 1;
return st;
}
void wm_set_icon(MwWidget widget, unsigned char* data, int width, int height) {
wmframe_t* f = widget->opaque;
MwLLPixmap px = NULL;
pthread_mutex_lock(&xmutex);
if(f->menu_button != NULL) {
if((px = MwGetVoid(f->menu_button, MwNpixmap)) != NULL) {
MwLLDestroyPixmap(px);
px = NULL;
}
px = MwLoadRaw(f->menu_button, data, width, height);
MwSetVoid(f->menu_button, MwNpixmap, px);
}
pthread_mutex_unlock(&xmutex);
}
static char tmp_bg[64];
MwLLPixmap lookup_col(MwWidget widget, const char* bgfg, const char* type, const char** bg) {

View file

@ -333,18 +333,88 @@ static int parent_eq(Window wnd, Window might_be_parent) {
return 0;
}
static void set_name(Window wnd) {
static void set_stuff(Window wnd) {
Atom type;
int format;
unsigned long nitem, after;
unsigned char* buf = NULL;
Atom atom = XInternAtom(xdisplay, "WM_NAME", False);
Atom utf8 = XInternAtom(xdisplay, "UTF8_STRING", False);
unsigned char* buf = NULL;
Atom atom_name = XInternAtom(xdisplay, "WM_NAME", False);
Atom atom_icon = XInternAtom(xdisplay, "_NET_WM_ICON", False);
Atom utf8 = XInternAtom(xdisplay, "UTF8_STRING", False);
int i;
for(i = 0; i < arrlen(windows); i++) {
if(windows[i].client == wnd) {
if(XGetWindowProperty(xdisplay, wnd, atom, 0, 1024, False, AnyPropertyType, &type, &format, &nitem, &after, &buf) == Success && buf != NULL) {
XClassHint* ch = XAllocClassHint();
int def = 1;
int l = 0;
int wid = 2048, hei = 2048;
unsigned char* data = NULL;
while(1) {
l += 2;
if(def && XGetWindowProperty(xdisplay, wnd, atom_icon, l - 2, 2, False, XA_CARDINAL, &type, &format, &nitem, &after, &buf) == Success && buf != NULL) {
if(nitem == 2) {
long* b = (long*)buf;
int w = b[0], h = b[1];
l += w * h;
XFree(buf);
if(w <= 1024 && h <= 1024) {
if(w == 16 || h == 16 || w < wid || h < hei) {
if(data != NULL) free(data);
data = malloc(4 * w * h);
if(XGetWindowProperty(xdisplay, wnd, atom_icon, l - w * h, w * h, False, XA_CARDINAL, &type, &format, &nitem, &after, &buf) == Success && buf != NULL) {
if(nitem == w * h) {
int i;
b = (long*)buf;
for(i = 0; i < w * h; i++) {
data[4 * i + 0] = (b[i] >> 16) & 0xff;
data[4 * i + 1] = (b[i] >> 8) & 0xff;
data[4 * i + 2] = (b[i] >> 0) & 0xff;
data[4 * i + 3] = (b[i] >> 24) & 0xff;
}
}
XFree(buf);
}
wid = w;
hei = h;
}
}
} else {
XFree(buf);
break;
}
} else {
break;
}
}
if(def && data != NULL) {
wm_set_icon(windows[i].frame, data, wid, hei);
free(data);
def = 0;
}
if(def && XGetClassHint(xdisplay, wnd, ch)) {
if(wm_set_icon_by_name(windows[i].frame, NULL, ch->res_name)) def = 0;
}
XFree(ch);
if(def) {
wm_set_icon_by_name(windows[i].frame, NULL, "unknown");
}
if(XGetWindowProperty(xdisplay, wnd, atom_name, 0, 1024, False, AnyPropertyType, &type, &format, &nitem, &after, &buf) == Success && buf != NULL) {
if(type == XA_STRING || type == utf8) wm_set_name(windows[i].frame, buf);
XFree(buf);
}
@ -409,7 +479,7 @@ void loop_x(void) {
arrput(windows, w);
set_name(w.client);
set_stuff(w.client);
}
}
XFree(children);
@ -617,7 +687,7 @@ void loop_x(void) {
} else {
arrput(windows, w);
set_name(w.client);
set_stuff(w.client);
}
XGetWindowAttributes(xdisplay, DefaultRootWindow(xdisplay), &xwar);
@ -635,8 +705,8 @@ void loop_x(void) {
}
if(arrlen(windows) == i) continue;
if(ev.xproperty.atom == XInternAtom(xdisplay, "WM_NAME", False)) {
set_name(windows[i].client);
if(ev.xproperty.atom == XInternAtom(xdisplay, "WM_NAME", False) || ev.xproperty.atom == XInternAtom(xdisplay, "WM_CLASS", False) || ev.xproperty.atom == XInternAtom(xdisplay, "_NET_WM_ICON", False)) {
set_stuff(windows[i].client);
}
} else if(ev.type == MapNotify) {
int i;

View file

@ -23,6 +23,9 @@
<Launcher ID="2">
<Execute Icon="firefox">firefox</Execute>
<Execute Icon="terminal">uxterm</Execute>
<Execute Icon="gimp">gimp</Execute>
<Execute Icon="unknown">xmms</Execute>
<Execute Icon="mbiff">mbiff</Execute>
</Launcher>
<Separator ID="3" />