-
Notifications
You must be signed in to change notification settings - Fork 5
/
xprompt.c
118 lines (111 loc) · 2.96 KB
/
xprompt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "shod.h"
/* calculate position and size of prompt window and the size of its frame */
static void
promptcalcgeom(int *x, int *y, int *w, int *h, int *fw, int *fh)
{
*w = min(*w, wm.selmon->ww - config.borderwidth * 2);
*h = min(*h, wm.selmon->wh - config.borderwidth);
*x = wm.selmon->wx + (wm.selmon->ww - *w) / 2 - config.borderwidth;
*y = wm.selmon->wy;
*fw = *w + config.borderwidth * 2;
*fh = *h + config.borderwidth;
}
/* check if event is related to the prompt or its frame */
static Bool
promptvalidevent(Display *dpy, XEvent *ev, XPointer arg)
{
Window win;
(void)dpy;
win = *(Window *)arg;
switch(ev->type) {
case DestroyNotify:
if (ev->xdestroywindow.window == win)
return True;
break;
case UnmapNotify:
if (ev->xunmap.window == win)
return True;
break;
case ConfigureRequest:
if (ev->xconfigurerequest.window == win)
return True;
break;
case ButtonPress:
return True;
}
return False;
}
/* decorate prompt frame */
static void
promptdecorate(Window frame, Pixmap *pix, int w, int h)
{
if (*pix != None)
XFreePixmap(dpy, *pix);
*pix = XCreatePixmap(dpy, frame, w, h, depth);
drawbackground(*pix, 0, 0, w, h, FOCUSED);
drawprompt(*pix, w, h);
drawcommit(*pix, frame);
}
static void
manage(struct Tab *tab, struct Monitor *mon, int desk, Window win,
Window leader, XRectangle rect, enum State state)
{
Window frame; /* prompt frame */
Pixmap pix; /* pixmap to draw the frame */
XEvent ev;
int x, y, w, h, fw, fh;
/*
* Map prompt, give it focus, wait for it to close, then revert
* focus to previously focused window.
*/
(void)tab;
(void)mon;
(void)desk;
(void)leader;
(void)state;
w = rect.width;
h = rect.height;
promptcalcgeom(&x, &y, &w, &h, &fw, &fh);
frame = createframe((XRectangle){x, y, fw, fh});
pix = None;
XReparentWindow(dpy, win, frame, config.borderwidth, 0);
XMapWindow(dpy, win);
XMapWindow(dpy, frame);
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
promptdecorate(frame, &pix, fw, fh);
while (!XIfEvent(dpy, &ev, promptvalidevent, (XPointer)&win)) {
switch (ev.type) {
case DestroyNotify:
case UnmapNotify:
goto done;
break;
case ConfigureRequest:
w = ev.xconfigurerequest.width;
h = ev.xconfigurerequest.height;
promptcalcgeom(&x, &y, &w, &h, &fw, &fh);
XMoveResizeWindow(dpy, frame, x, y, fw, fh);
XMoveResizeWindow(dpy, win, config.borderwidth, 0, w, h);
promptdecorate(frame, &pix, fw, fh);
break;
case ButtonPress:
if (ev.xbutton.window != win && ev.xbutton.window != frame)
winclose(win);
XAllowEvents(dpy, ReplayPointer, CurrentTime);
break;
}
}
done:
XReparentWindow(dpy, win, root, 0, 0);
XDestroyWindow(dpy, frame);
if (wm.focused) {
tabfocus(wm.focused->selcol->selrow->seltab, 0);
} else {
tabfocus(NULL, 0);
}
}
struct Class *prompt_class = &(struct Class){
.type = TYPE_PROMPT,
.setstate = NULL,
.manage = manage,
.unmanage = NULL,
};