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 Fontsz (32*popupscale)
|
||||||
#define PopupPad (4*popupscale)
|
#define PopupPad (4*popupscale)
|
||||||
#define PopupSep popupscale
|
#define PopupSep popupscale
|
||||||
|
#define PopupBorder popupscale
|
||||||
#define PopupNumw Fontsz
|
#define PopupNumw Fontsz
|
||||||
#define PopupTextw (12*Fontsz)
|
#define PopupTextw (12*Fontsz)
|
||||||
#define PopupBasew (2*PopupPad + PopupNumw + PopupTextw)
|
#define PopupBasew (2*PopupPad + PopupNumw + PopupTextw)
|
||||||
|
|||||||
@@ -149,7 +149,8 @@ popuplayout(Drawcmd *dc, int areaw, int areah, Popup *p)
|
|||||||
if(nmark == 0)
|
if(nmark == 0)
|
||||||
markrow = 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)
|
if(npre)
|
||||||
width = max(width, textwidth(&dc->pre) + 2*PopupPad);
|
width = max(width, textwidth(&dc->pre) + 2*PopupPad);
|
||||||
for(i = 0; i < p->n; i++)
|
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.rowsy);
|
||||||
CT_EQ_INT(t, -1, p.marky);
|
CT_EQ_INT(t, -1, p.marky);
|
||||||
|
|
||||||
/* Preedit only. */
|
/* Preedit only: as wide as its text. */
|
||||||
dc.pre = mkstr("preedit");
|
dc.pre = mkstr("preedit");
|
||||||
popuplayout(&dc, 2*PopupBasew, Imgh, &p);
|
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, PopupPad, p.prey);
|
||||||
CT_EQ_INT(t, -1, p.sepy);
|
CT_EQ_INT(t, -1, p.sepy);
|
||||||
CT_EQ_INT(t, -1, p.rowsy);
|
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 currentdesktop;
|
||||||
static xcb_atom_t workarea;
|
static xcb_atom_t workarea;
|
||||||
static int hasrandr, imgh, imgw;
|
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*
|
static xcb_screen_t*
|
||||||
getscr(xcb_connection_t *c, int n)
|
getscr(xcb_connection_t *c, int n)
|
||||||
@@ -201,7 +202,7 @@ static int
|
|||||||
wininit(void)
|
wininit(void)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
u32int mask, vals[4];
|
u32int mask, vals[5];
|
||||||
xcb_atom_t type, tooltip;
|
xcb_atom_t type, tooltip;
|
||||||
xcb_randr_query_version_cookie_t rc;
|
xcb_randr_query_version_cookie_t rc;
|
||||||
xcb_randr_query_version_reply_t *rr;
|
xcb_randr_query_version_reply_t *rr;
|
||||||
@@ -234,14 +235,17 @@ wininit(void)
|
|||||||
currentdesktop = getatom("_NET_CURRENT_DESKTOP");
|
currentdesktop = getatom("_NET_CURRENT_DESKTOP");
|
||||||
workarea = getatom("_NET_WORKAREA");
|
workarea = getatom("_NET_WORKAREA");
|
||||||
win = xcb_generate_id(conn);
|
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 |
|
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[0] = Colbg;
|
||||||
vals[1] = 0;
|
vals[1] = Colsep;
|
||||||
vals[2] = 1;
|
vals[2] = 1;
|
||||||
vals[3] = 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,
|
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);
|
scr->root_visual, mask, vals);
|
||||||
type = getatom("_NET_WM_WINDOW_TYPE");
|
type = getatom("_NET_WM_WINDOW_TYPE");
|
||||||
tooltip = getatom("_NET_WM_WINDOW_TYPE_TOOLTIP");
|
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);
|
xcb_clear_area(conn, 0, win, 0, 0, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
winhide(void)
|
winhide(void)
|
||||||
{
|
{
|
||||||
xcb_unmap_window(conn, win);
|
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)
|
winshow(Drawcmd *dc)
|
||||||
{
|
{
|
||||||
Area area;
|
Area area;
|
||||||
Popup p;
|
Popup p;
|
||||||
int ax, ay, px, py, x, y;
|
int ax, ay, x, y;
|
||||||
u32int vals[5];
|
u32int vals[5];
|
||||||
xcb_query_pointer_reply_t *ptr;
|
xcb_query_pointer_reply_t *ptr;
|
||||||
xcb_query_pointer_cookie_t cookie;
|
xcb_query_pointer_cookie_t cookie;
|
||||||
|
|
||||||
if(dc->nkouho == 0 && dc->pre.n == 0)
|
if(dc->nkouho == 0 && dc->pre.n == 0){
|
||||||
return winhide();
|
winhide();
|
||||||
px = py = 0;
|
return;
|
||||||
if(!dc->caret.valid){
|
}
|
||||||
|
if(!dc->caret.valid && !shown){
|
||||||
cookie = xcb_query_pointer(conn, scr->root);
|
cookie = xcb_query_pointer(conn, scr->root);
|
||||||
ptr = xcb_query_pointer_reply(conn, cookie, nil);
|
ptr = xcb_query_pointer_reply(conn, cookie, nil);
|
||||||
if(ptr == nil)
|
if(ptr == nil)
|
||||||
return 0;
|
return;
|
||||||
px = ptr->root_x;
|
ptrx = ptr->root_x;
|
||||||
py = ptr->root_y;
|
ptry = ptr->root_y;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
ax = dc->caret.valid ? dc->caret.x : px;
|
ax = dc->caret.valid ? dc->caret.x : ptrx;
|
||||||
ay = dc->caret.valid ? dc->caret.y : py;
|
ay = dc->caret.valid ? dc->caret.y : ptry;
|
||||||
popupwork(ax, ay, &area);
|
popupwork(ax, ay, &area);
|
||||||
popuplayout(dc, area.w, area.h, &p);
|
popuplayout(dc, area.w, area.h, &p);
|
||||||
if(p.w <= 0 || p.h <= 0 || !resizebacking(p.w, p.h))
|
if(p.w <= 0 || p.h <= 0){
|
||||||
return 0;
|
winhide();
|
||||||
popupposition(&dc->caret, px, py, &area, p.w, p.h, &x, &y);
|
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. */
|
/* Mapping does not restack: raise above windows opened since. */
|
||||||
vals[0] = x;
|
vals[0] = x;
|
||||||
vals[1] = y;
|
vals[1] = y;
|
||||||
@@ -352,7 +367,8 @@ winshow(Drawcmd *dc)
|
|||||||
popupdraw(img, dc, &p);
|
popupdraw(img, dc, &p);
|
||||||
putimage(p.w, p.h);
|
putimage(p.w, p.h);
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
return xcb_flush(conn) > 0;
|
xcb_flush(conn);
|
||||||
|
shown = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -363,8 +379,7 @@ drawthread(void*)
|
|||||||
threadsetname("draw");
|
threadsetname("draw");
|
||||||
if(!wininit())
|
if(!wininit())
|
||||||
return;
|
return;
|
||||||
while(chanrecv(drawc, &dc) > 0)
|
while(chanrecv(drawc, &dc) > 0 && !xcb_connection_has_error(conn))
|
||||||
if(!winshow(&dc))
|
winshow(&dc);
|
||||||
break;
|
|
||||||
wincleanup();
|
wincleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user