Skip to content

Commit f64c46e

Browse files
authored
Merge pull request #80 from open-webui/main
v0.0.3: fix spotlight focus after page interaction, fix ?q= query pas…
2 parents a230658 + 5aa13c8 commit f64c46e

4 files changed

Lines changed: 74 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.0.3] - 2026-04-06
11+
12+
### Fixed
13+
14+
- **Spotlight Focus** — Spotlight now reliably appears after interacting with the main window or webview (fixed blur-during-show race condition on macOS)
15+
- **Spotlight Query Passthrough** — The `?q=` search parameter from spotlight now correctly navigates already-open webviews instead of being silently ignored
16+
1017
## [0.0.2] - 2026-04-06
1118

1219
### Added

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "open-webui",
3-
"version": "0.0.2",
3+
"version": "0.0.3",
44
"license": "AGPL-3.0",
55
"description": "Open WebUI Desktop",
66
"main": "./out/main/index.js",

src/main/index.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ function createSpotlightWindow(): BrowserWindow {
180180
resizable: false,
181181
hasShadow: false,
182182
show: false,
183+
focusable: true,
183184
icon: path.join(__dirname, 'assets/icon.png'),
184185
webPreferences: {
185186
preload: join(__dirname, '../preload/spotlight-preload.js'),
@@ -206,8 +207,21 @@ function createSpotlightWindow(): BrowserWindow {
206207
}
207208
})
208209

210+
// Hide on blur — but only when the window was truly visible and settled.
211+
// Without the guard the blur fires during the show→focus transition and
212+
// the window disappears immediately (especially when the user had been
213+
// interacting with the main window / webview).
214+
let blurArmed = false
215+
spotlightWindow.on('focus', () => {
216+
blurArmed = false
217+
setTimeout(() => {
218+
blurArmed = true
219+
}, 200)
220+
})
209221
spotlightWindow.on('blur', () => {
210-
spotlightWindow?.hide()
222+
if (blurArmed) {
223+
spotlightWindow?.hide()
224+
}
211225
})
212226

213227
spotlightWindow.on('closed', () => {
@@ -217,26 +231,42 @@ function createSpotlightWindow(): BrowserWindow {
217231
return spotlightWindow
218232
}
219233

234+
function showAndFocusSpotlight(win: BrowserWindow): void {
235+
// On macOS the app may not be the "active" application when the global
236+
// shortcut fires (e.g. user clicked into a webview which is a separate
237+
// render process). Calling app.focus() first ensures macOS brings the
238+
// app to the foreground so the subsequent window.focus() actually works.
239+
if (process.platform === 'darwin') {
240+
app.focus({ steal: true })
241+
}
242+
243+
// Restore to saved position, or default if none saved
244+
if (spotlightPosition) {
245+
win.setPosition(spotlightPosition.x, spotlightPosition.y)
246+
} else {
247+
const pos = getDefaultSpotlightPosition()
248+
win.setPosition(pos.x, pos.y)
249+
}
250+
251+
win.show()
252+
win.focus()
253+
254+
// Tell the renderer to focus the input field (belt-and-suspenders —
255+
// the renderer also listens for the 'focus' window event)
256+
win.webContents.focus()
257+
}
258+
220259
function toggleSpotlight(): void {
221260
if (spotlightWindow && !spotlightWindow.isDestroyed()) {
222261
if (spotlightWindow.isVisible()) {
223262
spotlightWindow.hide()
224263
} else {
225-
// Restore to saved position, or default if none saved
226-
if (spotlightPosition) {
227-
spotlightWindow.setPosition(spotlightPosition.x, spotlightPosition.y)
228-
} else {
229-
const pos = getDefaultSpotlightPosition()
230-
spotlightWindow.setPosition(pos.x, pos.y)
231-
}
232-
spotlightWindow.show()
233-
spotlightWindow.focus()
264+
showAndFocusSpotlight(spotlightWindow)
234265
}
235266
} else {
236267
const win = createSpotlightWindow()
237268
win.once('ready-to-show', () => {
238-
win.show()
239-
win.focus()
269+
showAndFocusSpotlight(win)
240270
})
241271
}
242272
}

src/renderer/src/lib/components/Main/Connections.svelte

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,32 @@
306306
window.electronAPI.onData((data: any) => {
307307
if (data.type === 'connection:open' && data.data?.url) {
308308
const connId = data.data.connectionId ?? ''
309-
openConnections.set(connId, data.data.url)
309+
const incomingUrl = data.data.url
310+
const alreadyOpen = openConnections.has(connId)
311+
312+
openConnections.set(connId, incomingUrl)
310313
openConnections = new Map(openConnections)
311-
connectedUrl = data.data.url
314+
connectedUrl = incomingUrl
312315
activeConnectionId = connId
316+
317+
// If the webview for this connection already exists in the DOM,
318+
// updating the map value won't cause it to re-navigate (Electron
319+
// webview `src` changes on an existing element are ignored). We
320+
// need to explicitly call loadURL so that e.g. the spotlight ?q=
321+
// parameter actually reaches the Open WebUI instance.
322+
if (alreadyOpen) {
323+
requestAnimationFrame(() => {
324+
const container = document.querySelector('.content-webview-container')
325+
if (!container) return
326+
const wv = container.querySelector(
327+
`webview[partition="persist:connection-${connId}"]`
328+
) as any
329+
if (wv?.loadURL) {
330+
wv.loadURL(incomingUrl)
331+
}
332+
})
333+
}
334+
313335
// Don't switch to connected view during active install — the install
314336
// flow handles its own transition after confirming reachability.
315337
if (installPhase !== 'working') {

0 commit comments

Comments
 (0)