use games patch

This commit is contained in:
2026-07-15 22:33:00 +02:00
parent e9a681783b
commit a3bca752da
10 changed files with 338 additions and 386 deletions

View File

@@ -25,7 +25,6 @@
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -52,6 +51,7 @@
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLEONTAG(C, T) ((C->tags & T))
#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
#define MINIMIZED(C) ((getstate(C->win) == IconicState))
#define HIDDEN(C) ((getstate(C->win) == IconicState))
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
@@ -79,7 +79,7 @@
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */
enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck,
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop, NetLast }; /* EWMH atoms */
@@ -115,9 +115,8 @@ struct Client {
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
unsigned int icw, ich;
Picture icon;
int issteam;
int isgame;
int fakefullscreen;
Client *next;
Client *snext;
@@ -172,6 +171,7 @@ typedef struct {
unsigned int tags;
int isfloating;
int monitor;
int isgame;
} Rule;
typedef struct Systray Systray;
@@ -188,7 +188,6 @@ static void arrangemon(Monitor *m);
static void attach(Client *c);
static void attachaside(Client *c);
static void attachstack(Client *c);
static uint32_t *bilinear_scale(const uint32_t *src, int sw, int sh, uint32_t dw, uint32_t dh);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
static void cleanup(void);
@@ -214,11 +213,9 @@ static void focusmon(const Arg *arg);
static void focusstackvis(const Arg *arg);
static void focusstackhid(const Arg *arg);
static void focusstack(int inc, int vis);
static void freeicon(Client *c);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static Picture geticonprop(Display *dpy, Window w, int iconsize, unsigned int *icw, unsigned int *ich);
static unsigned int getsystraywidth();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
@@ -232,6 +229,7 @@ static void losefullscreen(Client *next);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void minimize(Client *c);
static void monocle(Monitor *m);
static void motionnotify(XEvent *e);
static void movemouse(const Arg *arg);
@@ -239,7 +237,6 @@ static Client *nexttagged(Client *c);
static Client *nexttiled(Client *c);
static void placedir(const Arg *arg);
static void pop(Client *c);
static uint32_t prealpha(uint32_t p);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
@@ -289,12 +286,12 @@ static void togglewin(const Arg *arg);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
static void unmapnotify(XEvent *e);
static void unminimize(Client *c);
static void updatecurrentdesktop(void);
static void updatebarpos(Monitor *m);
static void updatebars(void);
static void updateclientlist(void);
static int updategeom(void);
static void updateicon(Client *c);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
@@ -427,6 +424,7 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
c->isgame = r->isgame;
if ((r->tags & SPTAGMASK) && r->isfloating) {
c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
@@ -559,57 +557,6 @@ attachstack(Client *c)
c->mon->stack = c;
}
uint32_t *
bilinear_scale(const uint32_t *src, int sw, int sh, unsigned int dw, unsigned int dh)
{
uint32_t *dst = calloc(dw * dh, sizeof(uint32_t));
if (!dst) return NULL;
for (int y = 0; y < dh; y++) {
/* Source position (in fixed-point) */
float sy = (y + 0.5f) * sh / (float)dh - 0.5f;
int y0 = (sy < 0) ? (int)(sy - 1) : (int)(sy);;
int y1 = y0 + 1;
float fy = sy - y0;
if (y0 < 0) { y0 = 0; y1 = 0; fy = 0; }
if (y1 >= sh) { y1 = sh-1; y0 = y1; fy = 0; }
for (int x = 0; x < dw; x++) {
float sx = (x + 0.5f) * sw / (float)dw - 0.5f;
int x0 = (sx < 0) ? (int)(sx - 1) : (int)(sx);
int x1 = x0 + 1;
float fx = sx - x0;
if (x0 < 0) { x0 = 0; x1 = 0; fx = 0; }
if (x1 >= sw) { x1 = sw-1; x0 = x1; fx = 0; }
uint32_t p00 = prealpha(src[y0*sw + x0]);
uint32_t p10 = prealpha(src[y0*sw + x1]);
uint32_t p01 = prealpha(src[y1*sw + x0]);
uint32_t p11 = prealpha(src[y1*sw + x1]);
/* Extract premultiplied channels */
int a00 = p00 >> 24, r00 = (p00 >> 16) & 0xFF, g00 = (p00 >> 8) & 0xFF, b00 = p00 & 0xFF;
int a10 = p10 >> 24, r10 = (p10 >> 16) & 0xFF, g10 = (p10 >> 8) & 0xFF, b10 = p10 & 0xFF;
int a01 = p01 >> 24, r01 = (p01 >> 16) & 0xFF, g01 = (p01 >> 8) & 0xFF, b01 = p01 & 0xFF;
int a11 = p11 >> 24, r11 = (p11 >> 16) & 0xFF, g11 = (p11 >> 8) & 0xFF, b11 = p11 & 0xFF;
/* Bilinear weights */
float w00 = (1.0f - fx) * (1.0f - fy);
float w10 = fx * (1.0f - fy);
float w01 = (1.0f - fx) * fy;
float w11 = fx * fy;
int a = (int)(a00*w00 + a10*w10 + a01*w01 + a11*w11 + 0.5f);
int r = (int)(r00*w00 + r10*w10 + r01*w01 + r11*w11 + 0.5f);
int g = (int)(g00*w00 + g10*w10 + g01*w01 + g11*w11 + 0.5f);
int b = (int)(b00*w00 + b10*w10 + b01*w01 + b11*w11 + 0.5f);
dst[y*dw + x] = (a << 24) | (r << 16) | (g << 8) | b;
}
}
return dst;
}
void
buttonpress(XEvent *e)
{
@@ -1057,12 +1004,7 @@ drawbar(Monitor *m)
}
remainder--;
}
if (c->icon) {
drw_text(drw, x, 0, w > m->ww - tw - stw - x ? m->ww - tw - stw - x : w, bh, lrpad / 2 + c->ich + iconspacing, c->name, 0);
drw_pic(drw, x + lrpad / 2, (bh - c->ich) / 2, c->icw, c->ich, c->icon);
} else {
drw_text(drw, x, 0, tabw > m->ww - tw - stw - x ? m->ww - tw - stw - x : tabw, bh, lrpad / 2, c->name, 0);
}
drw_text(drw, x, 0, tabw > m->ww - tw - stw - x ? m->ww - tw - stw - x : tabw, bh, lrpad / 2, c->name, 0);
x += tabw;
}
} else {
@@ -1290,15 +1232,6 @@ focusstack(int inc, int hid)
}
}
void
freeicon(Client *c)
{
if (c->icon) {
XRenderFreePicture(dpy, c->icon);
c->icon = None;
}
}
Atom
getatomprop(Client *c, Atom prop)
{
@@ -1361,104 +1294,6 @@ getstate(Window w)
return result;
}
/* geticonprop: read, scale, and return an XRender Picture */
Picture
geticonprop(Display *dpy, Window win, int iconsize, unsigned int *icw, unsigned int *ich) {
Atom net_wm_icon = XInternAtom(dpy, "_NET_WM_ICON", False);
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *data = NULL;
Picture pict = None;
if (XGetWindowProperty(dpy, win, net_wm_icon, 0, LONG_MAX, False, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after, &data) != Success || !data) {
return None;
}
unsigned long *p = (unsigned long *)data;
unsigned long *end = p + nitems;
/* Pick icon closest to desired size */
unsigned long *best = NULL;
unsigned long best_w = 0, best_h = 0;
unsigned long best_diff = ~0UL;
while (p + 2 < end) {
unsigned long w0 = *p++;
unsigned long h0 = *p++;
if (w0 == 0 || h0 == 0 || p + w0*h0 > end) break;
unsigned long diff = (w0 > (unsigned long)iconsize ? w0 - iconsize : iconsize - w0)
+ (h0 > (unsigned long)iconsize ? h0 - iconsize : iconsize - h0);
if (diff < best_diff) {
best_diff = diff;
best_w = w0;
best_h = h0;
best = p;
}
p += w0 * h0;
}
if (!best) {
XFree(data);
return None;
}
/* Copy into fixed 32-bit array */
uint32_t *src = malloc(best_w * best_h * sizeof(uint32_t));
for (size_t i = 0; i < best_w * best_h; i++)
src[i] = (uint32_t)best[i];
/* Scale */
int dst_w, dst_h;
if (best_w > best_h) {
dst_w = iconsize;
dst_h = best_h * iconsize / best_w;
} else {
dst_h = iconsize;
dst_w = best_w * iconsize / best_h;
}
uint32_t *scaled = bilinear_scale(src, best_w, best_h, dst_w, dst_h);
free(src);
XFree(data);
if (!scaled) return None;
/* Create pixmap and upload pixels */
Pixmap pm = XCreatePixmap(dpy, root, dst_w, dst_h, 32);
XImage img;
memset(&img, 0, sizeof img);
img.width = dst_w;
img.height = dst_h;
img.format = ZPixmap;
img.data = (char*)scaled;
img.byte_order = LSBFirst;
img.bitmap_unit = 32;
img.bitmap_bit_order = LSBFirst;
img.bitmap_pad = 32;
img.depth = 32;
img.bits_per_pixel = 32;
img.bytes_per_line = dst_w * 4;
XInitImage(&img);
GC gc = XCreateGC(dpy, pm, 0, NULL);
XPutImage(dpy, pm, gc, &img, 0, 0, 0, 0, dst_w, dst_h);
XFreeGC(dpy, gc);
XRenderPictFormat *fmt = XRenderFindStandardFormat(dpy, PictStandardARGB32);
pict = XRenderCreatePicture(dpy, pm, fmt, 0, NULL);
XFreePixmap(dpy, pm);
free(scaled);
*icw = dst_w;
*ich = dst_h;
return pict;
}
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1640,7 +1475,6 @@ manage(Window w, XWindowAttributes *wa)
c->oldbw = wa->border_width;
c->cfact = 1.0;
updateicon(c);
updatetitle(c);
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
@@ -1738,6 +1572,29 @@ maprequest(XEvent *e)
manage(ev->window, &wa);
}
void
minimize(Client *c)
{
if (!c || MINIMIZED(c))
return;
Window w = c->win;
static XWindowAttributes ra, ca;
// more or less taken directly from blackbox's hide() function
XGrabServer(dpy);
XGetWindowAttributes(dpy, root, &ra);
XGetWindowAttributes(dpy, w, &ca);
// prevent UnmapNotify events
XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask);
XUnmapWindow(dpy, w);
setclientstate(c, IconicState);
XSelectInput(dpy, root, ra.your_event_mask);
XSelectInput(dpy, w, ca.your_event_mask);
XUngrabServer(dpy);
}
void
monocle(Monitor *m)
{
@@ -1953,14 +1810,6 @@ pop(Client *c)
arrange(c->mon);
}
uint32_t
prealpha(uint32_t p) {
uint8_t a = p >> 24u;
uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u;
uint32_t g = (a * (p & 0x00FF00u)) >> 8u;
return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u);
}
void
propertynotify(XEvent *e)
{
@@ -2004,11 +1853,6 @@ propertynotify(XEvent *e)
if (c == c->mon->sel)
drawbar(c->mon);
}
if (ev->atom == netatom[NetWMIcon]) {
updateicon(c);
if (c == c->mon->sel)
drawbar(c->mon);
}
if (ev->atom == netatom[NetWMWindowType])
updatewindowtype(c);
}
@@ -2017,17 +1861,19 @@ propertynotify(XEvent *e)
void
quit(const Arg *arg)
{
// fix: reloading dwm keeps all the hidden clients hidden
Monitor *m;
Client *c;
for (m = mons; m; m = m->next) {
if (m) {
for (c = m->stack; c; c = c->next)
if (c && HIDDEN(c)) showwin(c);
if(arg->i) restart = 1;
if (!restart) {
// fix: reloading dwm keeps all the hidden clients hidden
Monitor *m;
Client *c;
for (m = mons; m; m = m->next) {
if (m) {
for (c = m->stack; c; c = c->next)
if (c && HIDDEN(c)) showwin(c);
}
}
}
if(arg->i) restart = 1;
running = 0;
}
@@ -2319,6 +2165,10 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
if (c->isgame && c->isfullscreen)
unminimize(c);
if (c->issteam)
setclientstate(c, NormalState);
@@ -2494,7 +2344,6 @@ setup(void)
netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
@@ -2848,6 +2697,10 @@ unfocus(Client *c, int setfocus)
{
if (!c)
return;
if (c->isgame && c->isfullscreen)
minimize(c);
grabbuttons(c, 0);
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
if (setfocus) {
@@ -2864,7 +2717,6 @@ unmanage(Client *c, int destroyed)
detach(c);
detachstack(c);
freeicon(c);
if (!destroyed) {
wc.border_width = c->oldbw;
XGrabServer(dpy); /* avoid race conditions */
@@ -2903,6 +2755,16 @@ unmapnotify(XEvent *e)
}
}
void
unminimize(Client *c)
{
if (!c || !MINIMIZED(c))
return;
XMapWindow(dpy, c->win);
setclientstate(c, NormalState);
}
void
updatebars(void)
{
@@ -2967,13 +2829,6 @@ void updatecurrentdesktop(void){
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
void
updateicon(Client *c)
{
freeicon(c);
c->icon = geticonprop(dpy, c->win, iconsize, &c->icw, &c->ich);
}
int
updategeom(void)
{