Merge pull request #327 from atom/content-size

Provide ways to control window content's size
This commit is contained in:
Cheng Zhao 2014-05-18 21:46:37 +08:00
commit 6799fe5393
14 changed files with 173 additions and 17 deletions

View file

@ -181,6 +181,18 @@ std::vector<int> Window::GetSize() {
return result;
}
void Window::SetContentSize(int width, int height) {
window_->SetContentSize(gfx::Size(width, height));
}
std::vector<int> Window::GetContentSize() {
std::vector<int> result(2);
gfx::Size size = window_->GetContentSize();
result[0] = size.width();
result[1] = size.height();
return result;
}
void Window::SetMinimumSize(int width, int height) {
window_->SetMinimumSize(gfx::Size(width, height));
}
@ -332,6 +344,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("isFullScreen", &Window::IsFullscreen)
.SetMethod("getSize", &Window::GetSize)
.SetMethod("setSize", &Window::SetSize)
.SetMethod("getContentSize", &Window::GetContentSize)
.SetMethod("setContentSize", &Window::SetContentSize)
.SetMethod("setMinimumSize", &Window::SetMinimumSize)
.SetMethod("getMinimumSize", &Window::GetMinimumSize)
.SetMethod("setMaximumSize", &Window::SetMaximumSize)

View file

@ -73,6 +73,8 @@ class Window : public mate::EventEmitter,
bool IsFullscreen();
void SetSize(int width, int height);
std::vector<int> GetSize();
void SetContentSize(int width, int height);
std::vector<int> GetContentSize();
void SetMinimumSize(int width, int height);
std::vector<int> GetMinimumSize();
void SetMaximumSize(int width, int height);

View file

