Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable BrowserWindow level placement on Windows #18982

Merged
merged 1 commit into from Jul 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions docs/api/browser-window.md
Expand Up @@ -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`.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -127,4 +127,4 @@
"git add filenames.auto.gni"
]
}
}
}
33 changes: 31 additions & 2 deletions shell/browser/native_window_views.cc
Expand Up @@ -13,6 +13,7 @@
#include <utility>
#include <vector>

#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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<std::string> levels = {
"floating", "torn-off-menu", "modal-panel", "main-menu", "status"};
behind_task_bar_ = base::Contains(levels, level);
}
#endif
MoveBehindTaskBarIfNeeded();
}

bool NativeWindowViews::IsAlwaysOnTop() {
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 6 additions & 0 deletions shell/browser/native_window_views.h
Expand Up @@ -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<RootView> root_view_;

// The view should be focused by default.
Expand Down Expand Up @@ -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.
Expand Down