fix(xdrawer,dwm,dmenu): remove top bar gap and eliminate softkey menu latency
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+49
-27
@@ -956,9 +956,37 @@ query_softkeys_down(void)
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void
|
||||
read_softkey_state(int *mask_out, long long *ms_out)
|
||||
{
|
||||
char buf[64];
|
||||
int fd = open("/tmp/sxmo_softkey_state", O_RDONLY | O_CLOEXEC);
|
||||
*mask_out = 0;
|
||||
*ms_out = 0;
|
||||
if (fd >= 0) {
|
||||
ssize_t n = read(fd, buf, sizeof(buf) - 1);
|
||||
close(fd);
|
||||
if (n > 0) {
|
||||
buf[n] = '\0';
|
||||
sscanf(buf, "%d %lld", mask_out, ms_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_softkey_state(void)
|
||||
{
|
||||
int fd = open("/tmp/sxmo_softkey_state", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
||||
if (fd >= 0) {
|
||||
(void)write(fd, "0 0\n", 4);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
spawn_xdrawer_and_exit(void)
|
||||
{
|
||||
clear_softkey_state();
|
||||
write_softkey_suppress(dmenu_now_ms() + 500);
|
||||
cleanup();
|
||||
if (fork() == 0) {
|
||||
@@ -984,12 +1012,15 @@ run(void)
|
||||
{
|
||||
XEvent ev;
|
||||
int soft_pending = 0;
|
||||
long long soft_first_ms = 0;
|
||||
long long soft_deadline = 0;
|
||||
long long start_ignore = dmenu_now_ms() + 40;
|
||||
int initial_released = (query_softkeys_down() == 0);
|
||||
int init_soft_mask = 0;
|
||||
long long init_soft_ms = 0;
|
||||
int xfd = ConnectionNumber(dpy);
|
||||
|
||||
read_softkey_state(&init_soft_mask, &init_soft_ms);
|
||||
|
||||
for (;;) {
|
||||
if (!initial_released && query_softkeys_down() == 0)
|
||||
initial_released = 1;
|
||||
@@ -1004,28 +1035,23 @@ run(void)
|
||||
int is_right = (ks == XF86XK_Back || ks == XF86XK_KbdLcdMenu2 || ev.xkey.keycode == 166);
|
||||
if (is_left || is_right) {
|
||||
long long now = dmenu_now_ms();
|
||||
int which = (is_left ? 1 : 0) | (is_right ? 2 : 0);
|
||||
if (ev.type == KeyPress && init_soft_mask != 0 &&
|
||||
(init_soft_mask | which) == 3 &&
|
||||
(now - init_soft_ms) <= 320) {
|
||||
spawn_xdrawer_and_exit();
|
||||
}
|
||||
if (ev.type == KeyRelease) {
|
||||
initial_released = 1;
|
||||
if (soft_pending != 0 && soft_pending != 3) {
|
||||
long long grace = now + 65;
|
||||
if (grace > soft_deadline)
|
||||
soft_deadline = grace;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!initial_released || now < start_ignore)
|
||||
continue;
|
||||
if (is_left)
|
||||
soft_pending |= 1;
|
||||
if (is_right)
|
||||
soft_pending |= 2;
|
||||
soft_pending |= query_softkeys_down();
|
||||
soft_pending |= which | query_softkeys_down();
|
||||
if (soft_pending == 3)
|
||||
spawn_xdrawer_and_exit();
|
||||
if (soft_deadline == 0) {
|
||||
soft_first_ms = now;
|
||||
soft_deadline = now + 200;
|
||||
}
|
||||
if (soft_deadline == 0)
|
||||
soft_deadline = now + 30;
|
||||
continue;
|
||||
}
|
||||
if (!issoftkey(ev.xkey.keycode)) {
|
||||
@@ -1077,19 +1103,15 @@ run(void)
|
||||
spawn_xdrawer_and_exit();
|
||||
long long rem = soft_deadline - now;
|
||||
if (rem <= 0) {
|
||||
if (hw_down != 0 && (now - soft_first_ms) < 480) {
|
||||
soft_deadline = now + 25;
|
||||
rem = 25;
|
||||
clear_softkey_state();
|
||||
write_softkey_suppress(now + 250);
|
||||
if (soft_pending == 1) {
|
||||
puts((sel) ? sel->text : text);
|
||||
cleanup();
|
||||
exit(0);
|
||||
} else {
|
||||
write_softkey_suppress(now + 400);
|
||||
if (soft_pending == 1) {
|
||||
puts((sel) ? sel->text : text);
|
||||
cleanup();
|
||||
exit(0);
|
||||
} else {
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
struct pollfd pfd = { xfd, POLLIN, 0 };
|
||||
|
||||
+61
-23
@@ -1449,14 +1449,17 @@ ishold(KeySym keysym)
|
||||
|
||||
#define SOFTKEY_LEFT 1
|
||||
#define SOFTKEY_RIGHT 2
|
||||
#define SOFTKEY_CHORD_MS 200
|
||||
#define SOFTKEY_MAX_HOLD_MS 480
|
||||
#define SOFTKEY_CHORD_MS 30
|
||||
#define SOFTKEY_CANCEL_WINDOW_MS 320
|
||||
#define SOFTKEY_SUPPRESS_MS 500
|
||||
|
||||
static int softkey_pending = 0;
|
||||
static long long softkey_first_ms = 0;
|
||||
static long long softkey_deadline_ms = 0;
|
||||
static long long softkey_suppress_until_ms = 0;
|
||||
static int last_softkey_mask = 0;
|
||||
static long long last_softkey_ms = 0;
|
||||
static pid_t last_menu_pgid = 0;
|
||||
|
||||
static long long
|
||||
dwm_now_ms(void)
|
||||
@@ -1480,6 +1483,18 @@ write_softkey_suppress(long long until_ms)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_softkey_state(int mask, long long ms)
|
||||
{
|
||||
char buf[64];
|
||||
int fd = open("/tmp/sxmo_softkey_state", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
||||
if (fd >= 0) {
|
||||
int len = snprintf(buf, sizeof(buf), "%d %lld\n", mask, ms);
|
||||
(void)write(fd, buf, len);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static long long
|
||||
read_softkey_suppress(void)
|
||||
{
|
||||
@@ -1517,13 +1532,34 @@ is_right_softkey(KeySym ks, unsigned int keycode)
|
||||
return ks == XF86XK_Back || ks == XF86XK_KbdLcdMenu2 || keycode == 166;
|
||||
}
|
||||
|
||||
static pid_t
|
||||
spawn_pgid(const Arg *arg)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
if (dpy)
|
||||
close(ConnectionNumber(dpy));
|
||||
setsid();
|
||||
execvp(((char **)arg->v)[0], (char **)arg->v);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void
|
||||
trigger_xdrawer_chord(long long now)
|
||||
{
|
||||
const Arg xdrawercmd = { .v = (const char*[]){ "xdrawer", NULL } };
|
||||
if (last_menu_pgid > 0) {
|
||||
kill(-last_menu_pgid, SIGKILL);
|
||||
last_menu_pgid = 0;
|
||||
}
|
||||
softkey_pending = 0;
|
||||
softkey_first_ms = 0;
|
||||
softkey_deadline_ms = 0;
|
||||
last_softkey_mask = 0;
|
||||
last_softkey_ms = 0;
|
||||
write_softkey_state(0, 0);
|
||||
write_softkey_suppress(now + SOFTKEY_SUPPRESS_MS);
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
XFlush(dpy);
|
||||
@@ -1541,10 +1577,10 @@ flush_pending_softkey(void)
|
||||
XFlush(dpy);
|
||||
if (pending == SOFTKEY_LEFT) {
|
||||
const Arg syscmd = { .v = (const char*[]){ "sxmo_appmenu.sh", "sys", NULL } };
|
||||
spawn(&syscmd);
|
||||
last_menu_pgid = spawn_pgid(&syscmd);
|
||||
} else if (pending == SOFTKEY_RIGHT) {
|
||||
const Arg ctxcmd = { .v = (const char*[]){ "sxmo_appmenu.sh", NULL } };
|
||||
spawn(&ctxcmd);
|
||||
last_menu_pgid = spawn_pgid(&ctxcmd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1567,6 +1603,9 @@ keypress(XEvent *e)
|
||||
softkey_pending = 0;
|
||||
softkey_first_ms = 0;
|
||||
softkey_deadline_ms = 0;
|
||||
last_softkey_mask = 0;
|
||||
last_softkey_ms = 0;
|
||||
write_softkey_state(0, 0);
|
||||
write_softkey_suppress(dwm_now_ms() + SOFTKEY_SUPPRESS_MS);
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
XFlush(dpy);
|
||||
@@ -1583,16 +1622,25 @@ keypress(XEvent *e)
|
||||
XFlush(dpy);
|
||||
return;
|
||||
}
|
||||
int which = 0;
|
||||
if (is_left_softkey(keysym, ev->keycode))
|
||||
softkey_pending |= SOFTKEY_LEFT;
|
||||
which |= SOFTKEY_LEFT;
|
||||
if (is_right_softkey(keysym, ev->keycode))
|
||||
softkey_pending |= SOFTKEY_RIGHT;
|
||||
softkey_pending |= query_softkeys_down();
|
||||
if (softkey_pending == (SOFTKEY_LEFT | SOFTKEY_RIGHT)) {
|
||||
which |= SOFTKEY_RIGHT;
|
||||
int combined = softkey_pending | which | query_softkeys_down();
|
||||
if (last_softkey_mask != 0 && (now - last_softkey_ms) <= SOFTKEY_CANCEL_WINDOW_MS)
|
||||
combined |= last_softkey_mask;
|
||||
if (combined == (SOFTKEY_LEFT | SOFTKEY_RIGHT)) {
|
||||
trigger_xdrawer_chord(now);
|
||||
} else if (softkey_deadline_ms == 0) {
|
||||
softkey_first_ms = now;
|
||||
softkey_deadline_ms = now + SOFTKEY_CHORD_MS;
|
||||
} else {
|
||||
softkey_pending = which;
|
||||
last_softkey_mask = which;
|
||||
last_softkey_ms = now;
|
||||
write_softkey_state(which, now);
|
||||
if (softkey_deadline_ms == 0) {
|
||||
softkey_first_ms = now;
|
||||
softkey_deadline_ms = now + SOFTKEY_CHORD_MS;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1640,11 +1688,6 @@ keyrelease(XEvent *e)
|
||||
markreleased(keysym);
|
||||
|
||||
if (is_left_softkey(keysym, ev->keycode) || is_right_softkey(keysym, ev->keycode)) {
|
||||
if (softkey_pending != 0 && softkey_pending != (SOFTKEY_LEFT | SOFTKEY_RIGHT)) {
|
||||
long long grace = dwm_now_ms() + 65;
|
||||
if (grace > softkey_deadline_ms)
|
||||
softkey_deadline_ms = grace;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2100,13 +2143,8 @@ run(void)
|
||||
}
|
||||
long long rem = softkey_deadline_ms - now;
|
||||
if (rem <= 0) {
|
||||
if (hw_down != 0 && (now - softkey_first_ms) < SOFTKEY_MAX_HOLD_MS) {
|
||||
softkey_deadline_ms = now + 25;
|
||||
timeout_ms = 25;
|
||||
} else {
|
||||
flush_pending_softkey();
|
||||
continue;
|
||||
}
|
||||
flush_pending_softkey();
|
||||
continue;
|
||||
} else {
|
||||
timeout_ms = (int)rem;
|
||||
}
|
||||
|
||||
+14
-13
@@ -33,13 +33,12 @@ namespace {
|
||||
|
||||
constexpr int kScreenWidth = 240;
|
||||
constexpr int kScreenHeight = 320;
|
||||
constexpr int kTopBarHeight = 26;
|
||||
constexpr int kTopBarHeight = 24;
|
||||
constexpr int kWinX = 0;
|
||||
constexpr int kWinY = kTopBarHeight;
|
||||
constexpr int kWinWidth = kScreenWidth;
|
||||
constexpr int kWinHeight = kScreenHeight - kTopBarHeight; // 294px (7 * 42px)
|
||||
constexpr int kWinHeight = kScreenHeight - kTopBarHeight; // 296px flush below 24px dwm bar
|
||||
constexpr int kRowCount = 7;
|
||||
constexpr int kRowHeight = kWinHeight / kRowCount; // 42px per row
|
||||
|
||||
// Nerd Font PUA icons matching sxmo_hook_icons.sh & dwm ("Fira Code, DejaVuSansM Nerd Font")
|
||||
constexpr const char* kIconSpeaker = "\xef\x80\xa8"; // U+F028 speaker
|
||||
@@ -587,18 +586,20 @@ int main() {
|
||||
XSetForeground(dpy, gc, 0x222222);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
|
||||
|
||||
// 7 Control rows (42px each, 7 * 42 = 294px exact)
|
||||
// 7 Control rows filling the full 296px height flush from y=24 to y=320
|
||||
const auto& items = controller.items();
|
||||
for (size_t i = 0; i < items.size(); ++i) {
|
||||
int ry = static_cast<int>(i) * kRowHeight;
|
||||
int ry = static_cast<int>((i * kWinHeight) / kRowCount);
|
||||
int nextRy = static_cast<int>(((i + 1) * kWinHeight) / kRowCount);
|
||||
int rowH = nextRy - ry;
|
||||
bool isSel = (i == selected);
|
||||
|
||||
XSetForeground(dpy, gc, isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, kRowHeight);
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
|
||||
|
||||
if (isSel) {
|
||||
XSetForeground(dpy, gc, 0xf4d03f);
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, 4, kRowHeight);
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
|
||||
}
|
||||
|
||||
const ControlItem& it = items[i];
|
||||
@@ -607,8 +608,8 @@ int main() {
|
||||
|
||||
// Icon column (x = 8..28) + Label column (x = 30..112 for sliders, 30..166 for toggles)
|
||||
int labelMaxW = it.isSlider ? 82 : 136;
|
||||
drawPango(layoutIcon, isSel ? &colYellow : &colLight, 8, ry, kRowHeight, rowIcon);
|
||||
drawPango(layoutMain, isSel ? &colWhite : &colLight, 30, ry, kRowHeight,
|
||||
drawPango(layoutIcon, isSel ? &colYellow : &colLight, 8, ry, rowH, rowIcon);
|
||||
drawPango(layoutMain, isSel ? &colWhite : &colLight, 30, ry, rowH,
|
||||
it.label, labelMaxW);
|
||||
|
||||
if (it.isSlider) {
|
||||
@@ -627,7 +628,7 @@ int main() {
|
||||
int barX = 114;
|
||||
int barW = 78;
|
||||
int barH = 12;
|
||||
int barY = ry + (kRowHeight - barH) / 2;
|
||||
int barY = ry + (rowH - barH) / 2;
|
||||
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XFillRectangle(dpy, pix, gc, barX, barY, barW, barH);
|
||||
@@ -650,16 +651,16 @@ int main() {
|
||||
std::string pctStr(pctBuf);
|
||||
int pw = pangoWidth(layoutSmall, pctStr);
|
||||
drawPango(layoutSmall, isSel ? &colWhite : &colLight, kWinWidth - pw - 6,
|
||||
ry, kRowHeight, pctStr);
|
||||
ry, rowH, pctStr);
|
||||
} else {
|
||||
// Toggle switch icon + ON/OFF label (right-aligned within x = 160..234)
|
||||
bool on = (it.value != 0);
|
||||
std::string stStr = on ? "ON" : "OFF";
|
||||
int stW = pangoWidth(layoutMain, stStr);
|
||||
drawPango(layoutMain, on ? (isSel ? &colYellow : &colGreen) : &colMuted,
|
||||
kWinWidth - stW - 8, ry, kRowHeight, stStr);
|
||||
kWinWidth - stW - 8, ry, rowH, stStr);
|
||||
drawPango(layoutIcon, on ? (isSel ? &colYellow : &colGreen) : &colMuted,
|
||||
kWinWidth - stW - 30, ry, kRowHeight,
|
||||
kWinWidth - stW - 30, ry, rowH,
|
||||
on ? kIconToggleOn : kIconToggleOff);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user