diff --git a/overlay/rootfs/usr/bin/dwm b/overlay/rootfs/usr/bin/dwm index 9ff0292..dc13feb 100755 Binary files a/overlay/rootfs/usr/bin/dwm and b/overlay/rootfs/usr/bin/dwm differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/calllog.so b/overlay/rootfs/usr/lib/dwm/plugins/calllog.so index b23e9c2..898be8b 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/calllog.so and b/overlay/rootfs/usr/lib/dwm/plugins/calllog.so differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/camera.so b/overlay/rootfs/usr/lib/dwm/plugins/camera.so index d7a25d1..b9776cf 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/camera.so and b/overlay/rootfs/usr/lib/dwm/plugins/camera.so differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/contacts.so b/overlay/rootfs/usr/lib/dwm/plugins/contacts.so index c18f7d8..9bb360d 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/contacts.so and b/overlay/rootfs/usr/lib/dwm/plugins/contacts.so differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/dialer.so b/overlay/rootfs/usr/lib/dwm/plugins/dialer.so index 1351e51..33d921f 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/dialer.so and b/overlay/rootfs/usr/lib/dwm/plugins/dialer.so differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/files.so b/overlay/rootfs/usr/lib/dwm/plugins/files.so index 4cb49c6..28d8412 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/files.so and b/overlay/rootfs/usr/lib/dwm/plugins/files.so differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/sms.so b/overlay/rootfs/usr/lib/dwm/plugins/sms.so index 05ef3fb..0b1bf27 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/sms.so and b/overlay/rootfs/usr/lib/dwm/plugins/sms.so differ diff --git a/overlay/rootfs/usr/lib/dwm/plugins/xdrawer.so b/overlay/rootfs/usr/lib/dwm/plugins/xdrawer.so index 28a775c..a81842c 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/xdrawer.so and b/overlay/rootfs/usr/lib/dwm/plugins/xdrawer.so differ diff --git a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko index 64afdf5..e9283f7 100644 Binary files a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko and b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko differ diff --git a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst index 9d4df1c..d8f8229 100644 Binary files a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst and b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst differ diff --git a/prebuilt/sxmo-x11/usr/bin/dwm b/prebuilt/sxmo-x11/usr/bin/dwm index 9ff0292..dc13feb 100755 Binary files a/prebuilt/sxmo-x11/usr/bin/dwm and b/prebuilt/sxmo-x11/usr/bin/dwm differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/calllog.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/calllog.so index b23e9c2..898be8b 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/calllog.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/calllog.so differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so index d7a25d1..b9776cf 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/contacts.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/contacts.so index c18f7d8..9bb360d 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/contacts.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/contacts.so differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dialer.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dialer.so index 1351e51..33d921f 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dialer.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dialer.so differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/files.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/files.so index 4cb49c6..28d8412 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/files.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/files.so differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/sms.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/sms.so index 05ef3fb..0b1bf27 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/sms.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/sms.so differ diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/xdrawer.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/xdrawer.so index 28a775c..a81842c 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/xdrawer.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/xdrawer.so differ diff --git a/src/dwm-plugins/camera_plugin.cpp b/src/dwm-plugins/camera_plugin.cpp index b06f766..516e5a4 100644 --- a/src/dwm-plugins/camera_plugin.cpp +++ b/src/dwm-plugins/camera_plugin.cpp @@ -161,9 +161,7 @@ int runCameraApp(int argc, char** argv) { std::string daemonPidPath = getPluginDaemonPidPath("camera"); std::string activePidPath = getRuntimeFile("xcamera.pid"); - int existingDaemon = readIntFile(daemonPidPath, -1); - if (existingDaemon > 0 && existingDaemon != static_cast(::getpid()) && - ::kill(existingDaemon, 0) == 0) { + if (isPluginDaemonAlive("camera")) { if (!isPreload) { sendPluginCommand("camera", initArg.empty() ? "OPEN" : ("OPEN " + initArg)); @@ -422,6 +420,7 @@ int runCameraApp(int argc, char** argv) { { std::lock_guard lk(frameMutex); vfFront.swap(vfBack); + xImgVf->data = reinterpret_cast(vfFront.data()); cameraReady = true; cameraStatus.clear(); if (!savedName.empty()) { @@ -434,8 +433,12 @@ int runCameraApp(int argc, char** argv) { char c = 'F'; (void)::write(writePipe, &c, 1); } + for (int s = 0; s < 5 && !vfShouldStop && gRunning && !snapRequested.load(); ++s) { + struct timespec ts {0, 20 * 1000 * 1000}; + nanosleep(&ts, nullptr); + } } else { - struct timespec ts {0, 30 * 1000 * 1000}; + struct timespec ts {0, 50 * 1000 * 1000}; nanosleep(&ts, nullptr); } } diff --git a/src/dwm-plugins/contacts_plugin.cpp b/src/dwm-plugins/contacts_plugin.cpp index d35edea..6222b31 100644 --- a/src/dwm-plugins/contacts_plugin.cpp +++ b/src/dwm-plugins/contacts_plugin.cpp @@ -72,9 +72,7 @@ int runContactsApp(int argc, char** argv) { std::string daemonPidPath = getPluginDaemonPidPath("contacts"); std::string activePidPath = getRuntimeFile("xcontacts.pid"); - int existingDaemon = readIntFile(daemonPidPath, -1); - if (existingDaemon > 0 && existingDaemon != static_cast(::getpid()) && - ::kill(existingDaemon, 0) == 0) { + if (isPluginDaemonAlive("contacts")) { if (!isPreload) { sendPluginCommand("contacts", initArg.empty() ? "OPEN" : ("OPEN " + initArg)); diff --git a/src/dwm-plugins/files_plugin.cpp b/src/dwm-plugins/files_plugin.cpp index 9d29ba2..80e40e1 100644 --- a/src/dwm-plugins/files_plugin.cpp +++ b/src/dwm-plugins/files_plugin.cpp @@ -208,9 +208,7 @@ int runFilesApp(int argc, char** argv) { std::string daemonPidPath = getPluginDaemonPidPath("files"); std::string activePidPath = getRuntimeFile("xfiles.pid"); - int existingDaemon = readIntFile(daemonPidPath, -1); - if (existingDaemon > 0 && existingDaemon != static_cast(::getpid()) && - ::kill(existingDaemon, 0) == 0) { + if (isPluginDaemonAlive("files")) { if (!isPreload) { sendPluginCommand("files", initDir.empty() ? "OPEN" : ("OPEN " + initDir)); } diff --git a/src/dwm-plugins/phone_data.h b/src/dwm-plugins/phone_data.h index e2b1505..d7a0f20 100644 --- a/src/dwm-plugins/phone_data.h +++ b/src/dwm-plugins/phone_data.h @@ -125,11 +125,40 @@ inline std::string getPluginDaemonPidPath(const char* name) { return std::string("/tmp/dwm_plugin_") + name + ".pid"; } -inline bool sendPluginCommand(const char* name, const std::string& cmdLine) { +inline bool isPluginDaemonAlive(const char* name) { + if (!name || !name[0]) { + return false; + } int pid = readIntFile(getPluginDaemonPidPath(name), -1); if (pid <= 0 || pid == static_cast(::getpid()) || ::kill(pid, 0) != 0) { return false; } + char cmdPath[64]; + std::snprintf(cmdPath, sizeof(cmdPath), "/proc/%d/cmdline", pid); + int fd = ::open(cmdPath, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return false; + } + char buf[256]; + ssize_t n = ::read(fd, buf, sizeof(buf) - 1); + ::close(fd); + if (n <= 0) { + return false; + } + for (ssize_t i = 0; i < n; ++i) { + if (buf[i] == '\0') { + buf[i] = ' '; + } + } + buf[n] = '\0'; + return (std::strstr(buf, "dwm-plugin") != nullptr && + std::strstr(buf, name) != nullptr); +} + +inline bool sendPluginCommand(const char* name, const std::string& cmdLine) { + if (!isPluginDaemonAlive(name)) { + return false; + } std::string fifoPath = getPluginFifoPath(name); int fd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC); if (fd < 0) { diff --git a/src/dwm-plugins/sms_plugin.cpp b/src/dwm-plugins/sms_plugin.cpp index 312bd0a..956cf7e 100644 --- a/src/dwm-plugins/sms_plugin.cpp +++ b/src/dwm-plugins/sms_plugin.cpp @@ -94,9 +94,7 @@ int runSmsApp(int argc, char** argv) { std::string daemonPidPath = getPluginDaemonPidPath("sms"); std::string activePidPath = getRuntimeFile("xsms.pid"); - int existingDaemon = readIntFile(daemonPidPath, -1); - if (existingDaemon > 0 && existingDaemon != static_cast(::getpid()) && - ::kill(existingDaemon, 0) == 0) { + if (isPluginDaemonAlive("sms")) { if (!isPreload) { sendPluginCommand("sms", initArg.empty() ? "OPEN" : ("OPEN " + initArg)); } @@ -767,11 +765,16 @@ int runSmsApp(int argc, char** argv) { drawPango(layoutMain, &colYellow, 146, 234, 30, "Draft", 84); if (composeField == 0) { - drawSoftkeyBar("Contacts", "Next", + drawSoftkeyBar("Contacts", + composeRecipient.empty() ? "Contacts" : "Next", composeRecipient.empty() ? "Cancel" : "Clear"); - } else { + } else if (composeField == 1) { drawSoftkeyBar("Send", "Send", composeText.empty() ? "Cancel" : "Del"); + } else if (composeField == 2) { + drawSoftkeyBar("Send", "Send", "Cancel"); + } else { + drawSoftkeyBar("Send", "Draft", "Cancel"); } } else if (mode == ViewMode::PickContact) { diff --git a/src/msm8905-cam/msm8905-cam.c b/src/msm8905-cam/msm8905-cam.c index b68b259..64e07d4 100644 --- a/src/msm8905-cam/msm8905-cam.c +++ b/src/msm8905-cam/msm8905-cam.c @@ -81,7 +81,7 @@ static const struct gc2395_reg gc2395_init_regs[] = { { 0xf4, 0x03 }, { 0xf7, 0x01 }, { 0xf8, 0x28 }, { 0xf9, 0x02 }, { 0xfa, 0x08 }, { 0xfc, 0x8e }, { 0xe7, 0xcc }, { 0x88, 0x03 }, { 0x03, 0x04 }, { 0x04, 0x80 }, { 0x05, 0x02 }, { 0x06, 0x86 }, - { 0x07, 0x00 }, { 0x08, 0x20 }, { 0x09, 0x00 }, { 0x0a, 0x04 }, + { 0x07, 0x02 }, { 0x08, 0x00 }, { 0x09, 0x00 }, { 0x0a, 0x04 }, { 0x0b, 0x00 }, { 0x0c, 0x02 }, { 0x17, 0xd7 }, { 0x18, 0x02 }, { 0x19, 0x17 }, { 0x1c, 0x18 }, { 0x20, 0x73 }, { 0x22, 0xa2 }, { 0x21, 0x38 }, { 0x29, 0x20 }, { 0x2f, 0x14 }, { 0x3f, 0x40 }, @@ -314,14 +314,35 @@ static void gc2395_write_reg(struct msm8905_cam_dev *cam, u8 reg, u8 val) cam_i2c_stop(cam); } +static void msm8905_cam_enable_clocks(struct msm8905_cam_dev *cam) +{ + size_t i; + + if (cam_r32(cam->gcc_base, 0x58034U) & 1U) { + cam_w32(cam->gcc_base, 0x58034U, cam_r32(cam->gcc_base, 0x58034U) & ~1U); + usleep_range(1000, 2000); + } + if ((cam_r32(cam->gcc_base, 0x4500cU) & 0x3202U) != 0x3202U) { + cam_w32(cam->gcc_base, 0x4500cU, cam_r32(cam->gcc_base, 0x4500cU) | 0x3202U); + usleep_range(1000, 2000); + } + for (i = 0; i < ARRAY_SIZE(camss_cbcr_offsets); i++) { + if ((cam_r32(cam->gcc_base, camss_cbcr_offsets[i]) & 1U) == 0U || + (cam_r32(cam->gcc_base, camss_cbcr_offsets[i]) & 0x80000000U) != 0U) + cam_enable_cbcr(cam, camss_cbcr_offsets[i]); + } +} + static int msm8905_cam_hw_init(struct msm8905_cam_dev *cam) { size_t i; u16 chip_id; u32 r; - if (cam->hw_initialized) + if (cam->hw_initialized) { + msm8905_cam_enable_clocks(cam); return 0; + } /* 1. Ensure PM8909 LDO6 (1.8V) and LDO17 (2.85V) are enabled */ if (cam->usid1_regmap) { @@ -498,11 +519,16 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb) ret = msm8905_cam_hw_init(cam); if (ret) return ret; + } else { + msm8905_cam_enable_clocks(cam); } - /* Ensure GC2395 stream and VFE0 WM0/RDI0 are idle before resetting ISPIF */ + /* Ensure GC2395 stream and ISPIF/VFE0 are idle before arming next frame */ + cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU); + wmb(); gc2395_write_reg(cam, 0xfeU, 0x00U); gc2395_write_reg(cam, 0xedU, 0x00U); + usleep_range(600, 900); cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U); cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U); wmb(); @@ -538,7 +564,7 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb) cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U); cam_w32(cam->camss_base, VFE0_BASE + 0x260U, 0x00000002U); - /* Enable ISPIF RDI0 CID0 on frame boundary and start GC2395 MIPI stream */ + /* Enable ISPIF RDI0 on frame boundary and start GC2395 MIPI stream */ cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xfffffdffU); wmb(); @@ -546,30 +572,40 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb) gc2395_write_reg(cam, 0xedU, 0x90U); gc2395_write_reg(cam, 0xfeU, 0x00U); - /* Wait for WM0 PING_PONG_IRQ (bit 6 = 0x40) */ + /* + * Poll for WM0 PING_PONG_IRQ (bit 6 = 0x40) with sub-millisecond sleep so we + * catch EOF right inside the 14 ms vertical blanking window before Frame 2. + */ irq0 = 0; - for (poll_cnt = 0; poll_cnt < 150; poll_cnt++) { + for (poll_cnt = 0; poll_cnt < 400; poll_cnt++) { irq0 = cam_r32(cam->camss_base, VFE0_BASE + 0x02cU); if (irq0 & 0x00000040U) break; - usleep_range(2000, 3000); + usleep_range(400, 600); } - /* Stop GC2395 stream, WM0, and RDI0 cleanly */ + /* + * 1. Gate ISPIF at frame boundary FIRST so VFE0 never receives a partial frame. + * 2. Stop GC2395 MIPI stream during VBLANK (LP-11 state). + * 3. Wait for VFE0 WM0 / VBIF AXI write bursts to drain completely before + * clearing WM0_CFG and RDI0_CFG. + */ + cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU); + wmb(); gc2395_write_reg(cam, 0xfeU, 0x00U); gc2395_write_reg(cam, 0xedU, 0x00U); + usleep_range(800, 1200); cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U); cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U); cam_w32(cam->camss_base, VFE0_BASE + 0x024U, 0xffffffffU); cam_w32(cam->camss_base, VFE0_BASE + 0x028U, 0xffffffffU); cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U); - cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U); - usleep_range(500, 1000); - cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U); wmb(); - if (!(irq0 & 0x00000040U)) + if (!(irq0 & 0x00000040U)) { + cam->hw_initialized = false; return -ETIMEDOUT; + } msm8905_cam_demosaic(cam->raw_dma_buf, dst_rgb); cam->sequence++; diff --git a/src/sxmo-dwm/dwm.c b/src/sxmo-dwm/dwm.c index 3943b38..c0fe7cf 100644 --- a/src/sxmo-dwm/dwm.c +++ b/src/sxmo-dwm/dwm.c @@ -1537,8 +1537,15 @@ static long long read_softkey_suppress(void) { char buf[32]; + long long now = dwm_now_ms(); + if (softkey_suppress_until_ms > now + 5000LL) + softkey_suppress_until_ms = 0; read_sysfs_str("/tmp/sxmo_softkey_suppress", buf, sizeof(buf)); long long v = atoll(buf); + if (v > now + 5000LL) { + unlink("/tmp/sxmo_softkey_suppress"); + v = 0; + } if (v > softkey_suppress_until_ms) softkey_suppress_until_ms = v; return softkey_suppress_until_ms; @@ -1610,13 +1617,30 @@ host_spawn_command(const char *const *argv) static int is_plugin_daemon_alive(const char *plugin_name) { - char pidpath[128], buf[32]; + char pidpath[128], buf[256]; snprintf(pidpath, sizeof(pidpath), "/tmp/dwm_plugin_%s.pid", plugin_name); read_sysfs_str(pidpath, buf, sizeof(buf)); int pid = atoi(buf); - return (pid > 0 && kill(pid, 0) == 0); + if (pid <= 0 || kill(pid, 0) != 0) + return 0; + snprintf(pidpath, sizeof(pidpath), "/proc/%d/cmdline", pid); + int fd = open(pidpath, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return 0; + ssize_t n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n <= 0) + return 0; + for (ssize_t i = 0; i < n; i++) { + if (buf[i] == '\0') + buf[i] = ' '; + } + buf[n] = '\0'; + return (strstr(buf, "dwm-plugin") != NULL && strstr(buf, plugin_name) != NULL); } +static int preload_stagger_idx = 0; + static void host_spawn_plugin(const char *plugin_name, const char *arg) { @@ -1625,9 +1649,15 @@ host_spawn_plugin(const char *plugin_name, const char *arg) if (arg && strcmp(arg, "--preload") == 0) { if (is_plugin_daemon_alive(plugin_name)) return; - const char *cmd[4] = { "dwm-plugin", plugin_name, "--preload", NULL }; - Arg a = { .v = cmd }; - spawn(&a); + int stagger_ms = 600 + (preload_stagger_idx++ * 220); + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + usleep((useconds_t)stagger_ms * 1000U); + execlp("dwm-plugin", "dwm-plugin", plugin_name, "--preload", (char *)NULL); + _exit(EXIT_SUCCESS); + } return; } XUngrabKeyboard(dpy, CurrentTime); @@ -2677,6 +2707,8 @@ setup(void) lidfd = open("/dev/input/by-path/platform-gpio-keys-event", O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (lidfd < 0) lidfd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK | O_CLOEXEC); + unlink("/tmp/sxmo_softkey_suppress"); + unlink("/tmp/sxmo_softkey_state"); load_plugins(); grabkeys(); focus(NULL); diff --git a/src/xdrawer/xdrawer.cpp b/src/xdrawer/xdrawer.cpp index e4db2b1..d6d33c4 100644 --- a/src/xdrawer/xdrawer.cpp +++ b/src/xdrawer/xdrawer.cpp @@ -450,8 +450,28 @@ static int xdrawer_run_main(int argc, char** argv) { std::string pidPath = getRuntimeFile("xdrawer.pid"); int existingDaemon = readIntFile(daemonPidPath, -1); + bool daemonAlive = false; if (existingDaemon > 0 && existingDaemon != static_cast(::getpid()) && ::kill(existingDaemon, 0) == 0) { + char cmdPath[64]; + std::snprintf(cmdPath, sizeof(cmdPath), "/proc/%d/cmdline", existingDaemon); + int cfd = ::open(cmdPath, O_RDONLY | O_CLOEXEC); + if (cfd >= 0) { + char cbuf[256]; + ssize_t cn = ::read(cfd, cbuf, sizeof(cbuf) - 1); + ::close(cfd); + if (cn > 0) { + for (ssize_t i = 0; i < cn; ++i) { + if (cbuf[i] == '\0') cbuf[i] = ' '; + } + cbuf[cn] = '\0'; + if (std::strstr(cbuf, "xdrawer") != nullptr) { + daemonAlive = true; + } + } + } + } + if (daemonAlive) { if (!isPreload) { int ffd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC); if (ffd >= 0) {