diff --git a/wox.core/setting/manager.go b/wox.core/setting/manager.go index 4bbd3ae0..ddaebc34 100644 --- a/wox.core/setting/manager.go +++ b/wox.core/setting/manager.go @@ -677,6 +677,12 @@ func (m *Manager) SavePluginSetting(ctx context.Context, pluginId string, plugin return nil } +func (m *Manager) SaveWindowPosition(ctx context.Context, x, y int) error { + m.woxSetting.LastWindowX = x + m.woxSetting.LastWindowY = y + return m.SaveWoxSetting(ctx) +} + func (m *Manager) AddQueryHistory(ctx context.Context, query common.PlainQuery) { if query.IsEmpty() { return diff --git a/wox.core/setting/wox_setting.go b/wox.core/setting/wox_setting.go index bdbe719b..3b09fb85 100644 --- a/wox.core/setting/wox_setting.go +++ b/wox.core/setting/wox_setting.go @@ -37,6 +37,10 @@ type WoxSetting struct { AppWidth int MaxResultCount int ThemeId string + + // Window position for last location mode + LastWindowX int + LastWindowY int } type LastQueryMode = string @@ -141,5 +145,7 @@ func GetDefaultWoxSetting(ctx context.Context) WoxSetting { }, EnableAutoBackup: true, EnableAutoUpdate: true, + LastWindowX: -1, // -1 indicates no saved position + LastWindowY: -1, } } diff --git a/wox.core/ui/router.go b/wox.core/ui/router.go index f26dca68..52a2492f 100644 --- a/wox.core/ui/router.go +++ b/wox.core/ui/router.go @@ -48,6 +48,7 @@ var routers = map[string]func(w http.ResponseWriter, r *http.Request){ "/setting/plugin/update": handleSettingPluginUpdate, "/setting/userdata/location": handleUserDataLocation, "/setting/userdata/location/update": handleUserDataLocationUpdate, + "/setting/position": handleSaveWindowPosition, // events "/on/focus/lost": handleOnFocusLost, @@ -593,6 +594,34 @@ func handleOpen(w http.ResponseWriter, r *http.Request) { writeSuccessResponse(w, "") } +func handleSaveWindowPosition(w http.ResponseWriter, r *http.Request) { + ctx := util.NewTraceContext() + + type positionData struct { + X int `json:"x"` + Y int `json:"y"` + } + + var pos positionData + err := json.NewDecoder(r.Body).Decode(&pos) + if err != nil { + writeErrorResponse(w, err.Error()) + return + } + + logger.Info(ctx, fmt.Sprintf("Received window position save request: x=%d, y=%d", pos.X, pos.Y)) + + saveErr := setting.GetSettingManager().SaveWindowPosition(ctx, pos.X, pos.Y) + if saveErr != nil { + logger.Error(ctx, fmt.Sprintf("Failed to save window position: %s", saveErr.Error())) + writeErrorResponse(w, saveErr.Error()) + return + } + + logger.Info(ctx, fmt.Sprintf("Window position saved successfully: x=%d, y=%d", pos.X, pos.Y)) + writeSuccessResponse(w, "") +} + func handleBackupNow(w http.ResponseWriter, r *http.Request) { backupErr := setting.GetSettingManager().Backup(util.NewTraceContext(), setting.BackupTypeManual) if backupErr != nil { diff --git a/wox.core/ui/ui_impl.go b/wox.core/ui/ui_impl.go index 4637331b..a12c4850 100644 --- a/wox.core/ui/ui_impl.go +++ b/wox.core/ui/ui_impl.go @@ -186,7 +186,15 @@ func getShowAppParams(ctx context.Context, showContext common.ShowContext) map[s case setting.PositionTypeActiveScreen: position = NewActiveScreenPosition(woxSetting.AppWidth) case setting.PositionTypeLastLocation: - position = NewLastLocationPosition(0, 0) // Initial values, will be updated by UI + // Use saved window position if available, otherwise use mouse screen position as fallback + if woxSetting.LastWindowX != -1 && woxSetting.LastWindowY != -1 { + logger.Info(ctx, fmt.Sprintf("Using saved window position: x=%d, y=%d", woxSetting.LastWindowX, woxSetting.LastWindowY)) + position = NewLastLocationPosition(woxSetting.LastWindowX, woxSetting.LastWindowY) + } else { + logger.Info(ctx, "No saved window position, using mouse screen position as fallback") + // No saved position, fallback to mouse screen position + position = NewMouseScreenPosition(woxSetting.AppWidth) + } default: // Default to mouse screen position = NewMouseScreenPosition(woxSetting.AppWidth) } diff --git a/wox.ui.flutter/wox/lib/api/wox_api.dart b/wox.ui.flutter/wox/lib/api/wox_api.dart index 53981517..cc2ee897 100644 --- a/wox.ui.flutter/wox/lib/api/wox_api.dart +++ b/wox.ui.flutter/wox/lib/api/wox_api.dart @@ -214,4 +214,8 @@ class WoxApi { Future getWoxVersion() async { return await WoxHttpUtil.instance.postData("/version", null); } + + Future saveWindowPosition(int x, int y) async { + await WoxHttpUtil.instance.postData("/setting/position", {"x": x, "y": y}); + } } diff --git a/wox.ui.flutter/wox/lib/controllers/wox_launcher_controller.dart b/wox.ui.flutter/wox/lib/controllers/wox_launcher_controller.dart index 08f2d19c..fb6e300e 100644 --- a/wox.ui.flutter/wox/lib/controllers/wox_launcher_controller.dart +++ b/wox.ui.flutter/wox/lib/controllers/wox_launcher_controller.dart @@ -232,16 +232,8 @@ class WoxLauncherController extends GetxController { if (Platform.isLinux) { await windowManager.show(); } - if (params.position.type == WoxPositionTypeEnum.POSITION_TYPE_MOUSE_SCREEN.code || params.position.type == WoxPositionTypeEnum.POSITION_TYPE_ACTIVE_SCREEN.code) { - await windowManager.setPosition(Offset(params.position.x.toDouble(), params.position.y.toDouble())); - } else if (params.position.type == WoxPositionTypeEnum.POSITION_TYPE_LAST_LOCATION.code) { - // For last location, we don't need to set position as it will remain where it was last positioned - // but if it's the first time to show, we need to set the position to the center of the screen - var position = await windowManager.getPosition(); - if (position.dx == 0 && position.dy == 0) { - await windowManager.center(WoxSettingUtil.instance.currentSetting.appWidth.toDouble(), 600); - } - } + // Use the position calculated by backend + await windowManager.setPosition(Offset(params.position.x.toDouble(), params.position.y.toDouble())); await windowManager.show(); await windowManager.focus(); @@ -274,6 +266,21 @@ class WoxLauncherController extends GetxController { await WoxApi.instance.onHide(currentQuery.value); } + void saveWindowPositionIfNeeded() { + final setting = WoxSettingUtil.instance.currentSetting; + if (setting.showPosition == WoxPositionTypeEnum.POSITION_TYPE_LAST_LOCATION.code) { + // Run in async task with delay to ensure window position is fully updated + Future.delayed(const Duration(milliseconds: 500), () async { + try { + final position = await windowManager.getPosition(); + await WoxApi.instance.saveWindowPosition(position.dx.toInt(), position.dy.toInt()); + } catch (e) { + Logger.instance.error(const UuidV4().generate(), "Failed to save window position: $e"); + } + }); + } + } + Future toggleActionPanel(String traceId) async { if (resultListViewController.items.isEmpty) { return; diff --git a/wox.ui.flutter/wox/lib/main.dart b/wox.ui.flutter/wox/lib/main.dart index ba89d2ef..e4b96acf 100644 --- a/wox.ui.flutter/wox/lib/main.dart +++ b/wox.ui.flutter/wox/lib/main.dart @@ -200,6 +200,7 @@ class _WoxAppState extends State with WindowListener, ProtocolListener { } launcherController.focusQueryBox(); + launcherController.saveWindowPositionIfNeeded(); }, child: launcherController.isInSettingView.value ? const WoxSettingView() : const WoxLauncherView(), );