Introduction
Introduction Statistics Contact Development Disclaimer Help
xrandrfontsize-0.8.4-20211224-2f6e597.diff - sites - public wiki contents of su…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
xrandrfontsize-0.8.4-20211224-2f6e597.diff (8924B)
---
1 diff --git a/config.def.h b/config.def.h
2 index f92798a..517abbb 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -9,5 +9,19 @@
6 static int borderpx = 2;
7
8 +/*
9 + * Override/adjust fontsize of choosen monitors:
10 + */
11 +MonitorConfig monitors_config[] = {
12 + // skip = fixed relative points size (monitor dpi)
13 + // =0 : fixed absolute pixel size (default screen dpi)
14 + // >0 : auto absolute pixel size (monitor dpi)
15 + // <0 : auto relative points size (monitor dpi)
16 + // {"DP-1", 0}, // BUG:(size=0): not restored to default after …
17 + {"HDMI-0~1", -20}, // BUG:(ignored DPI=220): = 20 is eqv to 10…
18 + {"HDMI-0~2", -14},
19 +};
20 +float winmovethreshold = 0.6;
21 +
22 /*
23 * What program is execed by st depends of these precedence rules:
24 * 1: program passed with -e
25 @@ -272,6 +272,7 @@ static Shortcut shortcuts[] = {
26 { TERMMOD, XK_Prior, zoom, {.f = +…
27 { TERMMOD, XK_Next, zoom, {.f = -…
28 { TERMMOD, XK_Home, zoomreset, {.f = …
29 + { TERMMOD, XK_End, refreshxrandr, {.i = …
30 { TERMMOD, XK_C, clipcopy, {.i = …
31 { TERMMOD, XK_V, clippaste, {.i = …
32 { TERMMOD, XK_Y, selpaste, {.i = …
33 diff --git a/config.mk b/config.mk
34 index aaa54ff..2d28597 100644
35 --- a/config.mk
36 +++ b/config.mk
37 @@ -24,5 +24,7 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrend…
38
39 +LIBS += -lXrandr
40 +
41 # flags
42 STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
43 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS)
44 STLDFLAGS = $(LIBS) $(LDFLAGS)
45 diff --git a/x.c b/x.c
46 index 684311c..ce1c418 100644
47 --- a/x.c
48 +++ b/x.c
49 @@ -14,6 +14,7 @@
50 #include <X11/keysym.h>
51 #include <X11/Xft/Xft.h>
52 #include <X11/XKBlib.h>
53 +#include <X11/extensions/Xrandr.h>
54
55 char *argv0;
56 #include "arg.h"
57 @@ -45,5 +46,18 @@ typedef struct {
58 signed char appcursor; /* application cursor */
59 } Key;
60
61 +typedef struct {
62 + const char *name;
63 + float defaultfontsize;
64 +} MonitorConfig;
65 +
66 +typedef struct {
67 + Atom name;
68 + int x, y, w, h;
69 + float defaultfontsize, usedfontsize;
70 +} MonitorInfo;
71 +
72 +static void refreshxrandr(const Arg *dummy);
73 +
74 /* X modifiers */
75 #define XK_ANY_MOD UINT_MAX
76 @@ -233,7 +233,12 @@ static XWindow xw;
77 [PropertyNotify] = propnotify,
78 [SelectionRequest] = selrequest,
79 };
80
81 +static double defaultrelfontsize = 0;
82 +static MonitorInfo *monitors_info = NULL;
83 +static int monitors_num = 0;
84 +static int prev_mindex = -1;
85 +
86 /* Globals */
87 static DC dc;
88 static XWindow xw;
89 @@ -2280,6 +2280,144 @@ xseturgency(int add)
90 XFree(h);
91 }
92
93 +static void
94 +cachemonitorinfo()
95 +{
96 + int prev_num = monitors_num;
97 + MonitorInfo *prev_info = monitors_info;
98 + XRRMonitorInfo *xmonitors = XRRGetMonitors(xw.dpy, XRootWindow(…
99 + if (!monitors_num)
100 + die("xrandr found no monitors");
101 +
102 + monitors_info = xmalloc(monitors_num * sizeof(MonitorInfo));
103 +
104 + for (int i = 0; i < monitors_num; ++i) {
105 + XRRMonitorInfo *xm = &xmonitors[i];
106 + MonitorInfo *m = &monitors_info[i];
107 +
108 + m->name = xm->name;
109 + m->x = xm->x;
110 + m->y = xm->y;
111 + m->w = xm->width;
112 + m->h = xm->height;
113 +
114 + float px_mm = ((float)m->w / xm->mwidth + (float)m->h /…
115 + float px_pt = 25.4 * px_mm / 72;
116 + m->defaultfontsize = defaultrelfontsize * px_pt;
117 +
118 + // Override defaultfontsize (dpi) by user config
119 + char *name = XGetAtomName(xw.dpy, xm->name);
120 + for (int j = 0; j < LEN(monitors_config); ++j)
121 + if (!strcmp(name, monitors_config[j].name)) {
122 + m->defaultfontsize = monitors_config[j]…
123 + if (m->defaultfontsize < 0)
124 + m->defaultfontsize *= -px_pt;
125 + break;
126 + }
127 + // fprintf(stderr, "%s: %fpx, %f\n", name, m->defaultfo…
128 + XFree(name);
129 +
130 + // Restore usedfontsize (zoom) after re-cache for monit…
131 + m->usedfontsize = m->defaultfontsize;
132 + for (int j = 0; j < prev_num; ++j)
133 + if (prev_info[j].name == m->name) {
134 + m->usedfontsize = prev_info[j].usedfont…
135 + break;
136 + }
137 + }
138 +
139 + XRRFreeMonitors(xmonitors);
140 + free(prev_info);
141 +}
142 +
143 +static int
144 +getmonitorindex_threshold(int w, int h, int x, int y)
145 +{
146 + int mindex = -1;
147 + float fontsize = 0;
148 + int thresholdarea = winmovethreshold * w * h;
149 +
150 + for (int i = 0; i < monitors_num; ++i) {
151 + MonitorInfo *m = &monitors_info[i];
152 + int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x,…
153 + int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y,…
154 + int area = overlap_w * overlap_h;
155 + // Choose monitor with largest dpi (defaultfontsize)
156 + // from all "mirrored"/overlapped (e.g. projector)
157 + if (area >= thresholdarea && fontsize < m->defaultfonts…
158 + fontsize = m->defaultfontsize;
159 + mindex = i;
160 + }
161 + }
162 + return mindex;
163 +}
164 +
165 +static int
166 +getmonitorindex_nearest(int w, int h, int x, int y)
167 +{
168 + int mindex = -1;
169 + float fontsize = 0;
170 + int overlaparea = 0;
171 +
172 + for (int i = 0; i < monitors_num; ++i) {
173 + MonitorInfo *m = &monitors_info[i];
174 + int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x,…
175 + int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y,…
176 + int area = overlap_w * overlap_h;
177 + // Choose monitor with largest overlapping area
178 + // e.g. when "st" is initially spawned in-between moni…
179 + if (area > overlaparea) {
180 + overlaparea = area;
181 + mindex = i;
182 + }
183 + }
184 + return mindex;
185 +}
186 +
187 +static void
188 +adjustmonitorfontsize(int mindex)
189 +{
190 + if (mindex < 0 || prev_mindex == mindex)
191 + return;
192 + // Save zoom of current monitor before switching
193 + if (prev_mindex >= 0)
194 + monitors_info[prev_mindex].usedfontsize = usedfontsize;
195 +
196 + defaultfontsize = monitors_info[mindex].defaultfontsize;
197 + // fprintf(stderr, "Crossing: %fpx\n", defaultfontsize);
198 +
199 + // NOTE: do nothing if font size differs by less than 1%
200 + double fontsize = monitors_info[mindex].usedfontsize;
201 + double delta = 0.01 * usedfontsize;
202 + if (!BETWEEN(fontsize - usedfontsize, -delta, delta)) {
203 + // fprintf(stderr, "Adjusted: %fpx\n", fontsize);
204 + xunloadfonts();
205 + xloadfonts(usedfont, fontsize);
206 + }
207 + prev_mindex = mindex;
208 +}
209 +
210 +void
211 +refreshxrandr(const Arg *dummy)
212 +{
213 + // Reset index to detect change of window association on "xrand…
214 + // otherwise: zoom won't be saved on switching and new font si…
215 + // CRIT!!! event from xrandr may place another monitor into sam…
216 + if (prev_mindex >= 0)
217 + monitors_info[prev_mindex].usedfontsize = usedfontsize;
218 + prev_mindex = -1;
219 +
220 + XWindowAttributes xattr = {0};
221 + cachemonitorinfo();
222 + XGetWindowAttributes(xw.dpy, xw.win, &xattr);
223 +
224 + int mindex = getmonitorindex_threshold(xattr.width, xattr.heigh…
225 + if (mindex < 0)
226 + mindex = getmonitorindex_nearest(xattr.width, xattr.hei…
227 + adjustmonitorfontsize(mindex);
228 +}
229 +
230 +
231 void
232 xbell(void)
233 {
234 @@ -2437,6 +2437,14 @@ cmessage(XEvent *e)
235 void
236 resize(XEvent *e)
237 {
238 + // BAD: no resize on monitor plug/unplug/reconfigure -- until w…
239 + // NOTE: no resize event on zoomabs()
240 + // fprintf(stderr, "Resize: %dx%d+%d+%d\n",
241 + // e->xconfigure.width, e->xconfigure.height, e->xconfigure…
242 +
243 + adjustmonitorfontsize(getmonitorindex_threshold(
244 + e->xconfigure.width, e->xconfigure.height, e->xconfigure.x,…
245 +
246 if (e->xconfigure.width == win.w && e->xconfigure.height == win…
247 return;
248
249 @@ -2469,6 +2469,22 @@ run(void)
250 }
251 } while (ev.type != MapNotify);
252
253 + int rr_event_base, rr_error_base, rr_major, rr_minor;
254 + if (!XRRQueryExtension (xw.dpy, &rr_event_base, &rr_error_base)…
255 + !XRRQueryVersion (xw.dpy, &rr_major, &rr_minor) ||
256 + rr_major < 1 || (rr_major == 1 && rr_minor < 5))
257 + {
258 + die("RandR 1.5 extension isn't available\n");
259 + }
260 + XRRSelectInput(xw.dpy, xw.win, RRCrtcChangeNotifyMask);
261 +
262 + // WARN: can query actual window size/pos only after window is …
263 + // * x/y are WM-dependent and can't be determined beforehand a…
264 + // * defaultfontsize isn't available until font is loaded and …
265 + // BAD: fonts on startup are always reloaded -- how to specify …
266 + FcPatternGetDouble(dc.font.match->pattern, FC_SIZE, 0, &default…
267 + refreshxrandr(0);
268 +
269 ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
270 cresize(w, h);
271
272 @@ -2500,6 +2500,16 @@ run(void)
273 XNextEvent(xw.dpy, &ev);
274 if (XFilterEvent(&ev, None))
275 continue;
276 + if (LASTEvent <= ev.type) {
277 + if (rr_event_base + RRNotify == ev.type…
278 + RRNotify_CrtcChange == ((XRRNot…
279 + {
280 + XRRUpdateConfiguration(&ev);
281 + // fprintf(stderr, "Monitor cha…
282 + refreshxrandr(0);
283 + }
284 + continue;
285 + }
286 if (handler[ev.type])
287 (handler[ev.type])(&ev);
288 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.