diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 930f624ab0ef6..c254e354aac78 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -1100,10 +1100,15 @@ On Linux always returns `true`. #### `win.setAlwaysOnTop(flag[, level][, relativeLevel])` * `flag` Boolean -* `level` String (optional) _macOS_ - Values include `normal`, `floating`, - `torn-off-menu`, `modal-panel`, `main-menu`, `status`, `pop-up-menu`, - `screen-saver`, and ~~`dock`~~ (Deprecated). The default is `floating`. See the - [macOS docs][window-levels] for more details. +* `level` String (optional) _macOS_ _Windows_ - Values include `normal`, + `floating`, `torn-off-menu`, `modal-panel`, `main-menu`, `status`, + `pop-up-menu`, `screen-saver`, and ~~`dock`~~ (Deprecated). The default is + `floating` when `flag` is true. The `level` is reset to `normal` when the + flag is false. Note that from `floating` to `status` included, the window is + placed below the Dock on macOS and below the taskbar on Windows. From + `pop-up-menu` to a higher it is shown above the Dock on macOS and above the + taskbar on Windows. See the [macOS docs][window-levels] for more details. + * `relativeLevel` Integer (optional) _macOS_ - The number of layers higher to set this window relative to the given `level`. The default is `0`. Note that Apple discourages setting levels higher than 1 above `screen-saver`. diff --git a/package.json b/package.json index 0269e2587822b..4f4c53ab54b2a 100644 --- a/package.json +++ b/package.json @@ -127,4 +127,4 @@ "git add filenames.auto.gni" ] } -} \ No newline at end of file +} diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index 72585b84b1abf..d5a3beb5edae3 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -13,6 +13,7 @@ #include #include +#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "content/public/browser/browser_thread.h" #include "native_mate/dictionary.h" @@ -69,6 +70,8 @@ namespace electron { namespace { #if defined(OS_WIN) +const LPCWSTR kUniqueTaskBarClassName = L"Shell_TrayWnd"; + void FlipWindowStyle(HWND handle, bool on, DWORD flag) { DWORD style = ::GetWindowLong(handle, GWL_STYLE); if (on) @@ -757,6 +760,19 @@ void NativeWindowViews::SetAlwaysOnTop(bool top, NativeWindow::NotifyWindowAlwaysOnTopChanged(); widget()->SetAlwaysOnTop(top); + +#if defined(OS_WIN) + // Reset the placement flag. + behind_task_bar_ = false; + if (top) { + // On macOS the window is placed behind the Dock for the following levels. + // Re-use the same names on Windows to make it easier for the user. + static const std::vector levels = { + "floating", "torn-off-menu", "modal-panel", "main-menu", "status"}; + behind_task_bar_ = base::Contains(levels, level); + } +#endif + MoveBehindTaskBarIfNeeded(); } bool NativeWindowViews::IsAlwaysOnTop() { @@ -1184,10 +1200,12 @@ void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget, if (changed_widget != widget()) return; - if (active) + if (active) { + MoveBehindTaskBarIfNeeded(); NativeWindow::NotifyWindowFocus(); - else + } else { NativeWindow::NotifyWindowBlur(); + } // Hide menu bar when window is blured. if (!active && IsMenuBarAutoHide() && IsMenuBarVisible()) @@ -1346,6 +1364,17 @@ ui::WindowShowState NativeWindowViews::GetRestoredState() { return ui::SHOW_STATE_NORMAL; } +void NativeWindowViews::MoveBehindTaskBarIfNeeded() { +#if defined(OS_WIN) + if (behind_task_bar_) { + const HWND task_bar_hwnd = ::FindWindow(kUniqueTaskBarClassName, nullptr); + ::SetWindowPos(GetAcceleratedWidget(), task_bar_hwnd, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } +#endif + // TODO(julien.isorce): Implement X11 case. +} + // static NativeWindow* NativeWindow::Create(const mate::Dictionary& options, NativeWindow* parent) { diff --git a/shell/browser/native_window_views.h b/shell/browser/native_window_views.h index 16a7538dd71c9..46fe042255df7 100644 --- a/shell/browser/native_window_views.h +++ b/shell/browser/native_window_views.h @@ -214,6 +214,9 @@ class NativeWindowViews : public NativeWindow, // Returns the restore state for the window. ui::WindowShowState GetRestoredState(); + // Maintain window placement. + void MoveBehindTaskBarIfNeeded(); + std::unique_ptr root_view_; // The view should be focused by default. @@ -280,6 +283,9 @@ class NativeWindowViews : public NativeWindow, bool forwarding_mouse_messages_ = false; HWND legacy_window_ = NULL; bool layered_ = false; + + // Set to true if the window is always on top and behind the task bar. + bool behind_task_bar_ = false; #endif // Handles unhandled keyboard messages coming back from the renderer process.