@ -14,13 +14,11 @@ app.on('window-all-closed', function() {
app.on('ready', function() {
app.commandLine.appendSwitch('js-flags', '--harmony_collections');
var height = 600;
if (process.platform == 'win32')
height += 60;
else if (process.platform == 'linux')
height += 30;
mainWindow = new BrowserWindow({ width: 800, height: height });
mainWindow = new BrowserWindow({
width: 800,
height: 600,
'use-content-size': true,
});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
if (process.platform == 'darwin') {

View file

@ -111,6 +111,8 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
virtual bool IsFullscreen() = 0;
virtual void SetSize(const gfx::Size& size) = 0;
virtual gfx::Size GetSize() = 0;
virtual void SetContentSize(const gfx::Size& size) = 0;
virtual gfx::Size GetContentSize() = 0;
virtual void SetMinimumSize(const gfx::Size& size) = 0;
virtual gfx::Size GetMinimumSize() = 0;
virtual void SetMaximumSize(const gfx::Size& size) = 0;

View file

@ -114,8 +114,9 @@ NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
options->GetInteger(switches::kWidth, &width);
options->GetInteger(switches::kHeight, &height);
// Fixup the initial window size.
if (has_frame_)
bool use_content_size = false;
options->GetBoolean(switches::kUseContentSize, &use_content_size);
if (has_frame_ && !use_content_size)
SubstractBorderSize(&width, &height);
// Force a size allocation so the web page of hidden window can have correct
@ -261,6 +262,24 @@ gfx::Size NativeWindowGtk::GetSize() {
return gfx::Size(frame_extents.width, frame_extents.height);
}
void NativeWindowGtk::SetContentSize(const gfx::Size& size) {
if (!has_frame_ || !has_ever_been_shown_) {
gtk_window_util::SetWindowSize(window_, size);
} else {
gfx::Size large = GetSize();
gfx::Size small = GetContentSize();
gfx::Size target(size.width() + large.width() - small.width(),
size.height() + large.height() - small.height());
gtk_window_util::SetWindowSize(window_, target);
}
}
gfx::Size NativeWindowGtk::GetContentSize() {
gint width, height;
gtk_window_get_size(window_, &width, &height);
return gfx::Size(width, height);
}
void NativeWindowGtk::SetMinimumSize(const gfx::Size& size) {
minimum_size_ = size;

View file

@ -46,6 +46,8 @@ class NativeWindowGtk : public NativeWindow,
virtual bool IsFullscreen() OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
virtual void SetContentSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetContentSize() OVERRIDE;
virtual void SetMinimumSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual void SetMaximumSize(const gfx::Size& size) OVERRIDE;

View file

@ -38,6 +38,8 @@ class NativeWindowMac : public NativeWindow {
virtual bool IsFullscreen() OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
virtual void SetContentSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetContentSize() OVERRIDE;
virtual void SetMinimumSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual void SetMaximumSize(const gfx::Size& size) OVERRIDE;

View file

@ -6,18 +6,18 @@
#include <string>
#import "atom/browser/ui/cocoa/event_processing_window.h"
#include "atom/common/draggable_region.h"
#include "atom/common/options_switches.h"
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/values.h"
#import "atom/browser/ui/cocoa/event_processing_window.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "atom/common/draggable_region.h"
#include "atom/common/options_switches.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/render_view_host.h"
#include "vendor/brightray/browser/inspectable_web_contents.h"
#include "vendor/brightray/browser/inspectable_web_contents_view.h"
static const CGFloat kAtomWindowCornerRadius = 4.0;
@ -179,6 +179,12 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
// We will manage window's lifetime ourselves.
[window_ setReleasedWhenClosed:NO];
// On OS X the initial window size doesn't include window frame.
bool use_content_size = false;
options->GetBoolean(switches::kUseContentSize, &use_content_size);
if (has_frame_ && !use_content_size)
SetSize(gfx::Size(width, height));
// Enable the NSView to accept first mouse event.
bool acceptsFirstMouse = false;
options->GetBoolean(switches::kAcceptFirstMouse, &acceptsFirstMouse);
@ -299,6 +305,24 @@ gfx::Size NativeWindowMac::GetSize() {
return gfx::Size(frame.size.width, frame.size.height);
}
void NativeWindowMac::SetContentSize(const gfx::Size& size) {
NSRect frame_nsrect = [window_ frame];
NSSize frame = frame_nsrect.size;
NSSize content = [window_ contentRectForFrameRect:frame_nsrect].size;
int width = size.width() + frame.width - content.width;
int height = size.height() + frame.height - content.height;
frame_nsrect.origin.y -= height - frame_nsrect.size.height;
frame_nsrect.size.width = width;
frame_nsrect.size.height = height;
[window_ setFrame:frame_nsrect display:YES];
}
gfx::Size NativeWindowMac::GetContentSize() {
NSRect bounds = [[window_ contentView] bounds];
return gfx::Size(bounds.size.width, bounds.size.height);
}
void NativeWindowMac::SetMinimumSize(const gfx::Size& size) {
NSSize min_size = NSMakeSize(size.width(), size.height());
NSView* content = [window_ contentView];

View file

@ -203,6 +203,7 @@ NativeWindowWin::NativeWindowWin(content::WebContents* web_contents,
: NativeWindow(web_contents, options),
window_(new views::Widget),
web_view_(new views::WebView(NULL)),
use_content_size_(false),
resizable_(true) {
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.delegate = this;
@ -217,8 +218,11 @@ NativeWindowWin::NativeWindowWin(content::WebContents* web_contents,
options->GetInteger(switches::kHeight, &height);
gfx::Size size(width, height);
window_->CenterWindow(size);
options->GetBoolean(switches::kUseContentSize, &use_content_size_);
if (has_frame_ && use_content_size_)
ClientAreaSizeToWindowSize(&size);
window_->CenterWindow(size);
window_->UpdateWindowIcon();
web_view_->SetWebContents(web_contents);
@ -295,6 +299,16 @@ gfx::Size NativeWindowWin::GetSize() {
return window_->GetWindowBoundsInScreen().size();
}
void NativeWindowWin::SetContentSize(const gfx::Size& size) {
gfx::Size resized(size);
ClientAreaSizeToWindowSize(&resized);
SetSize(resized);
}
gfx::Size NativeWindowWin::GetContentSize() {
return window_->GetClientAreaBoundsInScreen().size();
}
void NativeWindowWin::SetMinimumSize(const gfx::Size& size) {
minimum_size_ = size;
}
@ -374,6 +388,13 @@ void NativeWindowWin::SetMenu(ui::MenuModel* menu_model) {
menu_.reset(new atom::Menu2(menu_model, true));
::SetMenu(GetNativeWindow(), menu_->GetNativeMenu());
RegisterAccelerators();
// Resize the window so SetMenu won't change client area size.
if (use_content_size_) {
gfx::Size size = GetSize();
size.set_height(size.height() + GetSystemMetrics(SM_CYMENU));
SetSize(size);
}
}
void NativeWindowWin::UpdateDraggableRegions(
@ -492,6 +513,13 @@ views::NonClientFrameView* NativeWindowWin::CreateNonClientFrameView(
return new NativeWindowFramelessView(widget, this);
}
void NativeWindowWin::ClientAreaSizeToWindowSize(gfx::Size* size) {
gfx::Size window = window_->GetWindowBoundsInScreen().size();
gfx::Size client = window_->GetClientAreaBoundsInScreen().size();
size->set_width(size->width() + window.width() - client.width());
size->set_height(size->height() + window.height() - client.height());
}
void NativeWindowWin::OnViewWasResized() {
// Set the window shape of the RWHV.
gfx::Size sz = web_view_->size();

View file

@ -53,6 +53,8 @@ class NativeWindowWin : public NativeWindow,
virtual bool IsFullscreen() OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
virtual void SetContentSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetContentSize() OVERRIDE;
virtual void SetMinimumSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual void SetMaximumSize(const gfx::Size& size) OVERRIDE;
@ -113,6 +115,8 @@ class NativeWindowWin : public NativeWindow,
typedef struct { int position; ui::MenuModel* model; } MenuItem;
typedef std::map<ui::Accelerator, MenuItem> AcceleratorTable;
void ClientAreaSizeToWindowSize(gfx::Size* size);
void OnViewWasResized();
// Register accelerators supported by the menu model.
@ -129,6 +133,8 @@ class NativeWindowWin : public NativeWindow,
scoped_ptr<SkRegion> draggable_region_;
bool use_content_size_;
bool resizable_;
string16 title_;
gfx::Size minimum_size_;

View file

@ -36,6 +36,9 @@ const char kNodeIntegration[] = "node-integration";
// Enable the NSView to accept first mouse event.
const char kAcceptFirstMouse[] = "accept-first-mouse";
// Whether window size should include window frame.
const char kUseContentSize[] = "use-content-size";
} // namespace switches
} // namespace atom

View file

@ -28,6 +28,7 @@ extern const char kKiosk[];
extern const char kAlwaysOnTop[];
extern const char kNodeIntegration[];
extern const char kAcceptFirstMouse[];
extern const char kUseContentSize[];
} // namespace switches

View file

@ -28,13 +28,19 @@ You can also create a window without chrome by using
* `options` Object
* `x` Integer - Window's left offset to screen
* `y` Integer - Window's top offset to screen
* `width` Integer - Window's width
* `height` Integer - Window's height
* `use-content-size` Boolean - The `width` and `height` would be used as web
page's size, which means the actual window's size will include window
frame's size and be slightly larger.
* `center` Boolean - Show window in the center of the screen
* `min-width` Integer - Minimum width
* `min-height` Integer - Minimum height
* `max-width` Integer - Maximum width
* `max-height` Integer - Maximum height
* `resizable` Boolean - Whether window is resizable
* `always-on-top` Boolean - Whether the window should always stay on top of other windows
* `always-on-top` Boolean - Whether the window should always stay on top of
other windows
* `fullscreen` Boolean - Whether the window should show in fullscreen
* `kiosk` Boolean - The kiosk mode
* `title` String - Default window title
@ -223,6 +229,17 @@ Resizes the window to `width` and `height`.
Returns an array that contains window's width and height.
### BrowserWindow.setContentSize(width, height)
* `width` Integer
* `height` Integer
Resizes the window's client area (e.g. the web page) to `width` and `height`.
### BrowserWindow.getContentSize()
Returns an array that contains window's client area's width and height.
### BrowserWindow.setMinimumSize(width, height)
* `width` Integer

View file

@ -11,7 +11,7 @@ describe 'browser-window module', ->
w = null
beforeEach ->
w.destroy() if w?
w = new BrowserWindow(show: false)
w = new BrowserWindow(show: false, width: 400, height: 400)
afterEach ->
w.destroy() if w?
w = null
@ -68,6 +68,44 @@ describe 'browser-window module', ->
assert.equal image.constructor.name, 'Buffer'
done()
describe 'BrowserWindow.setSize(width, height)', ->
it 'sets the window size', ->
# No way to reliably set size when window has not been shown on Linux.
return if process.platform is 'linux'
size = [400, 400]
w.setSize size[0], size[1]
after = w.getSize()
assert.equal after[0], size[0]
assert.equal after[1], size[1]
describe 'BrowserWindow.setContentSize(width, height)', ->
it 'sets the content size', ->
# No way to reliably set size when window has not been shown on Linux.
return if process.platform is 'linux'
size = [400, 400]
w.setContentSize size[0], size[1]
after = w.getContentSize()
assert.equal after[0], size[0]
assert.equal after[1], size[1]
describe '"use-content-size" option', ->
it 'make window created with content size when used', ->
w.destroy()
w = new BrowserWindow(show: false, width: 400, height: 400, 'use-content-size': true)
contentSize = w.getContentSize()
assert.equal contentSize[0], 400
assert.equal contentSize[1], 400
it 'make window created with window size when not used', ->
# No way to reliably set size when window has not been shown on Linux.
return if process.platform is 'linux'
contentSize = w.getSize()
assert.equal contentSize[0], 400
assert.equal contentSize[1], 400
describe 'beforeunload handler', ->
it 'returning true would not prevent close', (done) ->
w.on 'closed', ->