popup: a border, a preedit as wide as its text, one place by the pointer, and no dying
The popup was a white box on the usually white text it covered, with no edge to tell them apart; it has a border in the separator's colour. A syllable being composed came in a bar twelve ems wide, wiping out the line under it: only candidate rows share that steady width now, a preedit alone hugs its text. A popup placed by the pointer, when the client sends no caret, was placed again on every key and so followed the mouse; it stays where it came up. Clicks on it no longer fall through to the root window and its menu. And one failed draw — a lost pointer reply, a pixmap the server refused — ended the draw thread and the popup for the rest of the session; only a dead connection does now.
This commit is contained in:
1
dat.h
1
dat.h
@@ -41,6 +41,7 @@ extern int popupscale;
|
||||
#define Fontsz (32*popupscale)
|
||||
#define PopupPad (4*popupscale)
|
||||
#define PopupSep popupscale
|
||||
#define PopupBorder popupscale
|
||||
#define PopupNumw Fontsz
|
||||
#define PopupTextw (12*Fontsz)
|
||||
#define PopupBasew (2*PopupPad + PopupNumw + PopupTextw)
|
||||
|
||||
@@ -149,7 +149,8 @@ popuplayout(Drawcmd *dc, int areaw, int areah, Popup *p)
|
||||
if(nmark == 0)
|
||||
markrow = 0;
|
||||
|
||||
width = PopupBasew;
|
||||
/* Rows share one steady width; a preedit alone hugs its text. */
|
||||
width = p->n != 0 ? PopupBasew : 2*PopupPad;
|
||||
if(npre)
|
||||
width = max(width, textwidth(&dc->pre) + 2*PopupPad);
|
||||
for(i = 0; i < p->n; i++)
|
||||
|
||||
@@ -144,10 +144,10 @@ popup_layout(struct ct *t)
|
||||
CT_EQ_INT(t, -1, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
|
||||
/* Preedit only. */
|
||||
/* Preedit only: as wide as its text. */
|
||||
dc.pre = mkstr("preedit");
|
||||
popuplayout(&dc, 2*PopupBasew, Imgh, &p);
|
||||
CT_EQ_INT(t, PopupBasew, p.w);
|
||||
CT_EQ_INT(t, textwidth(&dc.pre) + 2*PopupPad, p.w);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, -1, p.sepy);
|
||||
CT_EQ_INT(t, -1, p.rowsy);
|
||||
|
||||
65
win.c
65
win.c
@@ -12,6 +12,7 @@ static u32int *img;
|
||||
static xcb_atom_t currentdesktop;
|
||||
static xcb_atom_t workarea;
|
||||
static int hasrandr, imgh, imgw;
|
||||
static int shown, ptrx, ptry; /* the popup, and where the pointer was as it came up */
|
||||
|
||||
static xcb_screen_t*
|
||||
getscr(xcb_connection_t *c, int n)
|
||||
@@ -201,7 +202,7 @@ static int
|
||||
wininit(void)
|
||||
{
|
||||
int n;
|
||||
u32int mask, vals[4];
|
||||
u32int mask, vals[5];
|
||||
xcb_atom_t type, tooltip;
|
||||
xcb_randr_query_version_cookie_t rc;
|
||||
xcb_randr_query_version_reply_t *rr;
|
||||
@@ -234,14 +235,17 @@ wininit(void)
|
||||
currentdesktop = getatom("_NET_CURRENT_DESKTOP");
|
||||
workarea = getatom("_NET_WORKAREA");
|
||||
win = xcb_generate_id(conn);
|
||||
/* Clicks on the popup go nowhere, not to the root window under it. */
|
||||
mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL |
|
||||
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER;
|
||||
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER |
|
||||
XCB_CW_DONT_PROPAGATE;
|
||||
vals[0] = Colbg;
|
||||
vals[1] = 0;
|
||||
vals[1] = Colsep;
|
||||
vals[2] = 1;
|
||||
vals[3] = 1;
|
||||
vals[4] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE;
|
||||
xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, scr->root,
|
||||
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
0, 0, 1, 1, PopupBorder, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
scr->root_visual, mask, vals);
|
||||
type = getatom("_NET_WM_WINDOW_TYPE");
|
||||
tooltip = getatom("_NET_WM_WINDOW_TYPE_TOOLTIP");
|
||||
@@ -302,43 +306,54 @@ putimage(int w, int h)
|
||||
xcb_clear_area(conn, 0, win, 0, 0, w, h);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
winhide(void)
|
||||
{
|
||||
xcb_unmap_window(conn, win);
|
||||
return xcb_flush(conn) > 0;
|
||||
xcb_flush(conn);
|
||||
shown = 0;
|
||||
}
|
||||
|
||||
/* Draws dc at the caret, or by the pointer when the caret is unknown. */
|
||||
static int
|
||||
/*
|
||||
* Draws dc at the caret, or by the pointer when the caret is unknown:
|
||||
* where the pointer was as the popup came up, so that it does not
|
||||
* follow the mouse from key to key.
|
||||
*/
|
||||
static void
|
||||
winshow(Drawcmd *dc)
|
||||
{
|
||||
Area area;
|
||||
Popup p;
|
||||
int ax, ay, px, py, x, y;
|
||||
int ax, ay, x, y;
|
||||
u32int vals[5];
|
||||
xcb_query_pointer_reply_t *ptr;
|
||||
xcb_query_pointer_cookie_t cookie;
|
||||
|
||||
if(dc->nkouho == 0 && dc->pre.n == 0)
|
||||
return winhide();
|
||||
px = py = 0;
|
||||
if(!dc->caret.valid){
|
||||
if(dc->nkouho == 0 && dc->pre.n == 0){
|
||||
winhide();
|
||||
return;
|
||||
}
|
||||
if(!dc->caret.valid && !shown){
|
||||
cookie = xcb_query_pointer(conn, scr->root);
|
||||
ptr = xcb_query_pointer_reply(conn, cookie, nil);
|
||||
if(ptr == nil)
|
||||
return 0;
|
||||
px = ptr->root_x;
|
||||
py = ptr->root_y;
|
||||
return;
|
||||
ptrx = ptr->root_x;
|
||||
ptry = ptr->root_y;
|
||||
free(ptr);
|
||||
}
|
||||
ax = dc->caret.valid ? dc->caret.x : px;
|
||||
ay = dc->caret.valid ? dc->caret.y : py;
|
||||
ax = dc->caret.valid ? dc->caret.x : ptrx;
|
||||
ay = dc->caret.valid ? dc->caret.y : ptry;
|
||||
popupwork(ax, ay, &area);
|
||||
popuplayout(dc, area.w, area.h, &p);
|
||||
if(p.w <= 0 || p.h <= 0 || !resizebacking(p.w, p.h))
|
||||
return 0;
|
||||
popupposition(&dc->caret, px, py, &area, p.w, p.h, &x, &y);
|
||||
if(p.w <= 0 || p.h <= 0){
|
||||
winhide();
|
||||
return;
|
||||
}
|
||||
if(!resizebacking(p.w, p.h))
|
||||
return;
|
||||
popupposition(&dc->caret, ptrx, ptry, &area, p.w + 2*PopupBorder,
|
||||
p.h + 2*PopupBorder, &x, &y);
|
||||
/* Mapping does not restack: raise above windows opened since. */
|
||||
vals[0] = x;
|
||||
vals[1] = y;
|
||||
@@ -352,7 +367,8 @@ winshow(Drawcmd *dc)
|
||||
popupdraw(img, dc, &p);
|
||||
putimage(p.w, p.h);
|
||||
xcb_map_window(conn, win);
|
||||
return xcb_flush(conn) > 0;
|
||||
xcb_flush(conn);
|
||||
shown = 1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -363,8 +379,7 @@ drawthread(void*)
|
||||
threadsetname("draw");
|
||||
if(!wininit())
|
||||
return;
|
||||
while(chanrecv(drawc, &dc) > 0)
|
||||
if(!winshow(&dc))
|
||||
break;
|
||||
while(chanrecv(drawc, &dc) > 0 && !xcb_connection_has_error(conn))
|
||||
winshow(&dc);
|
||||
wincleanup();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user