Harden DWM plugins against X11 stacking/keyboard grab races and speed up QMI status

This commit is contained in:
Luxferre
2026-10-25 14:14:21 +02:00
parent b2216c186f
commit e77be498bf
44 changed files with 432 additions and 211 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -65,10 +65,7 @@ detect_qmicli_modem() {
if ! command -v qmicli >/dev/null 2>&1; then if ! command -v qmicli >/dev/null 2>&1; then
return 1 return 1
fi fi
if timeout 3 qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then if [ -e "/dev/wwan0qmi0" ]; then
QMICLI_MODEM="timeout 4 qmicli --silent -pd qrtr://0"
return 0
elif [ -e "/dev/wwan0qmi0" ]; then
if timeout 3 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then if timeout 3 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi" QMICLI_MODEM="timeout 4 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi"
return 0 return 0
@@ -76,6 +73,10 @@ detect_qmicli_modem() {
QMICLI_MODEM="timeout 4 qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi" QMICLI_MODEM="timeout 4 qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi"
return 0 return 0
fi fi
fi
if timeout 3 qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 qmicli --silent -pd qrtr://0"
return 0
elif [ -e "/dev/modem" ]; then elif [ -e "/dev/modem" ]; then
if timeout 3 qmicli --silent -pd /dev/modem --uim-noop >/dev/null 2>&1; then if timeout 3 qmicli --silent -pd /dev/modem --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 qmicli --silent -pd /dev/modem" QMICLI_MODEM="timeout 4 qmicli --silent -pd /dev/modem"
@@ -636,26 +637,23 @@ case "$cmd" in
;; ;;
status) status)
if ! detect_qmicli_modem; then QMI_CARDS=""
echo "MODEM_AVAILABLE=0" if command -v qmicli >/dev/null 2>&1; then
echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT" if [ -e "/dev/wwan0qmi0" ]; then
exit 0 QMI_CARDS="$(timeout 3 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-get-card-status 2>/dev/null || true)"
if [ -n "$QMI_CARDS" ]; then
QMICLI_MODEM="timeout 3 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi"
fi fi
fi
if [ -z "$QMI_CARDS" ] && detect_qmicli_modem; then
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)" QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
fi
fi
if [ -z "$QMI_CARDS" ]; then if [ -z "$QMI_CARDS" ]; then
echo "MODEM_AVAILABLE=0" echo "MODEM_AVAILABLE=0"
echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT" echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT"
exit 0 exit 0
fi fi
eval "$(parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT")"
if [ "$PRIMARY_GW_SLOT" = "0" ] && { [ "$SLOT1_STATE" = "present" ] || [ "$SLOT2_STATE" = "present" ]; }; then
SIM_WAIT_TIME=1
provision_slot "$PREFERRED_SIM_SLOT" 2 >/dev/null 2>&1 || true
QMI_CARDS_NEW="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
if [ -n "$QMI_CARDS_NEW" ]; then
QMI_CARDS="$QMI_CARDS_NEW"
fi
fi
echo "MODEM_AVAILABLE=1" echo "MODEM_AVAILABLE=1"
parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT" parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT"
QMI_NAS="$($QMICLI_MODEM --nas-get-serving-system 2>/dev/null || true)" QMI_NAS="$($QMICLI_MODEM --nas-get-serving-system 2>/dev/null || true)"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+13 -8
View File
@@ -333,6 +333,7 @@ int calllog_run_main(int argc, char** argv) {
XSync(dpy, False); XSync(dpy, False);
auto showWindow = [&]() { auto showWindow = [&]() {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("calllog"); closeOtherPlugins("calllog");
bool themeChanged = theme.checkAndReload( bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon, dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
@@ -348,13 +349,7 @@ int calllog_run_main(int argc, char** argv) {
if (!themeChanged) { if (!themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0); XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
} }
for (int i = 0; i < 20; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) {
break;
}
usleep(2000);
}
if (reloadLogsIfNeeded() || themeChanged || filterTab != 0 || selected != 0) { if (reloadLogsIfNeeded() || themeChanged || filterTab != 0 || selected != 0) {
filterTab = 0; filterTab = 0;
selected = 0; selected = 0;
@@ -362,8 +357,9 @@ int calllog_run_main(int argc, char** argv) {
render(); render();
} }
XFlush(dpy); XFlush(dpy);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
} else { } else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
if (reloadLogsIfNeeded() || themeChanged) { if (reloadLogsIfNeeded() || themeChanged) {
render(); render();
} }
@@ -444,6 +440,15 @@ int calllog_run_main(int argc, char** argv) {
if (ev.xexpose.count == 0) { if (ev.xexpose.count == 0) {
render(); render();
} }
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("calllog")) {
hideWindow(false);
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
KeySym sym = XLookupKeysym(&ev.xkey, 0); KeySym sym = XLookupKeysym(&ev.xkey, 0);
if (sym == XK_Menu || sym == XF86XK_KbdLcdMenu1 || if (sym == XK_Menu || sym == XF86XK_KbdLcdMenu1 ||
+12 -8
View File
@@ -926,6 +926,7 @@ int callscreen_run_main(int argc, char** argv) {
XSync(dpy, False); XSync(dpy, False);
auto showWindow = [&]() { auto showWindow = [&]() {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("callscreen"); closeOtherPlugins("callscreen");
wakeDisplayHardware(dpy); wakeDisplayHardware(dpy);
theme.checkAndReload(dpy, screen, visual, cmap, layoutMain, layoutSmall, theme.checkAndReload(dpy, screen, visual, cmap, layoutMain, layoutSmall,
@@ -942,17 +943,11 @@ int callscreen_run_main(int argc, char** argv) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
render(); render();
for (int i = 0; i < 20; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) {
break;
}
usleep(2000);
}
XFlush(dpy); XFlush(dpy);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
} else { } else {
XMapRaised(dpy, win); XMapRaised(dpy, win);
grabPluginKeyboard(dpy, win);
render(); render();
} }
}; };
@@ -1379,6 +1374,15 @@ int callscreen_run_main(int argc, char** argv) {
if (ev.xexpose.count == 0) { if (ev.xexpose.count == 0) {
render(); render();
} }
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("callscreen")) {
hideWindow(false);
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
KeySym sym = XLookupKeysym(&ev.xkey, 0); KeySym sym = XLookupKeysym(&ev.xkey, 0);
if (sym == XK_Menu || sym == XF86XK_KbdLcdMenu1 || if (sym == XK_Menu || sym == XF86XK_KbdLcdMenu1 ||
+14 -10
View File
@@ -711,26 +711,19 @@ int runCameraApp(int argc, char** argv) {
}; };
auto showWindow = [&](const std::string& argStr) { auto showWindow = [&](const std::string& argStr) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("camera"); closeOtherPlugins("camera");
countdownActive = false; countdownActive = false;
torchOn = getTorchState(); torchOn = getTorchState();
torchRestoredOnClose = !torchOn; torchRestoredOnClose = !torchOn;
writeIntFile(activePidPath, static_cast<int>(::getpid()));
if (!visible) { if (!visible) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
for (int i = 0; i < 20; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(2000);
}
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime); grabPluginKeyboard(dpy, win);
openStartMs = nowMs(); openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180; startupIgnoreUntilMs = openStartMs + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -822,6 +815,15 @@ int runCameraApp(int argc, char** argv) {
if (ev.type == Expose && ev.xexpose.count == 0) { if (ev.type == Expose && ev.xexpose.count == 0) {
drawUI(); drawUI();
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("camera")) {
hideWindow();
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
drawUI();
}
} else if (ev.type == KeyPress) { } else if (ev.type == KeyPress) {
int64_t tNow = nowMs(); int64_t tNow = nowMs();
unsigned int kc = ev.xkey.keycode; unsigned int kc = ev.xkey.keycode;
@@ -925,7 +927,9 @@ int runCameraApp(int argc, char** argv) {
enterViewfinderMode(); enterViewfinderMode();
drawUI(); drawUI();
} else { } else {
runAsyncArgv("feh", photos[selectedPhoto].fullPath.c_str()); std::string path = photos[selectedPhoto].fullPath;
hideWindow();
runAsyncArgv("feh", path.c_str());
} }
} }
} else if (mode == ViewMode::ConfirmDelete) { } else if (mode == ViewMode::ConfirmDelete) {
+28 -11
View File
@@ -765,6 +765,7 @@ int runContactsApp(int argc, char** argv) {
}; };
auto showWindow = [&](const std::string& arg) { auto showWindow = [&](const std::string& arg) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("contacts"); closeOtherPlugins("contacts");
bool themeChanged = theme.checkAndReload( bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon, dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
@@ -784,13 +785,7 @@ int runContactsApp(int argc, char** argv) {
if (!openNewMode && !themeChanged) { if (!openNewMode && !themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0); XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
} }
for (int i = 0; i < 20; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) {
break;
}
usleep(2000);
}
bool reloaded = reloadContactsIfNeeded(); bool reloaded = reloadContactsIfNeeded();
if (openNewMode) { if (openNewMode) {
beginNewContact(prefill); beginNewContact(prefill);
@@ -804,8 +799,9 @@ int runContactsApp(int argc, char** argv) {
render(); render();
} }
XFlush(dpy); XFlush(dpy);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
} else { } else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
reloadContactsIfNeeded(); reloadContactsIfNeeded();
if (openNewMode) { if (openNewMode) {
beginNewContact(prefill); beginNewContact(prefill);
@@ -914,9 +910,13 @@ int runContactsApp(int argc, char** argv) {
render(); render();
int rc = 0; int rc = 0;
std::string out = runCaptureCmd( std::string out = runCaptureCmd(
"doas /usr/libexec/msm-modem-uim-selection sim-contacts-import " + "doas -n /usr/libexec/msm-modem-uim-selection sim-contacts-import " +
std::to_string(slotNum) + " 2>&1", std::to_string(slotNum) + " 2>&1",
&rc); &rc);
if (visible) {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
}
if (out.rfind("ERROR:", 0) == 0) { if (out.rfind("ERROR:", 0) == 0) {
std::string err = trimStr(out.substr(6)); std::string err = trimStr(out.substr(6));
setStatus(err.empty() ? "SIM import failed" : err, true); setStatus(err.empty() ? "SIM import failed" : err, true);
@@ -975,9 +975,13 @@ int runContactsApp(int argc, char** argv) {
render(); render();
int rc = 0; int rc = 0;
std::string out = runCaptureCmd( std::string out = runCaptureCmd(
"doas /usr/libexec/msm-modem-uim-selection sim-contacts-export " + "doas -n /usr/libexec/msm-modem-uim-selection sim-contacts-export " +
std::to_string(slotNum) + " " + shellQuote(srcFile) + " 2>&1", std::to_string(slotNum) + " " + shellQuote(srcFile) + " 2>&1",
&rc); &rc);
if (visible) {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
}
if (!tmpSingle.empty()) { if (!tmpSingle.empty()) {
::unlink(tmpSingle.c_str()); ::unlink(tmpSingle.c_str());
} }
@@ -1015,7 +1019,11 @@ int runContactsApp(int argc, char** argv) {
prevModeBeforeSim = prevModeBeforeSim =
(op == SimOp::ExportSingle) ? ViewMode::Detail : ViewMode::List; (op == SimOp::ExportSingle) ? ViewMode::Detail : ViewMode::List;
std::string st = runCaptureCmd( std::string st = runCaptureCmd(
"doas /usr/libexec/msm-modem-uim-selection status 2>/dev/null"); "doas -n /usr/libexec/msm-modem-uim-selection status 2>/dev/null");
if (visible) {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
}
bool s1Present = false; bool s1Present = false;
bool s2Present = false; bool s2Present = false;
int gwSlot = 1; int gwSlot = 1;
@@ -1203,6 +1211,15 @@ int runContactsApp(int argc, char** argv) {
if (ev.xexpose.count == 0) { if (ev.xexpose.count == 0) {
render(); render();
} }
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("contacts")) {
hideWindow(false);
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
KeySym sym = XLookupKeysym(&ev.xkey, 0); KeySym sym = XLookupKeysym(&ev.xkey, 0);
if (ev.xkey.keycode == 19 || sym == XK_0) { if (ev.xkey.keycode == 19 || sym == XK_0) {
+17 -8
View File
@@ -509,10 +509,15 @@ int dialer_run_main(int argc, char** argv) {
ussdReplyInput.clear(); ussdReplyInput.clear();
render(); render();
ussdResponse = sendModemUssd(codeOrReply, isReply, &ussdSessionActive); ussdResponse = sendModemUssd(codeOrReply, isReply, &ussdSessionActive);
if (visible) {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
}
render(); render();
}; };
auto showWindow = [&](const std::string& arg) { auto showWindow = [&](const std::string& arg) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("dialer"); closeOtherPlugins("dialer");
modal = DialerModal::Inactive; modal = DialerModal::Inactive;
bool themeChanged = theme.checkAndReload( bool themeChanged = theme.checkAndReload(
@@ -532,13 +537,7 @@ int dialer_run_main(int argc, char** argv) {
if (cleanArg.empty() && !themeChanged) { if (cleanArg.empty() && !themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0); XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
} }
for (int i = 0; i < 20; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) {
break;
}
usleep(2000);
}
bool reloaded = reloadContactsIfNeeded(); bool reloaded = reloadContactsIfNeeded();
if (cleanArg == "*#06#") { if (cleanArg == "*#06#") {
openImeiModal(); openImeiModal();
@@ -549,8 +548,9 @@ int dialer_run_main(int argc, char** argv) {
render(); render();
} }
XFlush(dpy); XFlush(dpy);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
} else if (!cleanArg.empty()) { } else if (!cleanArg.empty()) {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
if (nowMs() - openStartMs < 40 && number == cleanArg) { if (nowMs() - openStartMs < 40 && number == cleanArg) {
return; return;
} }
@@ -675,6 +675,15 @@ int dialer_run_main(int argc, char** argv) {
if (ev.xexpose.count == 0) { if (ev.xexpose.count == 0) {
render(); render();
} }
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("dialer")) {
hideWindow(false);
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
KeySym sym = XLookupKeysym(&ev.xkey, 0); KeySym sym = XLookupKeysym(&ev.xkey, 0);
if (ev.xkey.keycode == 19 || sym == XK_0) { if (ev.xkey.keycode == 19 || sym == XK_0) {
+23 -21
View File
@@ -530,6 +530,16 @@ int runFilesApp(int argc, char** argv) {
actionSelected = 0; actionSelected = 0;
}; };
auto hideWindow = [&]() {
if (!visible) return;
writeSoftkeySuppress(nowMs() + 450);
XUngrabKeyboard(dpy, CurrentTime);
XUnmapWindow(dpy, win);
XFlush(dpy);
visible = false;
::unlink(activePidPath.c_str());
};
auto openSelectedItem = [&]() { auto openSelectedItem = [&]() {
if (filteredItems.empty()) return; if (filteredItems.empty()) return;
const FileItem item = filteredItems[selected]; const FileItem item = filteredItems[selected];
@@ -549,9 +559,9 @@ int runFilesApp(int argc, char** argv) {
if (isImageExt(ext)) { if (isImageExt(ext)) {
openImageViewer(item); openImageViewer(item);
} else if (isMediaExt(ext)) { } else if (isMediaExt(ext)) {
hideWindow();
runAsyncArgv("sxmo_open.sh", item.fullPath.c_str()); runAsyncArgv("sxmo_open.sh", item.fullPath.c_str());
statusBanner = "Opening in media player..."; return;
statusBannerUntilMs = nowMs() + 1800;
} else if (isLikelyTextFile(item.fullPath, item.size)) { } else if (isLikelyTextFile(item.fullPath, item.size)) {
openTextViewer(item); openTextViewer(item);
} else { } else {
@@ -889,24 +899,17 @@ int runFilesApp(int argc, char** argv) {
}; };
auto showWindow = [&](const std::string& dirArg) { auto showWindow = [&](const std::string& dirArg) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("files"); closeOtherPlugins("files");
mode = ViewMode::Browser; mode = ViewMode::Browser;
loadDirectory(dirArg.empty() ? currentDir : dirArg); loadDirectory(dirArg.empty() ? currentDir : dirArg);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
if (!visible) { if (!visible) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
for (int i = 0; i < 20; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(2000);
}
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime); grabPluginKeyboard(dpy, win);
openStartMs = nowMs(); openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180; startupIgnoreUntilMs = openStartMs + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -914,16 +917,6 @@ int runFilesApp(int argc, char** argv) {
drawUI(); drawUI();
}; };
auto hideWindow = [&]() {
if (!visible) return;
writeSoftkeySuppress(nowMs() + 450);
XUngrabKeyboard(dpy, CurrentTime);
XUnmapWindow(dpy, win);
XFlush(dpy);
visible = false;
::unlink(activePidPath.c_str());
};
auto commitModalTap = [&](int digit) { auto commitModalTap = [&](int digit) {
const char* chars = kMultiTapFile[digit]; const char* chars = kMultiTapFile[digit];
int len = static_cast<int>(std::strlen(chars)); int len = static_cast<int>(std::strlen(chars));
@@ -1157,6 +1150,15 @@ int runFilesApp(int argc, char** argv) {
if (ev.type == Expose && ev.xexpose.count == 0) { if (ev.type == Expose && ev.xexpose.count == 0) {
drawUI(); drawUI();
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("files")) {
hideWindow();
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
drawUI();
}
} else if (ev.type == KeyPress) { } else if (ev.type == KeyPress) {
int64_t tNow = nowMs(); int64_t tNow = nowMs();
unsigned int kc = ev.xkey.keycode; unsigned int kc = ev.xkey.keycode;
+41 -13
View File
@@ -364,13 +364,26 @@ ModemStatusData queryModemAndSimStatus() {
} }
// 3. Query active SIM object if available // 3. Query active SIM object if available
static std::string cachedSimPath;
static std::string cachedSimIccid;
static std::string cachedSimOperator;
if (!d.simDbusPath.empty()) { if (!d.simDbusPath.empty()) {
if (d.simDbusPath == cachedSimPath && !cachedSimIccid.empty()) {
d.simIccid = cachedSimIccid;
d.simOperatorName = cachedSimOperator;
} else {
std::string simOut = runCaptureCmd( std::string simOut = runCaptureCmd(
"mmcli -i " + shellQuote(d.simDbusPath) + " -K 2>/dev/null"); "mmcli -i " + shellQuote(d.simDbusPath) + " -K 2>/dev/null");
std::unordered_map<std::string, std::string> simKv; std::unordered_map<std::string, std::string> simKv;
parseKvLines(simOut, simKv, ':'); parseKvLines(simOut, simKv, ':');
d.simIccid = cleanMmVal(simKv["sim.properties.iccid"]); d.simIccid = cleanMmVal(simKv["sim.properties.iccid"]);
d.simOperatorName = cleanMmVal(simKv["sim.properties.operator-name"]); d.simOperatorName = cleanMmVal(simKv["sim.properties.operator-name"]);
if (!d.simIccid.empty()) {
cachedSimPath = d.simDbusPath;
cachedSimIccid = d.simIccid;
cachedSimOperator = d.simOperatorName;
}
}
if (d.operatorName.empty() && !d.simOperatorName.empty()) { if (d.operatorName.empty() && !d.simOperatorName.empty()) {
d.operatorName = d.simOperatorName; d.operatorName = d.simOperatorName;
} }
@@ -609,6 +622,10 @@ int runModemApp(int argc, char** argv) {
} }
} }
lastRefreshMs = nowMs(); lastRefreshMs = nowMs();
if (visible && !isAnotherPluginActive("modem")) {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
}
}; };
auto defaultActiveOrPresentSlot = [&]() -> int { auto defaultActiveOrPresentSlot = [&]() -> int {
@@ -1222,13 +1239,7 @@ int runModemApp(int argc, char** argv) {
}; };
auto grabKeys = [&]() { auto grabKeys = [&]() {
for (int i = 0; i < 6; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(15000);
}
}; };
auto showWindow = [&](const std::string& arg = "") { auto showWindow = [&](const std::string& arg = "") {
@@ -1236,21 +1247,28 @@ int runModemApp(int argc, char** argv) {
if (visible && if (visible &&
(modal == ModalMode::VerifyPin || modal == ModalMode::UnblockPuk) && (modal == ModalMode::VerifyPin || modal == ModalMode::UnblockPuk) &&
(a == "unlock" || a == "pin" || a == "puk")) { (a == "unlock" || a == "pin" || a == "puk")) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("modem");
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
grabKeys(); grabKeys();
render(); render();
return; return;
} }
closeOtherPlugins("modem");
refreshData(true);
applyOpenArg(arg);
writeIntFile(activePidPath, static_cast<int>(::getpid())); writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("modem");
if (!visible) { if (!visible) {
XMapRaised(dpy, win); XMapRaised(dpy, win);
visible = true; visible = true;
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
grabKeys();
render();
refreshData(true);
applyOpenArg(arg);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("modem");
XRaiseWindow(dpy, win);
openStartMs = nowMs(); openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180; startupIgnoreUntilMs = openStartMs + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -1446,6 +1464,10 @@ int runModemApp(int argc, char** argv) {
if (ussdWaitingReply) { if (ussdWaitingReply) {
ussdInput.clear(); ussdInput.clear();
} }
if (visible) {
XRaiseWindow(dpy, win);
grabKeys();
}
} }
}; };
@@ -1693,7 +1715,13 @@ int runModemApp(int argc, char** argv) {
render(); render();
} else if (ev.type == VisibilityNotify && visible && } else if (ev.type == VisibilityNotify && visible &&
ev.xvisibility.state != VisibilityUnobscured) { ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("modem")) {
hideWindow();
} else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
grabKeys();
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) { if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
initialSoftkeysReleased = true; initialSoftkeysReleased = true;
@@ -2033,14 +2061,14 @@ int runModemApp(int argc, char** argv) {
timeoutMs = static_cast<int>(bRem); timeoutMs = static_cast<int>(bRem);
} }
} }
// Periodic 5-second status refresh while visible on SIM/Radio tabs // Periodic 10-second status refresh while visible on SIM/Radio tabs
if (modal == ModalMode::None && activeTab != TabId::ModemLog && if (modal == ModalMode::None && activeTab != TabId::ModemLog &&
activeTab != TabId::AtConsole) { activeTab != TabId::AtConsole) {
int64_t rRem = (lastRefreshMs + 5000) - now; int64_t rRem = (lastRefreshMs + 10000) - now;
if (rRem <= 0) { if (rRem <= 0) {
refreshData(false); refreshData(false);
render(); render();
rRem = 5000; rRem = 10000;
} }
if (timeoutMs < 0 || rRem < timeoutMs) { if (timeoutMs < 0 || rRem < timeoutMs) {
timeoutMs = static_cast<int>(rRem); timeoutMs = static_cast<int>(rRem);
+14 -9
View File
@@ -923,25 +923,24 @@ int runNetworksApp(int argc, char** argv) {
}; };
auto grabKeys = [&]() { auto grabKeys = [&]() {
for (int i = 0; i < 6; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(15000);
}
}; };
auto showWindow = [&](const std::string& arg = "") { auto showWindow = [&](const std::string& arg = "") {
closeOtherPlugins("networks");
applyOpenArg(arg);
writeIntFile(activePidPath, static_cast<int>(::getpid())); writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("networks");
if (!visible) { if (!visible) {
XMapRaised(dpy, win); XMapRaised(dpy, win);
visible = true; visible = true;
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
grabKeys();
render();
applyOpenArg(arg);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("networks");
XRaiseWindow(dpy, win);
openStartMs = nowMs(); openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180; startupIgnoreUntilMs = openStartMs + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -1256,7 +1255,13 @@ int runNetworksApp(int argc, char** argv) {
render(); render();
} else if (ev.type == VisibilityNotify && visible && } else if (ev.type == VisibilityNotify && visible &&
ev.xvisibility.state != VisibilityUnobscured) { ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("networks")) {
hideWindow();
} else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
grabKeys();
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) { if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
initialSoftkeysReleased = true; initialSoftkeysReleased = true;
+61 -1
View File
@@ -26,6 +26,7 @@
#include <string> #include <string>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
@@ -339,6 +340,7 @@ inline bool isKeycodeDown(Display* d, int keycode) {
inline void runAsyncCmd(const std::string& cmd) { inline void runAsyncCmd(const std::string& cmd) {
pid_t pid = ::fork(); pid_t pid = ::fork();
if (pid == 0) { if (pid == 0) {
if (::fork() == 0) {
::setsid(); ::setsid();
int nullfd = ::open("/dev/null", O_RDWR); int nullfd = ::open("/dev/null", O_RDWR);
if (nullfd >= 0) { if (nullfd >= 0) {
@@ -352,6 +354,11 @@ inline void runAsyncCmd(const std::string& cmd) {
execl("/bin/sh", "sh", "-c", cmd.c_str(), static_cast<char*>(nullptr)); execl("/bin/sh", "sh", "-c", cmd.c_str(), static_cast<char*>(nullptr));
_exit(0); _exit(0);
} }
_exit(0);
} else if (pid > 0) {
int st = 0;
(void)::waitpid(pid, &st, 0);
}
} }
inline std::string shellQuote(const std::string& s) { inline std::string shellQuote(const std::string& s) {
@@ -393,6 +400,7 @@ inline void runAsyncArgv(const char* prog,
const char* arg3 = nullptr) { const char* arg3 = nullptr) {
pid_t pid = ::fork(); pid_t pid = ::fork();
if (pid == 0) { if (pid == 0) {
if (::fork() == 0) {
::setsid(); ::setsid();
int nullfd = ::open("/dev/null", O_RDWR); int nullfd = ::open("/dev/null", O_RDWR);
if (nullfd >= 0) { if (nullfd >= 0) {
@@ -430,6 +438,11 @@ inline void runAsyncArgv(const char* prog,
} }
_exit(0); _exit(0);
} }
_exit(0);
} else if (pid > 0) {
int st = 0;
(void)::waitpid(pid, &st, 0);
}
} }
inline char mapDialKey(KeySym sym, unsigned int keycode, unsigned int state) { inline char mapDialKey(KeySym sym, unsigned int keycode, unsigned int state) {
@@ -1152,11 +1165,58 @@ inline void closeOtherPlugins(const char* selfPluginName) {
sendPluginCommand(p.name, "CLOSE"); sendPluginCommand(p.name, "CLOSE");
} }
} }
if (::access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0) { if ((!selfPluginName || std::strcmp(selfPluginName, "dmenu") != 0) &&
::access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0) {
sendPluginCommand("dmenu", "CLOSE"); sendPluginCommand("dmenu", "CLOSE");
} }
} }
inline bool isAnotherPluginActive(const char* selfPluginName) {
struct PluginRef {
const char* pidFile;
const char* name;
};
static const PluginRef kAllPlugins[] = {
{"xdrawer.pid", "xdrawer"},
{"xdialer.pid", "dialer"},
{"xcalllog.pid", "calllog"},
{"xcallscreen.pid", "callscreen"},
{"xcontacts.pid", "contacts"},
{"xsms.pid", "sms"},
{"xfiles.pid", "files"},
{"xcamera.pid", "camera"},
{"xthemes.pid", "themes"},
{"xmodem.pid", "modem"},
{"xnetworks.pid", "networks"},
{"xringtones.pid", "ringtones"},
{"xwallpapers.pid", "wallpapers"},
};
for (const auto& p : kAllPlugins) {
if (selfPluginName && std::strcmp(p.name, selfPluginName) == 0) {
continue;
}
if (isPidFileAlive(getRuntimeFile(p.pidFile))) {
return true;
}
}
if ((!selfPluginName || std::strcmp(selfPluginName, "dmenu") != 0) &&
::access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0) {
return true;
}
return false;
}
inline void grabPluginKeyboard(Display* dpy, Window win) {
for (int i = 0; i < 40; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
::usleep(3000);
}
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
}
inline void broadcastThemeReload(const char* selfPluginName = nullptr) { inline void broadcastThemeReload(const char* selfPluginName = nullptr) {
static const char* kPlugins[] = { static const char* kPlugins[] = {
"dmenu", "dmenu",
+8 -9
View File
@@ -576,6 +576,7 @@ int runRingtonesApp(int argc, char** argv) {
}; };
auto showWindow = [&]() { auto showWindow = [&]() {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("ringtones"); closeOtherPlugins("ringtones");
refreshData(); refreshData();
for (size_t i = 0; i < tones.size(); ++i) { for (size_t i = 0; i < tones.size(); ++i) {
@@ -584,7 +585,6 @@ int runRingtonesApp(int argc, char** argv) {
break; break;
} }
} }
writeIntFile(activePidPath, static_cast<int>(::getpid()));
if (!visible) { if (!visible) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
@@ -592,14 +592,7 @@ int runRingtonesApp(int argc, char** argv) {
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
for (int i = 0; i < 20; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(2000);
}
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
startupIgnoreUntilMs = nowMs() + 180; startupIgnoreUntilMs = nowMs() + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
softkeyPending = 0; softkeyPending = 0;
@@ -688,7 +681,13 @@ int runRingtonesApp(int argc, char** argv) {
render(); render();
} else if (ev.type == VisibilityNotify && visible && } else if (ev.type == VisibilityNotify && visible &&
ev.xvisibility.state != VisibilityUnobscured) { ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("ringtones")) {
hideWindow();
} else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) { if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
initialSoftkeysReleased = true; initialSoftkeysReleased = true;
+11 -9
View File
@@ -862,6 +862,7 @@ int runSmsApp(int argc, char** argv) {
}; };
auto showWindow = [&](const std::string& argStr) { auto showWindow = [&](const std::string& argStr) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("sms"); closeOtherPlugins("sms");
reloadAllData(true); reloadAllData(true);
lastTapDigit = -1; lastTapDigit = -1;
@@ -881,21 +882,13 @@ int runSmsApp(int argc, char** argv) {
selectedThread = 0; selectedThread = 0;
} }
writeIntFile(activePidPath, static_cast<int>(::getpid()));
if (!visible) { if (!visible) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
for (int i = 0; i < 20; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(2000);
}
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime); grabPluginKeyboard(dpy, win);
openStartMs = nowMs(); openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180; startupIgnoreUntilMs = openStartMs + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -1117,6 +1110,15 @@ int runSmsApp(int argc, char** argv) {
if (ev.type == Expose && ev.xexpose.count == 0) { if (ev.type == Expose && ev.xexpose.count == 0) {
drawUI(); drawUI();
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("sms")) {
hideWindow();
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
drawUI();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
unsigned int kc = ev.xkey.keycode; unsigned int kc = ev.xkey.keycode;
KeySym sym = XLookupKeysym(&ev.xkey, 0); KeySym sym = XLookupKeysym(&ev.xkey, 0);
+11 -9
View File
@@ -871,24 +871,17 @@ int runThemesApp(int argc, char** argv) {
}; };
auto showWindow = [&](const std::string& argStr) { auto showWindow = [&](const std::string& argStr) {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("themes"); closeOtherPlugins("themes");
mode = ViewMode::Browser; mode = ViewMode::Browser;
refreshThemes(argStr); refreshThemes(argStr);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
if (!visible) { if (!visible) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
for (int i = 0; i < 20; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(2000);
}
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime); grabPluginKeyboard(dpy, win);
openStartMs = nowMs(); openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180; startupIgnoreUntilMs = openStartMs + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -1132,6 +1125,15 @@ int runThemesApp(int argc, char** argv) {
if (ev.type == Expose && ev.xexpose.count == 0) { if (ev.type == Expose && ev.xexpose.count == 0) {
drawUI(); drawUI();
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("themes")) {
hideWindow();
} else {
XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
drawUI();
}
} else if (ev.type == KeyPress) { } else if (ev.type == KeyPress) {
int64_t tNow = nowMs(); int64_t tNow = nowMs();
unsigned int kc = ev.xkey.keycode; unsigned int kc = ev.xkey.keycode;
+8 -9
View File
@@ -504,6 +504,7 @@ int runWallpapersApp(int argc, char** argv) {
}; };
auto showWindow = [&]() { auto showWindow = [&]() {
writeIntFile(activePidPath, static_cast<int>(::getpid()));
closeOtherPlugins("wallpapers"); closeOtherPlugins("wallpapers");
fullscreenPreview = false; fullscreenPreview = false;
refreshData(); refreshData();
@@ -514,7 +515,6 @@ int runWallpapersApp(int argc, char** argv) {
} }
} }
updatePreviewCache(); updatePreviewCache();
writeIntFile(activePidPath, static_cast<int>(::getpid()));
if (!visible) { if (!visible) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
@@ -522,14 +522,7 @@ int runWallpapersApp(int argc, char** argv) {
} else { } else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
} }
for (int i = 0; i < 20; ++i) { grabPluginKeyboard(dpy, win);
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync,
CurrentTime) == GrabSuccess) {
break;
}
usleep(2000);
}
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
startupIgnoreUntilMs = nowMs() + 180; startupIgnoreUntilMs = nowMs() + 180;
initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0); initialSoftkeysReleased = (querySoftkeysDown(dpy) == 0);
softkeyPending = 0; softkeyPending = 0;
@@ -583,7 +576,13 @@ int runWallpapersApp(int argc, char** argv) {
render(); render();
} else if (ev.type == VisibilityNotify && visible && } else if (ev.type == VisibilityNotify && visible &&
ev.xvisibility.state != VisibilityUnobscured) { ev.xvisibility.state != VisibilityUnobscured) {
if (isAnotherPluginActive("wallpapers")) {
hideWindow();
} else {
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
grabPluginKeyboard(dpy, win);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) { if (!initialSoftkeysReleased && querySoftkeysDown(dpy) == 0) {
initialSoftkeysReleased = true; initialSoftkeysReleased = true;
+63 -6
View File
@@ -475,19 +475,21 @@ grabfocus(void)
static void static void
grabkeyboard(void) grabkeyboard(void)
{ {
struct timespec ts = { .tv_sec = 0, .tv_nsec = 2000000 }; struct timespec ts = { .tv_sec = 0, .tv_nsec = 3000000 };
Window grabwin; Window grabwin;
int i; int i;
if (embed || managed) if (embed || managed)
return; return;
grabwin = daemon_mode ? win : DefaultRootWindow(dpy); grabwin = daemon_mode ? win : DefaultRootWindow(dpy);
for (i = 0; i < 25; i++) { for (i = 0; i < 40; i++) {
if (XGrabKeyboard(dpy, grabwin, True, GrabModeAsync, if (XGrabKeyboard(dpy, grabwin, True, GrabModeAsync,
GrabModeAsync, CurrentTime) == GrabSuccess) GrabModeAsync, CurrentTime) == GrabSuccess)
return; break;
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
} }
if (win)
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
} }
static void static void
@@ -2385,6 +2387,46 @@ open_builtin_menu(const char *menu_name, int keep_idx)
show_menu(); show_menu();
} }
static int
any_other_plugin_active(void)
{
static const char *pid_files[] = {
"xdrawer.pid",
"xdialer.pid",
"xcalllog.pid",
"xcallscreen.pid",
"xcontacts.pid",
"xsms.pid",
"xfiles.pid",
"xcamera.pid",
"xthemes.pid",
"xmodem.pid",
"xnetworks.pid",
"xringtones.pid",
"xwallpapers.pid",
};
const char *rdir = getenv("XDG_RUNTIME_DIR");
const char *base = (rdir && rdir[0]) ? rdir : "/run/user/10000";
for (size_t i = 0; i < LENGTH(pid_files); i++) {
char ppath[256];
snprintf(ppath, sizeof(ppath), "%s/%s", base, pid_files[i]);
if (access(ppath, F_OK) != 0)
snprintf(ppath, sizeof(ppath), "/tmp/%s", pid_files[i]);
if (access(ppath, F_OK) == 0) {
FILE *pf = fopen(ppath, "r");
if (pf) {
int pid = -1;
if (fscanf(pf, "%d", &pid) == 1 && pid > 0 && kill(pid, 0) == 0) {
fclose(pf);
return 1;
}
fclose(pf);
}
}
}
return 0;
}
static void static void
close_other_active_plugins(void) close_other_active_plugins(void)
{ {
@@ -2639,6 +2681,8 @@ show_menu(void)
soft_deadline = 0; soft_deadline = 0;
if (!menu_active) { if (!menu_active) {
menu_active = 1;
mark_menu_active(1);
close_other_active_plugins(); close_other_active_plugins();
prevfocuswin = None; prevfocuswin = None;
Window fw = None; Window fw = None;
@@ -2654,8 +2698,6 @@ show_menu(void)
read_softkey_state(&init_soft_mask, &init_soft_ms); read_softkey_state(&init_soft_mask, &init_soft_ms);
start_ignore = dmenu_now_ms() + 180; start_ignore = dmenu_now_ms() + 180;
initial_released = (query_trigger_keys_down() == 0); initial_released = (query_trigger_keys_down() == 0);
menu_active = 1;
mark_menu_active(1);
drawmenu(); drawmenu();
XMapRaised(dpy, win); XMapRaised(dpy, win);
drawmenu(); drawmenu();
@@ -2666,11 +2708,13 @@ show_menu(void)
XSetICFocus(xic); XSetICFocus(xic);
XFlush(dpy); XFlush(dpy);
} else { } else {
close_other_active_plugins();
init_soft_mask = 0; init_soft_mask = 0;
init_soft_ms = 0; init_soft_ms = 0;
start_ignore = dmenu_now_ms() + 60; start_ignore = dmenu_now_ms() + 60;
initial_released = (query_trigger_keys_down() == 0); initial_released = (query_trigger_keys_down() == 0);
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
grabkeyboard();
drawmenu(); drawmenu();
if (xic && engage_ime) if (xic && engage_ime)
XSetICFocus(xic); XSetICFocus(xic);
@@ -2975,6 +3019,19 @@ process_x11_events(void)
if (ev.xexpose.count == 0 && (menu_active || !daemon_mode)) if (ev.xexpose.count == 0 && (menu_active || !daemon_mode))
drw_map(drw, win, 0, 0, mw, mh); drw_map(drw, win, 0, 0, mw, mh);
break; break;
case VisibilityNotify:
if (ev.xvisibility.state != VisibilityUnobscured &&
(menu_active || !daemon_mode)) {
if (any_other_plugin_active()) {
if (daemon_mode)
cancel_session();
} else {
XRaiseWindow(dpy, win);
grabkeyboard();
drw_map(drw, win, 0, 0, mw, mh);
}
}
break;
case FocusIn: case FocusIn:
if (menu_active || !daemon_mode) { if (menu_active || !daemon_mode) {
if (!daemon_mode && ev.xfocus.window != win) if (!daemon_mode && ev.xfocus.window != win)
@@ -3186,7 +3243,7 @@ setup(int map_immediately)
swa.override_redirect = managed ? False : True; swa.override_redirect = managed ? False : True;
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | VisibilityChangeMask;
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width,
CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
+40 -10
View File
@@ -771,12 +771,32 @@ static int xdrawer_run_main(int argc, char** argv) {
} }
}; };
auto isOtherPluginActive = [&]() {
static const char* kPids[] = {
"xdialer.pid", "xcalllog.pid", "xcallscreen.pid", "xcontacts.pid",
"xsms.pid", "xfiles.pid", "xcamera.pid", "xthemes.pid",
"xmodem.pid", "xnetworks.pid", "xringtones.pid", "xwallpapers.pid",
};
for (const char* pf : kPids) {
int p = readIntFile(getRuntimeFile(pf), -1);
if (p > 0 && ::kill(p, 0) == 0) {
return true;
}
}
if (::access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0) {
return true;
}
return false;
};
auto showWindow = [&]() { auto showWindow = [&]() {
if (visible) { if (visible) {
return; return;
} }
writeIntFile(pidPath, static_cast<int>(::getpid()));
closeOtherPlugin("xdialer.pid", "/tmp/dwm_plugin_dialer.fifo"); closeOtherPlugin("xdialer.pid", "/tmp/dwm_plugin_dialer.fifo");
closeOtherPlugin("xcalllog.pid", "/tmp/dwm_plugin_calllog.fifo"); closeOtherPlugin("xcalllog.pid", "/tmp/dwm_plugin_calllog.fifo");
closeOtherPlugin("xcallscreen.pid", "/tmp/dwm_plugin_callscreen.fifo");
closeOtherPlugin("xcontacts.pid", "/tmp/dwm_plugin_contacts.fifo"); closeOtherPlugin("xcontacts.pid", "/tmp/dwm_plugin_contacts.fifo");
closeOtherPlugin("xsms.pid", "/tmp/dwm_plugin_sms.fifo"); closeOtherPlugin("xsms.pid", "/tmp/dwm_plugin_sms.fifo");
closeOtherPlugin("xfiles.pid", "/tmp/dwm_plugin_files.fifo"); closeOtherPlugin("xfiles.pid", "/tmp/dwm_plugin_files.fifo");
@@ -786,6 +806,13 @@ static int xdrawer_run_main(int argc, char** argv) {
closeOtherPlugin("xnetworks.pid", "/tmp/dwm_plugin_networks.fifo"); closeOtherPlugin("xnetworks.pid", "/tmp/dwm_plugin_networks.fifo");
closeOtherPlugin("xringtones.pid", "/tmp/dwm_plugin_ringtones.fifo"); closeOtherPlugin("xringtones.pid", "/tmp/dwm_plugin_ringtones.fifo");
closeOtherPlugin("xwallpapers.pid", "/tmp/dwm_plugin_wallpapers.fifo"); closeOtherPlugin("xwallpapers.pid", "/tmp/dwm_plugin_wallpapers.fifo");
if (::access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0) {
int dfd = ::open("/tmp/dwm_plugin_dmenu.fifo", O_WRONLY | O_NONBLOCK | O_CLOEXEC);
if (dfd >= 0) {
(void)::write(dfd, "CLOSE\n", 6);
::close(dfd);
}
}
theme.checkAndReload(dpy, screen, visual, cmap, layoutMain, layoutSmall, theme.checkAndReload(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, nullptr, win); layoutIcon, nullptr, win);
openStartMs = nowMs(); openStartMs = nowMs();
@@ -794,24 +821,17 @@ static int xdrawer_run_main(int argc, char** argv) {
visible = true; visible = true;
XMapRaised(dpy, win); XMapRaised(dpy, win);
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0); XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
for (int i = 0; i < 20; ++i) { for (int i = 0; i < 40; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) == if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) { GrabSuccess) {
break; break;
} }
usleep(2000); usleep(3000);
} }
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
XFlush(dpy); XFlush(dpy);
writeIntFile(pidPath, static_cast<int>(::getpid()));
controller.refreshAll(); controller.refreshAll();
render(); render();
if (::access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0) {
int dfd = ::open("/tmp/dwm_plugin_dmenu.fifo", O_WRONLY | O_NONBLOCK | O_CLOEXEC);
if (dfd >= 0) {
(void)::write(dfd, "CLOSE\n", 6);
::close(dfd);
}
}
}; };
auto hideWindow = [&](bool drainSoftkeys) { auto hideWindow = [&](bool drainSoftkeys) {
@@ -889,6 +909,16 @@ static int xdrawer_run_main(int argc, char** argv) {
if (ev.xexpose.count == 0) { if (ev.xexpose.count == 0) {
render(); render();
} }
} else if (ev.type == VisibilityNotify &&
ev.xvisibility.state != VisibilityUnobscured) {
if (isOtherPluginActive()) {
hideWindow(false);
} else {
XRaiseWindow(dpy, win);
XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
render();
}
} else if (ev.type == KeyRelease) { } else if (ev.type == KeyRelease) {
KeySym sym = XLookupKeysym(&ev.xkey, 0); KeySym sym = XLookupKeysym(&ev.xkey, 0);
if (sym == XK_Menu || sym == XF86XK_KbdLcdMenu1 || if (sym == XK_Menu || sym == XF86XK_KbdLcdMenu1 ||