Compare commits

...

7 Commits

Author SHA1 Message Date
mintycube
b221ccbc21 Applied mouse hover patch 2024-07-17 08:01:32 +05:00
mintycube
d73301dee5 Merge upstream changes 2024-07-17 08:00:17 +05:00
bakkeby
a3a5229059 Aligning variables between exact and fuzzy highlighting 2024-07-16 23:03:10 +02:00
bakkeby
9a1d207eae xresources - fix window embedding ref. PR #19 2024-07-16 22:31:08 +02:00
bakkeby
e74a659468 Refactoring highlight and fuzzyhighlight patches
Follow-up on pull request #16 this change refactors and combines
the highlight and fuzzy highlight patches into one highlight
function.

Overall it does not make any sense using:
   - fuzzy highlighting when exact matching is used or
   - exact highlighting when fuzzy matching is used

As such it makes sense to combine the two such that:
   - exact highlighting is used when exact matching is used and
   - fuzzy highlighting is used when fuzzy matching is used

The FUZZYHIGHLIGHT_PATCH toggle has been removed in favour of
HIGHLIGHT_PATCH. The FUZZYMATCH_PATCH toggle controls whether
fuzzy matching is enabled. Enable both FUZZYMATCH_PATCH and
HIGHLIGHT_PATCH to enable fuzzy highlighting.

Additionally the fuzzy highlight patch only supported single-byte
characters and would break when encountering multi-byte UTF-8
characters. This was reported ref. #24.

This refactoring includes a change to work out the UTF-8 character
length for a given character rather than assuming that every
character uses one byte.
2024-07-16 21:45:01 +02:00
bakkeby
af373aa1cc Addressing some clang warnings 2024-07-16 21:43:57 +02:00
Marco
4a8b71c191 Added patch to highlight an entry when mouse-hovered. 2024-07-16 09:30:50 +02:00
28 changed files with 291 additions and 147 deletions

View File

