Preload DWM plugins (dialer, calllog, xdrawer) with resident X11/Pango state and FIFO IPC
This commit is contained in:
+216
-172
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Dialer DWM Plugin - Keypad-driven X11 dialer with contact & T9 integration (240x320)
|
||||
// Dialer DWM Plugin - Preloaded resident X11 dialer with contact & T9 integration (240x320)
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xft/Xft.h>
|
||||
@@ -37,51 +37,28 @@ void handleSignal(int) {
|
||||
gRunning = 0;
|
||||
}
|
||||
|
||||
constexpr const char* kQueuePath = "/tmp/sxmo_dialer_queue";
|
||||
|
||||
void enqueueDialChars(const char* chars) {
|
||||
if (!chars || !chars[0]) {
|
||||
return;
|
||||
}
|
||||
int fd = ::open(kQueuePath, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, 0644);
|
||||
if (fd >= 0) {
|
||||
(void)::write(fd, chars, std::strlen(chars));
|
||||
::close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
std::string drainDialQueue() {
|
||||
int fd = ::open(kQueuePath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
return "";
|
||||
}
|
||||
char buf[128];
|
||||
ssize_t n = ::read(fd, buf, sizeof(buf) - 1);
|
||||
::close(fd);
|
||||
::unlink(kQueuePath);
|
||||
if (n <= 0) {
|
||||
return "";
|
||||
}
|
||||
buf[n] = '\0';
|
||||
return normalizePhone(buf);
|
||||
}
|
||||
|
||||
int dialer_run_main(int argc, char** argv) {
|
||||
gRunning = 1;
|
||||
int64_t startMs = nowMs();
|
||||
bool isPreload = false;
|
||||
std::string initArg;
|
||||
|
||||
if (argc > 1 && argv[1] && argv[1][0]) {
|
||||
enqueueDialChars(argv[1]);
|
||||
}
|
||||
|
||||
std::string pidPath = getRuntimeFile("xdialer.pid");
|
||||
int existingPid = readIntFile(pidPath, -1);
|
||||
if (existingPid > 0 && existingPid != static_cast<int>(::getpid())) {
|
||||
if (::kill(existingPid, 0) == 0) {
|
||||
return 0;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (argv[i] && std::strcmp(argv[i], "--preload") == 0) {
|
||||
isPreload = true;
|
||||
} else if (argv[i] && argv[i][0]) {
|
||||
initArg += argv[i];
|
||||
}
|
||||
}
|
||||
writeIntFile(pidPath, static_cast<int>(::getpid()));
|
||||
|
||||
// If the resident dialer daemon is already running, forward the command via FIFO
|
||||
if (sendPluginCommand("dialer", isPreload ? "NOP" : (initArg.empty() ? "OPEN" : ("OPEN " + initArg)))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string daemonPidPath = getPluginDaemonPidPath("dialer");
|
||||
std::string activePidPath = getRuntimeFile("xdialer.pid");
|
||||
writeIntFile(daemonPidPath, static_cast<int>(::getpid()));
|
||||
int fifoFd = setupPluginDaemonFifo("dialer");
|
||||
|
||||
struct sigaction sa {};
|
||||
sa.sa_handler = handleSignal;
|
||||
@@ -91,7 +68,8 @@ int dialer_run_main(int argc, char** argv) {
|
||||
|
||||
Display* dpy = XOpenDisplay(nullptr);
|
||||
if (!dpy) {
|
||||
::unlink(pidPath.c_str());
|
||||
if (fifoFd >= 0) ::close(fifoFd);
|
||||
::unlink(daemonPidPath.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -120,17 +98,6 @@ int dialer_run_main(int argc, char** argv) {
|
||||
XSetClassHint(dpy, win, &ch);
|
||||
XStoreName(dpy, win, "Dialer");
|
||||
|
||||
XMapRaised(dpy, win);
|
||||
XSync(dpy, False);
|
||||
|
||||
for (int i = 0; i < 60; ++i) {
|
||||
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
|
||||
GrabSuccess) {
|
||||
break;
|
||||
}
|
||||
usleep(5000);
|
||||
}
|
||||
|
||||
Pixmap pix = XCreatePixmap(dpy, win, kWinWidth, kWinHeight, DefaultDepth(dpy, screen));
|
||||
GC gc = XCreateGC(dpy, pix, 0, nullptr);
|
||||
XftDraw* xftDraw = XftDrawCreate(dpy, pix, visual, cmap);
|
||||
@@ -172,17 +139,36 @@ int dialer_run_main(int argc, char** argv) {
|
||||
XftColor colBlue = allocColor("#5dade2");
|
||||
|
||||
ContactBook book;
|
||||
book.load();
|
||||
std::vector<ContactEntry> allContacts = book.buildDialerList();
|
||||
std::vector<ContactEntry> allContacts;
|
||||
std::vector<ContactEntry> filtered;
|
||||
FileStamp contactsStamp;
|
||||
FileStamp logStamp;
|
||||
bool contactsLoadedOnce = false;
|
||||
|
||||
std::string number = drainDialQueue();
|
||||
int selected = -1; // -1 = top number box focused; 0..N-1 = contact row
|
||||
auto reloadContactsIfNeeded = [&]() -> bool {
|
||||
bool cChanged = contactsStamp.checkAndUpdate(getContactsFilePath());
|
||||
bool lChanged = logStamp.checkAndUpdate(getModemLogFilePath());
|
||||
if (cChanged || lChanged || !contactsLoadedOnce) {
|
||||
contactsLoadedOnce = true;
|
||||
book.load();
|
||||
allContacts = book.buildDialerList();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// If launched with '0' from idle desktop and '0' (keycode 19) is still held,
|
||||
// allow long-pressing that initial '0' to turn into '+'.
|
||||
bool zeroHeld = (number == "0" && isKeycodeDown(dpy, 19));
|
||||
int64_t zeroPressMs = zeroHeld ? startMs : 0;
|
||||
reloadContactsIfNeeded();
|
||||
|
||||
std::string number;
|
||||
int selected = -1;
|
||||
bool visible = false;
|
||||
int64_t openStartMs = 0;
|
||||
int64_t startupIgnoreUntilMs = 0;
|
||||
bool initialSoftkeysReleased = true;
|
||||
int softkeyPending = 0;
|
||||
int64_t softkeyDeadlineMs = 0;
|
||||
bool zeroHeld = false;
|
||||
int64_t zeroPressMs = 0;
|
||||
|
||||
auto updateFilter = [&]() {
|
||||
filtered.clear();
|
||||
@@ -223,11 +209,6 @@ int dialer_run_main(int argc, char** argv) {
|
||||
}
|
||||
};
|
||||
|
||||
updateFilter();
|
||||
if (!number.empty()) {
|
||||
selected = -1;
|
||||
}
|
||||
|
||||
auto drawPango = [&](PangoLayout* layout, XftColor* color, int x, int y, int h,
|
||||
const std::string& text, int maxW = -1) {
|
||||
pango_layout_set_text(layout, text.c_str(), static_cast<int>(text.size()));
|
||||
@@ -256,14 +237,13 @@ int dialer_run_main(int argc, char** argv) {
|
||||
constexpr int kHeaderH = 56;
|
||||
constexpr int kSoftbarH = 26;
|
||||
constexpr int kListY = kHeaderH;
|
||||
constexpr int kListH = kWinHeight - kHeaderH - kSoftbarH; // 214px
|
||||
constexpr int kListH = kWinHeight - kHeaderH - kSoftbarH;
|
||||
constexpr int kVisibleRows = 5;
|
||||
|
||||
auto render = [&]() {
|
||||
XSetForeground(dpy, gc, 0x222222);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
|
||||
|
||||
// 1. Top Number Display Box (y = 0..56)
|
||||
bool topSel = (selected < 0);
|
||||
XSetForeground(dpy, gc, topSel ? 0x1b3b4b : 0x1c1c1c);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
|
||||
@@ -287,7 +267,6 @@ int dialer_run_main(int argc, char** argv) {
|
||||
drawPango(layoutIcon, &colMuted, 218, 4, 30, kIconBackspace);
|
||||
}
|
||||
|
||||
// Subtitle inside header box (y = 33..54)
|
||||
std::string subText;
|
||||
XftColor* subCol = &colMuted;
|
||||
if (selected >= 0 && selected < static_cast<int>(filtered.size())) {
|
||||
@@ -310,7 +289,6 @@ int dialer_run_main(int argc, char** argv) {
|
||||
}
|
||||
drawPango(layoutSmall, subCol, 32, 33, 20, subText, 202);
|
||||
|
||||
// 2. Contact / Recent Suggestions List (y = 56..270, 5 visible rows)
|
||||
if (filtered.empty()) {
|
||||
drawPango(layoutMain, &colMuted, 16, kListY + 40, 30,
|
||||
number.empty() ? "No saved contacts" : "New number (press Call)",
|
||||
@@ -372,7 +350,6 @@ int dialer_run_main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Bottom Softkey Bar (y = 270..296)
|
||||
int sbY = kWinHeight - kSoftbarH;
|
||||
XSetForeground(dpy, gc, 0x181818);
|
||||
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, kSoftbarH);
|
||||
@@ -391,20 +368,111 @@ int dialer_run_main(int argc, char** argv) {
|
||||
drawPango(layoutSmall, &colLight, kWinWidth - rw - 6, sbY + 1,
|
||||
kSoftbarH - 1, rightLabel);
|
||||
|
||||
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
|
||||
XFlush(dpy);
|
||||
if (visible) {
|
||||
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
|
||||
XFlush(dpy);
|
||||
}
|
||||
};
|
||||
|
||||
// Pre-warm Pango/FreeType/Xrender glyph caches into offscreen Pixmap at startup
|
||||
number = "+0123456789*#";
|
||||
updateFilter();
|
||||
render();
|
||||
drawPango(layoutIcon, &colGreen, 0, 0, 20,
|
||||
std::string(kIconPhone) + kIconBackspace + kIconClock + kIconUser);
|
||||
number.clear();
|
||||
updateFilter();
|
||||
render();
|
||||
XSync(dpy, False);
|
||||
|
||||
auto showWindow = [&](const std::string& arg) {
|
||||
if (isPidFileAlive(getRuntimeFile("xcalllog.pid"))) {
|
||||
sendPluginCommand("calllog", "CLOSE");
|
||||
}
|
||||
if (isPidFileAlive(getRuntimeFile("xdrawer.pid"))) {
|
||||
sendPluginCommand("xdrawer", "CLOSE");
|
||||
}
|
||||
std::string cleanArg = normalizePhone(arg);
|
||||
if (!visible) {
|
||||
openStartMs = nowMs();
|
||||
startupIgnoreUntilMs = openStartMs + 70;
|
||||
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
|
||||
softkeyPending = 0;
|
||||
softkeyDeadlineMs = 0;
|
||||
zeroHeld = (cleanArg == "0" && isKeycodeDown(dpy, 19));
|
||||
zeroPressMs = zeroHeld ? openStartMs : 0;
|
||||
visible = true;
|
||||
XMapRaised(dpy, win);
|
||||
if (cleanArg.empty()) {
|
||||
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
|
||||
}
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
|
||||
GrabSuccess) {
|
||||
break;
|
||||
}
|
||||
usleep(2000);
|
||||
}
|
||||
bool reloaded = reloadContactsIfNeeded();
|
||||
if (!cleanArg.empty() || reloaded || number != cleanArg) {
|
||||
number = cleanArg;
|
||||
selected = number.empty() ? (allContacts.empty() ? -1 : 0) : -1;
|
||||
updateFilter();
|
||||
render();
|
||||
}
|
||||
XFlush(dpy);
|
||||
writeIntFile(activePidPath, static_cast<int>(::getpid()));
|
||||
} else if (!cleanArg.empty()) {
|
||||
if (nowMs() - openStartMs < 40 && number == cleanArg) {
|
||||
return;
|
||||
}
|
||||
number += cleanArg;
|
||||
selected = -1;
|
||||
updateFilter();
|
||||
render();
|
||||
}
|
||||
};
|
||||
|
||||
auto hideWindow = [&](bool drainSoftkeys) {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
int xfd = ConnectionNumber(dpy);
|
||||
if (drainSoftkeys) {
|
||||
int64_t drainDeadline = nowMs() + 180;
|
||||
while (nowMs() < drainDeadline && querySoftkeysDown(dpy) != 0) {
|
||||
while (XPending(dpy)) {
|
||||
XEvent ev;
|
||||
XNextEvent(dpy, &ev);
|
||||
}
|
||||
struct pollfd pfd {};
|
||||
pfd.fd = xfd;
|
||||
pfd.events = POLLIN;
|
||||
::poll(&pfd, 1, 10);
|
||||
}
|
||||
writeSoftkeySuppress(nowMs() + 300);
|
||||
}
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
XUnmapWindow(dpy, win);
|
||||
XFlush(dpy);
|
||||
::unlink(activePidPath.c_str());
|
||||
visible = false;
|
||||
softkeyPending = 0;
|
||||
softkeyDeadlineMs = 0;
|
||||
zeroHeld = false;
|
||||
if (!number.empty() || selected != (allContacts.empty() ? -1 : 0)) {
|
||||
number.clear();
|
||||
selected = allContacts.empty() ? -1 : 0;
|
||||
updateFilter();
|
||||
render();
|
||||
XFlush(dpy);
|
||||
}
|
||||
};
|
||||
|
||||
if (!isPreload) {
|
||||
showWindow(initArg);
|
||||
}
|
||||
|
||||
int64_t startupIgnoreUntilMs = startMs + 90;
|
||||
bool initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
|
||||
int softkeyPending = 0;
|
||||
int64_t softkeyDeadlineMs = 0;
|
||||
bool closedByKey = false;
|
||||
std::string targetToDial;
|
||||
bool switchToCallLog = false;
|
||||
bool launchXDrawer = false;
|
||||
int xfd = ConnectionNumber(dpy);
|
||||
|
||||
auto selectActiveNumber = [&]() -> std::string {
|
||||
@@ -421,15 +489,20 @@ int dialer_run_main(int argc, char** argv) {
|
||||
};
|
||||
|
||||
while (gRunning) {
|
||||
std::string extra = drainDialQueue();
|
||||
if (!extra.empty()) {
|
||||
number += extra;
|
||||
selected = -1;
|
||||
updateFilter();
|
||||
render();
|
||||
// 1. Process any incoming FIFO commands
|
||||
for (const std::string& cmd : readFifoLines(fifoFd)) {
|
||||
if (cmd == "NOP") {
|
||||
continue;
|
||||
} else if (cmd == "CLOSE") {
|
||||
hideWindow(false);
|
||||
} else if (cmd == "OPEN") {
|
||||
showWindow("");
|
||||
} else if (cmd.rfind("OPEN ", 0) == 0) {
|
||||
showWindow(cmd.substr(5));
|
||||
}
|
||||
}
|
||||
|
||||
if (zeroHeld) {
|
||||
if (visible && zeroHeld) {
|
||||
if (!isKeycodeDown(dpy, 19)) {
|
||||
zeroHeld = false;
|
||||
} else if (nowMs() - zeroPressMs >= 420) {
|
||||
@@ -442,13 +515,16 @@ int dialer_run_main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
|
||||
if (visible && !initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
|
||||
initialSoftkeysReleased = true;
|
||||
}
|
||||
|
||||
while (XPending(dpy)) {
|
||||
XEvent ev;
|
||||
XNextEvent(dpy, &ev);
|
||||
if (!visible) {
|
||||
continue;
|
||||
}
|
||||
if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
|
||||
initialSoftkeysReleased = true;
|
||||
}
|
||||
@@ -489,22 +565,22 @@ int dialer_run_main(int argc, char** argv) {
|
||||
softkeyPending |= which | querySoftkeysDown(dpy);
|
||||
if (softkeyPending == 3) {
|
||||
writeSoftkeySuppress(nowMs() + 500);
|
||||
launchXDrawer = true;
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
hideWindow(false);
|
||||
if (!sendPluginCommand("xdrawer", "TOGGLE")) {
|
||||
runAsyncArgv("xdrawer");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (softkeyDeadlineMs == 0) {
|
||||
softkeyDeadlineMs = nowMs() + 45;
|
||||
softkeyDeadlineMs = nowMs() + 40;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char dialCh = mapDialKey(sym, ev.xkey.keycode, ev.xkey.state);
|
||||
if (dialCh != '\0') {
|
||||
if (nowMs() - startMs < 45 && number.size() == 1 &&
|
||||
if (nowMs() - openStartMs < 40 && number.size() == 1 &&
|
||||
number[0] == dialCh) {
|
||||
// Ignore duplicate event from the initial key press that opened dialer
|
||||
continue;
|
||||
}
|
||||
number.push_back(dialCh);
|
||||
@@ -522,9 +598,8 @@ int dialer_run_main(int argc, char** argv) {
|
||||
|
||||
switch (sym) {
|
||||
case XK_Escape:
|
||||
writeSoftkeySuppress(nowMs() + 350);
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
writeSoftkeySuppress(nowMs() + 300);
|
||||
hideWindow(true);
|
||||
break;
|
||||
case XK_BackSpace:
|
||||
case XK_Left:
|
||||
@@ -535,8 +610,7 @@ int dialer_run_main(int argc, char** argv) {
|
||||
updateFilter();
|
||||
render();
|
||||
} else if (sym == XK_BackSpace) {
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
hideWindow(true);
|
||||
}
|
||||
break;
|
||||
case XK_Right:
|
||||
@@ -582,10 +656,9 @@ int dialer_run_main(int argc, char** argv) {
|
||||
case XF86XK_PickupPhone: {
|
||||
std::string target = selectActiveNumber();
|
||||
if (!target.empty()) {
|
||||
targetToDial = target;
|
||||
writeSoftkeySuppress(nowMs() + 400);
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
writeSoftkeySuppress(nowMs() + 350);
|
||||
hideWindow(true);
|
||||
placePhoneCall(target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -595,28 +668,23 @@ int dialer_run_main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!gRunning) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (softkeyPending != 0 && nowMs() >= softkeyDeadlineMs) {
|
||||
if (visible && softkeyPending != 0 && nowMs() >= softkeyDeadlineMs) {
|
||||
int comb = softkeyPending | querySoftkeysDown(dpy);
|
||||
softkeyPending = 0;
|
||||
softkeyDeadlineMs = 0;
|
||||
if (comb == 3) {
|
||||
writeSoftkeySuppress(nowMs() + 500);
|
||||
launchXDrawer = true;
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
break;
|
||||
hideWindow(false);
|
||||
if (!sendPluginCommand("xdrawer", "TOGGLE")) {
|
||||
runAsyncArgv("xdrawer");
|
||||
}
|
||||
} else if (comb == 1) {
|
||||
// Left Softkey: if empty, switch to Call Log; if non-empty, toggle leading '+'
|
||||
if (number.empty()) {
|
||||
writeSoftkeySuppress(nowMs() + 350);
|
||||
switchToCallLog = true;
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
break;
|
||||
writeSoftkeySuppress(nowMs() + 250);
|
||||
hideWindow(false);
|
||||
if (!sendPluginCommand("calllog", "OPEN")) {
|
||||
runAsyncArgv("xcalllog");
|
||||
}
|
||||
} else {
|
||||
if (number[0] == '+') {
|
||||
number.erase(0, 1);
|
||||
@@ -628,50 +696,43 @@ int dialer_run_main(int argc, char** argv) {
|
||||
render();
|
||||
}
|
||||
} else if (comb == 2) {
|
||||
// Right Softkey: delete last character if non-empty, else close Dialer
|
||||
if (!number.empty()) {
|
||||
number.pop_back();
|
||||
selected = -1;
|
||||
updateFilter();
|
||||
render();
|
||||
} else {
|
||||
writeSoftkeySuppress(nowMs() + 400);
|
||||
closedByKey = true;
|
||||
gRunning = 0;
|
||||
break;
|
||||
writeSoftkeySuppress(nowMs() + 350);
|
||||
hideWindow(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int timeoutMs = 200;
|
||||
if (softkeyDeadlineMs > 0) {
|
||||
timeoutMs = static_cast<int>(std::max<int64_t>(5, softkeyDeadlineMs - nowMs()));
|
||||
} else if (zeroHeld) {
|
||||
timeoutMs = 25;
|
||||
}
|
||||
|
||||
struct pollfd pfd {};
|
||||
pfd.fd = xfd;
|
||||
pfd.events = POLLIN;
|
||||
::poll(&pfd, 1, timeoutMs);
|
||||
}
|
||||
|
||||
if (closedByKey && !launchXDrawer) {
|
||||
int64_t drainDeadline = nowMs() + 200;
|
||||
while (nowMs() < drainDeadline && querySoftkeysDown(dpy) != 0) {
|
||||
while (XPending(dpy)) {
|
||||
XEvent ev;
|
||||
XNextEvent(dpy, &ev);
|
||||
int timeoutMs = -1;
|
||||
if (visible) {
|
||||
timeoutMs = 200;
|
||||
if (softkeyDeadlineMs > 0) {
|
||||
timeoutMs = static_cast<int>(std::max<int64_t>(5, softkeyDeadlineMs - nowMs()));
|
||||
} else if (zeroHeld) {
|
||||
timeoutMs = 25;
|
||||
}
|
||||
struct pollfd pfd {};
|
||||
pfd.fd = xfd;
|
||||
pfd.events = POLLIN;
|
||||
::poll(&pfd, 1, 15);
|
||||
}
|
||||
writeSoftkeySuppress(nowMs() + 350);
|
||||
|
||||
struct pollfd pfds[2] {};
|
||||
pfds[0].fd = xfd;
|
||||
pfds[0].events = POLLIN;
|
||||
pfds[1].fd = fifoFd;
|
||||
pfds[1].events = POLLIN;
|
||||
::poll(pfds, (fifoFd >= 0) ? 2 : 1, timeoutMs);
|
||||
}
|
||||
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
hideWindow(false);
|
||||
if (fifoFd >= 0) {
|
||||
::close(fifoFd);
|
||||
}
|
||||
::unlink(getPluginFifoPath("dialer").c_str());
|
||||
::unlink(daemonPidPath.c_str());
|
||||
|
||||
pango_font_description_free(descIcon);
|
||||
pango_font_description_free(descSmall);
|
||||
pango_font_description_free(descMain);
|
||||
@@ -686,22 +747,13 @@ int dialer_run_main(int argc, char** argv) {
|
||||
XFreePixmap(dpy, pix);
|
||||
XDestroyWindow(dpy, win);
|
||||
XCloseDisplay(dpy);
|
||||
::unlink(pidPath.c_str());
|
||||
|
||||
if (launchXDrawer) {
|
||||
runAsyncArgv("xdrawer");
|
||||
} else if (switchToCallLog) {
|
||||
runAsyncArgv("xcalllog");
|
||||
} else if (!targetToDial.empty()) {
|
||||
placePhoneCall(targetToDial);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t gLastSpawnMs = 0;
|
||||
|
||||
int dialer_plugin_init(const DwmHostApi*) {
|
||||
int dialer_plugin_init(const DwmHostApi* host) {
|
||||
if (host && host->spawn_plugin) {
|
||||
host->spawn_plugin("dialer", "--preload");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -715,16 +767,8 @@ int dialer_on_idle_key(const DwmHostApi* host, KeySym keysym,
|
||||
return 0;
|
||||
}
|
||||
char buf[2] = {ch, '\0'};
|
||||
enqueueDialChars(buf);
|
||||
|
||||
int64_t now = nowMs();
|
||||
std::string pidPath = getRuntimeFile("xdialer.pid");
|
||||
int existingPid = readIntFile(pidPath, -1);
|
||||
bool alreadyRunning = (existingPid > 0 && ::kill(existingPid, 0) == 0);
|
||||
|
||||
if (!alreadyRunning && (now - gLastSpawnMs) > 250 && host->spawn_plugin) {
|
||||
gLastSpawnMs = now;
|
||||
host->spawn_plugin("dialer", nullptr);
|
||||
if (host->spawn_plugin) {
|
||||
host->spawn_plugin("dialer", buf);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user