Merge feature/next: Show in folder brings Explorer to the front
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -134,7 +134,7 @@
|
||||
|
||||
### 💬 From a Bilibili comment (来自 B 站评论)
|
||||
- **Esc closes the browser (Esc 关闭浏览器)**: Esc closes what is on top: a dialog or menu first, then the Workflows / Combos workspace, then the browser. The shortcut (Ctrl + Shift + M by default) and the Extensions menu entry now close the browser when it is open. Esc in a text box still belongs to the text box.
|
||||
- **Show in folder (打开所在文件夹)**: a model's details have **Show in folder** next to **Copy path**: Explorer (or Finder) opens with the file selected. Only on the computer ComfyUI runs on.
|
||||
- **Show in folder (打开所在文件夹)**: a model's details have **Show in folder** next to **Copy path**: Explorer (or Finder) opens in front of the browser with the file selected. Only on the computer ComfyUI runs on.
|
||||
- **Insert a picture as a node (图片作为节点插入)**: right-click a gallery picture → **Insert as a Load Image node** puts a Load Image node showing that picture in the middle of the canvas. It reads the picture from the output folder; nothing is copied.
|
||||
|
||||
### ⌨️ Arrow keys in picture details (查看参数里方向键切图)
|
||||
|
||||
@@ -5,15 +5,85 @@ computer ask (it is a POST)."""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from .utils import require_filename, resolve_folder_subdir, resolve_within
|
||||
|
||||
|
||||
def _explorer_windows():
|
||||
"""Handles of the open Explorer folder windows (window class CabinetWClass)."""
|
||||
import ctypes
|
||||
from ctypes import wintypes
|
||||
|
||||
found = []
|
||||
callback_type = ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM)
|
||||
|
||||
def collect(hwnd, _):
|
||||
name = ctypes.create_unicode_buffer(64)
|
||||
ctypes.windll.user32.GetClassNameW(hwnd, name, 64)
|
||||
if name.value == "CabinetWClass":
|
||||
found.append(hwnd)
|
||||
return True
|
||||
|
||||
ctypes.windll.user32.EnumWindows(callback_type(collect), 0)
|
||||
return found
|
||||
|
||||
|
||||
def _window_title(hwnd):
|
||||
import ctypes
|
||||
|
||||
title = ctypes.create_unicode_buffer(512)
|
||||
ctypes.windll.user32.GetWindowTextW(hwnd, title, 512)
|
||||
return title.value
|
||||
|
||||
|
||||
def _to_front(hwnd):
|
||||
"""Windows keeps a background program (ComfyUI here) from raising a window; borrowing the
|
||||
foreground window's input queue for a moment lets it."""
|
||||
import ctypes
|
||||
|
||||
user32, kernel32 = ctypes.windll.user32, ctypes.windll.kernel32
|
||||
foreground = user32.GetForegroundWindow()
|
||||
theirs = user32.GetWindowThreadProcessId(foreground, None)
|
||||
mine = kernel32.GetCurrentThreadId()
|
||||
attached = theirs and theirs != mine and user32.AttachThreadInput(mine, theirs, True)
|
||||
try:
|
||||
user32.ShowWindow(hwnd, 9 if user32.IsIconic(hwnd) else 5) # SW_RESTORE / SW_SHOW
|
||||
user32.BringWindowToTop(hwnd)
|
||||
user32.SetForegroundWindow(hwnd)
|
||||
finally:
|
||||
if attached:
|
||||
user32.AttachThreadInput(mine, theirs, False)
|
||||
|
||||
|
||||
def _raise_explorer(folder, before):
|
||||
"""Waits up to 3 s for the window showing `folder` (a new one, or the open one Explorer
|
||||
reused) and brings it to the front."""
|
||||
names = (os.path.basename(folder).lower(), os.path.normcase(folder).lower())
|
||||
|
||||
def shows_folder(hwnd):
|
||||
# The folder's name (or full path), then " - File Explorer" in the system's language.
|
||||
title = _window_title(hwnd).lower()
|
||||
return any(title == name or title.startswith(name + " - ") for name in names)
|
||||
|
||||
for _ in range(30):
|
||||
time.sleep(0.1)
|
||||
windows = _explorer_windows()
|
||||
fresh = [hwnd for hwnd in windows if hwnd not in before]
|
||||
match = fresh or [hwnd for hwnd in windows if shows_folder(hwnd)]
|
||||
if match:
|
||||
_to_front(match[0])
|
||||
return
|
||||
|
||||
|
||||
def _reveal(path):
|
||||
if sys.platform == "win32":
|
||||
before = set(_explorer_windows())
|
||||
subprocess.Popen(f'explorer /select,"{path}"')
|
||||
threading.Thread(target=_raise_explorer, args=(os.path.dirname(path), before), daemon=True).start()
|
||||
elif sys.platform == "darwin":
|
||||
subprocess.Popen(["open", "-R", path])
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user