From: Michael D. Lowis Date: Sun, 16 Dec 2018 03:25:43 +0000 (-0500) Subject: rework x11 stuff X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=529a27dec46c5cfbc20523c9cd30a4116b4c2132;p=projs%2Ftide.git rework x11 stuff --- diff --git a/inc/x11.h b/inc/x11.h index 80793bc..e2693fc 100644 --- a/inc/x11.h +++ b/inc/x11.h @@ -11,6 +11,7 @@ #pragma GCC diagnostic ignored "-Wunused-function" typedef struct XConf { + Bool running; int fd, screen, width, height; Window root; Display* display; @@ -19,6 +20,7 @@ typedef struct XConf { unsigned depth; Window self; XftDraw* xft; + XftFont *tagfont, *font; Pixmap pixmap; XIC xic; XIM xim; @@ -40,6 +42,7 @@ static int x11_init(XConf* x) { x->colormap = wa.colormap; x->screen = DefaultScreen(x->display); x->depth = DefaultDepth(x->display, x->screen); + x->running = True; return 0; } @@ -126,4 +129,48 @@ static void x11_event_loop(XConf* x, void (*redraw)(XConf* x)) { } } +static XftFont* x11_font_load(XConf* x, char* name) { + /* init the library and the base font pattern */ + if (!FcInit()) return NULL; + FcPattern* pattern = FcNameParse((FcChar8 *)name); + if (!pattern) return NULL; + /* load the base font */ + FcResult result; + FcPattern* match = XftFontMatch(x->display, x->screen, pattern, &result); + XftFont* font = NULL; + if (match) + font = XftFontOpenPattern(x->display, match); + FcPatternDestroy(pattern); + FcPatternDestroy(match); + return font; +} + +static void xftcolor(XConf* x, XftColor* xc, unsigned int c) { + #define COLOR(c) ((c) | ((c) >> 8)) + xc->color.alpha = 0xFFFF; + xc->color.red = COLOR((c & 0x00FF0000) >> 8); + xc->color.green = COLOR((c & 0x0000FF00)); + xc->color.blue = COLOR((c & 0x000000FF) << 8); + XftColorAllocValue(x->display, x->visual, x->colormap, &(xc->color), xc); +} + +static void x11_draw_rect(XConf* x, int color, int px, int py, int width, int height) { + XftColor clr; + xftcolor(x, &clr, color); + XftDrawRect(x->xft, &clr, px, py, width, height); + XftColorFree(x->display, x->visual, x->colormap, &clr); +} + +static void x11_draw_glyphs(XConf* x, int color, XftFont* font, XftGlyphSpec* specs, long nspecs) { + XftColor clr; + xftcolor(x, &clr, color); + XftDrawGlyphSpec(x->xft, &clr, font, specs, nspecs); + XftColorFree(x->display, x->visual, x->colormap, &clr); +} + +static void x11_flip(XConf* x) { + XCopyArea(x->display, x->pixmap, x->self, x->gc, 0, 0, x->width, x->height, 0, 0); + XFlush(x->display); +} + #pragma GCC diagnostic pop diff --git a/src/lib/x11.c b/src/lib/x11.c index f9f7407..0d3bdff 100644 --- a/src/lib/x11.c +++ b/src/lib/x11.c @@ -10,9 +10,8 @@ #include #include #include -#include -#include -#include +#include + #include "config.h" struct XSel { @@ -22,30 +21,9 @@ struct XSel { void (*callback)(char*); }; -struct XWin { - Bool running; - Time now; - Window root; - Display* display; - Visual* visual; - Colormap colormap; - unsigned depth; - int screen; - /* assume a single window for now. these are its attributes */ - Window self; - XftDraw* xft; - Pixmap pixmap; - int width; - int height; - XIC xic; - XIM xim; - GC gc; - XftFont* tagfont; - XftFont* font; -}; - /******************************************************************************/ -struct XWin X; +static Time Now; +static struct XConf X; static int KeyBtnState; static WinRegion Focused = EDIT; static View Regions[NREGIONS]; @@ -67,29 +45,9 @@ char* SearchTerm = NULL; #define PRESSED(btn) \ ((KeyBtnState & (1 << (btn + 7))) == (1 << (btn + 7))) -static void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - static void font_load(char* name) { - /* init the library and the base font pattern */ - if (!FcInit()) - die("Could not init fontconfig.\n"); - FcPattern* pattern = FcNameParse((FcChar8 *)name); - if (!pattern) - die("could not parse font name\n"); - /* load the base font */ - FcResult result; - FcPattern* match = XftFontMatch(X.display, X.screen, pattern, &result); - if (match) { - XftFont* font = XftFontOpenPattern(X.display, match); - X.font = (font ? font : X.font); // Update if we found a new font - } - if (!X.font) - die("could not load base font\n"); - FcPatternDestroy(pattern); - FcPatternDestroy(match); + XftFont* font = x11_font_load(&X, name); + X.font = (font ? font : X.font); // Update if we found a new font } static void get_position(WinRegion id, int x, int y, size_t* row, size_t* col) { @@ -112,51 +70,6 @@ static struct XSel* selfetch(Atom atom) { return NULL; } -static void x11_window(char* name) { - /* create the main window */ - X.width = WinWidth, X.height = WinHeight; - XWindowAttributes wa; - XGetWindowAttributes(X.display, X.root, &wa); - X.self = XCreateSimpleWindow(X.display, X.root, - (wa.width - X.width) / 2, - (wa.height - X.height) /2, - X.width, - X.height, - 0, X.depth, - Palette[EditBg]); - /* register interest in the delete window message */ - Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False); - XSetWMProtocols(X.display, X.self, &wmDeleteMessage, 1); - /* setup window attributes and events */ - XSetWindowAttributes swa; - swa.backing_store = WhenMapped; - swa.bit_gravity = NorthWestGravity; - XChangeWindowAttributes(X.display, X.self, CWBackingStore|CWBitGravity, &swa); - XStoreName(X.display, X.self, name); - XSelectInput(X.display, X.root, PropertyChangeMask); - XSelectInput(X.display, X.self, 0 - | FocusChangeMask - | KeyPressMask - | ButtonPressMask - | ButtonReleaseMask - | ButtonMotionMask - | StructureNotifyMask - | PropertyChangeMask - | ExposureMask - ); - /* set input methods */ - if ((X.xim = XOpenIM(X.display, 0, 0, 0))) - X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.self, XNFocusWindow, X.self, NULL); - /* initialize pixmap and drawing context */ - X.pixmap = XCreatePixmap(X.display, X.self, X.width, X.height, X.depth); - X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap); - /* initialize the graphics context */ - XGCValues gcv; - gcv.foreground = WhitePixel(X.display, X.screen); - gcv.graphics_exposures = False; - X.gc = XCreateGC(X.display, X.self, GCForeground|GCGraphicsExposures, &gcv); -} - static void tide_send(char* type) { XEvent ev; memset(&ev, 0, sizeof (ev)); @@ -215,8 +128,8 @@ static void mouse_left(WinRegion id, bool pressed, size_t row, size_t col) { static int count = 0; static Time before = 0; if (!pressed) return; - count = ((X.now - before) <= (uint64_t)ClickTime ? count+1 : 1); - before = X.now; + count = ((Now - before) <= (uint64_t)ClickTime ? count+1 : 1); + before = Now; if (PRESSED(MouseRight)) { puts("fetch tag"); } else if (PRESSED(MouseMiddle)) { @@ -280,16 +193,6 @@ static void mouse_click(int btn, bool pressed, int x, int y) { /******************************************************************************/ -static void xftcolor(XftColor* xc, int id) { - #define COLOR(c) ((c) | ((c) >> 8)) - uint32_t c = Palette[id]; - xc->color.alpha = 0xFFFF; - xc->color.red = COLOR((c & 0x00FF0000) >> 8); - xc->color.green = COLOR((c & 0x0000FF00)); - xc->color.blue = COLOR((c & 0x000000FF) << 8); - XftColorAllocValue(X.display, X.visual, X.colormap, &(xc->color), xc); -} - size_t glyph_width(View* view, int c) { FcChar32 rune = (FcChar32)c; XGlyphInfo extents; @@ -302,10 +205,7 @@ size_t glyph_width(View* view, int c) { } static void draw_rect(int color, int x, int y, int width, int height) { - XftColor clr; - xftcolor(&clr, color); - XftDrawRect(X.xft, &clr, x, y, width, height); - XftColorFree(X.display, X.visual, X.colormap, &clr); + x11_draw_rect(&X, Palette[color], x, y, width, height); } static void draw_statbox(void) { @@ -358,7 +258,7 @@ static void draw_view(View* view, XftFont* font, size_t nrows, drawcsr* csr, int x += row->cols[i].width; } XftColor fgc; - xftcolor(&fgc, fg); + xftcolor(&X, &fgc, Palette[fg]); XftDrawGlyphSpec(X.xft, &fgc, font, specs, row->len); XftColorFree(X.display, X.visual, X.colormap, &fgc); } @@ -391,13 +291,14 @@ static void draw_scroll(drawcsr* csr) { /******************************************************************************/ -static void xfocus(XEvent* e) { - if (X.xic) - (e->type == FocusIn ? XSetICFocus : XUnsetICFocus)(X.xic); +static void xfocus(XConf* x, XEvent* e) { + if (x->xic) + (e->type == FocusIn ? XSetICFocus : XUnsetICFocus)(x->xic); } -static void xkeypress(XEvent* e) { - X.now = e->xkey.time; +static void xkeypress(XConf* x, XEvent* e) { + (void)x; + Now = e->xkey.time; Focused = (e->xkey.y <= Divider ? TAGS : EDIT); uint32_t key = getkey(e); if (key == RUNE_ERR) return; @@ -420,43 +321,46 @@ static void xkeypress(XEvent* e) { view_insert(win_view(FOCUSED), key); } -static void xbtnpress(XEvent* e) { - X.now = e->xbutton.time; +static void xbtnpress(XConf* x, XEvent* e) { + (void)x; + Now = e->xbutton.time; KeyBtnState = (e->xbutton.state | (1 << (e->xbutton.button + 7))); mouse_click(e->xbutton.button, true, e->xbutton.x, e->xbutton.y); } -static void xbtnrelease(XEvent* e) { - X.now = e->xbutton.time; +static void xbtnrelease(XConf* x, XEvent* e) { + (void)x; + Now = e->xbutton.time; KeyBtnState = (e->xbutton.state & ~(1 << (e->xbutton.button + 7))); mouse_click(e->xbutton.button, false, e->xbutton.x, e->xbutton.y); } -static void xbtnmotion(XEvent* e) { - while (XCheckTypedEvent(X.display, MotionNotify, e)); - X.now = e->xbutton.time; +static void xbtnmotion(XConf* x, XEvent* e) { + while (XCheckTypedEvent(x->display, MotionNotify, e)); + Now = e->xbutton.time; size_t row, col; KeyBtnState = e->xbutton.state; - int x = e->xbutton.x, y = e->xbutton.y; - get_position(Focused, x, y, &row, &col); + int xpos = e->xbutton.x, ypos = e->xbutton.y; + get_position(Focused, xpos, ypos, &row, &col); if (PRESSED(MouseLeft)) view_setcursor(win_view(Focused), row, col, true); } -static void xselclear(XEvent* e) { +static void xselclear(XConf* x, XEvent* e) { + (void)x; struct XSel* sel = selfetch(e->xselectionclear.selection); if (!sel) return; free(sel->text); sel->text = NULL; } -static void xselquit(XEvent* e) { - xselclear(e); +static void xselquit(XConf* x, XEvent* e) { + xselclear(x, e); if (!Selections[PRIMARY].text && !Selections[CLIPBOARD].text) - X.running = False; + x->running = False; } -static void xselnotify(XEvent* e) { +static void xselnotify(XConf* x, XEvent* e) { /* bail if the selection cannot be converted */ if (e->xselection.property == None) return; @@ -464,7 +368,7 @@ static void xselnotify(XEvent* e) { Atom rtype; unsigned long format = 0, nitems = 0, nleft = 0; unsigned char* propdata = NULL; - XGetWindowProperty(X.display, X.self, sel->atom, 0, -1, False, AnyPropertyType, &rtype, + XGetWindowProperty(x->display, x->self, sel->atom, 0, -1, False, AnyPropertyType, &rtype, (int*)&format, &nitems, &nleft, &propdata); if (e->xselection.target == SelTarget) { void(*cbfn)(char*) = sel->callback; @@ -475,7 +379,7 @@ static void xselnotify(XEvent* e) { if (propdata) XFree(propdata); } -static void xselrequest(XEvent* e) { +static void xselrequest(XConf* x, XEvent* e) { XEvent s; struct XSel* sel = selfetch( e->xselectionrequest.selection ); s.xselection.type = SelectionNotify; @@ -485,57 +389,43 @@ static void xselrequest(XEvent* e) { s.xselection.target = e->xselectionrequest.target; s.xselection.time = e->xselectionrequest.time; Atom target = e->xselectionrequest.target; - Atom xatargets = XInternAtom(X.display, "TARGETS", 0); - Atom xastring = XInternAtom(X.display, "STRING", 0); + Atom xatargets = XInternAtom(x->display, "TARGETS", 0); + Atom xastring = XInternAtom(x->display, "STRING", 0); if (target == xatargets) { /* respond with the supported type */ XChangeProperty( - X.display, + x->display, s.xselection.requestor, s.xselection.property, XA_ATOM, 32, PropModeReplace, (unsigned char*)&SelTarget, 1); } else if (target == SelTarget || target == xastring) { XChangeProperty( - X.display, + x->display, s.xselection.requestor, s.xselection.property, SelTarget, 8, PropModeReplace, (unsigned char*)sel->text, strlen(sel->text)); } - XSendEvent(X.display, s.xselection.requestor, True, 0, &s); + XSendEvent(x->display, s.xselection.requestor, True, 0, &s); } -static void xclientmsg(XEvent* e) { - if ((Atom)(e->xclient.data.l[0]) == XInternAtom(X.display, "WM_DELETE_WINDOW", False)) +static void xclientmsg(XConf* x, XEvent* e) { + if ((Atom)(e->xclient.data.l[0]) == XInternAtom(x->display, "WM_DELETE_WINDOW", False)) win_quit(); - else if (e->xclient.message_type == XInternAtom(X.display, "GOTO", False)) + else if (e->xclient.message_type == XInternAtom(x->display, "GOTO", False)) view_setln(win_view(EDIT), e->xclient.data.l[0]); } -static void xresize(XEvent* e) { - if (e->xconfigure.width != X.width || e->xconfigure.height != X.height) { - X.width = e->xconfigure.width; - X.height = e->xconfigure.height; - X.pixmap = XCreatePixmap(X.display, X.self, X.width, X.height, X.depth); - X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap); +static void xresize(XConf* x, XEvent* e) { + if (e->xconfigure.width != x->width || e->xconfigure.height != x->height) { + x->width = e->xconfigure.width; + x->height = e->xconfigure.height; + x->pixmap = XCreatePixmap(x->display, x->self, x->width, x->height, x->depth); + x->xft = XftDrawCreate(x->display, x->pixmap, x->visual, x->colormap); } } -static void (*EventHandlers[LASTEvent])(XEvent*) = { - [FocusIn] = xfocus, - [FocusOut] = xfocus, - [KeyPress] = xkeypress, - [ButtonPress] = xbtnpress, - [ButtonRelease] = xbtnrelease, - [MotionNotify] = xbtnmotion, - [SelectionClear] = xselclear, - [SelectionNotify] = xselnotify, - [SelectionRequest] = xselrequest, - [ClientMessage] = xclientmsg, - [ConfigureNotify] = xresize, -}; - static void xupdate(Job* job) { (void)job; int nevents; @@ -544,8 +434,9 @@ static void xupdate(Job* job) { XGetMotionEvents(X.display, X.self, CurrentTime, CurrentTime, &nevents); for (XEvent e; XPending(X.display);) { XNextEvent(X.display, &e); - if (!XFilterEvent(&e, None) && EventHandlers[e.type]) - (EventHandlers[e.type])(&e); + if (!XFilterEvent(&e, None) && X.eventfns[e.type]) + (X.eventfns[e.type])(&X, &e); + for (int status; waitpid(-1, &status, WNOHANG) > 0;); } /* determine the size of the regions */ size_t maxtagrows = ((X.height/4) / X.tagfont->height); @@ -573,20 +464,44 @@ void win_init(KeyBinding* bindings) { signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); + /* open the X display and get basic attributes */ - if (!(X.display = XOpenDisplay(0))) - die("could not open display"); - X.root = DefaultRootWindow(X.display); - XWindowAttributes wa; - XGetWindowAttributes(X.display, X.root, &wa); - X.visual = wa.visual; - X.colormap = wa.colormap; - X.screen = DefaultScreen(X.display); - X.depth = DefaultDepth(X.display, X.screen); + x11_init(&X); font_load(Fonts[FontSel = 0]); X.tagfont = X.font; - x11_window("unnamed"); - /* initialize selection atoms */ + if (!X.font) { + perror("unable to load base font"); + exit(EXIT_FAILURE); + } + x11_mkwin(&X, 640, 480, 0 + | FocusChangeMask + | KeyPressMask + | ButtonPressMask + | ButtonReleaseMask + | ButtonMotionMask + | StructureNotifyMask + | PropertyChangeMask + | ExposureMask + ); + x11_init_gc(&X); + x11_centerwin(&X); + x11_show(&X); + + /* register event handlers */ + X.eventfns[FocusIn] = xfocus; + X.eventfns[FocusOut] = xfocus; + X.eventfns[KeyPress] = xkeypress; + X.eventfns[ButtonPress] = xbtnpress; + X.eventfns[ButtonRelease] = xbtnrelease; + X.eventfns[MotionNotify] = xbtnmotion; + X.eventfns[SelectionClear] = xselclear; + X.eventfns[SelectionNotify] = xselnotify; + X.eventfns[SelectionRequest] = xselrequest; + X.eventfns[ClientMessage] = xclientmsg; + X.eventfns[ConfigureNotify] = xresize; + + /* initialize +selection atoms */ for (unsigned int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++) Selections[i].atom = XInternAtom(X.display, Selections[i].name, 0); SelTarget = XInternAtom(X.display, "UTF8_STRING", 0); @@ -642,9 +557,9 @@ void win_loop(void) { void win_quit(void) { static uint64_t before = 0; - if ((win_buf(EDIT)->status != MODIFIED) || (X.now - before) <= (uint64_t)ClickTime) { + if ((win_buf(EDIT)->status != MODIFIED) || (Now - before) <= (uint64_t)ClickTime) { tide_send("DEL"); - EventHandlers[SelectionClear] = xselquit; + X.eventfns [SelectionClear] = xselquit; XUnmapWindow(X.display, X.self); if (!Selections[PRIMARY].text && !Selections[CLIPBOARD].text) { X.running = False; @@ -652,7 +567,7 @@ void win_quit(void) { if (fork()) exit(0); /* fork into background if we still have selection */ } } - before = X.now; + before = Now; } void win_togglefocus(void) { diff --git a/src/pick.c b/src/pick.c index c2810a7..2113b65 100644 --- a/src/pick.c +++ b/src/pick.c @@ -125,26 +125,9 @@ static void xresize(XConf* x, XEvent* e) { } } -static void xftcolor(XConf* x, XftColor* xc, unsigned int c) { - #define COLOR(c) ((c) | ((c) >> 8)) - xc->color.alpha = 0xFFFF; - xc->color.red = COLOR((c & 0x00FF0000) >> 8); - xc->color.green = COLOR((c & 0x0000FF00)); - xc->color.blue = COLOR((c & 0x000000FF) << 8); - XftColorAllocValue(x->display, x->visual, x->colormap, &(xc->color), xc); -} - -static void draw_rect(XConf* x, int color, int px, int py, int width, int height) { - XftColor clr; - xftcolor(x, &clr, color); - XftDrawRect(x->xft, &clr, px, py, width, height); - XftColorFree(x->display, x->visual, x->colormap, &clr); -} - static void redraw(XConf* x) { - draw_rect(x, 0x00, 0, 0, x->width, x->height); - XCopyArea(x->display, x->pixmap, x->self, x->gc, 0, 0, x->width, x->height, 0, 0); - XFlush(x->display); + x11_draw_rect(x, 0x00, 0, 0, x->width, x->height); + x11_flip(x); } static void filter(void) {