feat: add Linux inotify real-time kernel watching for instant app install/uninstall detection
This commit is contained in:
parent
6520f54ee9
commit
9c628e28ec
@ -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(() => {
|
||||||
|
|||||||
@ -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,21 +283,33 @@ 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:
|
||||||
line = sys.stdin.readline()
|
for fd in rlist:
|
||||||
if line:
|
if fd == sys.stdin:
|
||||||
parse_desktop_apps()
|
line = sys.stdin.readline()
|
||||||
last_snapshot = get_state_snapshot()
|
if line:
|
||||||
continue
|
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()
|
current_snapshot = get_state_snapshot()
|
||||||
if current_snapshot != last_snapshot:
|
if current_snapshot != last_snapshot:
|
||||||
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()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user