@ -39,6 +39,9 @@ Personal build of dmenu generated using [dmenu-flexipatch](https://github.com/ba
- [mouse-support](https://tools.suckless.org/dmenu/patches/mouse-support/) - [mouse-support](https://tools.suckless.org/dmenu/patches/mouse-support/)
- adds basic mouse support for dmenu - adds basic mouse support for dmenu
- [motion-support](https://tools.suckless.org/dmenu/patches/mouse-support/)
- Expands the above to support mouse hovering.
- [password](https://tools.suckless.org/dmenu/patches/password/) - [password](https://tools.suckless.org/dmenu/patches/password/)
- with this patch dmenu will not directly display the keyboard input, but instead replace it - with this patch dmenu will not directly display the keyboard input, but instead replace it
with dots with dots

View File

@ -67,10 +67,10 @@ static const unsigned int alphas[][3] = {
#if MORECOLOR_PATCH #if MORECOLOR_PATCH
[SchemeMid] = { OPAQUE, baralpha, borderalpha }, [SchemeMid] = { OPAQUE, baralpha, borderalpha },
#endif // MORECOLOR_PATCH #endif // MORECOLOR_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
[SchemeSelHighlight] = { OPAQUE, baralpha, borderalpha }, [SchemeSelHighlight] = { OPAQUE, baralpha, borderalpha },
[SchemeNormHighlight] = { OPAQUE, baralpha, borderalpha }, [SchemeNormHighlight] = { OPAQUE, baralpha, borderalpha },
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if HIGHPRIORITY_PATCH #if HIGHPRIORITY_PATCH
[SchemeHp] = { OPAQUE, baralpha, borderalpha }, [SchemeHp] = { OPAQUE, baralpha, borderalpha },
#endif // HIGHPRIORITY_PATCH #endif // HIGHPRIORITY_PATCH
@ -100,10 +100,10 @@ char *colors[][2] = {
#if MORECOLOR_PATCH #if MORECOLOR_PATCH
[SchemeMid] = { "#eeeeee", "#770000" }, [SchemeMid] = { "#eeeeee", "#770000" },
#endif // MORECOLOR_PATCH #endif // MORECOLOR_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
[SchemeSelHighlight] = { "#ffc978", "#005577" }, [SchemeSelHighlight] = { "#ffc978", "#005577" },
[SchemeNormHighlight] = { "#ffc978", "#222222" }, [SchemeNormHighlight] = { "#ffc978", "#222222" },
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if HIGHPRIORITY_PATCH #if HIGHPRIORITY_PATCH
[SchemeHp] = { "#bbbbbb", "#333333" }, [SchemeHp] = { "#bbbbbb", "#333333" },
#endif // HIGHPRIORITY_PATCH #endif // HIGHPRIORITY_PATCH

View File

@ -67,10 +67,10 @@ static const unsigned int alphas[][3] = {
#if MORECOLOR_PATCH #if MORECOLOR_PATCH
[SchemeMid] = { OPAQUE, baralpha, borderalpha }, [SchemeMid] = { OPAQUE, baralpha, borderalpha },
#endif // MORECOLOR_PATCH #endif // MORECOLOR_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
[SchemeSelHighlight] = { OPAQUE, baralpha, borderalpha }, [SchemeSelHighlight] = { OPAQUE, baralpha, borderalpha },
[SchemeNormHighlight] = { OPAQUE, baralpha, borderalpha }, [SchemeNormHighlight] = { OPAQUE, baralpha, borderalpha },
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if HIGHPRIORITY_PATCH #if HIGHPRIORITY_PATCH
[SchemeHp] = { OPAQUE, baralpha, borderalpha }, [SchemeHp] = { OPAQUE, baralpha, borderalpha },
#endif // HIGHPRIORITY_PATCH #endif // HIGHPRIORITY_PATCH
@ -100,10 +100,10 @@ char *colors[][2] = {
#if MORECOLOR_PATCH #if MORECOLOR_PATCH
[SchemeMid] = { "#eeeeee", "#770000" }, [SchemeMid] = { "#eeeeee", "#770000" },
#endif // MORECOLOR_PATCH #endif // MORECOLOR_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
[SchemeSelHighlight] = { "#ffc978", "#005577" }, [SchemeSelHighlight] = { "#ffc978", "#005577" },
[SchemeNormHighlight] = { "#ffc978", "#222222" }, [SchemeNormHighlight] = { "#ffc978", "#222222" },
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if HIGHPRIORITY_PATCH #if HIGHPRIORITY_PATCH
[SchemeHp] = { "#bbbbbb", "#333333" }, [SchemeHp] = { "#bbbbbb", "#333333" },
#endif // HIGHPRIORITY_PATCH #endif // HIGHPRIORITY_PATCH

66
dmenu.c
View File

@ -55,10 +55,10 @@ enum {
#if MORECOLOR_PATCH #if MORECOLOR_PATCH
SchemeMid, SchemeMid,
#endif // MORECOLOR_PATCH #endif // MORECOLOR_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
SchemeNormHighlight, SchemeNormHighlight,
SchemeSelHighlight, SchemeSelHighlight,
#endif // HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if HIGHPRIORITY_PATCH #if HIGHPRIORITY_PATCH
SchemeHp, SchemeHp,
#endif // HIGHPRIORITY_PATCH #endif // HIGHPRIORITY_PATCH
@ -330,11 +330,11 @@ drawitem(struct item *item, int x, int y, int w)
case 'p': case 'p':
drw_setscheme(drw, scheme[SchemePurple]); drw_setscheme(drw, scheme[SchemePurple]);
break; break;
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
case 'h': case 'h':
drw_setscheme(drw, scheme[SchemeNormHighlight]); drw_setscheme(drw, scheme[SchemeNormHighlight]);
break; break;
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
case 's': case 's':
drw_setscheme(drw, scheme[SchemeSel]); drw_setscheme(drw, scheme[SchemeSel]);
break; break;
@ -366,11 +366,11 @@ drawitem(struct item *item, int x, int y, int w)
case 'p': case 'p':
drw_setscheme(drw, scheme[SchemePurple]); drw_setscheme(drw, scheme[SchemePurple]);
break; break;
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
case 'h': case 'h':
drw_setscheme(drw, scheme[SchemeNormHighlight]); drw_setscheme(drw, scheme[SchemeNormHighlight]);
break; break;
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
case 's': case 's':
drw_setscheme(drw, scheme[SchemeSel]); drw_setscheme(drw, scheme[SchemeSel]);
break; break;
@ -471,13 +471,13 @@ drawitem(struct item *item, int x, int y, int w)
, True , True
#endif // PANGO_PATCH #endif // PANGO_PATCH
); );
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
#if EMOJI_HIGHLIGHT_PATCH #if EMOJI_HIGHLIGHT_PATCH
drawhighlights(item, output + iscomment, x + ((iscomment == 6) ? temppadding : 0), y, w); drawhighlights(item, output + iscomment, x + ((iscomment == 6) ? temppadding : 0), y, w);
#else #else
drawhighlights(item, x, y, w); drawhighlights(item, x, y, w);
#endif // EMOJI_HIGHLIGHT_PATCH #endif // EMOJI_HIGHLIGHT_PATCH
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
return r; return r;
} }
@ -1383,7 +1383,7 @@ paste(void)
#if ALPHA_PATCH #if ALPHA_PATCH
static void static void
xinitvisual() xinitvisual(void)
{ {
XVisualInfo *infos; XVisualInfo *infos;
XRenderPictFormat *fmt; XRenderPictFormat *fmt;
@ -1527,6 +1527,11 @@ run(void)
case ButtonPress: case ButtonPress:
buttonpress(&ev); buttonpress(&ev);
break; break;
#if MOTION_SUPPORT_PATCH
case MotionNotify:
motionevent(&ev.xbutton);
break;
#endif // MOTION_SUPPORT_PATCH
#endif // MOUSE_SUPPORT_PATCH #endif // MOUSE_SUPPORT_PATCH
case DestroyNotify: case DestroyNotify:
if (ev.xdestroywindow.window != win) if (ev.xdestroywindow.window != win)
@ -1749,6 +1754,9 @@ setup(void)
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask
#if MOUSE_SUPPORT_PATCH #if MOUSE_SUPPORT_PATCH
| ButtonPressMask | ButtonPressMask
#if MOTION_SUPPORT_PATCH
| PointerMotionMask
#endif // MOTION_SUPPORT_PATCH
#endif // MOUSE_SUPPORT_PATCH #endif // MOUSE_SUPPORT_PATCH
; ;
win = XCreateWindow( win = XCreateWindow(
@ -1904,9 +1912,9 @@ usage(void)
#if XYW_PATCH #if XYW_PATCH
" [-X xoffset] [-Y yoffset] [-W width]" // (arguments made upper case due to conflicts) " [-X xoffset] [-Y yoffset] [-W width]" // (arguments made upper case due to conflicts)
#endif // XYW_PATCH #endif // XYW_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
"\n [-nhb color] [-nhf color] [-shb color] [-shf color]" // highlight colors "\n [-nhb color] [-nhf color] [-shb color] [-shf color]" // highlight colors
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if SEPARATOR_PATCH #if SEPARATOR_PATCH
"\n [-d separator] [-D separator]" "\n [-d separator] [-D separator]"
#endif // SEPARATOR_PATCH #endif // SEPARATOR_PATCH
@ -1927,6 +1935,25 @@ main(int argc, char *argv[])
fputs("warning: no locale support\n", stderr); fputs("warning: no locale support\n", stderr);
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("cannot open display"); die("cannot open display");
/* These need to be checked before we init the visuals and read X resources. */
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-v")) { /* prints version information */
puts("dmenu-"VERSION);
exit(0);
} else if (!strcmp(argv[i], "-w")) {
argv[i][0] = '\0';
embed = strdup(argv[++i]);
#if ALPHA_PATCH
} else if (!strcmp(argv[i], "-o")) { /* opacity, pass -o 0 to disable alpha */
opacity = atoi(argv[++i]);
#endif // ALPHA_PATCH
} else {
continue;
}
argv[i][0] = '\0'; // mark as used
}
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
if (!embed || !(parentwin = strtol(embed, NULL, 0))) if (!embed || !(parentwin = strtol(embed, NULL, 0)))
@ -1936,15 +1963,6 @@ main(int argc, char *argv[])
parentwin); parentwin);
#if ALPHA_PATCH #if ALPHA_PATCH
/* These need to be checked before we init the visuals. */
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-o")) { /* opacity, pass -o 0 to disable alpha */
opacity = atoi(argv[++i]);
} else {
continue;
}
argv[i][0] = '\0'; // mark as used
}
xinitvisual(); xinitvisual();
drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap);
#else #else
@ -2054,7 +2072,7 @@ main(int argc, char *argv[])
#endif // XYW_PATCH #endif // XYW_PATCH
else if (!strcmp(argv[i], "-m")) else if (!strcmp(argv[i], "-m"))
mon = atoi(argv[++i]); mon = atoi(argv[++i]);
#if ALPHA_PATCH #if ALPHA_PATCH && !XRESOURCES_PATCH
else if (!strcmp(argv[i], "-o")) /* opacity, pass -o 0 to disable alpha */ else if (!strcmp(argv[i], "-o")) /* opacity, pass -o 0 to disable alpha */
opacity = atoi(argv[++i]); opacity = atoi(argv[++i]);
#endif // ALPHA_PATCH #endif // ALPHA_PATCH
@ -2088,7 +2106,7 @@ main(int argc, char *argv[])
else if (!strcmp(argv[i], "-hp")) else if (!strcmp(argv[i], "-hp"))
hpitems = tokenize(argv[++i], ",", &hplength); hpitems = tokenize(argv[++i], ",", &hplength);
#endif // HIGHPRIORITY_PATCH #endif // HIGHPRIORITY_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */ else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */
colors[SchemeNormHighlight][ColBg] = argv[++i]; colors[SchemeNormHighlight][ColBg] = argv[++i];
else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */ else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */
@ -2097,13 +2115,15 @@ main(int argc, char *argv[])
colors[SchemeSelHighlight][ColBg] = argv[++i]; colors[SchemeSelHighlight][ColBg] = argv[++i];
else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */ else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */
colors[SchemeSelHighlight][ColFg] = argv[++i]; colors[SchemeSelHighlight][ColFg] = argv[++i];
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if CARET_WIDTH_PATCH #if CARET_WIDTH_PATCH
else if (!strcmp(argv[i], "-cw")) /* sets caret witdth */ else if (!strcmp(argv[i], "-cw")) /* sets caret witdth */
caret_width = atoi(argv[++i]); caret_width = atoi(argv[++i]);
#endif // CARET_WIDTH_PATCH #endif // CARET_WIDTH_PATCH
#if !XRESOURCES_PATCH
else if (!strcmp(argv[i], "-w")) /* embedding window id */ else if (!strcmp(argv[i], "-w")) /* embedding window id */
embed = argv[++i]; embed = argv[++i];
#endif // XRESOURCES_PATCH
#if SEPARATOR_PATCH #if SEPARATOR_PATCH
else if (!strcmp(argv[i], "-d") || /* field separator */ else if (!strcmp(argv[i], "-d") || /* field separator */
(separator_greedy = !strcmp(argv[i], "-D"))) { (separator_greedy = !strcmp(argv[i], "-D"))) {

11
drw.c
View File

@ -9,7 +9,7 @@
#include "drw.h" #include "drw.h"
#include "util.h" #include "util.h"
#if !PANGO_PATCH #if !PANGO_PATCH || HIGHLIGHT_PATCH
#define UTF_INVALID 0xFFFD #define UTF_INVALID 0xFFFD
#define UTF_SIZ 4 #define UTF_SIZ 4
@ -61,6 +61,15 @@ utf8decode(const char *c, long *u, size_t clen)
return len; return len;
} }
#if HIGHLIGHT_PATCH
size_t
utf8len(const char *c)
{
long utf8codepoint = 0;
return utf8decode(c, &utf8codepoint, UTF_SIZ);
}
#endif // HIGHLIGHT_PATCH
#endif // PANGO_PATCH #endif // PANGO_PATCH
Drw * Drw *

4
drw.h
View File

@ -68,6 +68,10 @@ unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
#endif // PANGO_PATCH #endif // PANGO_PATCH
#if HIGHLIGHT_PATCH
size_t utf8len(const char *c);
#endif // HIGHLIGHT_PATCH
/* Colorscheme abstraction */ /* Colorscheme abstraction */
#if ALPHA_PATCH #if ALPHA_PATCH
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha);

View File

@ -1,5 +1,5 @@
static void static void
refreshoptions() refreshoptions(void)
{ {
int dynlen = strlen(dynamic); int dynlen = strlen(dynamic);
char* cmd= malloc(dynlen + strlen(text) + 2); char* cmd= malloc(dynlen + strlen(text) + 2);

View File

@ -1,2 +1,2 @@
static void refreshoptions(); static void refreshoptions(void);
static void readstream(FILE* stream); static void readstream(FILE* stream);

View File

@ -1,66 +0,0 @@
static void
#if EMOJI_HIGHLIGHT_PATCH
drawhighlights(struct item *item, char *output, int x, int y, int maxw)
#else
drawhighlights(struct item *item, int x, int y, int maxw)
#endif // EMOJI_HIGHLIGHT_PATCH
{
int i, indent;
char *highlight;
char c;
#if EMOJI_HIGHLIGHT_PATCH
char *itemtext = output;
#elif TSV_PATCH && !SEPARATOR_PATCH
char *itemtext = item->stext;
#else
char *itemtext = item->text;
#endif // TSV_PATCH
if (!(strlen(itemtext) && strlen(text)))
return;
/* Do not highlight items scheduled for output */
#if MULTI_SELECTION_PATCH
if (issel(item->id))
return;
#else
if (item->out)
return;
#endif // MULTI_SELECTION_PATCH
drw_setscheme(drw, scheme[item == sel
? SchemeSelHighlight
: SchemeNormHighlight]);
for (i = 0, highlight = itemtext; *highlight && text[i];) {
#if FUZZYMATCH_PATCH
if (!fstrncmp(&(*highlight), &text[i], 1))
#else
if (*highlight == text[i])
#endif // FUZZYMATCH_PATCH
{
/* get indentation */
c = *highlight;
*highlight = '\0';
indent = TEXTW(itemtext) - lrpad;
*highlight = c;
/* highlight character */
c = highlight[1];
highlight[1] = '\0';
drw_text(
drw,
x + indent + (lrpad / 2),
y,
MIN(maxw - indent - lrpad, TEXTW(highlight) - lrpad),
bh, 0, highlight, 0
#if PANGO_PATCH
, True
#endif // PANGO_PATCH
);
highlight[1] = c;
i++;
}
highlight++;
}
}

View File

@ -6,7 +6,12 @@ drawhighlights(struct item *item, int x, int y, int maxw)
#endif // EMOJI_HIGHLIGHT_PATCH #endif // EMOJI_HIGHLIGHT_PATCH
{ {
char restorechar, tokens[sizeof text], *highlight, *token; char restorechar, tokens[sizeof text], *highlight, *token;
int indentx, highlightlen; int indent, highlightlen;
#if FUZZYMATCH_PATCH
int i;
#endif // FUZZYMATCH_PATCH
#if EMOJI_HIGHLIGHT_PATCH #if EMOJI_HIGHLIGHT_PATCH
char *itemtext = output; char *itemtext = output;
#elif TSV_PATCH && !SEPARATOR_PATCH #elif TSV_PATCH && !SEPARATOR_PATCH
@ -15,6 +20,9 @@ drawhighlights(struct item *item, int x, int y, int maxw)
char *itemtext = item->text; char *itemtext = item->text;
#endif // EMOJI_HIGHLIGHT_PATCH | TSV_PATCH #endif // EMOJI_HIGHLIGHT_PATCH | TSV_PATCH
if (!(strlen(itemtext) && strlen(text)))
return;
/* Do not highlight items scheduled for output */ /* Do not highlight items scheduled for output */
#if MULTI_SELECTION_PATCH #if MULTI_SELECTION_PATCH
if (issel(item->id)) if (issel(item->id))
@ -25,6 +33,45 @@ drawhighlights(struct item *item, int x, int y, int maxw)
#endif // MULTI_SELECTION_PATCH #endif // MULTI_SELECTION_PATCH
drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : SchemeNormHighlight]); drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : SchemeNormHighlight]);
#if FUZZYMATCH_PATCH
if (fuzzy) {
for (i = 0, highlight = itemtext; *highlight && text[i];) {
highlightlen = utf8len(highlight);
#if FUZZYMATCH_PATCH
if (!fstrncmp(&(*highlight), &text[i], highlightlen))
#else
if (*highlight == text[i])
#endif // FUZZYMATCH_PATCH
{
/* get indentation */
restorechar = *highlight;
*highlight = '\0';
indent = TEXTW(itemtext) - lrpad;
*highlight = restorechar;
/* highlight character */
restorechar = highlight[highlightlen];
highlight[highlightlen] = '\0';
drw_text(
drw,
x + indent + (lrpad / 2),
y,
MIN(maxw - indent - lrpad, TEXTW(highlight) - lrpad),
bh, 0, highlight, 0
#if PANGO_PATCH
, True
#endif // PANGO_PATCH
);
highlight[highlightlen] = restorechar;
i += highlightlen;
}
highlight++;
}
return;
}
#endif // FUZZYMATCH_PATCH
strcpy(tokens, text); strcpy(tokens, text);
for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) { for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) {
highlight = fstrstr(itemtext, token); highlight = fstrstr(itemtext, token);
@ -33,18 +80,18 @@ drawhighlights(struct item *item, int x, int y, int maxw)
highlightlen = highlight - itemtext; highlightlen = highlight - itemtext;
restorechar = *highlight; restorechar = *highlight;
itemtext[highlightlen] = '\0'; itemtext[highlightlen] = '\0';
indentx = TEXTW(itemtext); indent = TEXTW(itemtext);
itemtext[highlightlen] = restorechar; itemtext[highlightlen] = restorechar;
// Move highlight str end, draw highlight, & restore // Move highlight str end, draw highlight, & restore
restorechar = highlight[strlen(token)]; restorechar = highlight[strlen(token)];
highlight[strlen(token)] = '\0'; highlight[strlen(token)] = '\0';
if (indentx - (lrpad / 2) - 1 < maxw) if (indent - (lrpad / 2) - 1 < maxw)
drw_text( drw_text(
drw, drw,
x + indentx - (lrpad / 2) - 1, x + indent - (lrpad / 2) - 1,
y, y,
MIN(maxw - indentx, TEXTW(highlight) - lrpad), MIN(maxw - indent, TEXTW(highlight) - lrpad),
bh, 0, highlight, 0 bh, 0, highlight, 0
#if PANGO_PATCH #if PANGO_PATCH
, True , True

View File

@ -1,2 +1 @@
static int arrayhas(char **list, int length, char *item); static int arrayhas(char **list, int length, char *item);

View File

@ -1,9 +1,7 @@
#if CENTER_PATCH #if CENTER_PATCH
#include "center.c" #include "center.c"
#endif #endif
#if FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
#include "fuzzyhighlight.c"
#elif HIGHLIGHT_PATCH
#include "highlight.c" #include "highlight.c"
#endif #endif
#if FUZZYMATCH_PATCH #if FUZZYMATCH_PATCH

View File

@ -4,6 +4,9 @@ buttonpress(XEvent *e)
struct item *item; struct item *item;
XButtonPressedEvent *ev = &e->xbutton; XButtonPressedEvent *ev = &e->xbutton;
int x = 0, y = 0, h = bh, w; int x = 0, y = 0, h = bh, w;
#if GRID_PATCH
int i, cols;
#endif // GRID_PATCH
if (ev->window != win) if (ev->window != win)
return; return;
@ -66,8 +69,40 @@ buttonpress(XEvent *e)
if (ev->state & ~ControlMask) if (ev->state & ~ControlMask)
return; return;
if (lines > 0) { if (lines > 0) {
#if GRID_PATCH
cols = columns ? columns : 1;
for (i = 0, item = curr; item != next; item = item->right, i++) {
if (
(ev->y >= y + ((i % lines) + 1) * bh) && // line y start
(ev->y <= y + ((i % lines) + 2) * bh) && // line y end
(ev->x >= x + ((i / lines) * (w / cols))) && // column x start
(ev->x <= x + ((i / lines + 1) * (w / cols))) // column x end
) {
#if !MULTI_SELECTION_PATCH
puts(item->text);
#endif // MULTI_SELECTION_PATCH
if (!(ev->state & ControlMask)) {
#if MULTI_SELECTION_PATCH
sel = item;
selsel();
printsel(ev->state);
#endif // MULTI_SELECTION_PATCH
exit(0);
}
sel = item;
if (sel) {
#if MULTI_SELECTION_PATCH
selsel();
#else
sel->out = 1;
#endif // MULTI_SELECTION_PATCH
drawmenu();
}
return;
}
}
#else
/* vertical list: (ctrl)left-click on item */ /* vertical list: (ctrl)left-click on item */
w = mw - x;
for (item = curr; item != next; item = item->right) { for (item = curr; item != next; item = item->right) {
y += h; y += h;
if (ev->y >= y && ev->y <= (y + h)) { if (ev->y >= y && ev->y <= (y + h)) {
@ -94,6 +129,7 @@ buttonpress(XEvent *e)
return; return;
} }
} }
#endif // GRID_PATCH
} else if (matches) { } else if (matches) {
/* left-click on left arrow */ /* left-click on left arrow */
x += inputw; x += inputw;
@ -157,3 +193,79 @@ buttonpress(XEvent *e)
} }
} }
} }
#if MOTION_SUPPORT_PATCH
static void
motionevent(XButtonEvent *ev)
{
struct item *item;
int x = 0, y = 0, w;
#if GRID_PATCH
int i, cols;
#endif // GRID_PATCH
if (ev->window != win || matches == 0)
return;
if (prompt && *prompt)
x += promptw;
if (lines > 0) {
/* input field */
w = mw - x;
#if GRID_PATCH
cols = columns ? columns : 1;
/* grid view or vertical list */
for (i = 0, item = curr; item != next; item = item->right, i++) {
if (
(ev->y >= y + ((i % lines) + 1) * bh) && // line y start
(ev->y <= y + ((i % lines) + 2) * bh) && // line y end
(ev->x >= x + ((i / lines) * (w / cols))) && // column x start
(ev->x <= x + ((i / lines + 1) * (w / cols))) // column x end
) {
sel = item;
calcoffsets();
drawmenu();
break;
}
}
#else
/* vertical list */
w = mw - x;
for (item = curr; item != next; item = item->right) {
y += bh;
if (ev->y >= y && ev->y <= (y + bh)) {
sel = item;
calcoffsets();
drawmenu();
break;
}
}
#endif // GRID_PATCH
return;
}
/* left-click on left arrow */
x += inputw;
#if SYMBOLS_PATCH
w = TEXTW(symbol_1);
#else
w = TEXTW("<");
#endif // SYMBOLS_PATCH
/* horizontal list */
for (item = curr; item != next; item = item->right) {
x += w;
#if SYMBOLS_PATCH
w = MIN(TEXTW(item->text), mw - x - TEXTW(symbol_2));
#else
w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
#endif // SYMBOLS_PATCH
if (ev->x >= x && ev->x <= x + w) {
sel = item;
calcoffsets();
drawmenu();
break;
}
}
}
#endif

