From 2b8b2b03d0ca67ce25e72540e42abf91e7884db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Fri, 2 Jun 2023 13:56:09 -0400 Subject: [PATCH] Create a Pixmap for the icon rather than _NET_WM_ICON It seems whatever WM XWayland uses doesn't actually use _NET_WM_ICON like pretty much everything else for the last 30 years does, so we need to go old-school or settle for the default pengion icon, which offends me personally. --- src/conio/x_cio.c | 12 +++++++ src/conio/x_events.c | 75 +++++++++++++++++++++++++++++++++++++++++++- src/conio/x_events.h | 3 ++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c index edb6de3baf..fc5da66959 100644 --- a/src/conio/x_cio.c +++ b/src/conio/x_cio.c @@ -333,6 +333,10 @@ int x_init(void) xp_dlclose(dl); return(-1); } + if((x11.XFreeGC=xp_dlsym(dl,XFreeGC))==NULL) { + xp_dlclose(dl); + return(-1); + } if((x11.XSelectInput=xp_dlsym(dl,XSelectInput))==NULL) { xp_dlclose(dl); return(-1); @@ -489,6 +493,14 @@ int x_init(void) return(-1); } #endif + if((x11.XGetWMHints=xp_dlsym(dl,XGetWMHints))==NULL) { + xp_dlclose(dl); + return(-1); + } + if((x11.XSetWMHints=xp_dlsym(dl,XSetWMHints))==NULL) { + xp_dlclose(dl); + return(-1); + } #ifdef WITH_XRENDER xrender_found = true; if ((dl2 = xp_dlopen(libnames2,RTLD_LAZY,7)) == NULL) { diff --git a/src/conio/x_events.c b/src/conio/x_events.c index c8950838db..4155e8571a 100644 --- a/src/conio/x_events.c +++ b/src/conio/x_events.c @@ -71,6 +71,9 @@ static Display *dpy=NULL; static Window win; static Cursor curs = None; static Visual *visual; +static Colormap wincmap; +static Pixmap icn; +static Pixmap icn_mask; static bool VisualIsRGB8 = false; static XImage *xim; static XIM im; @@ -458,7 +461,8 @@ static int init_window() /* Create window, but defer setting a size and GC. */ XSetWindowAttributes wa = {0}; - wa.colormap = x11.XCreateColormap(dpy, DefaultRootWindow(dpy), visual, AllocNone); + wincmap = x11.XCreateColormap(dpy, DefaultRootWindow(dpy), visual, AllocNone); + wa.colormap = wincmap; wa.background_pixel = black; wa.border_pixel = black; x11_get_maxsize(&mw, &mh); @@ -1533,6 +1537,8 @@ void x11_event_thread(void *args) x11.XBell(dpy, 100); break; case X11_LOCAL_SETICON: { +#if 0 + // This doesn't work on ChromeOS, presumably because XWayland sucks. Atom wmicon = x11.XInternAtom(dpy, "_NET_WM_ICON", False); if (wmicon) { x11.XChangeProperty(dpy, win, wmicon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)lev.data.icon_data, lev.data.icon_data[0] * lev.data.icon_data[1] + 2); @@ -1540,6 +1546,73 @@ void x11_event_thread(void *args) } free(lev.data.icon_data); break; +#else + Pixmap opm = icn; + Pixmap opmm = icn_mask; + XGCValues gcv = { + .function = GXcopy, + .foreground = black | 0xff000000, + .background = white + }; + icn = x11.XCreatePixmap(dpy, DefaultRootWindow(dpy), lev.data.icon_data[0], lev.data.icon_data[1], depth); + GC igc = x11.XCreateGC(dpy, icn, GCFunction | GCForeground | GCBackground | GCGraphicsExposures, &gcv); + icn_mask = x11.XCreatePixmap(dpy, DefaultRootWindow(dpy), lev.data.icon_data[0], lev.data.icon_data[1], 1); + GC imgc = x11.XCreateGC(dpy, icn_mask, GCFunction | GCForeground | GCBackground | GCGraphicsExposures, &gcv); + int x,y,i; + bool fail = (!icn) || (!icn_mask); + if (!fail) { + for (x = 0, i = 2; x < lev.data.icon_data[0]; x++) { + for (y = 0; y < lev.data.icon_data[1]; y++) { + XColor fg = {0}; + unsigned short tmp; + if (lev.data.icon_data[i] & 0xff000000) { + tmp = (lev.data.icon_data[i] & 0xff0000) >> 16; + fg.red = tmp << 8 | tmp; + tmp = (lev.data.icon_data[i] & 0xff00) >> 8; + fg.green = tmp << 8 | tmp; + tmp = (lev.data.icon_data[i] & 0xff); + fg.blue = tmp << 8 | tmp; + fg.flags = DoRed | DoGreen | DoBlue; + if (x11.XAllocColor(dpy, wincmap, &fg) == 0) + fail = true; + else { + x11.XSetForeground(dpy, igc, fg.pixel); + x11.XDrawPoint(dpy, icn, igc, y, x); + x11.XSetForeground(dpy, imgc, white); + x11.XDrawPoint(dpy, icn_mask, imgc, y, x); + } + if (fail) + break; + } + else { + x11.XSetForeground(dpy, imgc, black); + x11.XDrawPoint(dpy, icn_mask, imgc, y, x); + } + i++; + } + if (fail) + break; + } + } + if (!fail) { + XWMHints *hints = x11.XGetWMHints(dpy, win); + if (!hints) + hints = x11.XAllocWMHints(); + if (hints) { + hints->flags |= IconPixmapHint | IconMaskHint; + hints->icon_pixmap = icn; + hints->icon_mask = icn_mask; + x11.XSetWMHints(dpy, win, hints); + x11.XFree(hints); + if (opm) + x11.XFreePixmap(dpy, opm); + if (opmm) + x11.XFreePixmap(dpy, opmm); + } + } + x11.XFreeGC(dpy, igc); + x11.XFreeGC(dpy, imgc); +#endif } case X11_LOCAL_MOUSEPOINTER: { unsigned shape = UINT_MAX; diff --git a/src/conio/x_events.h b/src/conio/x_events.h index 3496795b27..b611981f7f 100644 --- a/src/conio/x_events.h +++ b/src/conio/x_events.h @@ -62,6 +62,7 @@ struct x11 { int (*XCloseDisplay) (Display*); Window (*XCreateSimpleWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*); + int (*XFreeGC) (Display*, GC); int (*XSelectInput) (Display*, Window, long); int (*XStoreName) (Display*, Window, _Xconst char*); Window (*XGetSelectionOwner) (Display*, Atom); @@ -102,6 +103,8 @@ struct x11 { int (*XDefineCursor)(Display *display, Window w, Cursor cursor); int (*XFreeCursor)(Display *display, Cursor cursor); Status (*XGetGeometry)(Display *, Drawable, Window *, int *, int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *); + XWMHints *(*XGetWMHints)(Display *, Window); + int (*XSetWMHints)(Display *, Window, XWMHints *); #ifndef DefaultDepth int (*DefaultDepth)(Display *, int); #endif -- GitLab