feat: add Linux inotify real-time kernel watching for instant app install/uninstall detection

This commit is contained in:
Sho 2026-08-02 02:13:33 +09:00
parent 6520f54ee9
commit 9c628e28ec
2 changed files with 44 additions and 8 deletions

View File

@ -51,6 +51,7 @@ PanelWindow {
openProgress = 0.0
openAnim.restart()
AppLauncherService.reset()
AppLauncherService.reload()
searchField.text = ""
root.selectedIndex = 0
Qt.callLater(() => {

View File

@ -231,6 +231,8 @@ def parse_desktop_apps():
def watch_directory_changes():
import select
import ctypes
dirs = [
'/usr/share/applications',
'/usr/local/share/applications',
@ -239,6 +241,27 @@ def watch_directory_changes():
os.path.expanduser('~/.local/share/flatpak/exports/share/applications')
]
# Initialize Linux kernel inotify for 0ms instant file creation/deletion notifications
inotify_fd = -1
try:
libc = ctypes.CDLL("libc.so.6")
inotify_init = libc.inotify_init
inotify_add_watch = libc.inotify_add_watch
inotify_init.restype = ctypes.c_int
inotify_add_watch.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_uint32]
inotify_add_watch.restype = ctypes.c_int
fd = inotify_init()
if fd >= 0:
# IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO | IN_ATTRIB
mask = 0x00000100 | 0x00000200 | 0x00000002 | 0x00000040 | 0x00000080 | 0x00000004
for d in dirs:
if os.path.exists(d):
inotify_add_watch(fd, d.encode('utf-8'), mask)
inotify_fd = fd
except Exception:
inotify_fd = -1
def get_state_snapshot():
snapshot = {}
for d in dirs:
@ -260,21 +283,33 @@ def watch_directory_changes():
while True:
try:
# Check for non-blocking stdin input (reload requests from QML)
rlist, _, _ = select.select([sys.stdin], [], [], 0.5)
read_fds = [sys.stdin]
if inotify_fd >= 0:
read_fds.append(inotify_fd)
rlist, _, _ = select.select(read_fds, [], [], 0.4)
if rlist:
line = sys.stdin.readline()
if line:
parse_desktop_apps()
last_snapshot = get_state_snapshot()
continue
for fd in rlist:
if fd == sys.stdin:
line = sys.stdin.readline()
if line:
parse_desktop_apps()
last_snapshot = get_state_snapshot()
elif fd == inotify_fd:
# Flush inotify events and trigger re-parse
try:
os.read(inotify_fd, 4096)
except Exception: pass
parse_desktop_apps()
last_snapshot = get_state_snapshot()
continue
current_snapshot = get_state_snapshot()
if current_snapshot != last_snapshot:
last_snapshot = current_snapshot
parse_desktop_apps()
except Exception:
time.sleep(0.5)
time.sleep(0.4)
if __name__ == '__main__':
watch_directory_changes()