commit - 92803b004812d95b2147c6c8a54618bc26d7d98a
commit + a81dbe5ddfb13ed5d74cafe65fdce0abaf30d953
blob - 0acc85f1ffb1bd74b78377df58003831bf306669
blob + 87c3a615620c6002cee935e34c93f387b85e9cb5
--- mymenu.1
+++ mymenu.1
really want to choose ``fire''. While you can type some spaces, this
keybinding is a more elegant way to change, at runtime, the behaviour
of the first completion.
+.It Button1
+Confirm the clicked item
+.It Button3
+Confirm but keep looping (if enabled) the clicked item, like C-m
+.It Button4,Button5 / scroll
+Scroll through the completions (without changing the selection)
.El
.Sh EXIT STATUS
0 when the user select an entry, 1 when the user press Esc, EX_USAGE
As a general rule of thumb, if you're overriding the width and/or the
height of the window, remember to override the x and y coordinates as
well.
+.It
+Clicking past the last item will be equivalent to clicking the last item.
.El
blob - b90e5bd093cc36c2ecc50d67aa0c9f8bf6aa7626
blob + 2614cfe00b435f178360885cffec255d8eb18f95
--- mymenu.1.md
+++ mymenu.1.md
> really want to choose \`\`fire''. While you can type some spaces, this
> keybinding is a more elegant way to change, at runtime, the behaviour
> of the first completion.
+
+Button1
+
+> Confirm the clicked item
+
+Button3
+
+> Confirm but keep looping (if enabled) the clicked item, like C-m
+Button4,Button5 / scroll
+
+> Scroll through the completions (without changing the selection)
+
# EXIT STATUS
0 when the user select an entry, 1 when the user press Esc, EX\_USAGE
height of the window, remember to override the x and y coordinates as
well.
-Void Linux - October 18, 2019
+Void Linux - October 19, 2019
blob - a55338f82b1ebd2768cd614edb414bbaad506cbe
blob + 5536c9ee22520d3992c12e00937bec30034ef8f6
--- mymenu.c
+++ mymenu.c
/* These are the possible action to be performed after user input. */
enum action {
+ NO_OP,
EXIT,
CONFIRM,
CONFIRM_CONTINUE,
DEL_WORD,
DEL_LINE,
ADD_CHAR,
- TOGGLE_FIRST_SELECTED
+ TOGGLE_FIRST_SELECTED,
+ SCROLL_DOWN,
+ SCROLL_UP,
};
/* A big set of values that needs to be carried around for drawing. A
-big struct to rule them all */
+ * big struct to rule them all */
struct rendering {
Display *d; /* Connection to xorg */
Window w;
the borders) */
int y_zero; /* like x_zero but for the y axis */
- size_t offset; /* scroll offset */
+ int offset; /* scroll offset */
short free_text;
short first_selected;
struct completion {
char *completion;
char *rcompletion;
+ int offset; /* the x (or y, depending on the layout) coordinate at
+ which the item is rendered */
};
/* Wrap the linked list of completions */
enum obj_type t
= cs->selected == (ssize_t)i ? COMPL_HIGH : COMPL;
+ cs->completions[i].offset = x;
+
x += draw_h_box(
r, x, NULL, 0, t, cs->completions[i].completion);
if (x > inner_width(r))
break;
}
+
+ for (i += 1; i < cs->length; ++i)
+ cs->completions[i].offset = -1;
}
/* ,-----------------------------------------------------------------, */
enum obj_type t
= cs->selected == (ssize_t)i ? COMPL_HIGH : COMPL;
+ cs->completions[i].offset = y;
+
y += draw_v_box(
r, y, NULL, 0, t, cs->completions[i].completion);
if (y > inner_height(r))
break;
}
+
+ for (i += 1; i < cs->length; ++i)
+ cs->completions[i].offset = -1;
}
void
if (!r->free_text) /* cannot accept arbitrary text */
*status = LOOPING;
+}
+
+/* cs: completion list
+ * offset: the offset of the click
+ * first: the first (rendered) item
+ * def: the default action
+ */
+enum action
+select_clicked(
+ struct completions *cs, size_t offset, size_t first, enum action def)
+{
+ ssize_t selected = first;
+ int set = 0;
+
+ if (cs->length == 0)
+ return NO_OP;
+
+ if (offset < cs->completions[selected].offset)
+ return NO_OP;
+
+ /* skip the first entry */
+ for (selected += 1; selected < cs->length; ++selected) {
+ if (cs->completions[selected].offset == -1) {
+ printf("caught -1\n");
+ break;
+ }
+ if (offset < cs->completions[selected].offset) {
+ cs->selected = selected - 1;
+ set = 1;
+ break;
+ }
+ }
+
+ if (!set)
+ cs->selected = selected - 1;
+
+ return def;
+}
+
+enum action
+handle_mouse(
+ struct rendering *r, struct completions *cs, XButtonPressedEvent *e)
+{
+ size_t off;
+
+ if (r->horizontal_layout)
+ off = e->x;
+ else
+ off = e->y;
+
+ switch (e->button) {
+ case Button1:
+ return select_clicked(cs, off, r->offset, CONFIRM);
+
+ case Button3:
+ return select_clicked(cs, off, r->offset, CONFIRM_CONTINUE);
+
+ case Button4:
+ return SCROLL_UP;
+
+ case Button5:
+ return SCROLL_DOWN;
+ }
+
+ return NO_OP;
}
/* event loop */
draw(r, *text, cs);
break;
- case KeyPress: {
- XKeyPressedEvent *ev = (XKeyPressedEvent *)&e;
- char *input;
+ case KeyPress:
+ case ButtonPress: {
+ enum action a;
+ char *input = NULL;
- switch (parse_event(r->d, ev, r->xic, &input)) {
+ if (e.type == KeyPress)
+ a = parse_event(r->d, (XKeyPressedEvent *)&e,
+ r->xic, &input);
+ else
+ a = handle_mouse(
+ r, cs, (XButtonPressedEvent *)&e);
+
+ switch (a) {
+ case NO_OP:
+ break;
+
case EXIT:
status = ERR;
break;
if (!r->first_selected && cs->selected == 0)
cs->selected = -1;
break;
- }
- }
- case ButtonPress: {
- XButtonPressedEvent *ev = (XButtonPressedEvent *)&e;
- /* if (ev->button == Button1) { /\* click *\/ */
- /* int x = ev->x - r.border_w; */
- /* int y = ev->y - r.border_n; */
- /* fprintf(stderr, "Click @ (%d, %d)\n", x, y); */
- /* } */
-
- if (ev->button == Button4) /* scroll up */
- r->offset = MAX((ssize_t)r->offset - 1, 0);
-
- if (ev->button == Button5) /* scroll down */
+ case SCROLL_DOWN:
r->offset
= MIN(r->offset + 1, cs->length - 1);
+ break;
- break;
+ case SCROLL_UP:
+ r->offset = MAX((ssize_t)r->offset - 1, 0);
+ break;
+ }
}
}