Merge pull request #4156 from evgenyzinoviev/windows-pr

Improvements in BrowserWindow
This commit is contained in:
Cheng Zhao 2016-01-22 23:42:41 -08:00
commit 8cabe0f008
12 changed files with 429 additions and 46 deletions

View file

@ -408,6 +408,46 @@ bool Window::IsResizable() {
return window_->IsResizable();
}
void Window::SetMovable(bool movable) {
window_->SetMovable(movable);
}
bool Window::IsMovable() {
return window_->IsMovable();
}
void Window::SetMinimizable(bool minimizable) {
window_->SetMinimizable(minimizable);
}
bool Window::IsMinimizable() {
return window_->IsMinimizable();
}
void Window::SetMaximizable(bool maximizable) {
window_->SetMaximizable(maximizable);
}
bool Window::IsMaximizable() {
return window_->IsMaximizable();
}
void Window::SetFullscreenable(bool fullscreenable) {
window_->SetFullscreenable(fullscreenable);
}
bool Window::IsFullscreenable() {
return window_->IsFullscreenable();
}
void Window::SetClosable(bool closable) {
window_->SetClosable(closable);
}
bool Window::IsClosable() {
return window_->IsClosable();
}
void Window::SetAlwaysOnTop(bool top) {
window_->SetAlwaysOnTop(top);
}
@ -659,6 +699,16 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getMaximumSize", &Window::GetMaximumSize)
.SetMethod("setResizable", &Window::SetResizable)
.SetMethod("isResizable", &Window::IsResizable)
.SetMethod("setMovable", &Window::SetMovable)
.SetMethod("isMovable", &Window::IsMovable)
.SetMethod("setMinimizable", &Window::SetMinimizable)
.SetMethod("isMinimizable", &Window::IsMinimizable)
.SetMethod("setMaximizable", &Window::SetMaximizable)
.SetMethod("isMaximizable", &Window::IsMaximizable)
.SetMethod("setFullscreenable", &Window::SetFullscreenable)
.SetMethod("isFullscreenable", &Window::IsFullscreenable)
.SetMethod("setClosable", &Window::SetClosable)
.SetMethod("isClosable", &Window::IsClosable)
.SetMethod("setAlwaysOnTop", &Window::SetAlwaysOnTop)
.SetMethod("isAlwaysOnTop", &Window::IsAlwaysOnTop)
.SetMethod("center", &Window::Center)

View file

@ -106,6 +106,16 @@ class Window : public mate::TrackableObject<Window>,
std::vector<int> GetMaximumSize();
void SetResizable(bool resizable);
bool IsResizable();
void SetMovable(bool movable);
bool IsMovable();
void SetMinimizable(bool minimizable);
bool IsMinimizable();
void SetMaximizable(bool maximizable);
bool IsMaximizable();
void SetFullscreenable(bool fullscreenable);
bool IsFullscreenable();
void SetClosable(bool closable);
bool IsClosable();
void SetAlwaysOnTop(bool top);
bool IsAlwaysOnTop();
void Center();

View file

