diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f2d8dc6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +// .clang-format +DisableFormat: true diff --git a/config.def.h b/config.def.h index 952efed..51a35d3 100644 --- a/config.def.h +++ b/config.def.h @@ -1,16 +1,35 @@ /* See LICENSE file for copyright and license details. */ +/* + * Override/adjust fontsize of choosen monitors: + */ +MonitorConfig monitors_config[] = { + // skip = fixed relative points size (monitor dpi) + // =0 : fixed absolute pixel size (default screen dpi) + // >0 : auto absolute pixel size (monitor dpi) + // <0 : auto relative points size (monitor dpi) + {"eDP-1", -10}, // BUG:(size=0): not restored to default after back'n'forth + // {"HDMI-0~1", -20}, // BUG:(ignored DPI=220): = 20 is eqv to 10pt (DPI=110) + // {"HDMI-0~2", -14}, +}; +float winmovethreshold = 0.6; + /* * appearance * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +// static char *font = "JetBrainsMonoNL Nerd Font:pixelsize=30:antialias=true:autohint=true"; +static char *font = "JetBrainsMonoNL Nerd Font:size=16:antialias=true:autohint=true"; #if FONT2_PATCH /* Spare fonts */ static char *font2[] = { -/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ -/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ + // "Iosevka Nerd Font:size=30:antialias=true:autohint=true", + // "monospace:size=30:antialias=true:autohint=true", + // "DM Mono:size=30:antialias=true:autohint=true" + "Iosevka Nerd Font:size=16:antialias=true:autohint=true", + "monospace:size=16:antialias=true:autohint=true", + "DM Mono:size=16:antialias=true:autohint=true" }; #endif // FONT2_PATCH @@ -88,7 +107,7 @@ int allowaltscreen = 1; /* allow certain non-interactive (insecure) window operations such as: setting the clipboard text */ -int allowwindowops = 0; +int allowwindowops = 1; /* * draw latency range in ms - from new content/keypress/etc until drawing. @@ -165,7 +184,7 @@ unsigned int tabspaces = 8; #if ALPHA_PATCH /* bg opacity */ -float alpha = 0.8; +float alpha = 0.95; #if ALPHA_GRADIENT_PATCH float grad_alpha = 0.54; //alpha value that'll change float stat_alpha = 0.46; //constant alpha value that'll get added to grad_alpha @@ -176,34 +195,33 @@ float alphaUnfocused = 0.6; #endif // ALPHA_PATCH /* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", +const char *colorname[] = { - [255] = 0, + /* 8 normal colors */ + [0] = "#101010", /* black */ + [1] = "#7c7c7c", /* red */ + [2] = "#8e8e8e", /* green */ + [3] = "#a0a0a0", /* yellow */ + [4] = "#686868", /* blue */ + [5] = "#747474", /* magenta */ + [6] = "#868686", /* cyan */ + [7] = "#b9b9b9", /* white */ - /* more colors can be added after 255 to use with DefaultXX */ - "#add8e6", /* 256 -> cursor */ - "#555555", /* 257 -> rev cursor*/ - "#000000", /* 258 -> bg */ - "#e5e5e5", /* 259 -> fg */ + /* 8 bright colors */ + [8] = "#525252", /* black */ + [9] = "#7c7c7c", /* red */ + [10] = "#8e8e8e", /* green */ + [11] = "#a0a0a0", /* yellow */ + [12] = "#686868", /* blue */ + [13] = "#747474", /* magenta */ + [14] = "#868686", /* cyan */ + [15] = "#f7f7f7", /* white */ + + /* special colors */ + [256] = "#101010", /* background */ + [257] = "#b9b9b9", /* foreground */ + [258] = "#b9b9b9", /* cursor */ }; @@ -215,11 +233,13 @@ static const char *colorname[] = { unsigned int defaultbg = 0; unsigned int bg = 17, bgUnfocused = 16; #else -unsigned int defaultbg = 258; +unsigned int defaultbg = 0; #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH -unsigned int defaultfg = 259; -unsigned int defaultcs = 256; -unsigned int defaultrcs = 257; +/* Default colors (colorname index) + * foreground, background, cursor */ +unsigned int defaultfg = 257; +unsigned int defaultcs = 258; +unsigned int defaultrcs = 258; #if SELECTION_COLORS_PATCH unsigned int selectionfg = 258; unsigned int selectionbg = 259; @@ -413,6 +433,7 @@ static Shortcut shortcuts[] = { { TERMMOD, XK_Prior, zoom, {.f = +1} }, { TERMMOD, XK_Next, zoom, {.f = -1} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_End, refreshxrandr, {.i = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, #if ALPHA_PATCH diff --git a/config.mk b/config.mk index ffcd3cb..35d5554 100644 --- a/config.mk +++ b/config.mk @@ -15,20 +15,20 @@ X11LIB = /usr/X11R6/lib PKG_CONFIG = pkg-config # Uncomment this for the alpha patch / ALPHA_PATCH -#XRENDER = `$(PKG_CONFIG) --libs xrender` +XRENDER = `$(PKG_CONFIG) --libs xrender` # Uncomment this for the themed cursor patch / THEMED_CURSOR_PATCH #XCURSOR = `$(PKG_CONFIG) --libs xcursor` # Uncomment the lines below for the ligatures patch / LIGATURES_PATCH -#LIGATURES_C = hb.c -#LIGATURES_H = hb.h -#LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` -#LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` +LIGATURES_C = hb.c +LIGATURES_H = hb.h +LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` +LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` # Uncomment this for the SIXEL patch / SIXEL_PATCH -#SIXEL_C = sixel.c sixel_hls.c -#SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` +SIXEL_C = sixel.c sixel_hls.c +SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` # Uncomment for the netwmicon patch / NETWMICON_PATCH #NETWMICON_LIBS = `$(PKG_CONFIG) --libs gdlib` @@ -38,7 +38,7 @@ INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` \ $(LIGATURES_INC) -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrandr ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` \ $(LIGATURES_LIBS) \ diff --git a/patches.def.h b/patches.def.h index 65d883c..19979e3 100644 --- a/patches.def.h +++ b/patches.def.h @@ -22,29 +22,29 @@ * https://github.com/juliusHuelsmann/st-focus/ * https://st.suckless.org/patches/alpha_focus_highlight/ */ -#define ALPHA_FOCUS_HIGHLIGHT_PATCH 0 +#define ALPHA_FOCUS_HIGHLIGHT_PATCH 1 /* Adds gradient transparency to st, depends on the alpha patch. * https://st.suckless.org/patches/gradient/ */ -#define ALPHA_GRADIENT_PATCH 0 +#define ALPHA_GRADIENT_PATCH 1 /* Allows for the initial size of the terminal to be specified as pixel width and height * using the -G command line option. Can be combined with the anysize patch to also allow * the window to be resized to any pixel size. * https://st.suckless.org/patches/anygeometry/ */ -#define ANYGEOMETRY_PATCH 0 +#define ANYGEOMETRY_PATCH 1 /* This patch allows st to resize to any pixel size rather than snapping to character width/height. * https://st.suckless.org/patches/anysize/ */ -#define ANYSIZE_PATCH 0 +#define ANYSIZE_PATCH 1 /* A simple variant of the anysize patch that only changes the resize hints to allow the window to * be resized to any size. */ -#define ANYSIZE_SIMPLE_PATCH 0 +#define ANYSIZE_SIMPLE_PATCH 1 /* Draws a background image in farbfeld format in place of the defaultbg color allowing for pseudo * transparency. @@ -64,7 +64,7 @@ * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81 * https://st.suckless.org/patches/blinking_cursor/ */ -#define BLINKING_CURSOR_PATCH 0 +#define BLINKING_CURSOR_PATCH 1 /* By default bold text is rendered with a bold font in the bright variant of the current color. * This patch makes bold text rendered simply as bold, leaving the color unaffected. @@ -75,13 +75,13 @@ /* This patch adds custom rendering of lines/blocks/braille characters for gapless alignment. * https://st.suckless.org/patches/boxdraw/ */ -#define BOXDRAW_PATCH 0 +#define BOXDRAW_PATCH 1 /* By default st only sets PRIMARY on selection. * This patch makes st set CLIPBOARD on selection. * https://st.suckless.org/patches/clipboard/ */ -#define CLIPBOARD_PATCH 0 +#define CLIPBOARD_PATCH 1 /* This patch allows st to be resized without cutting off text when the terminal window is * made larger again. Text does not wrap when the terminal window is made smaller, you may @@ -89,25 +89,25 @@ * * https://github.com/bakkeby/st-flexipatch/issues/34 */ -#define COLUMNS_PATCH 0 +#define COLUMNS_PATCH 1 /* Select and copy the last URL displayed with Mod+l. Multiple invocations cycle through the * available URLs. * https://st.suckless.org/patches/copyurl/ */ -#define COPYURL_PATCH 0 +#define COPYURL_PATCH 1 /* Select and copy the last URL displayed with Mod+l. Multiple invocations cycle through the * available URLs. This variant also highlights the selected URLs. * https://st.suckless.org/patches/copyurl/ */ -#define COPYURL_HIGHLIGHT_SELECTED_URLS_PATCH 0 +#define COPYURL_HIGHLIGHT_SELECTED_URLS_PATCH 1 /* This patch adds support for CSI escape sequences 22 and 23, which save and * restores the window title (for instance nvim does this when opening and closing). * https://st.suckless.org/patches/csi_22_23/ */ -#define CSI_22_23_PATCH 0 +#define CSI_22_23_PATCH 1 /* According to the specification (see link in BLINKING_CURSOR_PATCH) the "Set cursor style * (DECSCUSR), VT520." escape sequences define both values of 0 and 1 as a blinking block, @@ -122,7 +122,7 @@ * While many terminal emulators do this it is not adhering to specification. xterm is an * example terminal that sets a blinking block instead of the configured one, same as st. */ -#define DEFAULT_CURSOR_PATCH 0 +#define DEFAULT_CURSOR_PATCH 1 /* Return BS on pressing backspace and DEL on pressing the delete key. * https://st.suckless.org/patches/delkey/ @@ -152,7 +152,7 @@ /* Reading and writing st's screen through a pipe, e.g. pass info to dmenu. * https://st.suckless.org/patches/externalpipe/ */ -#define EXTERNALPIPE_PATCH 0 +#define EXTERNALPIPE_PATCH 1 /* This patch improves and extends the externalpipe patch in two ways: * - it prevents the reset of the signal handler set on SIGCHILD, when @@ -170,13 +170,13 @@ * https://github.com/sos4nt/dynamic-colors * https://lists.suckless.org/hackers/2004/17218.html */ -#define EXTERNALPIPEIN_PATCH 0 +#define EXTERNALPIPEIN_PATCH 1 /* This patch allows command line applications to use all the fancy key combinations * that are available to GUI applications. * https://st.suckless.org/patches/fix_keyboard_input/ */ -#define FIXKEYBOARDINPUT_PATCH 0 +#define FIXKEYBOARDINPUT_PATCH 1 /* This patch allows you to add spare font besides the default. Some glyphs can be not present in * the default font. For this glyphs st uses font-config and try to find them in font cache first. @@ -184,14 +184,14 @@ * So they will be used first for glyphs that are absent in the default font. * https://st.suckless.org/patches/font2/ */ -#define FONT2_PATCH 0 +#define FONT2_PATCH 1 /* This patch adds the ability to toggle st into fullscreen mode. * Two key bindings are defined: F11 which is typical with other applications and Alt+Enter * which matches the default xterm behavior. * https://st.suckless.org/patches/fullscreen/ */ -#define FULLSCREEN_PATCH 0 +#define FULLSCREEN_PATCH 1 /* Hide the X cursor whenever a key is pressed and show it back when the mouse is moved in * the terminal window. @@ -216,7 +216,7 @@ * codepoint that will be converted to a glyph and then pushed to st. * https://st.suckless.org/patches/iso14755/ */ -#define ISO14755_PATCH 0 +#define ISO14755_PATCH 1 /* This patch allows you to select text on the terminal using keyboard shortcuts. * NB: An improved variant of this patch is enabled if combined with the reflow patch. @@ -233,7 +233,7 @@ * https://github.com/cog1to/st-ligatures * https://st.suckless.org/patches/ligatures/ */ -#define LIGATURES_PATCH 0 +#define LIGATURES_PATCH 1 /* This patch makes st ignore terminal color attributes by forcing display of the default * foreground and background colors only - making for a monochrome look. Idea ref. @@ -279,7 +279,7 @@ * same CWD (current working directory) as the original st instance. * https://st.suckless.org/patches/newterm/ */ -#define NEWTERM_PATCH 0 +#define NEWTERM_PATCH 1 /* This patch will set the _MOTIF_WM_HINTS property for the st window which, if the window manager * respects it, will show the st window without window decorations. @@ -287,7 +287,7 @@ * In dwm, if the decoration hints patch is applied, then the st window will start out without a * border. In GNOME and KDE the window should start without a window title. */ -#define NO_WINDOW_DECORATIONS_PATCH 0 +#define NO_WINDOW_DECORATIONS_PATCH 1 /* Open contents of the clipboard in a user-defined browser. * https://st.suckless.org/patches/open_copied_url/ @@ -299,21 +299,21 @@ * * https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/ */ -#define OPENURLONCLICK_PATCH 0 +#define OPENURLONCLICK_PATCH 1 /* This patch allows jumping between prompts by utilizing the OSC 133 escape sequence * emitted by shells. Must be used with either reflow or scrollback patch. * * https://codeberg.org/dnkl/foot#jumping-between-prompts */ -#define OSC133_PATCH 0 +#define OSC133_PATCH 1 /* Reflow. * Allows st to be resized without cutting off text when the terminal window is made larger again. * Text wraps when the terminal window is made smaller. * Comes with scrollback. */ -#define REFLOW_PATCH 0 +#define REFLOW_PATCH 1 /* This patch allows you to specify a border that is relative in size to the width of a cell * in the terminal. @@ -330,19 +330,19 @@ /* Scroll back through terminal output using Shift+{PageUp, PageDown}. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_PATCH 0 +#define SCROLLBACK_PATCH 1 /* Scroll back through terminal output using Shift+MouseWheel. * This variant depends on SCROLLBACK_PATCH being enabled. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_MOUSE_PATCH 0 +#define SCROLLBACK_MOUSE_PATCH 1 /* Scroll back through terminal output using mouse wheel (when not in MODE_ALTSCREEN). * This variant depends on SCROLLBACK_PATCH being enabled. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 0 +#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 1 /* This patch adds the two color-settings selectionfg and selectionbg to config.def.h. * Those define the fore- and background colors which are used when text on the screen is selected @@ -370,7 +370,7 @@ * * https://gist.github.com/saitoha/70e0fdf22e3e8f63ce937c7f7da71809 */ -#define SIXEL_PATCH 0 +#define SIXEL_PATCH 1 /* This patch allows clients to embed into the st window and is useful if you tend to * start X applications from the terminal. For example: @@ -405,7 +405,7 @@ * * https://st.suckless.org/patches/sync/ */ -#define SYNC_PATCH 0 +#define SYNC_PATCH 1 /* Instead of a default X cursor, use the xterm cursor from your cursor theme. * You need to uncomment the corresponding line in config.mk to use the -lXcursor library @@ -430,13 +430,13 @@ * * https://st.suckless.org/patches/undercurl/ */ -#define UNDERCURL_PATCH 0 +#define UNDERCURL_PATCH 1 /* Allows mouse scroll without modifier keys for regardless of alt screen using the external * scroll program. * https://st.suckless.org/patches/universcroll/ */ -#define UNIVERSCROLL_PATCH 0 +#define UNIVERSCROLL_PATCH 1 /* Use XftFontMatch in place of FcFontMatch. * @@ -450,12 +450,12 @@ * * https://git.suckless.org/st/commit/528241aa3835e2f1f052abeeaf891737712955a0.html */ -#define USE_XFTFONTMATCH_PATCH 0 +#define USE_XFTFONTMATCH_PATCH 1 /* Vertically center lines in the space available if you have set a larger chscale in config.h * https://st.suckless.org/patches/vertcenter/ */ -#define VERTCENTER_PATCH 0 +#define VERTCENTER_PATCH 1 /* Briefly inverts window content on terminal bell event. * https://st.suckless.org/patches/visualbell/ @@ -465,14 +465,14 @@ /* Adds support for w3m images. * https://st.suckless.org/patches/w3m/ */ -#define W3M_PATCH 0 +#define W3M_PATCH 1 /* Adds proper glyphs rendering in st allowing wide glyphs to be drawn as-is as opposed to * smaller or cut glyphs being rendered. * https://github.com/Dreomite/st/commit/e3b821dcb3511d60341dec35ee05a4a0abfef7f2 * https://www.reddit.com/r/suckless/comments/jt90ai/update_support_for_proper_glyph_rendering_in_st/ */ -#define WIDE_GLYPHS_PATCH 0 +#define WIDE_GLYPHS_PATCH 1 /* There is a known issue that Google's Variable Fonts (VF) can end up with letter spacing * that is too wide in programs that use Xft, for example Inconsolata v3.000. diff --git a/x.c b/x.c index be1a6ba..20b9403 100644 --- a/x.c +++ b/x.c @@ -14,6 +14,7 @@ #include #include #include +#include char *argv0; #include "arg.h" @@ -49,6 +50,19 @@ typedef enum { } Geometry; #endif // ANYGEOMETRY_PATCH +typedef struct { + const char *name; + float defaultfontsize; +} MonitorConfig; + +typedef struct { + Atom name; + int x, y, w, h; + float defaultfontsize, usedfontsize; +} MonitorInfo; + +static void refreshxrandr(const Arg *dummy); + /* X modifiers */ #define XK_ANY_MOD UINT_MAX #define XK_NO_MOD 0 @@ -176,6 +190,12 @@ static void (*handler[LASTEvent])(XEvent *) = { #endif // ST_EMBEDDER_PATCH }; +static double defaultrelfontsize = 0; +static MonitorInfo *monitors_info = NULL; +static int monitors_num = 0; +static int prev_mindex = -1; + + /* Globals */ Term term; DC dc; @@ -3437,6 +3457,144 @@ xseturgency(int add) XFree(h); } +static void +cachemonitorinfo() +{ + int prev_num = monitors_num; + MonitorInfo *prev_info = monitors_info; + XRRMonitorInfo *xmonitors = XRRGetMonitors(xw.dpy, XRootWindow(xw.dpy, xw.scr), 1, &monitors_num); + if (!monitors_num) + die("xrandr found no monitors"); + + monitors_info = xmalloc(monitors_num * sizeof(MonitorInfo)); + + for (int i = 0; i < monitors_num; ++i) { + XRRMonitorInfo *xm = &xmonitors[i]; + MonitorInfo *m = &monitors_info[i]; + + m->name = xm->name; + m->x = xm->x; + m->y = xm->y; + m->w = xm->width; + m->h = xm->height; + + float px_mm = ((float)m->w / xm->mwidth + (float)m->h / xm->mheight) / 2; + float px_pt = 25.4 * px_mm / 72; + m->defaultfontsize = defaultrelfontsize * px_pt; + + // Override defaultfontsize (dpi) by user config + char *name = XGetAtomName(xw.dpy, xm->name); + for (int j = 0; j < LEN(monitors_config); ++j) + if (!strcmp(name, monitors_config[j].name)) { + m->defaultfontsize = monitors_config[j].defaultfontsize; + if (m->defaultfontsize < 0) + m->defaultfontsize *= -px_pt; + break; + } + // fprintf(stderr, "%s: %fpx, %f\n", name, m->defaultfontsize, m->usedfontsize); + XFree(name); + + // Restore usedfontsize (zoom) after re-cache for monitors with the same name + m->usedfontsize = m->defaultfontsize; + for (int j = 0; j < prev_num; ++j) + if (prev_info[j].name == m->name) { + m->usedfontsize = prev_info[j].usedfontsize; + break; + } + } + + XRRFreeMonitors(xmonitors); + free(prev_info); +} + +static int +getmonitorindex_threshold(int w, int h, int x, int y) +{ + int mindex = -1; + float fontsize = 0; + int thresholdarea = winmovethreshold * w * h; + + for (int i = 0; i < monitors_num; ++i) { + MonitorInfo *m = &monitors_info[i]; + int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x, m->x)); + int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y, m->y)); + int area = overlap_w * overlap_h; + // Choose monitor with largest dpi (defaultfontsize) + // from all "mirrored"/overlapped (e.g. projector) + if (area >= thresholdarea && fontsize < m->defaultfontsize) { + fontsize = m->defaultfontsize; + mindex = i; + } + } + return mindex; +} + +static int +getmonitorindex_nearest(int w, int h, int x, int y) +{ + int mindex = -1; + float fontsize = 0; + int overlaparea = 0; + + for (int i = 0; i < monitors_num; ++i) { + MonitorInfo *m = &monitors_info[i]; + int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x, m->x)); + int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y, m->y)); + int area = overlap_w * overlap_h; + // Choose monitor with largest overlapping area + // e.g. when "st" is initially spawned in-between monitors + if (area > overlaparea) { + overlaparea = area; + mindex = i; + } + } + return mindex; +} + +static void +adjustmonitorfontsize(int mindex) +{ + if (mindex < 0 || prev_mindex == mindex) + return; + // Save zoom of current monitor before switching + if (prev_mindex >= 0) + monitors_info[prev_mindex].usedfontsize = usedfontsize; + + defaultfontsize = monitors_info[mindex].defaultfontsize; + // fprintf(stderr, "Crossing: %fpx\n", defaultfontsize); + + // NOTE: do nothing if font size differs by less than 1% + double fontsize = monitors_info[mindex].usedfontsize; + double delta = 0.01 * usedfontsize; + if (!BETWEEN(fontsize - usedfontsize, -delta, delta)) { + // fprintf(stderr, "Adjusted: %fpx\n", fontsize); + xunloadfonts(); + xloadfonts(usedfont, fontsize); + } + prev_mindex = mindex; +} + +void +refreshxrandr(const Arg *dummy) +{ + // Reset index to detect change of window association on "xrandr ... --primary" + // otherwise: zoom won't be saved on switching and new font size won't be loaded + // CRIT!!! event from xrandr may place another monitor into same index + if (prev_mindex >= 0) + monitors_info[prev_mindex].usedfontsize = usedfontsize; + prev_mindex = -1; + + XWindowAttributes xattr = {0}; + cachemonitorinfo(); + XGetWindowAttributes(xw.dpy, xw.win, &xattr); + + int mindex = getmonitorindex_threshold(xattr.width, xattr.height, xattr.x, xattr.y); + if (mindex < 0) + mindex = getmonitorindex_nearest(xattr.width, xattr.height, xattr.x, xattr.y); + adjustmonitorfontsize(mindex); +} + + void xbell(void) { @@ -3672,6 +3830,15 @@ cmessage(XEvent *e) void resize(XEvent *e) { + // BAD: no resize on monitor plug/unplug/reconfigure -- until window itself is kept in the same place + // NOTE: no resize event on zoomabs() + // fprintf(stderr, "Resize: %dx%d+%d+%d\n", + // e->xconfigure.width, e->xconfigure.height, e->xconfigure.x, e->xconfigure.y); + + adjustmonitorfontsize(getmonitorindex_threshold( + e->xconfigure.width, e->xconfigure.height, e->xconfigure.x, e->xconfigure.y)); + + #if ST_EMBEDDER_PATCH XWindowChanges wc; #endif // ST_EMBEDDER_PATCH @@ -3725,6 +3892,22 @@ run(void) } } while (ev.type != MapNotify); + int rr_event_base, rr_error_base, rr_major, rr_minor; + if (!XRRQueryExtension (xw.dpy, &rr_event_base, &rr_error_base) || + !XRRQueryVersion (xw.dpy, &rr_major, &rr_minor) || + rr_major < 1 || (rr_major == 1 && rr_minor < 5)) + { + die("RandR 1.5 extension isn't available\n"); + } + XRRSelectInput(xw.dpy, xw.win, RRCrtcChangeNotifyMask); + + // WARN: can query actual window size/pos only after window is mapped and its width/height are adjusted by WM + // * x/y are WM-dependent and can't be determined beforehand anyway + // * defaultfontsize isn't available until font is loaded and actual Fc*() size queried + // BAD: fonts on startup are always reloaded -- how to specify their size beforehand ? + FcPatternGetDouble(dc.font.match->pattern, FC_SIZE, 0, &defaultrelfontsize); + refreshxrandr(0); + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); cresize(w, h); @@ -3766,6 +3949,16 @@ run(void) XNextEvent(xw.dpy, &ev); if (XFilterEvent(&ev, None)) continue; + if (LASTEvent <= ev.type) { + if (rr_event_base + RRNotify == ev.type && + RRNotify_CrtcChange == ((XRRNotifyEvent *)&ev)->subtype) + { + XRRUpdateConfiguration(&ev); + // fprintf(stderr, "Monitor change: %d > %d\n", rr_event_base, LASTEvent); + refreshxrandr(0); + } + continue; + } if (handler[ev.type]) (handler[ev.type])(&ev); }