2023-05-14 00:21:16 +02:00
|
|
|
/* See LICENSE file for copyright and license details. */
|
2023-05-23 22:14:24 +02:00
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void prepare_window_size(void) {
|
2023-03-31 12:42:15 +02:00
|
|
|
// set horizontal and vertical padding
|
2023-03-08 17:20:32 +01:00
|
|
|
sp = menupaddingh;
|
2023-05-08 23:00:45 +02:00
|
|
|
vp = (menuposition == 1) ? menupaddingv : - menupaddingv;
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-21 23:40:19 +02:00
|
|
|
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
|
|
|
|
lines = MAX(lines, 0);
|
|
|
|
reallines = lines;
|
|
|
|
|
|
|
|
lrpad = drw->font->h + textpadding;
|
|
|
|
mh = (lines + 1) * bh + 2 * menumarginv; // lines + 1 * bh is the menu height
|
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
return;
|
2023-03-08 17:20:32 +01:00
|
|
|
}
|
2023-03-02 12:15:36 +01:00
|
|
|
|
2023-05-21 23:52:28 +02:00
|
|
|
void get_width(int numwidthchecks, unsigned int minstrlen, unsigned int curstrlen) {
|
|
|
|
struct item *item;
|
|
|
|
unsigned int tmp = 0;
|
|
|
|
|
|
|
|
// get accurate width
|
|
|
|
if (accuratewidth) {
|
|
|
|
for (item = items; !lines && item && item->text; ++item) {
|
|
|
|
curstrlen = strlen(item->text);
|
|
|
|
if (numwidthchecks || minstrlen < curstrlen) {
|
|
|
|
numwidthchecks = MAX(numwidthchecks - 1, 0);
|
|
|
|
minstrlen = MAX(minstrlen, curstrlen);
|
|
|
|
if ((tmp = MIN(TEXTW(item->text), mw/3) > inputw)) {
|
|
|
|
inputw = tmp;
|
|
|
|
if (tmp == mw/3)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void create_window(int x, int y, int w, int h) {
|
2023-03-02 12:15:36 +01:00
|
|
|
XSetWindowAttributes swa;
|
|
|
|
|
|
|
|
swa.override_redirect = managed ? False : True;
|
2023-05-08 23:00:45 +02:00
|
|
|
swa.background_pixel = 0;
|
|
|
|
swa.colormap = cmap;
|
|
|
|
swa.event_mask =
|
2023-03-31 12:42:15 +02:00
|
|
|
ExposureMask | // mapping the drawing
|
|
|
|
KeyPressMask | // keypresses
|
|
|
|
VisibilityChangeMask | // whether or not client is visible
|
|
|
|
ButtonPressMask | // see buttonpress in libs/mouse.c for usage
|
|
|
|
PointerMotionMask; // we need pointer for selecting entries using the mouse
|
2023-03-02 12:15:36 +01:00
|
|
|
|
2023-03-12 21:03:35 +01:00
|
|
|
// create client
|
2023-04-30 00:45:48 +02:00
|
|
|
win = XCreateWindow(dpy, root, x, y, w, h, borderwidth,
|
2023-05-08 23:00:45 +02:00
|
|
|
depth, InputOutput, visual,
|
|
|
|
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
|
2023-03-12 21:03:35 +01:00
|
|
|
|
2023-03-02 12:15:36 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void set_window(void) {
|
2023-03-02 12:15:36 +01:00
|
|
|
XClassHint ch = { class, class };
|
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
// set border and class
|
2023-03-02 12:15:36 +01:00
|
|
|
XSetWindowBorder(dpy, win, scheme[SchemeBorder][ColBg].pixel);
|
2023-05-08 23:00:45 +02:00
|
|
|
XSetClassHint(dpy, win, &ch);
|
2023-05-06 14:29:45 +02:00
|
|
|
|
2023-03-02 12:15:36 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void set_prop(void) {
|
2023-05-21 23:40:19 +02:00
|
|
|
// set properties indicating what spmenu handles
|
|
|
|
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
|
|
|
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
|
|
|
types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
|
|
|
|
|
|
|
|
// set dock property
|
|
|
|
if (dockproperty) {
|
|
|
|
dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
|
|
|
XChangeProperty(dpy, win, types, XA_ATOM, 32, PropModeReplace, (unsigned char *) &dock, 1); // set dock property
|
|
|
|
}
|
2023-03-02 12:15:36 +01:00
|
|
|
}
|
2023-03-13 22:45:04 +01:00
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void resizeclient(void) {
|
2023-03-13 22:45:04 +01:00
|
|
|
int omh = mh;
|
2023-04-17 18:58:34 +02:00
|
|
|
int x, y;
|
2023-05-08 23:00:45 +02:00
|
|
|
#if USEXINERAMA
|
2023-04-17 18:58:34 +02:00
|
|
|
int j, di, a, n, area = 0;
|
|
|
|
XineramaScreenInfo *info;
|
2023-05-08 23:00:45 +02:00
|
|
|
Window pw;
|
2023-04-17 18:58:34 +02:00
|
|
|
unsigned int du;
|
|
|
|
Window w, dw, *dws;
|
2023-05-08 23:00:45 +02:00
|
|
|
#endif
|
2023-04-17 18:58:34 +02:00
|
|
|
XWindowAttributes wa;
|
2023-03-19 14:26:36 +01:00
|
|
|
struct item *item;
|
2023-05-21 23:52:28 +02:00
|
|
|
int ic = 0; // item count
|
2023-03-19 14:26:36 +01:00
|
|
|
|
|
|
|
// walk through all items
|
|
|
|
for (item = items; item && item->text; item++)
|
2023-05-21 23:52:28 +02:00
|
|
|
ic++;
|
2023-03-13 22:45:04 +01:00
|
|
|
|
2023-03-18 21:20:00 +01:00
|
|
|
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
|
2023-05-21 23:52:28 +02:00
|
|
|
lines = MIN(ic, MAX(lines, 0));
|
2023-03-18 21:20:00 +01:00
|
|
|
reallines = lines;
|
2023-03-13 22:45:04 +01:00
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
// resize client to image height
|
2023-05-08 23:00:45 +02:00
|
|
|
#if USEIMAGE
|
2023-03-31 12:42:15 +02:00
|
|
|
if (image) resizetoimageheight(imageheight);
|
2023-05-08 23:00:45 +02:00
|
|
|
#endif
|
2023-03-13 22:45:04 +01:00
|
|
|
|
2023-04-16 23:57:02 +02:00
|
|
|
mh = (lines + 1) * bh + 2 * menumarginv;
|
2023-03-13 22:45:04 +01:00
|
|
|
|
2023-04-17 18:58:34 +02:00
|
|
|
// init xinerama screens
|
2023-05-08 23:00:45 +02:00
|
|
|
#if USEXINERAMA
|
|
|
|
int i = 0;
|
|
|
|
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
|
|
|
XGetInputFocus(dpy, &w, &di);
|
|
|
|
if (mon >= 0 && mon < n) {
|
|
|
|
i = mon;
|
2023-04-17 20:03:02 +02:00
|
|
|
} else if (w != root && w != PointerRoot && w != None) {
|
|
|
|
do {
|
2023-05-08 23:00:45 +02:00
|
|
|
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
|
|
|
XFree(dws);
|
2023-04-17 20:03:02 +02:00
|
|
|
} while (w != root && w != pw);
|
2023-05-08 23:00:45 +02:00
|
|
|
if (XGetWindowAttributes(dpy, pw, &wa)) {
|
|
|
|
for (j = 0; j < n; j++) {
|
|
|
|
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
|
|
|
area = a;
|
|
|
|
i = j;
|
2023-04-17 20:03:02 +02:00
|
|
|
}
|
|
|
|
}
|
2023-05-08 23:00:45 +02:00
|
|
|
}
|
2023-04-17 20:03:02 +02:00
|
|
|
|
|
|
|
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
if (INTERSECT(x, y, 1, 1, info[i])) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-17 18:58:34 +02:00
|
|
|
|
|
|
|
// calculate x/y position
|
2023-05-08 23:00:45 +02:00
|
|
|
if (menuposition == 2) { // centered
|
|
|
|
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
|
|
|
x = info[i].x_org + ((info[i].width - mw) / 2);
|
|
|
|
y = info[i].y_org + ((info[i].height - mh) / 2);
|
|
|
|
} else { // top or bottom
|
|
|
|
x = info[i].x_org + xpos;
|
|
|
|
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
|
|
|
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree(info);
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2023-04-22 21:39:22 +02:00
|
|
|
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
2023-05-08 23:00:45 +02:00
|
|
|
die("spmenu: could not get embedding window attributes: 0x%lx",
|
|
|
|
parentwin); // die because unable to get attributes for the parent window
|
|
|
|
if (menuposition == 2) { // centered
|
|
|
|
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
|
|
|
x = (wa.width - mw) / 2;
|
|
|
|
y = (wa.height - mh) / 2;
|
|
|
|
} else { // top or bottom
|
|
|
|
x = 0;
|
|
|
|
y = menuposition ? 0 : wa.height - mh - ypos;
|
|
|
|
mw = wa.width;
|
|
|
|
}
|
|
|
|
}
|
2023-04-17 18:58:34 +02:00
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
// why have an empty line? when there's nothing to draw there anyway?
|
2023-03-28 17:37:06 +02:00
|
|
|
if (hideprompt && hideinput && hidemode && hidematchcount)
|
|
|
|
mh += bh;
|
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
// no window/invalid window or menu height we had before is the same as the current window height
|
2023-03-13 22:45:04 +01:00
|
|
|
if (!win || omh == mh) return;
|
|
|
|
|
2023-04-22 00:50:26 +02:00
|
|
|
XMoveResizeWindow(dpy, win, x + sp, y + vp, mw - 2 * sp - borderwidth * 2, mh);
|
2023-04-07 14:43:45 +02:00
|
|
|
drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
|
2023-03-13 22:45:04 +01:00
|
|
|
}
|