@ -120,6 +120,18 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
if (options.Get(options::kResizable, &resizable)) {
SetResizable(resizable);
}
bool minimizable;
if (options.Get(options::kMinimizable, &minimizable)) {
SetMinimizable(minimizable);
}
bool closable;
if (options.Get(options::kClosable, &closable)) {
SetClosable(closable);
}
bool maximizable;
if (options.Get(options::kMaximizable, &maximizable)) {
SetMaximizable(maximizable);
}
#endif
bool top;
if (options.Get(options::kAlwaysOnTop, &top) && top) {

View file

@ -125,6 +125,16 @@ class NativeWindow : public base::SupportsUserData,
virtual gfx::Size GetMaximumSize();
virtual void SetResizable(bool resizable) = 0;
virtual bool IsResizable() = 0;
virtual void SetMovable(bool movable) = 0;
virtual bool IsMovable() = 0;
virtual void SetMinimizable(bool minimizable) = 0;
virtual bool IsMinimizable() = 0;
virtual void SetMaximizable(bool maximizable) = 0;
virtual bool IsMaximizable() = 0;
virtual void SetFullscreenable(bool fullscreenable) = 0;
virtual bool IsFullscreenable() = 0;
virtual void SetClosable(bool closable) = 0;
virtual bool IsClosable() = 0;
virtual void SetAlwaysOnTop(bool top) = 0;
virtual bool IsAlwaysOnTop() = 0;
virtual void Center() = 0;

View file

@ -48,6 +48,16 @@ class NativeWindowMac : public NativeWindow {
const extensions::SizeConstraints& size_constraints) override;
void SetResizable(bool resizable) override;
bool IsResizable() override;
void SetMovable(bool movable) override;
bool IsMovable() override;
void SetMinimizable(bool minimizable) override;
bool IsMinimizable() override;
void SetMaximizable(bool maximizable) override;
bool IsMaximizable() override;
void SetFullscreenable(bool fullscreenable) override;
bool IsFullscreenable() override;
void SetClosable(bool closable) override;
bool IsClosable() override;
void SetAlwaysOnTop(bool top) override;
bool IsAlwaysOnTop() override;
void Center() override;

View file

@ -369,6 +369,18 @@ NativeWindowMac::NativeWindowMac(
bool resizable = true;
options.Get(options::kResizable, &resizable);
bool minimizable = true;
options.Get(options::kMinimizable, &minimizable);
bool maximizable = true;
options.Get(options::kMaximizable, &maximizable);
bool fullscreenable = true;
options.Get(options::kFullscreenable, &fullscreenable);
bool closable = true;
options.Get(options::kClosable, &closable);
// New title bar styles are available in Yosemite or newer
std::string titleBarStyle;
if (base::mac::IsOSYosemiteOrLater())
@ -385,8 +397,13 @@ NativeWindowMac::NativeWindowMac(
useStandardWindow = false;
}
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask;
if (minimizable) {
styleMask |= NSMiniaturizableWindowMask;
}
if (!closable) {
styleMask &= ~NSClosableWindowMask;
}
if (!useStandardWindow || transparent() || !has_frame()) {
styleMask |= NSTexturedBackgroundWindowMask;
}
@ -475,11 +492,10 @@ NativeWindowMac::NativeWindowMac(
// Disable fullscreen button when 'fullscreen' is specified to false.
bool fullscreen = false;
if (!(options.Get(options::kFullscreen, &fullscreen) &&
!fullscreen)) {
NSUInteger collectionBehavior = [window_ collectionBehavior];
collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
[window_ setCollectionBehavior:collectionBehavior];
options.Get(options::kFullscreen, &fullscreen);
if (fullscreenable) {
SetFullscreenable(true);
} else if (base::mac::IsOSElCapitanOrLater()) {
// On EL Capitan this flag is required to hide fullscreen button.
NSUInteger collectionBehavior = [window_ collectionBehavior];
@ -487,6 +503,11 @@ NativeWindowMac::NativeWindowMac(
[window_ setCollectionBehavior:collectionBehavior];
}
// Disable zoom button if window is not resizable
if (!maximizable) {
SetMaximizable(false);
}
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
@ -628,22 +649,95 @@ void NativeWindowMac::SetContentSizeConstraints(
}
void NativeWindowMac::SetResizable(bool resizable) {
bool maximizable = IsMaximizable();
// Change styleMask for frameless causes the window to change size, so we have
// to explicitly disables that.
ScopedDisableResize disable_resize;
if (resizable) {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:YES];
[window_ setStyleMask:[window_ styleMask] | NSResizableWindowMask];
} else {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
[window_ setStyleMask:[window_ styleMask] & (~NSResizableWindowMask)];
}
if (!maximizable) {
SetMaximizable(false);
}
}
bool NativeWindowMac::IsResizable() {
return [window_ styleMask] & NSResizableWindowMask;
}
void NativeWindowMac::SetMovable(bool movable) {
[window_ setMovable:movable];
}
bool NativeWindowMac::IsMovable() {
return [window_ isMovable];
}
void NativeWindowMac::SetMinimizable(bool minimizable) {
bool maximizable = IsMaximizable();
if (minimizable) {
[window_ setStyleMask:[window_ styleMask] | NSMiniaturizableWindowMask];
} else {
[window_ setStyleMask:[window_ styleMask] & (~NSMiniaturizableWindowMask)];
}
// If fullscreen has not been disabled via `fullscreenable: false` (i.e. when
// collectionBehavior has NSWindowCollectionBehaviorFullScreenPrimary mask),
// zoom button is reset to it's default (enabled) state when window's
// styleMask has been changed. So if the button was disabled, we have to
// disable it again. I think it's a bug in Cocoa.
if (!maximizable) {
SetMaximizable(false);
}
}
bool NativeWindowMac::IsMinimizable() {
return [window_ styleMask] & NSMiniaturizableWindowMask;
}
void NativeWindowMac::SetMaximizable(bool maximizable) {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:maximizable];
}
bool NativeWindowMac::IsMaximizable() {
return [[window_ standardWindowButton:NSWindowZoomButton] isEnabled];
}
void NativeWindowMac::SetFullscreenable(bool fullscreenable) {
bool maximizable = IsMaximizable();
NSUInteger collectionBehavior = [window_ collectionBehavior];
if (fullscreenable) {
collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
} else {
collectionBehavior &= (~NSWindowCollectionBehaviorFullScreenPrimary);
}
[window_ setCollectionBehavior:collectionBehavior];
if (!maximizable) {
SetMaximizable(false);
}
}
bool NativeWindowMac::IsFullscreenable() {
return [window_ collectionBehavior] & NSWindowCollectionBehaviorFullScreenPrimary;
}
void NativeWindowMac::SetClosable(bool closable) {
bool maximizable = IsMaximizable();
if (closable) {
[window_ setStyleMask:[window_ styleMask] | NSClosableWindowMask];
} else {
[window_ setStyleMask:[window_ styleMask] & (~NSClosableWindowMask)];
}
if (!maximizable) {
SetMaximizable(false);
}
}
bool NativeWindowMac::IsClosable() {
return [window_ styleMask] & NSClosableWindowMask;
}
void NativeWindowMac::SetAlwaysOnTop(bool top) {
[window_ setLevel:(top ? NSFloatingWindowLevel : NSNormalWindowLevel)];
}

View file

@ -103,7 +103,10 @@ NativeWindowViews::NativeWindowViews(
menu_bar_alt_pressed_(false),
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
use_content_size_(false),
resizable_(true) {
resizable_(true),
maximizable_(true),
movable_(true),
minimizable_(true) {
options.Get(options::kTitle, &title_);
options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_);
@ -111,6 +114,9 @@ NativeWindowViews::NativeWindowViews(
// On Windows we rely on the CanResize() to indicate whether window can be
// resized, and it should be set before window is created.
options.Get(options::kResizable, &resizable_);
options.Get(options::kMovable, &movable_);
options.Get(options::kMinimizable, &minimizable_);
options.Get(options::kMaximizable, &maximizable_);
#endif
if (enable_larger_than_screen())
@ -213,22 +219,22 @@ NativeWindowViews::NativeWindowViews(
last_normal_size_ = gfx::Size(widget_size_);
if (!has_frame()) {
// Set Window style so that we get a minimize and maximize animation when
// frameless.
DWORD frame_style = WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
WS_CAPTION;
// We should not show a frame for transparent window.
if (transparent())
frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
}
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
style |= WS_THICKFRAME | WS_CAPTION | WS_MINIMIZEBOX;
if (transparent()) {
// Transparent window on Windows has to have WS_EX_COMPOSITED style.
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
DWORD ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
ex_style |= WS_EX_COMPOSITED;
::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
if (!has_frame()) {
// We should not show a frame for transparent window.
style &= ~(WS_THICKFRAME | WS_CAPTION);
}
}
if (!transparent() || !has_frame()) {
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
}
#endif
@ -404,10 +410,11 @@ void NativeWindowViews::SetResizable(bool resizable) {
// WS_THICKFRAME => Resize handle
if (!transparent()) {
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
if (resizable)
style |= WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
else
style = (style & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)) | WS_MINIMIZEBOX;
if (resizable) {
style |= WS_THICKFRAME;
} else {
style &= ~(WS_THICKFRAME);
}
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
}
#elif defined(USE_X11)
@ -433,6 +440,95 @@ bool NativeWindowViews::IsResizable() {
return resizable_;
}
void NativeWindowViews::SetMovable(bool movable) {
movable_ = movable;
}
bool NativeWindowViews::IsMovable() {
#if defined(OS_WIN)
return movable_;
#elif defined(USE_X11)
return true;
#endif
}
void NativeWindowViews::SetMinimizable(bool minimizable) {
#if defined(OS_WIN)
if (!transparent()) {
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
if (minimizable)
style |= WS_MINIMIZEBOX;
else
style &= (~WS_MINIMIZEBOX);
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
}
#endif
minimizable_ = minimizable;
}
bool NativeWindowViews::IsMinimizable() {
#if defined(OS_WIN)
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MINIMIZEBOX;
#elif defined(USE_X11)
return true;
#endif
}
void NativeWindowViews::SetMaximizable(bool maximizable) {
#if defined(OS_WIN)
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
if (maximizable) {
style |= WS_MAXIMIZEBOX;
} else {
style &= (~WS_MAXIMIZEBOX);
}
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
#endif
}
bool NativeWindowViews::IsMaximizable() {
#if defined(OS_WIN)
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MAXIMIZEBOX;
#elif defined(USE_X11)
return true;
#endif
}
void NativeWindowViews::SetFullscreenable(bool maximizable) {
}
bool NativeWindowViews::IsFullscreenable() {
return true;
}
void NativeWindowViews::SetClosable(bool closable) {
#if defined(OS_WIN)
HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
if (closable) {
EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
} else {
EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
#endif
}
bool NativeWindowViews::IsClosable() {
#if defined(OS_WIN)
HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
MENUITEMINFO info;
memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
info.fMask = MIIM_STATE;
if (!GetMenuItemInfo(menu, SC_CLOSE, false, &info)) {
return false;
}
return !(info.fState & MFS_DISABLED);
#elif defined(USE_X11)
return true;
#endif
}
void NativeWindowViews::SetAlwaysOnTop(bool top) {
window_->SetAlwaysOnTop(top);
}
@ -694,7 +790,11 @@ bool NativeWindowViews::CanMaximize() const {
}
bool NativeWindowViews::CanMinimize() const {
#if defined(OS_WIN)
return minimizable_;
#elif defined(USE_X11)
return true;
#endif
}
base::string16 NativeWindowViews::GetWindowTitle() const {

View file

@ -68,6 +68,16 @@ class NativeWindowViews : public NativeWindow,
const extensions::SizeConstraints& size_constraints) override;
void SetResizable(bool resizable) override;
bool IsResizable() override;
void SetMovable(bool movable) override;
bool IsMovable() override;
void SetMinimizable(bool minimizable) override;
bool IsMinimizable() override;
void SetMaximizable(bool maximizable) override;
bool IsMaximizable() override;
void SetFullscreenable(bool fullscreenable) override;
bool IsFullscreenable() override;
void SetClosable(bool closable) override;
bool IsClosable() override;
void SetAlwaysOnTop(bool top) override;
bool IsAlwaysOnTop() override;
void Center() override;
@ -197,6 +207,9 @@ class NativeWindowViews : public NativeWindow,
bool use_content_size_;
bool resizable_;
bool maximizable_;
bool movable_;
bool minimizable_;
std::string title_;
gfx::Size widget_size_;

View file

@ -89,10 +89,19 @@ bool NativeWindowViews::PreHandleMSG(
if (HIWORD(w_param) == THBN_CLICKED)
return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
return false;
case WM_SIZE:
// Handle window state change.
HandleSizeEvent(w_param, l_param);
return false;
case WM_MOVING: {
if (!movable_) {
::GetWindowRect(GetAcceleratedWidget(), (LPRECT)l_param);
}
return false;
}
default:
return false;
}

View file

@ -8,22 +8,26 @@ namespace atom {
namespace options {
const char kTitle[] = "title";
const char kIcon[] = "icon";
const char kFrame[] = "frame";
const char kShow[] = "show";
const char kCenter[] = "center";
const char kX[] = "x";
const char kY[] = "y";
const char kWidth[] = "width";
const char kHeight[] = "height";
const char kMinWidth[] = "minWidth";
const char kMinHeight[] = "minHeight";
const char kMaxWidth[] = "maxWidth";
const char kMaxHeight[] = "maxHeight";
const char kResizable[] = "resizable";
const char kMovable[] = "movable";
const char kFullscreen[] = "fullscreen";
const char kTitle[] = "title";
const char kIcon[] = "icon";
const char kFrame[] = "frame";
const char kShow[] = "show";
const char kCenter[] = "center";
const char kX[] = "x";
const char kY[] = "y";
const char kWidth[] = "width";
const char kHeight[] = "height";
const char kMinWidth[] = "minWidth";
const char kMinHeight[] = "minHeight";
const char kMaxWidth[] = "maxWidth";
const char kMaxHeight[] = "maxHeight";
const char kResizable[] = "resizable";
const char kMovable[] = "movable";
const char kMinimizable[] = "minimizable";
const char kMaximizable[] = "maximizable";
const char kFullscreenable[] = "fullscreenable";
const char kClosable[] = "closable";
const char kFullscreen[] = "fullscreen";
// Whether the window should show in taskbar.
const char kSkipTaskbar[] = "skipTaskbar";

View file

@ -24,6 +24,10 @@ extern const char kMaxWidth[];
extern const char kMaxHeight[];
extern const char kResizable[];
extern const char kMovable[];
extern const char kMinimizable[];
extern const char kMaximizable[];
extern const char kFullscreenable[];
extern const char kClosable[];
extern const char kFullscreen[];
extern const char kSkipTaskbar[];
extern const char kKiosk[];

View file

@ -47,13 +47,22 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
* `maxWidth` Integer - Window's maximum width. Default is no limit.
* `maxHeight` Integer - Window's maximum height. Default is no limit.
* `resizable` Boolean - Whether window is resizable. Default is `true`.
* `movable` Boolean - Whether window is movable. This is only implemented
on OS X. Default is `true`.
* `movable` Boolean - Whether window is movable. This is not implemented
on Linux. Default is `true`.
* `minimizable` Boolean - Whether window is minimizable. This is not
implemented on Linux. Default is `true`.
* `maximizable` Boolean - Whether window is maximizable. This is not
implemented on Linux. Default is `true`.
* `closable` Boolean - Whether window is closable. This is not implemented
on Linux. Default is `true`.
* `alwaysOnTop` Boolean - Whether the window should always stay on top of
other windows. Default is `false`.
* `fullscreen` Boolean - Whether the window should show in fullscreen. When
set to `false` the fullscreen button will be hidden or disabled on OS X.
Default is `false`.
explicity set to `false` the fullscreen button will be hidden or disabled
on OS X, or the maximize button will be disabled on Windows. Default is
`false`.
* `fullscreenable` Boolean - Whether the maximize/zoom button on OS X should
toggle full screen mode or maximize window. Default is `true`.
* `skipTaskbar` Boolean - Whether to show the window in taskbar. Default is
`false`.
* `kiosk` Boolean - The kiosk mode. Default is `false`.
@ -529,6 +538,64 @@ Sets whether the window can be manually resized by user.
Returns whether the window can be manually resized by user.
### `win.setMovable(movable)` _OS X_ _Windows_
* `movable` Boolean
Sets whether the window can be moved by user. On Linux does nothing.
### `win.isMovable()` _OS X_ _Windows_
Returns whether the window can be moved by user. On Linux always returns
`true`.
### `win.setMinimizable(minimizable)` _OS X_ _Windows_
* `minimizable` Boolean
Sets whether the window can be manually minimized by user. On Linux does
nothing.
### `win.isMinimizable()` _OS X_ _Windows_
Returns whether the window can be manually minimized by user. On Linux always
returns `true`.
### `win.setMaximizable(maximizable)` _OS X_ _Windows_
* `maximizable` Boolean
Sets whether the window can be manually maximized by user. On Linux does
nothing.
### `win.isMaximizable()` _OS X_ _Windows_
Returns whether the window can be manually maximized by user. On Linux always
returns `true`.
### `win.setFullscreenable(fullscreenable)` _OS X_
* `fullscreenable` Boolean
Sets whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window. On Windows and Linux does nothing.
### `win.isFullscreenable()` _OS X_
Returns whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window. On Windows and Linux always returns `true`.
### `win.setClosable(closable)` _OS X_ _Windows_
* `closable` Boolean
Sets whether the window can be manually closed by user. On Linux does nothing.
### `win.isClosable()` _OS X_ _Windows_
Returns whether the window can be manually closed by user. On Linux always
returns `true`.
### `win.setAlwaysOnTop(flag)`
* `flag` Boolean