commit - 9ff10a0f897bf216fbea6b2bf5c8ccfb9d1b0d9b
commit + 844addbb3803e8f077087ce69fdaaf32b0ea4395
blob - 7aa4f86701101cbc050057c97db8c9d85a4c54a5
blob + 30172d531c4e6ecb5843222e3dd95f94a1ce98f2
--- mymenu.1
+++ mymenu.1
.Op Fl p Ar prompt
.Op Fl x Ar coord
.Op Fl y Ar coord
-.Op Fl w Ar width
-.Op Fl h Ar height
+.Op Fl W Ar width
+.Op Fl H Ar height
.Op Fl P Ar padding
.Op Fl l Ar layout
.Op Fl f Ar font
.Op Fl b Ar borders
-.Op Fl B Ar color
+.Op Fl B Ar colors
.Op Fl t Ar color
.Op Fl T Ar color
.Op Fl c Ar color
.Op Fl C Ar color
.Op Fl s Ar color
.Op Fl S Ar color
+.Op Fl w Ar window
.Ek
.Sh DESCRIPTION
The
Override the highlighted completion foreground color. See MyMenu.completion_highlighted.foreground.
.It Fl S Ar color
Override the highlighted completion background color. See MyMenu.completion_highlighted.background.
+.It Fl w Ar window
+Embed into the given window id.
.El
.Sh RESOURCES
.Bl -tag -width Ds
blob - a3799a212afaf7e478c6c183efd87a9b0d36f9d6
blob + 11461dc55c32d53b0ec151ac8ee391cf9ef1ade8
--- mymenu.1.md
+++ mymenu.1.md
\[**-p** *prompt*]
\[**-x** *coord*]
\[**-y** *coord*]
-\[**-w** *width*]
-\[**-h** *height*]
+\[**-W** *width*]
+\[**-H** *height*]
\[**-P** *padding*]
\[**-l** *layout*]
\[**-f** *font*]
\[**-b** *borders*]
-\[**-B** *color*]
+\[**-B** *colors*]
\[**-t** *color*]
\[**-T** *color*]
\[**-c** *color*]
\[**-C** *color*]
\[**-s** *color*]
\[**-S** *color*]
+\[**-w** *window*]
# DESCRIPTION
> Override the highlighted completion background color. See MyMenu.completion\_highlighted.background.
+**-w** *window*
+
+> Embed into the given window id.
+
# RESOURCES
MyMenu.font
Omar Polo <omar.polo@europecom.net>
-OpenBSD 6.3 - July 13, 2018
+OpenBSD 6.3 - July 15, 2018
blob - a8792fdcffe280276c3b1dacc1740b5d5d395ed8
blob + e4558fc6d4f892c6bb22a6710c205cdb3ced7dcd
--- mymenu.c
+++ mymenu.c
# define default_fontname "fixed"
#endif
-#define ARGS "hvap:P:l:f:w:h:x:y:b:B:t:T:c:C:s:S:"
+#define ARGS "hvae:p:P:l:f:W:H:x:y:b:B:t:T:c:C:s:S:"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
start_at = r->x_zero + text_extents("n", 1, r, nil, nil);
start_at = start_at * prompt_width + r->padding;
- int texty = (height + r->height) >>1;
+ int texty = (inner_height(r) + height + r->y_zero) / 2;
XFillRectangle(r->d, r->w, r->prompt_bg, r->x_zero, r->y_zero, start_at, inner_height(r));
draw_string(r->ps1, r->ps1len, r->x_zero + r->padding, texty, r, PROMPT);
draw_string(text, MIN(text_len, prompt_width), r->x_zero + r->padding + ps1xlen, texty, r, PROMPT);
- XFillRectangle(r->d, r->w, r->completion_bg, start_at, r->y_zero, r->width, r->height);
+ XFillRectangle(r->d, r->w, r->completion_bg, start_at, r->y_zero, r->width, inner_height(r));
struct completion *c = cs->completions;
for (int i = 0; c != nil; ++i) {
XGetWindowAttributes(d, *w, &win_attr);
*height = win_attr.height;
*width = win_attr.width;
+}
+
+int grabfocus(Display *d, Window w) {
+ for (int i = 0; i < 100; ++i) {
+ Window focuswin;
+ int revert_to_win;
+ XGetInputFocus(d, &focuswin, &revert_to_win);
+ if (focuswin == w)
+ return true;
+ XSetInputFocus(d, w, RevertToParent, CurrentTime);
+ usleep(1000);
+ }
+ return 0;
}
// I know this may seem a little hackish BUT is the only way I managed
return 1;
usleep(1000);
}
+ fprintf(stderr, "Cannot grab keyboard\n");
return 0;
}
// Given the name of the program (argv[0]?) print a small help on stderr
void usage(char *prgname) {
- fprintf(stderr, "Usage: %s [flags]\n", prgname);
- fprintf(stderr, "\t-a: automatic mode, the first completion is "
- "always selected;\n");
- fprintf(stderr, "\t-h: print this help.\n");
+ fprintf(stderr, "%s [-hva] [-p prompt] [-x coord] [-y coord] [-W width] [-H height]\n"
+ " [-P padding] [-l layout] [-f font] [-b borders] [-B colors]\n"
+ " [-t color] [-T color] [-c color] [-C color] [-s color] [-S color]\n"
+ " [-w window_id]\n", prgname);
}
int main(int argc, char **argv) {
// by default the first completion isn't selected
bool first_selected = false;
- // first round of args parsing for early terminating options
+ char *parent_window_id = nil;
+
+ // first round of args parsing
int ch;
while ((ch = getopt(argc, argv, ARGS)) != -1) {
switch (ch) {
- /* case 'a': */
- /* first_selected = true; */
- /* break; */
- case 'h':
+ case 'h': // help
usage(*argv);
return 0;
- case 'v':
+ case 'v': // version
fprintf(stderr, "%s version: %s\n", *argv, VERSION);
return 0;
+ case 'e': // embed
+ parent_window_id = strdup(optarg);
+ check_allocation(parent_window_id);
+ break;
default:
break;
}
return EX_UNAVAILABLE;
}
+ Window parent_window;
+ bool embed = true;
+ if (! (parent_window_id && (parent_window = strtol(parent_window_id, nil, 0)))) {
+ parent_window = DefaultRootWindow(d);
+ embed = false;
+ }
+
// get display size
- // XXX: is getting the default root window dimension correct?
- XWindowAttributes xwa;
- XGetWindowAttributes(d, DefaultRootWindow(d), &xwa);
- int d_width = xwa.width;
- int d_height = xwa.height;
+ int d_width;
+ int d_height;
+ get_wh(d, &parent_window, &d_width, &d_height);
+ fprintf(stderr, "d_width %d, d_height %d\n", d_width, d_height);
+
#ifdef USE_XINERAMA
- if (XineramaIsActive(d)) {
+ if (!embed && XineramaIsActive(d)) {
// find the mice
int number_of_screens = XScreenCount(d);
Window r;
case 'a':
first_selected = true;
break;
+ case 'e':
+ // (embedding mymenu) this case was already catched.
+ break;
case 'p': {
char *newprompt = strdup(optarg);
if (newprompt != nil) {
}
break;
}
- case 'w':
+ case 'W':
width = parse_int_with_percentage(optarg, width, d_width);
break;
- case 'h':
+ case 'H':
height = parse_int_with_percentage(optarg, height, d_height);
break;
case 'b': {
// create the window
XSetWindowAttributes attr;
attr.override_redirect = true;
+ attr.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
Window w = XCreateWindow(d, // display
- DefaultRootWindow(d), // parent
+ parent_window, // parent
x + offset_x, y + offset_y, // x y
width, height, // w h
0, // border width
- DefaultDepth(d, DefaultScreen(d)), // depth
+ CopyFromParent, // depth
InputOutput, // class
- DefaultVisual(d, DefaultScreen(d)), // visual
- CWOverrideRedirect, // value mask
+ CopyFromParent, // visual
+ CWEventMask | CWOverrideRedirect, // value mask (CWBackPixel in the future also?)
&attr);
set_win_atoms_hints(d, w, width, height);
// we want some events
XSelectInput(d, w, StructureNotifyMask | KeyPressMask | KeymapStateMask);
+ XMapRaised(d, w);
- // make the window appear on the screen
- XMapWindow(d, w);
-
- // wait for the MapNotify event (i.e. the event "window rendered")
- for (;;) {
- XEvent e;
- XNextEvent(d, &e);
- if (e.type == MapNotify)
- break;
+ // if embed, listen for other events as well
+ if (embed) {
+ XSelectInput(d, parent_window, FocusChangeMask);
+ Window *children, parent, root;
+ unsigned int children_no;
+ if (XQueryTree(d, parent_window, &root, &parent, &children, &children_no) && children) {
+ for (unsigned int i = 0; i < children_no && children[i] != w; ++i)
+ XSelectInput(d, children[i], FocusChangeMask);
+ XFree(children);
+ }
+ grabfocus(d, w);
}
- // get the *real* width & height after the window was rendered
- get_wh(d, &w, &width, &height);
-
// grab keyboard
take_keyboard(d, w);
switch (e.type) {
case KeymapNotify:
XRefreshKeyboardMapping(&e.xmapping);
+ break;
+
+ case FocusIn:
+ // re-grab focus
+ if (e.xfocus.window != w)
+ grabfocus(d, w);
break;
+ case VisibilityNotify:
+ if (e.xvisibility.state != VisibilityUnobscured)
+ XRaiseWindow(d, w);
+ break;
+
+ case MapNotify:
+ /* fprintf(stderr, "Map Notify!\n"); */
+ /* TODO: update the computed window and height! */
+ /* get_wh(d, &w, width, height); */
+ draw(&r, text, cs);
+ break;
+
case KeyPress: {
XKeyPressedEvent *ev = (XKeyPressedEvent*)&e;