View File

@ -32,7 +32,7 @@ printsel(unsigned int state)
} }
static void static void
selsel() selsel(void)
{ {
if (!sel) if (!sel)
return; return;

View File

@ -1,7 +1,7 @@
static char numbers[NUMBERSBUFSIZE] = ""; static char numbers[NUMBERSBUFSIZE] = "";
static void static void
recalculatenumbers() recalculatenumbers(void)
{ {
unsigned int numer = 0, denom = 0; unsigned int numer = 0, denom = 0;
struct item *item; struct item *item;

View File

@ -1,4 +1,4 @@
#define NUMBERSMAXDIGITS 100 #define NUMBERSMAXDIGITS 100
#define NUMBERSBUFSIZE (NUMBERSMAXDIGITS * 2) + 1 #define NUMBERSBUFSIZE (NUMBERSMAXDIGITS * 2) + 1
static void recalculatenumbers(); static void recalculatenumbers(void);

View File

@ -43,7 +43,7 @@ readxresources(void)
if (XrmGetResource(xdb, "dmenu.bordercolor", "*", &type, &xval)) if (XrmGetResource(xdb, "dmenu.bordercolor", "*", &type, &xval))
colors[SchemeBorder][ColBg] = strdup(xval.addr); colors[SchemeBorder][ColBg] = strdup(xval.addr);
#endif // BORDER_PATCH #endif // BORDER_PATCH
#if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH #if HIGHLIGHT_PATCH
if (XrmGetResource(xdb, "dmenu.selhlbackground", "*", &type, &xval)) if (XrmGetResource(xdb, "dmenu.selhlbackground", "*", &type, &xval))
colors[SchemeSelHighlight][ColBg] = strdup(xval.addr); colors[SchemeSelHighlight][ColBg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dmenu.selhlforeground", "*", &type, &xval)) if (XrmGetResource(xdb, "dmenu.selhlforeground", "*", &type, &xval))
@ -52,7 +52,7 @@ readxresources(void)
colors[SchemeNormHighlight][ColBg] = strdup(xval.addr); colors[SchemeNormHighlight][ColBg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dmenu.hlforeground", "*", &type, &xval)) if (XrmGetResource(xdb, "dmenu.hlforeground", "*", &type, &xval))
colors[SchemeNormHighlight][ColFg] = strdup(xval.addr); colors[SchemeNormHighlight][ColFg] = strdup(xval.addr);
#endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH #endif // HIGHLIGHT_PATCH
#if HIGHPRIORITY_PATCH #if HIGHPRIORITY_PATCH
if (XrmGetResource(xdb, "dmenu.hpbackground", "*", &type, &xval)) if (XrmGetResource(xdb, "dmenu.hpbackground", "*", &type, &xval))
colors[SchemeHp][ColBg] = strdup(xval.addr); colors[SchemeHp][ColBg] = strdup(xval.addr);

View File

@ -57,12 +57,6 @@
*/ */
#define EMOJI_HIGHLIGHT_PATCH 0 #define EMOJI_HIGHLIGHT_PATCH 0
/* This patch make it so that fuzzy matches gets highlighted and is therefore meant
* to be used together with the fuzzymatch patch.
* https://tools.suckless.org/dmenu/patches/fuzzyhighlight/
*/
#define FUZZYHIGHLIGHT_PATCH 0
/* This patch adds support for fuzzy-matching to dmenu, allowing users to type non-consecutive /* This patch adds support for fuzzy-matching to dmenu, allowing users to type non-consecutive
* portions of the string to be matched. * portions of the string to be matched.
* https://tools.suckless.org/dmenu/patches/fuzzymatch/ * https://tools.suckless.org/dmenu/patches/fuzzymatch/
@ -89,8 +83,13 @@
#define GRIDNAV_PATCH 0 #define GRIDNAV_PATCH 0
/* This patch highlights the individual characters of matched text for each dmenu list entry. /* This patch highlights the individual characters of matched text for each dmenu list entry.
* The fuzzy highlight patch takes precedence over this patch. * If combined with the fuzzymatch patch then fuzzy highlight will be used for highlighting
* depending on whether fuzzy matching is enabled.
*
* Known issue: highlighting does not work properly when pango markup is used
*
* https://tools.suckless.org/dmenu/patches/highlight/ * https://tools.suckless.org/dmenu/patches/highlight/
* https://tools.suckless.org/dmenu/patches/fuzzyhighlight/
*/ */
#define HIGHLIGHT_PATCH 0 #define HIGHLIGHT_PATCH 0
@ -141,6 +140,11 @@
*/ */
#define MOUSE_SUPPORT_PATCH 0 #define MOUSE_SUPPORT_PATCH 0
/* Expands the above to support mouse hovering.
* https://tools.suckless.org/dmenu/patches/mouse-support/
*/
#define MOTION_SUPPORT_PATCH 0
/* Without this patch when you press Ctrl+Enter dmenu just outputs current item and it is not /* Without this patch when you press Ctrl+Enter dmenu just outputs current item and it is not
* possible to undo that. * possible to undo that.
* With this patch dmenu will output all selected items only on exit. It is also possible to * With this patch dmenu will output all selected items only on exit. It is also possible to
@ -211,6 +215,8 @@
* A long term fix for the libXft library is pending approval of this pull request: * A long term fix for the libXft library is pending approval of this pull request:
* https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1 * https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1
* *
* Known issue: not compatible with the scroll patch
*
* Also see: * Also see:
* https://developer.gnome.org/pygtk/stable/pango-markup-language.html * https://developer.gnome.org/pygtk/stable/pango-markup-language.html
* https://github.com/StillANixRookie/dmenu-pango * https://github.com/StillANixRookie/dmenu-pango
@ -297,6 +303,9 @@
/* This patch adds support for text scrolling and no longer appends '...' for long input as /* This patch adds support for text scrolling and no longer appends '...' for long input as
* it can handle long text. * it can handle long text.
*
* Known issue: not compatible with the pango patch
*
* https://tools.suckless.org/dmenu/patches/scroll/ * https://tools.suckless.org/dmenu/patches/scroll/
*/ */
#define SCROLL_PATCH 0 #define SCROLL_PATCH 0

View File

@ -57,12 +57,6 @@
*/ */
#define EMOJI_HIGHLIGHT_PATCH 0 #define EMOJI_HIGHLIGHT_PATCH 0
/* This patch make it so that fuzzy matches gets highlighted and is therefore meant
* to be used together with the fuzzymatch patch.
* https://tools.suckless.org/dmenu/patches/fuzzyhighlight/
*/
#define FUZZYHIGHLIGHT_PATCH 0
/* This patch adds support for fuzzy-matching to dmenu, allowing users to type non-consecutive /* This patch adds support for fuzzy-matching to dmenu, allowing users to type non-consecutive
* portions of the string to be matched. * portions of the string to be matched.
* https://tools.suckless.org/dmenu/patches/fuzzymatch/ * https://tools.suckless.org/dmenu/patches/fuzzymatch/
@ -89,8 +83,13 @@
#define GRIDNAV_PATCH 1 #define GRIDNAV_PATCH 1
/* This patch highlights the individual characters of matched text for each dmenu list entry. /* This patch highlights the individual characters of matched text for each dmenu list entry.
* The fuzzy highlight patch takes precedence over this patch. * If combined with the fuzzymatch patch then fuzzy highlight will be used for highlighting
* depending on whether fuzzy matching is enabled.
*
* Known issue: highlighting does not work properly when pango markup is used
*
* https://tools.suckless.org/dmenu/patches/highlight/ * https://tools.suckless.org/dmenu/patches/highlight/
* https://tools.suckless.org/dmenu/patches/fuzzyhighlight/
*/ */
#define HIGHLIGHT_PATCH 0 #define HIGHLIGHT_PATCH 0
@ -141,6 +140,11 @@
*/ */
#define MOUSE_SUPPORT_PATCH 1 #define MOUSE_SUPPORT_PATCH 1
/* Expands the above to support mouse hovering.
* https://tools.suckless.org/dmenu/patches/mouse-support/
*/
#define MOTION_SUPPORT_PATCH 1
/* Without this patch when you press Ctrl+Enter dmenu just outputs current item and it is not /* Without this patch when you press Ctrl+Enter dmenu just outputs current item and it is not
* possible to undo that. * possible to undo that.
* With this patch dmenu will output all selected items only on exit. It is also possible to * With this patch dmenu will output all selected items only on exit. It is also possible to
@ -211,6 +215,8 @@
* A long term fix for the libXft library is pending approval of this pull request: * A long term fix for the libXft library is pending approval of this pull request:
* https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1 * https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1
* *
* Known issue: not compatible with the scroll patch
*
* Also see: * Also see:
* https://developer.gnome.org/pygtk/stable/pango-markup-language.html * https://developer.gnome.org/pygtk/stable/pango-markup-language.html
* https://github.com/StillANixRookie/dmenu-pango * https://github.com/StillANixRookie/dmenu-pango
@ -297,6 +303,9 @@
/* This patch adds support for text scrolling and no longer appends '...' for long input as /* This patch adds support for text scrolling and no longer appends '...' for long input as
* it can handle long text. * it can handle long text.
*
* Known issue: not compatible with the pango patch
*
* https://tools.suckless.org/dmenu/patches/scroll/ * https://tools.suckless.org/dmenu/patches/scroll/
*/ */
#define SCROLL_PATCH 1 #define SCROLL_PATCH 1