Browse Source

And another one?

xdw 2 months ago
parent
commit
d1abd1b446
1 changed files with 36 additions and 104 deletions
  1. 36 104
      server/index.ts

+ 36 - 104
server/index.ts

@@ -146,90 +146,30 @@ async function libreofficeWinId(): Promise<string> {
   return run("xdotool", ["search", "--name", "LibreOffice Impress"]);
 }
 
-// Navigate via UNO — separate script per action to avoid indentation issues
-function pyUnoNav(direction: "next" | "prev" | "start" | "end"): Promise<string> {
-  // Helper snippet reused in next/prev to read position after nav
-  const readPos = `
-current = 0
-controller = comp.getCurrentController()
-draw = comp.DrawPages
-total = draw.Count
-if hasattr(controller, 'getCurrentSlideIndex'):
-    current = controller.getCurrentSlideIndex() + 1
-    print(f"[nav] slideshow mode, index={current}", file=sys.stderr)
-else:
-    page = controller.getCurrentPage()
-    for i in range(draw.Count):
-        if draw.getByIndex(i) == page:
-            current = i + 1
-            break
-    print(f"[nav] editor mode, index={current}", file=sys.stderr)
-print(f"{current}/{total}")
-`;
+// Navigate via xdotool — focus the window first, then send the key.
+// This is more reliable than UNO for navigation since UNO has threading
+// issues with LibreOffice's Qt backend.
+async function xdotoolNav(key: string): Promise<void> {
+  // Search for both the editor and fullscreen slideshow window
+  const widRaw = await run("xdotool", [
+    "search", "--onlyvisible", "--name", "Impress"
+  ]).catch(() => "");
+  const wids = widRaw.split("\n").map(s => s.trim()).filter(Boolean);
+  if (!wids.length) {
+    console.warn("[xdotool] no Impress window found");
+    return;
+  }
+  // Use the last window ID — fullscreen slideshow appears last
+  const wid = wids[wids.length - 1];
+  console.log(`[xdotool] focusing wid=${wid}, sending key=${key}`);
+  await run("xdotool", ["windowactivate", "--sync", wid]);
+  await Bun.sleep(100);
+  await run("xdotool", ["key", "--clearmodifiers", key]);
+}
 
+// Navigate via UNO — used only for start/end and reading position
+function pyUnoNav(direction: "start" | "end"): Promise<string> {
   const scripts: Record<string, string> = {
-    next: `
-import sys, time
-try:
-    import uno
-    localCtx = uno.getComponentContext()
-    resolver = localCtx.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localCtx)
-    ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
-    smgr = ctx.ServiceManager
-    desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
-    comp = desktop.getCurrentComponent()
-    controller = comp.getCurrentController()
-    draw = comp.DrawPages
-    print(f"[nav] next, controller: {type(controller).__name__}", file=sys.stderr)
-    if hasattr(controller, 'gotoNextSlide'):
-        controller.gotoNextSlide()
-    else:
-        page = controller.getCurrentPage()
-        idx = 0
-        for i in range(draw.Count):
-            if draw.getByIndex(i) == page:
-                idx = i
-                break
-        next_idx = min(idx + 1, draw.Count - 1)
-        print(f"[nav] setCurrentPage {idx} -> {next_idx}", file=sys.stderr)
-        controller.setCurrentPage(draw.getByIndex(next_idx))
-    time.sleep(0.3)
-    ${readPos}
-except Exception as e:
-    import traceback; traceback.print_exc(file=sys.stderr)
-    print("0/0")
-`,
-    prev: `
-import sys, time
-try:
-    import uno
-    localCtx = uno.getComponentContext()
-    resolver = localCtx.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localCtx)
-    ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
-    smgr = ctx.ServiceManager
-    desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
-    comp = desktop.getCurrentComponent()
-    controller = comp.getCurrentController()
-    draw = comp.DrawPages
-    print(f"[nav] prev, controller: {type(controller).__name__}", file=sys.stderr)
-    if hasattr(controller, 'gotoPreviousSlide'):
-        controller.gotoPreviousSlide()
-    else:
-        page = controller.getCurrentPage()
-        idx = 0
-        for i in range(draw.Count):
-            if draw.getByIndex(i) == page:
-                idx = i
-                break
-        prev_idx = max(idx - 1, 0)
-        print(f"[nav] setCurrentPage {idx} -> {prev_idx}", file=sys.stderr)
-        controller.setCurrentPage(draw.getByIndex(prev_idx))
-    time.sleep(0.3)
-    ${readPos}
-except Exception as e:
-    import traceback; traceback.print_exc(file=sys.stderr)
-    print("0/0")
-`,
     start: `
 import sys, time
 try:
@@ -241,29 +181,21 @@ try:
     desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
     comp = desktop.getCurrentComponent()
     pres = comp.Presentation
-    print(f"[nav] starting presentation", file=sys.stderr)
+    print("[nav] starting presentation", file=sys.stderr)
     pres.start()
     time.sleep(1.5)
     controller = comp.getCurrentController()
     draw = comp.DrawPages
     total = draw.Count
-    current = 0
+    current = 1
     print(f"[nav] controller after start: {type(controller).__name__}", file=sys.stderr)
     if hasattr(controller, 'getCurrentSlideIndex'):
         current = controller.getCurrentSlideIndex() + 1
-    else:
-        try:
-            page = controller.getCurrentPage()
-            for i in range(draw.Count):
-                if draw.getByIndex(i) == page:
-                    current = i + 1
-                    break
-        except:
-            current = 1
     print(f"[nav] start -> {current}/{total}", file=sys.stderr)
     print(f"{current}/{total}")
 except Exception as e:
-    import traceback; traceback.print_exc(file=sys.stderr)
+    import traceback
+    traceback.print_exc(file=sys.stderr)
     print("0/0")
 `,
     end: `
@@ -287,27 +219,27 @@ try:
     print(f"[nav] end -> 0/{total}", file=sys.stderr)
     print(f"0/{total}")
 except Exception as e:
-    import traceback; traceback.print_exc(file=sys.stderr)
+    import traceback
+    traceback.print_exc(file=sys.stderr)
     print("0/0")
 `,
   };
-
   return pyUno(scripts[direction]);
 }
 
 const LinuxDriver: Driver = {
   async next() {
-    console.log("[linux] next: navigating via UNO");
-    const raw = await pyUnoNav("next");
-    console.log(`[linux] next raw: "${raw}"`);
-    return parseSlide(raw);
+    console.log("[linux] next: sending Right key via xdotool");
+    await xdotoolNav("Right");
+    await Bun.sleep(300);
+    return LinuxDriver.status();
   },
 
   async prev() {
-    console.log("[linux] prev: navigating via UNO");
-    const raw = await pyUnoNav("prev");
-    console.log(`[linux] prev raw: "${raw}"`);
-    return parseSlide(raw);
+    console.log("[linux] prev: sending Left key via xdotool");
+    await xdotoolNav("Left");
+    await Bun.sleep(300);
+    return LinuxDriver.status();
   },
 
   async start() {