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 openProgress = 0.0
openAnim.restart() openAnim.restart()
AppLauncherService.reset() AppLauncherService.reset()
AppLauncherService.reload()
searchField.text = "" searchField.text = ""
root.selectedIndex = 0 root.selectedIndex = 0
Qt.callLater(() => { Qt.callLater(() => {

View File

@ -231,6 +231,8 @@ def parse_desktop_apps():
def watch_directory_changes(): def watch_directory_changes():
import select import select
import ctypes
dirs = [ dirs = [
'/usr/share/applications', '/usr/share/applications',
'/usr/local/share/applications', '/usr/local/share/applications',
@ -239,6 +241,27 @@ def watch_directory_changes():
os.path.expanduser('~/.local/share/flatpak/exports/share/applications') 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(): def get_state_snapshot():
snapshot = {} snapshot = {}
for d in dirs: for d in dirs:
@ -260,13 +283,25 @@ def watch_directory_changes():
while True: while True:
try: try:
# Check for non-blocking stdin input (reload requests from QML) read_fds = [sys.stdin]
rlist, _, _ = select.select([sys.stdin], [], [], 0.5) if inotify_fd >= 0:
read_fds.append(inotify_fd)
rlist, _, _ = select.select(read_fds, [], [], 0.4)
if rlist: if rlist:
for fd in rlist:
if fd == sys.stdin:
line = sys.stdin.readline() line = sys.stdin.readline()
if line: if line:
parse_desktop_apps() parse_desktop_apps()
last_snapshot = get_state_snapshot() 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 continue
current_snapshot = get_state_snapshot() current_snapshot = get_state_snapshot()
@ -274,7 +309,7 @@ def watch_directory_changes():
last_snapshot = current_snapshot last_snapshot = current_snapshot
parse_desktop_apps() parse_desktop_apps()
except Exception: except Exception:
time.sleep(0.5) time.sleep(0.4)
if __name__ == '__main__': if __name__ == '__main__':
watch_directory_changes() watch_directory_changes()