typedef struct XConf {
Bool running, error;
- int fd, screen, width, height;
+ int fd, screen, width, height, mods;
Window root;
Display* display;
Visual* visual;
void x11_mkwin(XConf* x, int width, int height, int evmask);
void x11_mkdialog(XConf* x, int width, int height, int evmask);
-int x11_process_events(XConf* x);
+int x11_process_events(XConf* x, void (*redrawfn)(XConf*));
void x11_event_loop(XConf* x, void (*redraw)(XConf* x));
int x11_getptr(XConf* x, int* ptrx, int* ptry);
uint32_t x11_getkey(XConf* x, XEvent* e);
XChangeProperty(x->display, x->self, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1);
}
-static void update_time(XConf* x, XEvent* e) {
+static void update_state(XConf* x, XEvent* e) {
if (
(e->type == KeyPress) || (e->type == ButtonPress) ||
(e->type == ButtonRelease) || (e->type == MotionNotify)
) {
x->now = e->xkey.time;
+ x->mods = e->xkey.state;
}
}
-int x11_process_events(XConf* x) {
- int nqueued, nevents, dirty = false;
+int x11_process_events(XConf* x, void (*redrawfn)(XConf*)) {
+ int nqueued, nevents;
/* reap zombie background processes */
for (int status; waitpid(-1, &status, WNOHANG) > 0;);
/* process the entire event queue */
XGetMotionEvents(x->display, x->self, CurrentTime, CurrentTime, &nevents);
for (XEvent e; XPending(x->display);) {
XNextEvent(x->display, &e);
- update_time(x, &e);
- if (e.type == Expose) dirty = 1;
+ update_state(x, &e);
if (!XFilterEvent(&e, None) && x->eventfns[e.type])
(x->eventfns[e.type])(x, &e);
}
- dirty = dirty || nqueued;
+ if (nqueued) redrawfn(x);
} while ((nqueued = XEventsQueued(x->display, QueuedAfterFlush)) > 0);
- return dirty;
+ return 0;
}
void x11_event_loop(XConf* x, void (*redraw)(XConf* x)) {
/* X11 Drawing Code
******************************************************************************/
-static void xupdate(Job* job) {
- /* redraw if we have changes */
- if (!x11_process_events(&X) && job) return;
+
+static void xredraw(XConf* x) {
/* determine the size of the regions */
- size_t maxtagrows = ((X.height/4) / X.font->height);
+ size_t maxtagrows = ((x->height/4) / x->font->height);
size_t tagrows = view_limitrows(&Tags, maxtagrows);
/* draw the regions to the window */
- drawcsr csr = { .w = X.width, .h = X.height };
+ drawcsr csr = { .w = x->width, .h = x->height };
csr.x += ScrollWidth + 1;
- draw_statbox(&X, NORMAL);
- draw_view(&X, &Tags, X.font, tagrows, &csr, TagsBg, TagsFg, TagsSel, false);
+ draw_statbox(x, NORMAL);
+ draw_view(x, &Tags, x->font, tagrows, &csr, TagsBg, TagsFg, TagsSel, false);
int prev_div = Divider;
- Divider = draw_hrule(&X, &csr);
- draw_rect(&X, EditBg, 0, Divider+2, csr.w, csr.h);
- XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0);
+ Divider = draw_hrule(x, &csr);
+ draw_rect(x, EditBg, 0, Divider+2, csr.w, csr.h);
+ XCopyArea(x->display, x->pixmap, x->self, x->gc, 0, 0, x->width, x->height, 0, 0);
if ((retile || prev_div != Divider) && Child) {
- XMoveResizeWindow(X.display, Child, -1, Divider, X.width, X.height - Divider);
+ XMoveResizeWindow(x->display, Child, -1, Divider, x->width, x->height - Divider);
retile = 0;
}
- XFlush(X.display);
+ XFlush(x->display);
+}
+
+static void xupdate(Job* job) {
+ x11_process_events(&X, xredraw);
+ if (!job) xredraw(&X);
}
void win_init(void) {
static Tag Builtins[18];
static KeyBinding Bindings[];
static struct XConf X;
-static int KeyBtnState;
static WinRegion Focused = EDIT;
static View Regions[NREGIONS];
static int Divider;
static void xkeypress(XConf* x, XEvent* e) {
uint32_t key = x11_process_key(x, e, Bindings);
Focused = (e->xkey.y <= Divider ? TAGS : EDIT);
- KeyBtnState = e->xkey.state;
if (key != RUNE_ERR)
view_insert(win_view(FOCUSED), key);
}
static void xbtnpress(XConf* x, XEvent* e) {
(void)x;
- KeyBtnState = (e->xbutton.state | (1 << (e->xbutton.button + 7)));
mouse_click(e->xbutton.button, e->xbutton.state, true, e->xbutton.x, e->xbutton.y);
}
static void xbtnrelease(XConf* x, XEvent* e) {
(void)x;
- KeyBtnState = (KeyBtnState & ~(1 << (e->xbutton.button + 7)));
mouse_click(e->xbutton.button, e->xbutton.state, false, e->xbutton.x, e->xbutton.y);
}
static void xbtnmotion(XConf* x, XEvent* e) {
while (XCheckTypedEvent(x->display, MotionNotify, e));
size_t row, col;
- KeyBtnState = e->xbutton.state;
int xpos = e->xbutton.x, ypos = e->xbutton.y;
get_position(Focused, xpos, ypos, &row, &col);
if (PRESSED(e->xbutton.state, MouseLeft))
win_setln(e->xclient.data.l[0]);
}
-static void xupdate(Job* job) {
- /* redraw if we have changes */
- if (!x11_process_events(&X) && job) return;
+static void xredraw(XConf* x) {
/* force update the title */
win_title(NULL);
/* determine the size of the regions */
- size_t maxtagrows = ((X.height/4) / X.tagfont->height);
+ size_t maxtagrows = ((x->height/4) / x->tagfont->height);
size_t tagrows = view_limitrows(win_view(TAGS), maxtagrows);
- size_t tagregsz = (tagrows * X.tagfont->height) + 7;
- size_t editrows = (X.height - tagregsz) / X.font->height ;
+ size_t tagregsz = (tagrows * x->tagfont->height) + 7;
+ size_t editrows = (x->height - tagregsz) / x->font->height ;
/* draw the regions to the window */
- drawcsr csr = { .w = X.width, .h = X.height };
+ drawcsr csr = { .w = x->width, .h = x->height };
csr.x += ScrollWidth + 1;
- draw_statbox(&X, win_view(EDIT)->buffer.status);
- draw_view(&X, &Regions[TAGS], X.tagfont, tagrows, &csr, TagsBg, TagsFg, TagsSel, false);
- Divider = draw_hrule(&X, &csr);
- draw_view(&X, &Regions[EDIT], X.font, editrows, &csr, EditBg, EditFg, EditSel, SyncMouse);
- draw_scroll(&X, &csr, win_view(EDIT), Divider);
- XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0);
+ draw_statbox(x, win_view(EDIT)->buffer.status);
+ draw_view(x, &Regions[TAGS], x->tagfont, tagrows, &csr, TagsBg, TagsFg, TagsSel, false);
+ Divider = draw_hrule(x, &csr);
+ draw_view(x, &Regions[EDIT], x->font, editrows, &csr, EditBg, EditFg, EditSel, SyncMouse);
+ draw_scroll(x, &csr, win_view(EDIT), Divider);
+ XCopyArea(x->display, x->pixmap, x->self, x->gc, 0, 0, x->width, x->height, 0, 0);
SyncMouse = false;
- XFlush(X.display);
+ XFlush(x->display);
+}
+
+static void xupdate(Job* job) {
+ /* redraw if we have changes */
+ if (!x11_process_events(&X, xredraw) && job) return;
}
void win_init(void) {
}
bool win_keymodsset(int mask) {
- return ((KeyBtnState & mask) == mask);
+ return ((X.mods & mask) == mask);
}
void win_setln(int line_num) {