diff --git a/README.md b/README.md index 3710d13..ec590cb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (6009e6e, 2024-11-25) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (98610fc, 2025-01-26) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/st-flexipatch/blob/master/patches.def.h): ```c @@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: +2025-02-20 - Added the drag-n-drop and open-selected-text patches + 2024-05-31 - Added the anygeometry patch 2024-03-13 - Added the reflow patch and upgraded the netwmicon patch @@ -162,6 +164,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [disable-fonts](https://st.suckless.org/patches/disable_bold_italic_fonts/) - this patch adds the option of disabling bold/italic/roman fonts globally + - [drag-n-drop](https://st.suckless.org/patches/drag-n-drop) + - allows dragging a file into the terminal and have the path printed + - [dynamic-cursor-color](https://st.suckless.org/patches/dynamic-cursor-color/) - this patch makes the cursor color the inverse of the current cell color @@ -230,6 +235,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [open-copied-url](https://st.suckless.org/patches/open_copied_url/) - open contents of the clipboard in a user-defined browser + - [open-selected-text](https://st.suckless.org/patches/open_selected_text) + - open the selected text using `xdg-open` + - [openurlonclick](https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/) - allows for URLs to be opened directly when you click on them diff --git a/config.def.h b/config.def.h index 952efed..7a349b2 100644 --- a/config.def.h +++ b/config.def.h @@ -5,13 +5,10 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *font = "Cascadia Code NF:regular:pixelsize=13.5:fontfeatures=calt,ss01: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", */ -}; +static char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=13.5:antialias=true:autohint=true" }; #endif // FONT2_PATCH #if BACKGROUND_IMAGE_PATCH @@ -130,11 +127,11 @@ int hidecursor = 1; * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. * 0: disable (render all U25XX glyphs normally from the font). */ -const int boxdraw = 0; -const int boxdraw_bold = 0; +const int boxdraw = 1; +const int boxdraw_bold = 1; /* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -const int boxdraw_braille = 0; +const int boxdraw_braille = 1; #endif // BOXDRAW_PATCH /* @@ -165,7 +162,7 @@ unsigned int tabspaces = 8; #if ALPHA_PATCH /* bg opacity */ -float alpha = 0.8; +float alpha = 0.9; #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 @@ -175,37 +172,79 @@ float alphaUnfocused = 0.6; #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH #endif // ALPHA_PATCH +#if DRAG_AND_DROP_PATCH +/* + * drag and drop escape characters + * + * this will add a '\' before any characters specified in the string. + */ +char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; +#endif // DRAG_AND_DROP_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", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#add8e6", /* 256 -> cursor */ - "#555555", /* 257 -> rev cursor*/ - "#000000", /* 258 -> bg */ - "#e5e5e5", /* 259 -> fg */ +static char *colorname[] = { + "#000000", + "#ff3333", + "#86b200", + "#f19618", + "#41a6d9", + "#f07078", + "#4cbe99", + "#ffffff", + "#323232", + "#ff6565", + "#b8e532", + "#ffc849", + "#73d7ff", + "#ffa3aa", + "#7ff0cb", + "#ffffff", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#403f53", /* 256 -> cursor */ + "#f0ede4", /* 257 -> rev cursor*/ + "#fafafa", /* 258 -> bg */ + "#5b6673", /* 259 -> fg */ }; +#if DARKMAN_PATCH +#define colorname_len (sizeof(colorname) / sizeof(char *)) + +enum theme { + THEME_LIGHT, + THEME_DARK, + THEME_NUM, +}; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colornames[THEME_NUM][colorname_len] = { + { }, { + "#1a1a1a", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#f4005f", + "#98e024", + "#fa8419", + "#9d65ff", + "#f4005f", + "#58d1eb", + "#c4c5b5", + "#625e4c", + "#f4005f", + "#98e024", + "#e0d561", + "#9d65ff", + "#f4005f", + "#58d1eb", + "#f6f6ef", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#aaaaaa", /* 256 -> cursor */ + "#555555", /* 257 -> rev cursor*/ + "#000000", /* 258 -> bg */ + "#ffffff", /* 259 -> fg */ +}}; + +#endif // DARKMAN_PATCH + /* * Default colors (colorname index) @@ -362,14 +401,17 @@ static uint forcemousemod = ShiftMask; */ static MouseShortcut mshortcuts[] = { /* mask button function argument release screen */ + #if OPEN_SELECTED_TEXT_PATCH + { ControlMask, Button2, selopen, {.i = 0}, 1 }, + #endif // OPEN_SELECTED_TEXT_PATCH #if CLIPBOARD_PATCH { XK_ANY_MOD, Button2, clippaste, {.i = 0}, 1 }, #else { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, #endif // CLIPBOARD_PATCH #if SCROLLBACK_MOUSE_PATCH - { ShiftMask, Button4, kscrollup, {.i = 1}, 0, S_PRI}, - { ShiftMask, Button5, kscrolldown, {.i = 1}, 0, S_PRI}, + { ShiftMask, Button4, kscrollup, {.i = 4}, 0, S_PRI}, + { ShiftMask, Button5, kscrolldown, {.i = 4}, 0, S_PRI}, #elif UNIVERSCROLL_PATCH { XK_ANY_MOD, Button4, ttysend, {.s = "\033[5;2~"}, 0, S_PRI }, { XK_ANY_MOD, Button5, ttysend, {.s = "\033[6;2~"}, 0, S_PRI }, @@ -378,8 +420,8 @@ static MouseShortcut mshortcuts[] = { { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, #endif // SCROLLBACK_MOUSE_PATCH #if SCROLLBACK_MOUSE_ALTSCREEN_PATCH || REFLOW_PATCH - { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, S_PRI }, - { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, S_PRI }, + { XK_ANY_MOD, Button4, kscrollup, {.i = 4}, 0, S_PRI }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 4}, 0, S_PRI }, { XK_ANY_MOD, Button4, ttysend, {.s = "\031"}, 0, S_ALT }, { XK_ANY_MOD, Button5, ttysend, {.s = "\005"}, 0, S_ALT }, #else @@ -410,8 +452,8 @@ static Shortcut shortcuts[] = { { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, + { MODKEY | ControlMask, XK_comma, zoom, {.f = +1} }, + { MODKEY | ControlMask, XK_semicolon, zoom, {.f = -1} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, @@ -430,6 +472,10 @@ static Shortcut shortcuts[] = { #if SCROLLBACK_PATCH { ShiftMask, XK_Page_Up, kscrollup, {.i = -1}, S_PRI }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}, S_PRI }, + { TERMMOD, XK_U, kscrollup, {.i = -1}, S_PRI }, + { TERMMOD, XK_D, kscrolldown, {.i = -1}, S_PRI }, + { TERMMOD, XK_K, kscrollup, {.i = 4}, S_PRI }, + { TERMMOD, XK_J, kscrolldown, {.i = 4}, S_PRI }, #endif // SCROLLBACK_PATCH #if CLIPBOARD_PATCH { TERMMOD, XK_Y, clippaste, {.i = 0} }, @@ -455,7 +501,7 @@ static Shortcut shortcuts[] = { #endif // EXTERNALPIPEIN_PATCH #endif // EXTERNALPIPE_PATCH #if KEYBOARDSELECT_PATCH - { TERMMOD, XK_Escape, keyboard_select, { 0 } }, + { TERMMOD, XK_space, keyboard_select, { 0 } }, #endif // KEYBOARDSELECT_PATCH #if KEYBOARDSELECT_PATCH && REFLOW_PATCH { TERMMOD, XK_F, searchforward, { 0 } }, diff --git a/config.mk b/config.mk index ffcd3cb..260fff0 100644 --- a/config.mk +++ b/config.mk @@ -21,14 +21,14 @@ PKG_CONFIG = pkg-config #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 -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` \ $(LIGATURES_LIBS) \ @@ -50,10 +50,7 @@ STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) # OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `pkg-config --libs fontconfig` \ -# `pkg-config --libs freetype2` +#CPPFLAGS = $(STCPPFLAGS) -D_XOPEN_SOURCE=600 #MANPREFIX = ${PREFIX}/man # compiler and linker diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..0450b6c --- /dev/null +++ b/default.nix @@ -0,0 +1,56 @@ +{ lib +, stdenv +, pkg-config +, fontconfig +, freetype +, libX11 +, libXft +, harfbuzz +, gd +, glib +, ncurses +, writeText +, conf ? null +, patches ? [] +, extraLibs ? [] +, nixosTests +, imlib2 +}: + +stdenv.mkDerivation rec { + pname = "st"; + version = "0.8.5"; + + src = ./.; + inherit patches; + + configFile = + lib.optionalString (conf != null) (writeText "config.def.h" conf); + + postPatch = lib.optionalString (conf != null) "cp ${configFile} config.def.h" + + lib.optionalString stdenv.isDarwin '' + substituteInPlace config.mk --replace "-lrt" "" + ''; + + strictDeps = true; + + makeFlags = [ "PKG_CONFIG=${stdenv.cc.targetPrefix}pkg-config" ]; + + nativeBuildInputs = [ pkg-config ncurses fontconfig freetype ]; + buildInputs = [ libX11 libXft harfbuzz gd glib imlib2 ] ++ extraLibs; + + preInstall = '' + export TERMINFO=$out/share/terminfo + ''; + + installFlags = [ "PREFIX=$(out)" ]; + + passthru.tests.test = nixosTests.terminal-emulators.st; + + meta = with lib; { + description = "st terminal"; + license = licenses.mit; + maintainers = with maintainers; [ sioodmy ]; + platforms = platforms.unix; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..586a00c --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1736549401, + "narHash": "sha256-ibkQrMHxF/7TqAYcQE+tOnIsSEzXmMegzyBWza6uHKM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1dab772dd4a68a7bba5d9460685547ff8e17d899", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a30e80d --- /dev/null +++ b/flake.nix @@ -0,0 +1,41 @@ +{ + description = "st terminal"; + + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let pkgs = nixpkgs.legacyPackages.${system}; + in rec { + packages = flake-utils.lib.flattenTree { + st = pkgs.callPackage ./default.nix { }; + }; + defaultPackage = packages.st; + apps.st = flake-utils.lib.mkApp { + drv = packages.st; + exePath = "/bin/st"; + }; + apps.default = apps.st; + defaultApp = apps.st; + devShell = pkgs.mkShell rec { + name = "st"; + packages = with pkgs; [ + pkg-config + xorg.libX11 + xorg.libXft + fontconfig + harfbuzz.dev + imlib2 + gd + glib + # ccls + # bear + # lldb + # gdb + # valgrind + ]; + }; + + }); +} diff --git a/hb.c b/hb.c index ae3dcc3..d2edd98 100644 --- a/hb.c +++ b/hb.c @@ -35,13 +35,6 @@ typedef struct { static RuneBuffer hbrunebuffer = { 0, NULL }; static hb_buffer_t *hbbuffer; -/* - * Poplulate the array with a list of font features, wrapped in FEATURE macro, - * e. g. - * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') - */ -hb_feature_t features[] = { }; - void hbcreatebuffer(void) { @@ -125,7 +118,11 @@ hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int star hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); /* Shape the segment. */ - hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); + #if FONTFEATURES_PATCH + hb_shape(font, buffer, data->features, data->features_count); + #else + hb_shape(font, buffer, NULL, 0); + #endif /* Get new glyph info. */ hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); diff --git a/hb.h b/hb.h index cb7ea48..3517855 100644 --- a/hb.h +++ b/hb.h @@ -7,6 +7,10 @@ typedef struct { hb_glyph_info_t *glyphs; hb_glyph_position_t *positions; unsigned int count; +#if FONTFEATURES_PATCH + hb_feature_t *features; + int features_count; +#endif // FONTFEATURES_PATCH } HbTransformData; void hbcreatebuffer(void); diff --git a/patch/drag-n-drop.c b/patch/drag-n-drop.c new file mode 100644 index 0000000..917a9aa --- /dev/null +++ b/patch/drag-n-drop.c @@ -0,0 +1,204 @@ +const char XdndVersion = 5; + +void +xdndsel(XEvent *e) +{ + char* data; + unsigned long result; + + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + XGetWindowProperty((Display*) xw.dpy, e->xselection.requestor, + e->xselection.property, 0, LONG_MAX, False, + e->xselection.target, &actualType, &actualFormat, &result, + &bytesAfter, (unsigned char**) &data); + + if (result == 0) + return; + + if (data) { + xdndpastedata(data); + XFree(data); + } + + if (xw.XdndSourceVersion >= 2) { + reply.xclient.message_type = xw.XdndFinished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = xw.XdndActionCopy; + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, + &reply); + XFlush((Display*) xw.dpy); + } +} + +int +xdndurldecode(char *src, char *dest) +{ + char c; + int i = 0; + + while (*src) { + if (*src == '%' && HEX_TO_INT(src[1]) != -1 && HEX_TO_INT(src[2]) != -1) { + /* handle %xx escape sequences in url e.g. %20 == ' ' */ + c = (char)((HEX_TO_INT(src[1]) << 4) | HEX_TO_INT(src[2])); + src += 3; + } else { + c = *src++; + } + if (strchr(xdndescchar, c) != NULL) { + *dest++ = '\\'; + i++; + } + *dest++ = c; + i++; + } + *dest++ = ' '; + *dest = '\0'; + return i + 1; +} + +void +xdndpastedata(char *data) +{ + char *pastedata, *t; + int i = 0; + + pastedata = (char *)malloc(strlen(data) * 2 + 1); + *pastedata = '\0'; + + t = strtok(data, "\n\r"); + while(t != NULL) { + /* Remove 'file://' prefix if it exists */ + if (strncmp(data, "file://", 7) == 0) { + t += 7; + } + i += xdndurldecode(t, pastedata + i); + t = strtok(NULL, "\n\r"); + } + + xsetsel(pastedata); + selpaste(0); +} + +void +xdndenter(XEvent *e) +{ + unsigned long count; + Atom* formats; + Atom real_formats[6]; + Bool list; + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + unsigned long i; + + list = e->xclient.data.l[1] & 1; + + if (list) { + XGetWindowProperty((Display*) xw.dpy, + xw.XdndSourceWin, + xw.XdndTypeList, + 0, + LONG_MAX, + False, + 4, + &actualType, + &actualFormat, + &count, + &bytesAfter, + (unsigned char**) &formats); + } else { + count = 0; + + if (e->xclient.data.l[2] != None) + real_formats[count++] = e->xclient.data.l[2]; + if (e->xclient.data.l[3] != None) + real_formats[count++] = e->xclient.data.l[3]; + if (e->xclient.data.l[4] != None) + real_formats[count++] = e->xclient.data.l[4]; + + formats = real_formats; + } + + for (i = 0; i < count; i++) { + if (formats[i] == xw.XtextUriList || formats[i] == xw.XtextPlain) { + xw.XdndSourceFormat = formats[i]; + break; + } + } + + if (list) + XFree(formats); +} + +void +xdndpos(XEvent *e) +{ + const int32_t xabs = (e->xclient.data.l[2] >> 16) & 0xffff; + const int32_t yabs = (e->xclient.data.l[2]) & 0xffff; + Window dummy; + int32_t xpos, ypos; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + XTranslateCoordinates((Display*) xw.dpy, + XDefaultRootWindow((Display*) xw.dpy), + (Window) xw.win, + xabs, yabs, + &xpos, &ypos, + &dummy); + + reply.xclient.message_type = xw.XdndStatus; + + if (xw.XdndSourceFormat) { + reply.xclient.data.l[1] = 1; + if (xw.XdndSourceVersion >= 2) + reply.xclient.data.l[4] = xw.XdndActionCopy; + } + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, + &reply); + XFlush((Display*) xw.dpy); +} + +void +xdnddrop(XEvent *e) +{ + Time time = CurrentTime; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + if (xw.XdndSourceFormat) { + if (xw.XdndSourceVersion >= 1) + time = e->xclient.data.l[2]; + + XConvertSelection((Display*) xw.dpy, xw.XdndSelection, + xw.XdndSourceFormat, xw.XdndSelection, (Window) xw.win, time); + } else if (xw.XdndSourceVersion >= 2) { + reply.xclient.message_type = xw.XdndFinished; + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, + False, NoEventMask, &reply); + XFlush((Display*) xw.dpy); + } +} diff --git a/patch/drag-n-drop.h b/patch/drag-n-drop.h new file mode 100644 index 0000000..ee8e82b --- /dev/null +++ b/patch/drag-n-drop.h @@ -0,0 +1,5 @@ +static void xdndenter(XEvent *); +static void xdndpos(XEvent *); +static void xdnddrop(XEvent *); +static void xdndsel(XEvent *); +static void xdndpastedata(char *); diff --git a/patch/openselectedtext.c b/patch/openselectedtext.c new file mode 100644 index 0000000..42d40e2 --- /dev/null +++ b/patch/openselectedtext.c @@ -0,0 +1,13 @@ +void +selopen(const Arg *dummy) +{ + pid_t chpid; + + if ((chpid = fork()) == 0) { + if (fork() == 0) + execlp("xdg-open", "xdg-open", getsel(), NULL); + exit(1); + } + if (chpid > 0) + waitpid(chpid, NULL, 0); +} diff --git a/patch/openselectedtext.h b/patch/openselectedtext.h new file mode 100644 index 0000000..3dccbc6 --- /dev/null +++ b/patch/openselectedtext.h @@ -0,0 +1,3 @@ +#include + +static void selopen(const Arg *); diff --git a/patch/reflow.c b/patch/reflow.c index bf145a6..dac7b9d 100644 --- a/patch/reflow.c +++ b/patch/reflow.c @@ -619,8 +619,8 @@ tclearregion(int x1, int y1, int x2, int y2, int usecurattr) int x, y; /* regionselected() takes relative coordinates */ - if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) - selremove(); + if (regionselected(x1, y1+term.scr, x2, y2+term.scr)) + selclear(); for (y = y1; y <= y2; y++) { term.dirty[y] = 1; diff --git a/patch/x_include.c b/patch/x_include.c index 30b77da..5a0ba58 100644 --- a/patch/x_include.c +++ b/patch/x_include.c @@ -8,6 +8,9 @@ #if BOXDRAW_PATCH #include "boxdraw.c" #endif +#if DRAG_AND_DROP_PATCH +#include "drag-n-drop.c" +#endif #if OPENCOPIED_PATCH #include "opencopied.c" #endif @@ -35,6 +38,9 @@ #elif NETWMICON_LEGACY_PATCH #include "netwmicon_legacy.c" #endif +#if OPEN_SELECTED_TEXT_PATCH +#include "openselectedtext.c" +#endif #if OPENURLONCLICK_PATCH #include "openurlonclick.c" #endif diff --git a/patch/x_include.h b/patch/x_include.h index 78290e1..ed10e8c 100644 --- a/patch/x_include.h +++ b/patch/x_include.h @@ -8,6 +8,9 @@ #if BOXDRAW_PATCH #include "boxdraw.h" #endif +#if DRAG_AND_DROP_PATCH +#include "drag-n-drop.h" +#endif #if OPENCOPIED_PATCH #include "opencopied.h" #endif @@ -32,6 +35,9 @@ #if NETWMICON_PATCH || NETWMICON_FF_PATCH || NETWMICON_LEGACY_PATCH #include "netwmicon.h" #endif +#if OPEN_SELECTED_TEXT_PATCH +#include "openselectedtext.h" +#endif #if RIGHTCLICKTOPLUMB_PATCH #include "rightclicktoplumb_x.h" #endif diff --git a/patches.def.h b/patches.def.h index ae5d37b..1e92a9f 100644 --- a/patches.def.h +++ b/patches.def.h @@ -14,7 +14,7 @@ * when including this patch. * https://st.suckless.org/patches/alpha/ */ -#define ALPHA_PATCH 0 +#define ALPHA_PATCH 1 /* The alpha focus highlight patch allows the user to specify two distinct opacity values or * background colors in order to easily differentiate between focused and unfocused terminal @@ -70,12 +70,12 @@ * This patch makes bold text rendered simply as bold, leaving the color unaffected. * https://st.suckless.org/patches/bold-is-not-bright/ */ -#define BOLD_IS_NOT_BRIGHT_PATCH 0 +#define BOLD_IS_NOT_BRIGHT_PATCH 1 /* 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. @@ -144,11 +144,27 @@ */ #define DISABLE_ROMAN_FONTS_PATCH 0 +/* Allows dragging a file into the terminal and have the path printed. + * https://st.suckless.org/patches/drag-n-drop + */ +#define DRAG_AND_DROP_PATCH 0 + /* This patch makes the cursor color the inverse of the current cell color. * https://st.suckless.org/patches/dynamic-cursor-color/ */ #define DYNAMIC_CURSOR_COLOR_PATCH 0 +/* This is a variant of the anysize patch that explicitly do not change the size increment hints, + * i.e. only keeping the dynamic padding which is the main thing the anysize patch introduces. + * In practice this means that the dynamic padding / anysize functionality only ever comes into + * effect when the size hints are intentionally ignored. + * An example of this would be dwm respecting the size hints of floating windows, but disrespecting + * the size hints when the window is tiled (provided that resizehints config is set to 0). + * + * Note that this patch depends on ANYSIZE_PATCH being enabled to have an effect. + */ +#define DYNAMIC_PADDING_PATCH 0 + /* Reading and writing st's screen through a pipe, e.g. pass info to dmenu. * https://st.suckless.org/patches/externalpipe/ */ @@ -176,7 +192,7 @@ * 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,7 +200,7 @@ * 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 @@ -223,7 +239,7 @@ * * https://st.suckless.org/patches/keyboard_select/ */ -#define KEYBOARDSELECT_PATCH 0 +#define KEYBOARDSELECT_PATCH 1 /* This patch adds support for drawing ligatures using the Harfbuzz library to transform * original text of a single line to a list of glyphs with ligatures included. @@ -233,7 +249,14 @@ * https://github.com/cog1to/st-ligatures * https://st.suckless.org/patches/ligatures/ */ -#define LIGATURES_PATCH 0 +#define LIGATURES_PATCH 1 + +/* This patch add support for custom font features. It depends on the LIGATURES_PATCH patch + */ +#define FONTFEATURES_PATCH 1 + +#define DARKMAN_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 +302,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. @@ -294,12 +317,17 @@ */ #define OPENCOPIED_PATCH 0 +/* Open the selected text using xdg-open. + * https://st.suckless.org/patches/open_selected_text/ + */ +#define OPEN_SELECTED_TEXT_PATCH 0 + /* This patch allows for URLs to be opened directly when you click on them. This may not work with * all terminal applications. * * https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/ */ -#define OPENURLONCLICK_PATCH 0 +#define OPENURLONCLICK_PATCH 1 /* This patch allows st to fetch the current working directory through the OSC 7 escape * sequence emitted by shells. Must be used with newterm patch. @@ -321,7 +349,7 @@ * 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. @@ -338,19 +366,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 @@ -378,7 +406,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: @@ -438,7 +466,7 @@ * * 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. diff --git a/st.c b/st.c index 5efe122..1be93f2 100644 --- a/st.c +++ b/st.c @@ -2039,6 +2039,15 @@ tsetmode(int priv, int set, const int *args, int narg) MODBIT(term.mode, set, MODE_SIXEL_CUR_RT); break; #endif // SIXEL_PATCH + #if SYNC_PATCH + case 2026: + if (set) { + tsync_begin(); + } else { + tsync_end(); + } + break; + #endif // SYNC_PATCH default: fprintf(stderr, "erresc: unknown private set/reset mode %d\n", @@ -2435,6 +2444,23 @@ csihandle(void) goto unknown; } break; + #if SYNC_PATCH + case '$': /* DECRQM -- DEC Request Mode (private) */ + if (csiescseq.mode[1] == 'p' && csiescseq.priv) { + switch (csiescseq.arg[0]) { + #if SYNC_PATCH + case 2026: + /* https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036 */ + ttywrite(su ? "\033[?2026;1$y" : "\033[?2026;2$y", 11, 0); + break; + #endif // SYNC_PATCH + default: + goto unknown; + } + break; + } + goto unknown; + #endif // SYNC_PATCH case 'r': /* DECSTBM -- Set Scrolling Region */ if (csiescseq.priv) { goto unknown; @@ -2498,7 +2524,11 @@ csihandle(void) break; #endif // CSI_22_23_PATCH | SIXEL_PATCH case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); + if (csiescseq.priv) { + goto unknown; + } else { + tcursor(CURSOR_LOAD); + } break; case ' ': switch (csiescseq.mode[1]) { @@ -3434,7 +3464,7 @@ check_control_code: #if REFLOW_PATCH /* selected() takes relative coordinates */ - if (selected(term.c.x + term.scr, term.c.y + term.scr)) + if (selected(term.c.x, term.c.y + term.scr)) selclear(); #else if (selected(term.c.x, term.c.y)) diff --git a/st.h b/st.h index 0682a0e..0464f24 100644 --- a/st.h +++ b/st.h @@ -37,6 +37,12 @@ #define HISTSIZE 2000 #endif // SCROLLBACK_PATCH | REFLOW_PATCH +#if DRAG_AND_DROP_PATCH +#define HEX_TO_INT(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \ + (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \ + (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : -1) +#endif // DRAG_AND_DROP_PATCH + enum glyph_attribute { ATTR_NULL = 0, ATTR_SET = 1 << 0, @@ -247,6 +253,14 @@ typedef struct { GlyphFontSeq *specseq; #endif // LIGATURES_PATCH Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + #if DRAG_AND_DROP_PATCH + Atom XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, + XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, + XdndActionLink, XdndActionAsk, XdndActionPrivate, XtextUriList, + XtextPlain, XdndAware; + int64_t XdndSourceWin, XdndSourceVersion; + int32_t XdndSourceFormat; + #endif // DRAG_AND_DROP_PATCH #if FULLSCREEN_PATCH Atom netwmstate, netwmfullscreen; #endif // FULLSCREEN_PATCH diff --git a/x.c b/x.c index be1a6ba..0de0ac7 100644 --- a/x.c +++ b/x.c @@ -603,6 +603,13 @@ selnotify(XEvent *e) if (property == None) return; + #if DRAG_AND_DROP_PATCH + if (property == xw.XdndSelection) { + xdndsel(e); + return; + } + #endif // DRAG_AND_DROP_PATCH + do { if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ/4, False, AnyPropertyType, @@ -795,10 +802,13 @@ setsel(char *str, Time t) #endif // CLIPBOARD_PATCH } -#if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH +#if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH || DARKMAN_PATCH void sigusr1_reload(int sig) { + #if DARKMAN_PATCH + xloadcols(); + #endif // DARKMAN_PATCH #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH reload_config(sig); #endif // XRESOURCES_RELOAD_PATCH @@ -976,6 +986,28 @@ xloadalpha(void) } #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH +#if DARKMAN_PATCH +void +darkmanThemeChoose() { + FILE *fp; + char path[128]; + + fp = popen("darkman get", "r"); + if (fp == NULL) { + memcpy(colorname, colornames[0], sizeof(colorname)); + } else { + /* match the stdout with the theme */ + while (fgets(path, sizeof(path)-1, fp) != NULL) { + if (strcmp(path, "light\n") == 0) { + memcpy(colorname, colornames[0], sizeof(colorname)); + } else if (strcmp(path, "dark\n") == 0) { + memcpy(colorname, colornames[1], sizeof(colorname)); + } + } + } +} +#endif // DARKMAN_PATCH + #if ALPHA_PATCH && ALPHA_FOCUS_HIGHLIGHT_PATCH void xloadcols(void) @@ -1009,6 +1041,8 @@ xloadcols(void) static int loaded; Color *cp; + darkmanThemeChoose(); + if (loaded) { for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); @@ -1130,7 +1164,7 @@ xhints(void) sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; sizeh->height = win.h; sizeh->width = win.w; - #if ANYSIZE_PATCH || ANYSIZE_SIMPLE_PATCH + #if ANYSIZE_PATCH && !DYNAMIC_PADDING_PATCH || ANYSIZE_SIMPLE_PATCH sizeh->height_inc = 1; sizeh->width_inc = 1; #else @@ -1656,6 +1690,28 @@ xinit(int cols, int rows) xw.netwmfullscreen = XInternAtom(xw.dpy, "_NET_WM_STATE_FULLSCREEN", False); #endif // FULLSCREEN_PATCH + #if DRAG_AND_DROP_PATCH + /* Xdnd setup */ + xw.XdndTypeList = XInternAtom(xw.dpy, "XdndTypeList", 0); + xw.XdndSelection = XInternAtom(xw.dpy, "XdndSelection", 0); + xw.XdndEnter = XInternAtom(xw.dpy, "XdndEnter", 0); + xw.XdndPosition = XInternAtom(xw.dpy, "XdndPosition", 0); + xw.XdndStatus = XInternAtom(xw.dpy, "XdndStatus", 0); + xw.XdndLeave = XInternAtom(xw.dpy, "XdndLeave", 0); + xw.XdndDrop = XInternAtom(xw.dpy, "XdndDrop", 0); + xw.XdndFinished = XInternAtom(xw.dpy, "XdndFinished", 0); + xw.XdndActionCopy = XInternAtom(xw.dpy, "XdndActionCopy", 0); + xw.XdndActionMove = XInternAtom(xw.dpy, "XdndActionMove", 0); + xw.XdndActionLink = XInternAtom(xw.dpy, "XdndActionLink", 0); + xw.XdndActionAsk = XInternAtom(xw.dpy, "XdndActionAsk", 0); + xw.XdndActionPrivate = XInternAtom(xw.dpy, "XdndActionPrivate", 0); + xw.XtextUriList = XInternAtom((Display*) xw.dpy, "text/uri-list", 0); + xw.XtextPlain = XInternAtom((Display*) xw.dpy, "text/plain", 0); + xw.XdndAware = XInternAtom(xw.dpy, "XdndAware", 0); + XChangeProperty(xw.dpy, xw.win, xw.XdndAware, 4, 32, PropModeReplace, + &XdndVersion, 1); + #endif // DRAG_AND_DROP_PATCH + win.mode = MODE_NUMLOCK; resettitle(); xhints(); @@ -1724,6 +1780,26 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x xp = winx, yp = winy + font->ascent; #endif // VERTCENTER_PATCH cluster_xp = xp; cluster_yp = yp; + #if FONTFEATURES_PATCH + { // Get font features + shaped.features = (hb_feature_t *) malloc(sizeof(hb_feature_t) * 128); + FcChar8 *s; + int feature_idx = 0; + while (FcPatternGetString(font->pattern, FC_FONT_FEATURES, feature_idx, &s) == FcResultMatch) { + if (strlen(s) != 4) + die("Invalid font feature tag"); + if (feature_idx >= 128) + die("Too many font features"); + shaped.features[feature_idx].tag = HB_TAG(s[0], s[1], s[2], s[3]); + shaped.features[feature_idx].value = 1; + shaped.features[feature_idx].start = HB_FEATURE_GLOBAL_START; + shaped.features[feature_idx].end = HB_FEATURE_GLOBAL_END; + feature_idx++; + } + shaped.features_count = feature_idx; + } + #endif // FONTFEATURES_PATCH + /* Shape the segment. */ hbtransform(&shaped, font->match, glyphs, 0, len); #endif // LIGATURES_PATCH @@ -2205,20 +2281,9 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i else #endif // BACKGROUND_IMAGE_PATCH - #if !WIDE_GLYPHS_PATCH - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - #endif // WIDE_GLYPHS_PATCH - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - #if WIDE_GLYPHS_PATCH /* Fill the background */ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + #if WIDE_GLYPHS_PATCH } #endif // WIDE_GLYPHS_PATCH @@ -2229,12 +2294,27 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i if (base.mode & ATTR_BOXDRAW) { drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); } else { - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - } + #endif // BOXDRAW_PATCH + /* Set the clip region because Xft is sometimes dirty. */ + #if WIDE_GLYPHS_PATCH + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = win.w; + XftDrawSetClipRectangles(xw.draw, 0, winy, &r, 1); #else + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + #endif // WIDE_GLYPHS_PATCH + /* Render the glyphs. */ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + + #if BOXDRAW_PATCH + } #endif // BOXDRAW_PATCH /* Render underline and strikethrough. */ @@ -2671,21 +2751,19 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XRenderColor colbg; #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if !DYNAMIC_CURSOR_COLOR_PATCH - /* remove the old cursor */ + #if LIGATURES_PATCH + /* Redraw the line where cursor was previously. + * It will restore the ligatures broken by the cursor. */ + xdrawline(line, 0, oy, len); + #else + /* Remove the old cursor */ if (selected(ox, oy)) #if SELECTION_COLORS_PATCH og.mode |= ATTR_SELECTED; #else og.mode ^= ATTR_REVERSE; #endif // SELECTION_COLORS_PATCH - #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if LIGATURES_PATCH - /* Redraw the line where cursor was previously. - * It will restore the ligatures broken by the cursor. */ - xdrawline(line, 0, oy, len); - #else xdrawglyph(og, ox, oy); #endif // LIGATURES_PATCH @@ -2728,7 +2806,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) } #endif // SELECTION_COLORS_PATCH } else { - #if SELECTION_COLORS_PATCH + #if SELECTION_COLORS_PATCH && !DYNAMIC_CURSOR_COLOR_PATCH g.fg = defaultbg; g.bg = defaultcs; drawcol = dc.col[defaultcs]; @@ -3666,6 +3744,21 @@ cmessage(XEvent *e) } else if (e->xclient.data.l[0] == xw.wmdeletewin) { ttyhangup(); exit(0); + #if DRAG_AND_DROP_PATCH + } else if (e->xclient.message_type == xw.XdndEnter) { + xw.XdndSourceWin = e->xclient.data.l[0]; + xw.XdndSourceVersion = e->xclient.data.l[1] >> 24; + xw.XdndSourceFormat = None; + if (xw.XdndSourceVersion > 5) + return; + xdndenter(e); + } else if (e->xclient.message_type == xw.XdndPosition + && xw.XdndSourceVersion <= 5) { + xdndpos(e); + } else if (e->xclient.message_type == xw.XdndDrop + && xw.XdndSourceVersion <= 5) { + xdnddrop(e); + #endif // DRAG_AND_DROP_PATCH } } @@ -3762,8 +3855,12 @@ run(void) xev = 0; while (XPending(xw.dpy)) { - xev = 1; XNextEvent(xw.dpy, &ev); + #if BLINKING_CURSOR_PATCH + xev = (!xev || xev == SelectionRequest) ? ev.type : xev; + #else + xev = 1; + #endif // BLINKING_CURSOR_PATCH if (XFilterEvent(&ev, None)) continue; if (handler[ev.type]) @@ -3790,10 +3887,10 @@ run(void) if (!drawing) { trigger = now; #if BLINKING_CURSOR_PATCH - if (IS_SET(MODE_BLINK)) { - win.mode ^= MODE_BLINK; + if (xev != SelectionRequest) { + win.mode &= ~MODE_BLINK; + lastblink = now; } - lastblink = now; #endif // BLINKING_CURSOR_PATCH drawing = 1; } @@ -3958,9 +4055,12 @@ run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH + #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH || DARKMAN_PATCH signal(SIGUSR1, sigusr1_reload); - #endif // XRESOURCES_RELOAD_PATCH | BACKGROUND_IMAGE_RELOAD_PATCH + #endif // XRESOURCES_RELOAD_PATCH | BACKGROUND_IMAGE_RELOAD_PATCH | DARKMAN_PATCH + #if DARKMAN_PATCH + memcpy(colornames[0], colorname, sizeof(colorname)); + #endif // DARKMAN_PATCH #if XRESOURCES_PATCH if (!(xw.dpy = XOpenDisplay(NULL))) die("Can't open display\n");