added or/and improved closable, minimizable, movable, resizable features for windows on os x and windows

This commit is contained in:
evgenyzinoviev 2016-01-18 23:46:35 +01:00
parent 7842a657d0
commit 2a554cb138
11 changed files with 255 additions and 36 deletions

View file

@ -408,6 +408,30 @@ 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::SetClosable(bool closable) {
window_->SetClosable(closable);
}
bool Window::IsClosable() {
return window_->IsClosable();
}
void Window::SetAlwaysOnTop(bool top) {
window_->SetAlwaysOnTop(top);
}
@ -659,6 +683,12 @@ 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("setClosable", &Window::SetClosable)
.SetMethod("isClosable", &Window::IsClosable)
.SetMethod("setAlwaysOnTop", &Window::SetAlwaysOnTop)
.SetMethod("isAlwaysOnTop", &Window::IsAlwaysOnTop)
.SetMethod("center", &Window::Center)

View file

@ -106,6 +106,12 @@ 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 SetClosable(bool closable);
bool IsClosable();
void SetAlwaysOnTop(bool top);
bool IsAlwaysOnTop();
void Center();

View file

@ -120,6 +120,14 @@ 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);
}
#endif
bool top;
if (options.Get(options::kAlwaysOnTop, &top) && top) {

View file

@ -125,6 +125,12 @@ 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 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,12 @@ 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 SetClosable(bool closable) override;
bool IsClosable() override;
void SetAlwaysOnTop(bool top) override;
bool IsAlwaysOnTop() override;
void Center() override;
@ -100,6 +106,7 @@ class NativeWindowMac : public NativeWindow {
gfx::Size WindowSizeToContentSize(const gfx::Size& size) override;
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;
void FixZoomButton();
void InstallView();
void UninstallView();

View file

@ -369,6 +369,12 @@ NativeWindowMac::NativeWindowMac(
bool resizable = true;
options.Get(options::kResizable, &resizable);
bool minimizable = true;
options.Get(options::kMinimizable, &minimizable);
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 +391,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;
}
@ -487,6 +498,11 @@ NativeWindowMac::NativeWindowMac(
[window_ setCollectionBehavior:collectionBehavior];
}
// Disable zoom button if window is not resizable
if (!resizable) {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
}
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
@ -635,8 +651,10 @@ void NativeWindowMac::SetResizable(bool resizable) {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:YES];
[window_ setStyleMask:[window_ styleMask] | NSResizableWindowMask];
} else {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
// If we disable the button before changing the styleMask, button is not
// disabled. Looks like a bug in Cocoa (OS X 10.10.5)
[window_ setStyleMask:[window_ styleMask] & (~NSResizableWindowMask)];
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
}
}
@ -644,10 +662,56 @@ 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) {
if (minimizable) {
[window_ setStyleMask:[window_ styleMask] | NSMiniaturizableWindowMask];
} else {
[window_ setStyleMask:[window_ styleMask] & (~NSMiniaturizableWindowMask)];
}
FixZoomButton();
}
bool NativeWindowMac::IsMinimizable() {
return [window_ styleMask] & NSMiniaturizableWindowMask;
}
void NativeWindowMac::SetClosable(bool closable) {
if (closable) {
[window_ setStyleMask:[window_ styleMask] | NSClosableWindowMask];
} else {
[window_ setStyleMask:[window_ styleMask] & (~NSClosableWindowMask)];
}
FixZoomButton();
}
bool NativeWindowMac::IsClosable() {
return [window_ styleMask] & NSClosableWindowMask;
}
void NativeWindowMac::SetAlwaysOnTop(bool top) {
[window_ setLevel:(top ? NSFloatingWindowLevel : NSNormalWindowLevel)];
}
void NativeWindowMac::FixZoomButton() {
// If fullscreen has not been disabled via `fullscreen: 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 ([window_ collectionBehavior] & NSWindowCollectionBehaviorFullScreenPrimary
&& !([window_ styleMask] & NSResizableWindowMask)) {
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
}
}
bool NativeWindowMac::IsAlwaysOnTop() {
return [window_ level] == NSFloatingWindowLevel;
}

View file

@ -126,7 +126,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_);
@ -134,6 +137,8 @@ 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_);
#endif
if (enable_larger_than_screen())
@ -182,7 +187,9 @@ NativeWindowViews::NativeWindowViews(
window_->Init(params);
bool fullscreen = false;
options.Get(options::kFullscreen, &fullscreen);
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen) {
maximizable_ = false;
}
#if defined(USE_X11)
// Start monitoring window states.
@ -236,22 +243,27 @@ 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 (!maximizable_) {
style &= (~WS_MAXIMIZEBOX);
} else {
style |= WS_MAXIMIZEBOX;
}
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
@ -427,10 +439,12 @@ 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;
if (maximizable_) style |= WS_MAXIMIZEBOX;
} else {
style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
}
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
}
#elif defined(USE_X11)
@ -456,6 +470,64 @@ bool NativeWindowViews::IsResizable() {
return resizable_;
}
void NativeWindowViews::SetMovable(bool movable) {
movable_ = movable;
}
bool NativeWindowViews::IsMovable() {
return movable_;
}
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::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);
}
@ -717,7 +789,11 @@ bool NativeWindowViews::CanMaximize() const {
}
bool NativeWindowViews::CanMinimize() const {
#ifdef (OS_WIN)
return minimizable_;
#elif defined(USE_X11)
return true;
#endif
}
base::string16 NativeWindowViews::GetWindowTitle() const {

View file

@ -68,6 +68,12 @@ 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 SetClosable(bool closable) override;
bool IsClosable() override;
void SetAlwaysOnTop(bool top) override;
bool IsAlwaysOnTop() override;
void Center() override;
@ -197,6 +203,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,24 @@ 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 kClosable[] = "closable";
const char kFullscreen[] = "fullscreen";
// Whether the window should show in taskbar.
const char kSkipTaskbar[] = "skipTaskbar";

View file

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