Merge pull request #85 from atom/frameless-window
Add frameless window support, fixes #72.
This commit is contained in:
commit
eb6fa98ed0
15 changed files with 567 additions and 9 deletions
2
atom.gyp
2
atom.gyp
|
@ -139,6 +139,8 @@
|
||||||
'common/api/atom_extensions.h',
|
'common/api/atom_extensions.h',
|
||||||
'common/api/object_life_monitor.cc',
|
'common/api/object_life_monitor.cc',
|
||||||
'common/api/object_life_monitor.h',
|
'common/api/object_life_monitor.h',
|
||||||
|
'common/draggable_region.cc',
|
||||||
|
'common/draggable_region.h',
|
||||||
'common/node_bindings.cc',
|
'common/node_bindings.cc',
|
||||||
'common/node_bindings.h',
|
'common/node_bindings.h',
|
||||||
'common/node_bindings_mac.cc',
|
'common/node_bindings_mac.cc',
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
var app = require('app');
|
||||||
var argv = require('optimist').argv;
|
var argv = require('optimist').argv;
|
||||||
var dialog = require('dialog');
|
var dialog = require('dialog');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
|
// Quit when all windows are closed and no other one is listening to this.
|
||||||
|
app.on('window-all-closed', function() {
|
||||||
|
if (app.listeners('window-all-closed').length == 1)
|
||||||
|
app.quit();
|
||||||
|
});
|
||||||
|
|
||||||
// Start the specified app if there is one specified in command line, otherwise
|
// Start the specified app if there is one specified in command line, otherwise
|
||||||
// start the default app.
|
// start the default app.
|
||||||
if (argv._.length > 0) {
|
if (argv._.length > 0) {
|
||||||
|
@ -9,6 +16,7 @@ if (argv._.length > 0) {
|
||||||
require(path.resolve(argv._[0]));
|
require(path.resolve(argv._[0]));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e.code == 'MODULE_NOT_FOUND') {
|
if (e.code == 'MODULE_NOT_FOUND') {
|
||||||
|
console.error(e.stack);
|
||||||
console.error('Specified app is invalid');
|
console.error('Specified app is invalid');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -39,10 +39,13 @@ namespace atom {
|
||||||
NativeWindow::NativeWindow(content::WebContents* web_contents,
|
NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||||
base::DictionaryValue* options)
|
base::DictionaryValue* options)
|
||||||
: content::WebContentsObserver(web_contents),
|
: content::WebContentsObserver(web_contents),
|
||||||
|
has_frame_(true),
|
||||||
is_closed_(false),
|
is_closed_(false),
|
||||||
not_responding_(false),
|
not_responding_(false),
|
||||||
inspectable_web_contents_(
|
inspectable_web_contents_(
|
||||||
brightray::InspectableWebContents::Create(web_contents)) {
|
brightray::InspectableWebContents::Create(web_contents)) {
|
||||||
|
options->GetBoolean(switches::kFrame, &has_frame_);
|
||||||
|
|
||||||
web_contents->SetDelegate(this);
|
web_contents->SetDelegate(this);
|
||||||
|
|
||||||
WindowList::AddWindow(this);
|
WindowList::AddWindow(this);
|
||||||
|
@ -298,6 +301,8 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
|
||||||
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
|
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
|
||||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
||||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message_Sync, OnRendererMessageSync)
|
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message_Sync, OnRendererMessageSync)
|
||||||
|
IPC_MESSAGE_HANDLER(AtomViewHostMsg_UpdateDraggableRegions,
|
||||||
|
UpdateDraggableRegions)
|
||||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||||
IPC_END_MESSAGE_MAP()
|
IPC_END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ class Size;
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
class AtomJavaScriptDialogManager;
|
class AtomJavaScriptDialogManager;
|
||||||
|
struct DraggableRegion;
|
||||||
|
|
||||||
class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||||
public content::WebContentsObserver,
|
public content::WebContentsObserver,
|
||||||
|
@ -125,6 +126,10 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||||
void NotifyWindowClosed();
|
void NotifyWindowClosed();
|
||||||
void NotifyWindowBlur();
|
void NotifyWindowBlur();
|
||||||
|
|
||||||
|
// Called when the window needs to update its draggable region.
|
||||||
|
virtual void UpdateDraggableRegions(
|
||||||
|
const std::vector<DraggableRegion>& regions) = 0;
|
||||||
|
|
||||||
// Implementations of content::WebContentsDelegate.
|
// Implementations of content::WebContentsDelegate.
|
||||||
virtual void WebContentsCreated(content::WebContents* source_contents,
|
virtual void WebContentsCreated(content::WebContents* source_contents,
|
||||||
int64 source_frame_id,
|
int64 source_frame_id,
|
||||||
|
@ -160,6 +165,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||||
const content::NotificationSource& source,
|
const content::NotificationSource& source,
|
||||||
const content::NotificationDetails& details) OVERRIDE;
|
const content::NotificationDetails& details) OVERRIDE;
|
||||||
|
|
||||||
|
// Whether window has standard frame.
|
||||||
|
bool has_frame_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RendererUnresponsiveDelayed();
|
void RendererUnresponsiveDelayed();
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "browser/native_window.h"
|
#include "browser/native_window.h"
|
||||||
|
|
||||||
|
class SkRegion;
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
class NativeWindowMac : public NativeWindow {
|
class NativeWindowMac : public NativeWindow {
|
||||||
|
@ -52,11 +54,22 @@ class NativeWindowMac : public NativeWindow {
|
||||||
virtual bool IsKiosk() OVERRIDE;
|
virtual bool IsKiosk() OVERRIDE;
|
||||||
virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
|
virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
|
||||||
|
|
||||||
NSWindow*& window() { return window_; }
|
|
||||||
|
|
||||||
void NotifyWindowBlur() { NativeWindow::NotifyWindowBlur(); }
|
void NotifyWindowBlur() { NativeWindow::NotifyWindowBlur(); }
|
||||||
|
|
||||||
|
// Returns true if |point| in local Cocoa coordinate system falls within
|
||||||
|
// the draggable region.
|
||||||
|
bool IsWithinDraggableRegion(NSPoint point) const;
|
||||||
|
|
||||||
|
// Called to handle a mouse event.
|
||||||
|
void HandleMouseEvent(NSEvent* event);
|
||||||
|
|
||||||
|
NSWindow*& window() { return window_; }
|
||||||
|
SkRegion* draggable_region() const { return draggable_region_.get(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void UpdateDraggableRegions(
|
||||||
|
const std::vector<DraggableRegion>& regions) OVERRIDE;
|
||||||
|
|
||||||
// Implementations of content::WebContentsDelegate.
|
// Implementations of content::WebContentsDelegate.
|
||||||
virtual void HandleKeyboardEvent(
|
virtual void HandleKeyboardEvent(
|
||||||
content::WebContents*,
|
content::WebContents*,
|
||||||
|
@ -65,6 +78,9 @@ class NativeWindowMac : public NativeWindow {
|
||||||
private:
|
private:
|
||||||
void InstallView();
|
void InstallView();
|
||||||
void UninstallView();
|
void UninstallView();
|
||||||
|
void InstallDraggableRegionViews();
|
||||||
|
void UpdateDraggableRegionsForCustomDrag(
|
||||||
|
const std::vector<DraggableRegion>& regions);
|
||||||
|
|
||||||
NSWindow* window_;
|
NSWindow* window_;
|
||||||
|
|
||||||
|
@ -72,6 +88,18 @@ class NativeWindowMac : public NativeWindow {
|
||||||
|
|
||||||
NSInteger attention_request_id_; // identifier from requestUserAttention
|
NSInteger attention_request_id_; // identifier from requestUserAttention
|
||||||
|
|
||||||
|
// For system drag, the whole window is draggable and the non-draggable areas
|
||||||
|
// have to been explicitly excluded.
|
||||||
|
std::vector<gfx::Rect> system_drag_exclude_areas_;
|
||||||
|
|
||||||
|
// For custom drag, the whole window is non-draggable and the draggable region
|
||||||
|
// has to been explicitly provided.
|
||||||
|
scoped_ptr<SkRegion> draggable_region_; // used in custom drag.
|
||||||
|
|
||||||
|
// Mouse location since the last mouse event, in screen coordinates. This is
|
||||||
|
// used in custom drag to compute the window movement.
|
||||||
|
NSPoint last_mouse_offset_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(NativeWindowMac);
|
DISALLOW_COPY_AND_ASSIGN(NativeWindowMac);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,25 @@
|
||||||
#import "browser/atom_event_processing_window.h"
|
#import "browser/atom_event_processing_window.h"
|
||||||
#include "brightray/browser/inspectable_web_contents.h"
|
#include "brightray/browser/inspectable_web_contents.h"
|
||||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||||
|
#include "common/draggable_region.h"
|
||||||
#include "common/options_switches.h"
|
#include "common/options_switches.h"
|
||||||
#include "content/public/browser/native_web_keyboard_event.h"
|
#include "content/public/browser/native_web_keyboard_event.h"
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "content/public/browser/web_contents_view.h"
|
#include "content/public/browser/web_contents_view.h"
|
||||||
#include "content/public/browser/render_view_host.h"
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
|
||||||
|
@interface NSWindow (NSPrivateApis)
|
||||||
|
- (void)setBottomCornerRounded:(BOOL)rounded;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSView (WebContentsView)
|
||||||
|
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSView (PrivateMethods)
|
||||||
|
- (CGFloat)roundedCornerRadius;
|
||||||
|
@end
|
||||||
|
|
||||||
@interface AtomNSWindowDelegate : NSObject<NSWindowDelegate> {
|
@interface AtomNSWindowDelegate : NSObject<NSWindowDelegate> {
|
||||||
@private
|
@private
|
||||||
atom::NativeWindowMac* shell_;
|
atom::NativeWindowMac* shell_;
|
||||||
|
@ -80,6 +93,83 @@
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface AtomFramelessNSWindow : AtomNSWindow
|
||||||
|
- (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation AtomFramelessNSWindow
|
||||||
|
|
||||||
|
- (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view {
|
||||||
|
[[NSBezierPath bezierPathWithRect:rect] addClip];
|
||||||
|
[[NSColor clearColor] set];
|
||||||
|
NSRectFill(rect);
|
||||||
|
|
||||||
|
// Set up our clip.
|
||||||
|
CGFloat cornerRadius = 4.0;
|
||||||
|
if ([view respondsToSelector:@selector(roundedCornerRadius)])
|
||||||
|
cornerRadius = [view roundedCornerRadius];
|
||||||
|
[[NSBezierPath bezierPathWithRoundedRect:[view bounds]
|
||||||
|
xRadius:cornerRadius
|
||||||
|
yRadius:cornerRadius] addClip];
|
||||||
|
[[NSColor whiteColor] set];
|
||||||
|
NSRectFill(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSRect)frameRectForContentRect:(NSRect)contentRect
|
||||||
|
styleMask:(NSUInteger)mask {
|
||||||
|
return contentRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSRect)contentRectForFrameRect:(NSRect)frameRect
|
||||||
|
styleMask:(NSUInteger)mask {
|
||||||
|
return frameRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSRect)frameRectForContentRect:(NSRect)contentRect {
|
||||||
|
return contentRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSRect)contentRectForFrameRect:(NSRect)frameRect {
|
||||||
|
return frameRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface ControlRegionView : NSView {
|
||||||
|
@private
|
||||||
|
atom::NativeWindowMac* shellWindow_; // Weak; owns self.
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ControlRegionView
|
||||||
|
|
||||||
|
- (id)initWithShellWindow:(atom::NativeWindowMac*)shellWindow {
|
||||||
|
if ((self = [super init]))
|
||||||
|
shellWindow_ = shellWindow;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)mouseDownCanMoveWindow {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||||
|
if (!shellWindow_->IsWithinDraggableRegion(aPoint)) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent*)event {
|
||||||
|
shellWindow_->HandleMouseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDragged:(NSEvent*)event {
|
||||||
|
shellWindow_->HandleMouseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
||||||
|
@ -100,7 +190,13 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
||||||
NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask |
|
NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask |
|
||||||
NSMiniaturizableWindowMask | NSResizableWindowMask |
|
NSMiniaturizableWindowMask | NSResizableWindowMask |
|
||||||
NSTexturedBackgroundWindowMask;
|
NSTexturedBackgroundWindowMask;
|
||||||
AtomNSWindow* atom_window = [[AtomNSWindow alloc]
|
AtomNSWindow* atom_window = has_frame_ ?
|
||||||
|
[[AtomNSWindow alloc]
|
||||||
|
initWithContentRect:cocoa_bounds
|
||||||
|
styleMask:style_mask
|
||||||
|
backing:NSBackingStoreBuffered
|
||||||
|
defer:YES] :
|
||||||
|
[[AtomNSWindow alloc]
|
||||||
initWithContentRect:cocoa_bounds
|
initWithContentRect:cocoa_bounds
|
||||||
styleMask:style_mask
|
styleMask:style_mask
|
||||||
backing:NSBackingStoreBuffered
|
backing:NSBackingStoreBuffered
|
||||||
|
@ -119,6 +215,9 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
||||||
[window() setCollectionBehavior:collectionBehavior];
|
[window() setCollectionBehavior:collectionBehavior];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||||
|
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||||
|
|
||||||
InstallView();
|
InstallView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,6 +423,43 @@ gfx::NativeWindow NativeWindowMac::GetNativeWindow() {
|
||||||
return window();
|
return window();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
|
||||||
|
if (!draggable_region_)
|
||||||
|
return false;
|
||||||
|
NSView* webView = web_contents()->GetView()->GetNativeView();
|
||||||
|
NSInteger webViewHeight = NSHeight([webView bounds]);
|
||||||
|
// |draggable_region_| is stored in local platform-indepdent coordiate system
|
||||||
|
// while |point| is in local Cocoa coordinate system. Do the conversion
|
||||||
|
// to match these two.
|
||||||
|
return draggable_region_->contains(point.x, webViewHeight - point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeWindowMac::HandleMouseEvent(NSEvent* event) {
|
||||||
|
NSPoint current_mouse_location =
|
||||||
|
[window() convertBaseToScreen:[event locationInWindow]];
|
||||||
|
|
||||||
|
if ([event type] == NSLeftMouseDown) {
|
||||||
|
NSPoint frame_origin = [window() frame].origin;
|
||||||
|
last_mouse_offset_ = NSMakePoint(
|
||||||
|
frame_origin.x - current_mouse_location.x,
|
||||||
|
frame_origin.y - current_mouse_location.y);
|
||||||
|
} else if ([event type] == NSLeftMouseDragged) {
|
||||||
|
[window() setFrameOrigin:NSMakePoint(
|
||||||
|
current_mouse_location.x + last_mouse_offset_.x,
|
||||||
|
current_mouse_location.y + last_mouse_offset_.y)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeWindowMac::UpdateDraggableRegions(
|
||||||
|
const std::vector<DraggableRegion>& regions) {
|
||||||
|
// Draggable region is not supported for non-frameless window.
|
||||||
|
if (has_frame_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateDraggableRegionsForCustomDrag(regions);
|
||||||
|
InstallDraggableRegionViews();
|
||||||
|
}
|
||||||
|
|
||||||
void NativeWindowMac::HandleKeyboardEvent(
|
void NativeWindowMac::HandleKeyboardEvent(
|
||||||
content::WebContents*,
|
content::WebContents*,
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
@ -339,16 +475,87 @@ void NativeWindowMac::HandleKeyboardEvent(
|
||||||
|
|
||||||
void NativeWindowMac::InstallView() {
|
void NativeWindowMac::InstallView() {
|
||||||
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||||
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
if (has_frame_) {
|
||||||
[view setFrame:[[window() contentView] bounds]];
|
[view setFrame:[[window() contentView] bounds]];
|
||||||
[[window() contentView] addSubview:view];
|
[[window() contentView] addSubview:view];
|
||||||
|
} else {
|
||||||
|
NSView* frameView = [[window() contentView] superview];
|
||||||
|
[view setFrame:[frameView bounds]];
|
||||||
|
[frameView addSubview:view];
|
||||||
|
|
||||||
|
[[window() standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||||
|
[[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
||||||
|
[[window() standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
||||||
|
[[window() standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::UninstallView() {
|
void NativeWindowMac::UninstallView() {
|
||||||
NSView* view = GetWebContents()->GetView()->GetNativeView();
|
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||||
[view removeFromSuperview];
|
[view removeFromSuperview];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeWindowMac::InstallDraggableRegionViews() {
|
||||||
|
DCHECK(!has_frame_);
|
||||||
|
|
||||||
|
// All ControlRegionViews should be added as children of the WebContentsView,
|
||||||
|
// because WebContentsView will be removed and re-added when entering and
|
||||||
|
// leaving fullscreen mode.
|
||||||
|
NSView* webView = GetWebContents()->GetView()->GetNativeView();
|
||||||
|
NSInteger webViewHeight = NSHeight([webView bounds]);
|
||||||
|
|
||||||
|
// Remove all ControlRegionViews that are added last time.
|
||||||
|
// Note that [webView subviews] returns the view's mutable internal array and
|
||||||
|
// it should be copied to avoid mutating the original array while enumerating
|
||||||
|
// it.
|
||||||
|
scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
|
||||||
|
for (NSView* subview in subviews.get())
|
||||||
|
if ([subview isKindOfClass:[ControlRegionView class]])
|
||||||
|
[subview removeFromSuperview];
|
||||||
|
|
||||||
|
// Create and add ControlRegionView for each region that needs to be excluded
|
||||||
|
// from the dragging.
|
||||||
|
for (std::vector<gfx::Rect>::const_iterator iter =
|
||||||
|
system_drag_exclude_areas_.begin();
|
||||||
|
iter != system_drag_exclude_areas_.end();
|
||||||
|
++iter) {
|
||||||
|
scoped_nsobject<NSView> controlRegion(
|
||||||
|
[[ControlRegionView alloc] initWithShellWindow:this]);
|
||||||
|
[controlRegion setFrame:NSMakeRect(iter->x(),
|
||||||
|
webViewHeight - iter->bottom(),
|
||||||
|
iter->width(),
|
||||||
|
iter->height())];
|
||||||
|
[webView addSubview:controlRegion];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeWindowMac::UpdateDraggableRegionsForCustomDrag(
|
||||||
|
const std::vector<DraggableRegion>& regions) {
|
||||||
|
// We still need one ControlRegionView to cover the whole window such that
|
||||||
|
// mouse events could be captured.
|
||||||
|
NSView* web_view = GetWebContents()->GetView()->GetNativeView();
|
||||||
|
gfx::Rect window_bounds(
|
||||||
|
0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
|
||||||
|
system_drag_exclude_areas_.clear();
|
||||||
|
system_drag_exclude_areas_.push_back(window_bounds);
|
||||||
|
|
||||||
|
// Aggregate the draggable areas and non-draggable areas such that hit test
|
||||||
|
// could be performed easily.
|
||||||
|
SkRegion* draggable_region = new SkRegion;
|
||||||
|
for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
|
||||||
|
iter != regions.end();
|
||||||
|
++iter) {
|
||||||
|
const DraggableRegion& region = *iter;
|
||||||
|
draggable_region->op(
|
||||||
|
region.bounds.x(),
|
||||||
|
region.bounds.y(),
|
||||||
|
region.bounds.right(),
|
||||||
|
region.bounds.bottom(),
|
||||||
|
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
|
||||||
|
}
|
||||||
|
draggable_region_.reset(draggable_region);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
|
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
|
||||||
base::DictionaryValue* options) {
|
base::DictionaryValue* options) {
|
||||||
|
|
|
@ -6,8 +6,14 @@
|
||||||
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
|
#include "common/draggable_region.h"
|
||||||
#include "common/options_switches.h"
|
#include "common/options_switches.h"
|
||||||
#include "content/public/browser/native_web_keyboard_event.h"
|
#include "content/public/browser/native_web_keyboard_event.h"
|
||||||
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
#include "content/public/browser/render_widget_host_view.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "content/public/browser/web_contents_view.h"
|
||||||
|
#include "ui/gfx/path.h"
|
||||||
#include "ui/views/controls/webview/webview.h"
|
#include "ui/views/controls/webview/webview.h"
|
||||||
#include "ui/views/widget/widget.h"
|
#include "ui/views/widget/widget.h"
|
||||||
#include "ui/views/window/client_view.h"
|
#include "ui/views/window/client_view.h"
|
||||||
|
@ -17,6 +23,9 @@ namespace atom {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const int kResizeInsideBoundsSize = 5;
|
||||||
|
const int kResizeAreaCornerSize = 16;
|
||||||
|
|
||||||
class NativeWindowClientView : public views::ClientView {
|
class NativeWindowClientView : public views::ClientView {
|
||||||
public:
|
public:
|
||||||
NativeWindowClientView(views::Widget* widget,
|
NativeWindowClientView(views::Widget* widget,
|
||||||
|
@ -60,6 +69,99 @@ class NativeWindowFrameView : public views::NativeFrameView {
|
||||||
DISALLOW_COPY_AND_ASSIGN(NativeWindowFrameView);
|
DISALLOW_COPY_AND_ASSIGN(NativeWindowFrameView);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NativeWindowFramelessView : public views::NonClientFrameView {
|
||||||
|
public:
|
||||||
|
explicit NativeWindowFramelessView(views::Widget* frame,
|
||||||
|
NativeWindowWin* shell)
|
||||||
|
: frame_(frame),
|
||||||
|
shell_(shell) {
|
||||||
|
}
|
||||||
|
virtual ~NativeWindowFramelessView() {}
|
||||||
|
|
||||||
|
// views::NonClientFrameView implementations:
|
||||||
|
virtual gfx::Rect NativeWindowFramelessView::GetBoundsForClientView() const
|
||||||
|
OVERRIDE {
|
||||||
|
return bounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual gfx::Rect NativeWindowFramelessView::GetWindowBoundsForClientBounds(
|
||||||
|
const gfx::Rect& client_bounds) const OVERRIDE {
|
||||||
|
gfx::Rect window_bounds = client_bounds;
|
||||||
|
// Enforce minimum size (1, 1) in case that client_bounds is passed with
|
||||||
|
// empty size. This could occur when the frameless window is being
|
||||||
|
// initialized.
|
||||||
|
if (window_bounds.IsEmpty()) {
|
||||||
|
window_bounds.set_width(1);
|
||||||
|
window_bounds.set_height(1);
|
||||||
|
}
|
||||||
|
return window_bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
|
||||||
|
if (frame_->IsFullscreen())
|
||||||
|
return HTCLIENT;
|
||||||
|
|
||||||
|
// Check the frame first, as we allow a small area overlapping the contents
|
||||||
|
// to be used for resize handles.
|
||||||
|
bool can_ever_resize = frame_->widget_delegate() ?
|
||||||
|
frame_->widget_delegate()->CanResize() :
|
||||||
|
false;
|
||||||
|
// Don't allow overlapping resize handles when the window is maximized or
|
||||||
|
// fullscreen, as it can't be resized in those states.
|
||||||
|
int resize_border =
|
||||||
|
frame_->IsMaximized() || frame_->IsFullscreen() ? 0 :
|
||||||
|
kResizeInsideBoundsSize;
|
||||||
|
int frame_component = GetHTComponentForFrame(point,
|
||||||
|
resize_border,
|
||||||
|
resize_border,
|
||||||
|
kResizeAreaCornerSize,
|
||||||
|
kResizeAreaCornerSize,
|
||||||
|
can_ever_resize);
|
||||||
|
if (frame_component != HTNOWHERE)
|
||||||
|
return frame_component;
|
||||||
|
|
||||||
|
// Check for possible draggable region in the client area for the frameless
|
||||||
|
// window.
|
||||||
|
if (shell_->draggable_region() &&
|
||||||
|
shell_->draggable_region()->contains(point.x(), point.y()))
|
||||||
|
return HTCAPTION;
|
||||||
|
|
||||||
|
int client_component = frame_->client_view()->NonClientHitTest(point);
|
||||||
|
if (client_component != HTNOWHERE)
|
||||||
|
return client_component;
|
||||||
|
|
||||||
|
// Caption is a safe default.
|
||||||
|
return HTCAPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void GetWindowMask(const gfx::Size& size,
|
||||||
|
gfx::Path* window_mask) OVERRIDE {}
|
||||||
|
virtual void ResetWindowControls() OVERRIDE {}
|
||||||
|
virtual void UpdateWindowIcon() OVERRIDE {}
|
||||||
|
virtual void UpdateWindowTitle() OVERRIDE {}
|
||||||
|
|
||||||
|
// views::View implementations:
|
||||||
|
virtual gfx::Size NativeWindowFramelessView::GetPreferredSize() OVERRIDE {
|
||||||
|
gfx::Size pref = frame_->client_view()->GetPreferredSize();
|
||||||
|
gfx::Rect bounds(0, 0, pref.width(), pref.height());
|
||||||
|
return frame_->non_client_view()->GetWindowBoundsForClientBounds(
|
||||||
|
bounds).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual gfx::Size GetMinimumSize() OVERRIDE {
|
||||||
|
return shell_->GetMinimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual gfx::Size GetMaximumSize() OVERRIDE {
|
||||||
|
return shell_->GetMaximumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
views::Widget* frame_;
|
||||||
|
NativeWindowWin* shell_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(NativeWindowFramelessView);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -71,6 +173,7 @@ NativeWindowWin::NativeWindowWin(content::WebContents* web_contents,
|
||||||
resizable_(true) {
|
resizable_(true) {
|
||||||
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
|
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
|
||||||
params.delegate = this;
|
params.delegate = this;
|
||||||
|
params.remove_standard_frame = !has_frame_;
|
||||||
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
||||||
window_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_NATIVE);
|
window_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_NATIVE);
|
||||||
window_->Init(params);
|
window_->Init(params);
|
||||||
|
@ -83,6 +186,7 @@ NativeWindowWin::NativeWindowWin(content::WebContents* web_contents,
|
||||||
window_->CenterWindow(size);
|
window_->CenterWindow(size);
|
||||||
|
|
||||||
web_view_->SetWebContents(web_contents);
|
web_view_->SetWebContents(web_contents);
|
||||||
|
OnViewWasResized();
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeWindowWin::~NativeWindowWin() {
|
NativeWindowWin::~NativeWindowWin() {
|
||||||
|
@ -221,6 +325,30 @@ gfx::NativeWindow NativeWindowWin::GetNativeWindow() {
|
||||||
return window_->GetNativeView();
|
return window_->GetNativeView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeWindowWin::UpdateDraggableRegions(
|
||||||
|
const std::vector<DraggableRegion>& regions) {
|
||||||
|
if (has_frame_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SkRegion* draggable_region = new SkRegion;
|
||||||
|
|
||||||
|
// By default, the whole window is non-draggable. We need to explicitly
|
||||||
|
// include those draggable regions.
|
||||||
|
for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
|
||||||
|
iter != regions.end(); ++iter) {
|
||||||
|
const DraggableRegion& region = *iter;
|
||||||
|
draggable_region->op(
|
||||||
|
region.bounds.x(),
|
||||||
|
region.bounds.y(),
|
||||||
|
region.bounds.right(),
|
||||||
|
region.bounds.bottom(),
|
||||||
|
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
|
||||||
|
}
|
||||||
|
|
||||||
|
draggable_region_.reset(draggable_region);
|
||||||
|
OnViewWasResized();
|
||||||
|
}
|
||||||
|
|
||||||
void NativeWindowWin::HandleKeyboardEvent(
|
void NativeWindowWin::HandleKeyboardEvent(
|
||||||
content::WebContents*,
|
content::WebContents*,
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
@ -264,7 +392,40 @@ views::ClientView* NativeWindowWin::CreateClientView(views::Widget* widget) {
|
||||||
|
|
||||||
views::NonClientFrameView* NativeWindowWin::CreateNonClientFrameView(
|
views::NonClientFrameView* NativeWindowWin::CreateNonClientFrameView(
|
||||||
views::Widget* widget) {
|
views::Widget* widget) {
|
||||||
|
if (has_frame_)
|
||||||
return new NativeWindowFrameView(widget, this);
|
return new NativeWindowFrameView(widget, this);
|
||||||
|
|
||||||
|
return new NativeWindowFramelessView(widget, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeWindowWin::OnViewWasResized() {
|
||||||
|
// Set the window shape of the RWHV.
|
||||||
|
gfx::Size sz = web_view_->size();
|
||||||
|
int height = sz.height(), width = sz.width();
|
||||||
|
gfx::Path path;
|
||||||
|
path.addRect(0, 0, width, height);
|
||||||
|
SetWindowRgn(web_contents()->GetView()->GetNativeView(),
|
||||||
|
path.CreateNativeRegion(),
|
||||||
|
1);
|
||||||
|
|
||||||
|
SkRegion* rgn = new SkRegion;
|
||||||
|
if (!window_->IsFullscreen() && !window_->IsMaximized()) {
|
||||||
|
if (draggable_region())
|
||||||
|
rgn->op(*draggable_region(), SkRegion::kUnion_Op);
|
||||||
|
|
||||||
|
if (!has_frame_ && CanResize()) {
|
||||||
|
rgn->op(0, 0, width, kResizeInsideBoundsSize, SkRegion::kUnion_Op);
|
||||||
|
rgn->op(0, 0, kResizeInsideBoundsSize, height, SkRegion::kUnion_Op);
|
||||||
|
rgn->op(width - kResizeInsideBoundsSize, 0, width, height,
|
||||||
|
SkRegion::kUnion_Op);
|
||||||
|
rgn->op(0, height - kResizeInsideBoundsSize, width, height,
|
||||||
|
SkRegion::kUnion_Op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content::WebContents* web_contents = GetWebContents();
|
||||||
|
if (web_contents->GetRenderViewHost()->GetView())
|
||||||
|
web_contents->GetRenderViewHost()->GetView()->SetClickthroughRegion(rgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -60,7 +60,12 @@ class NativeWindowWin : public NativeWindow,
|
||||||
virtual bool IsKiosk() OVERRIDE;
|
virtual bool IsKiosk() OVERRIDE;
|
||||||
virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
|
virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
|
||||||
|
|
||||||
|
SkRegion* draggable_region() { return draggable_region_.get(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void UpdateDraggableRegions(
|
||||||
|
const std::vector<DraggableRegion>& regions) OVERRIDE;
|
||||||
|
|
||||||
// Overridden from content::WebContentsDelegate:
|
// Overridden from content::WebContentsDelegate:
|
||||||
virtual void HandleKeyboardEvent(
|
virtual void HandleKeyboardEvent(
|
||||||
content::WebContents*,
|
content::WebContents*,
|
||||||
|
@ -79,9 +84,13 @@ class NativeWindowWin : public NativeWindow,
|
||||||
views::Widget* widget) OVERRIDE;
|
views::Widget* widget) OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void OnViewWasResized();
|
||||||
|
|
||||||
scoped_ptr<views::Widget> window_;
|
scoped_ptr<views::Widget> window_;
|
||||||
views::WebView* web_view_; // managed by window_.
|
views::WebView* web_view_; // managed by window_.
|
||||||
|
|
||||||
|
scoped_ptr<SkRegion> draggable_region_;
|
||||||
|
|
||||||
bool resizable_;
|
bool resizable_;
|
||||||
string16 title_;
|
string16 title_;
|
||||||
gfx::Size minimum_size_;
|
gfx::Size minimum_size_;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
|
#include "common/draggable_region.h"
|
||||||
#include "content/public/common/common_param_traits.h"
|
#include "content/public/common/common_param_traits.h"
|
||||||
#include "ipc/ipc_message_macros.h"
|
#include "ipc/ipc_message_macros.h"
|
||||||
|
|
||||||
|
@ -15,6 +16,11 @@
|
||||||
|
|
||||||
#define IPC_MESSAGE_START ShellMsgStart
|
#define IPC_MESSAGE_START ShellMsgStart
|
||||||
|
|
||||||
|
IPC_STRUCT_TRAITS_BEGIN(atom::DraggableRegion)
|
||||||
|
IPC_STRUCT_TRAITS_MEMBER(draggable)
|
||||||
|
IPC_STRUCT_TRAITS_MEMBER(bounds)
|
||||||
|
IPC_STRUCT_TRAITS_END()
|
||||||
|
|
||||||
IPC_MESSAGE_ROUTED2(AtomViewHostMsg_Message,
|
IPC_MESSAGE_ROUTED2(AtomViewHostMsg_Message,
|
||||||
std::string /* channel */,
|
std::string /* channel */,
|
||||||
ListValue /* arguments */)
|
ListValue /* arguments */)
|
||||||
|
@ -27,3 +33,7 @@ IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync,
|
||||||
IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
|
IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
|
||||||
std::string /* channel */,
|
std::string /* channel */,
|
||||||
ListValue /* arguments */)
|
ListValue /* arguments */)
|
||||||
|
|
||||||
|
// Sent by the renderer when the draggable regions are updated.
|
||||||
|
IPC_MESSAGE_ROUTED1(AtomViewHostMsg_UpdateDraggableRegions,
|
||||||
|
std::vector<atom::DraggableRegion> /* regions */)
|
||||||
|
|
13
common/draggable_region.cc
Normal file
13
common/draggable_region.cc
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "common/draggable_region.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
DraggableRegion::DraggableRegion()
|
||||||
|
: draggable(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
21
common/draggable_region.h
Normal file
21
common/draggable_region.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_COMMON_DRAGGABLE_REGION_H_
|
||||||
|
#define ATOM_COMMON_DRAGGABLE_REGION_H_
|
||||||
|
|
||||||
|
#include "ui/gfx/rect.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
struct DraggableRegion {
|
||||||
|
bool draggable;
|
||||||
|
gfx::Rect bounds;
|
||||||
|
|
||||||
|
DraggableRegion();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_COMMON_DRAGGABLE_REGION_H_
|
|
@ -1,4 +1,4 @@
|
||||||
## Synopsis
|
# browser-window
|
||||||
|
|
||||||
The `BrowserWindow` class gives you ability to create a browser window, an
|
The `BrowserWindow` class gives you ability to create a browser window, an
|
||||||
example is:
|
example is:
|
||||||
|
@ -15,6 +15,10 @@ win.loadUrl('https://github.com');
|
||||||
win.show();
|
win.show();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also create a window without chrome by using
|
||||||
|
[Frameless Window](frameless-window.md) API.
|
||||||
|
|
||||||
|
|
||||||
**Note:** Be careful not to use `window` as the variable name.
|
**Note:** Be careful not to use `window` as the variable name.
|
||||||
|
|
||||||
## Class: BrowserWindow
|
## Class: BrowserWindow
|
||||||
|
@ -38,6 +42,8 @@ win.show();
|
||||||
* `kiosk` Boolean - The kiosk mode
|
* `kiosk` Boolean - The kiosk mode
|
||||||
* `title` String - Default window title
|
* `title` String - Default window title
|
||||||
* `show` Boolean - Whether window should be shown when created
|
* `show` Boolean - Whether window should be shown when created
|
||||||
|
* `frame` Boolean - Specify `false` to create a
|
||||||
|
[Frameless Window](frameless-window.md)
|
||||||
|
|
||||||
Creates a new `BrowserWindow` with native properties set by the `options`.
|
Creates a new `BrowserWindow` with native properties set by the `options`.
|
||||||
Usually you only need to set the `width` and `height`, other properties will
|
Usually you only need to set the `width` and `height`, other properties will
|
||||||
|
|
64
docs/frameless-window.md
Normal file
64
docs/frameless-window.md
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# Frameless window
|
||||||
|
|
||||||
|
A frameless window is a window that has no chrome.
|
||||||
|
|
||||||
|
## Create a frameless window
|
||||||
|
|
||||||
|
To create a frameless window, you only need to specify `frame` to `false` in
|
||||||
|
[BrowserWindow](browser-window.md)'s `options`:
|
||||||
|
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var BrowserWindow = require('browser-window');
|
||||||
|
var win = new BrowserWindow({ width: 800, height: 600, frame: false });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Draggable region
|
||||||
|
|
||||||
|
By default, the frameless window is non-draggable. Apps need to specify
|
||||||
|
`-webkit-app-region: drag` in CSS to tell atom-shell which regions are draggable
|
||||||
|
(like the OS's standard titlebar), and apps can also use
|
||||||
|
`-webkit-app-region: no-drag` to exclude the non-draggable area from the
|
||||||
|
draggable region. Note that only rectangular shape is currently supported.
|
||||||
|
|
||||||
|
To make the whole window draggable, you can add `-webkit-app-region: drag` as
|
||||||
|
`body`'s style:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body style="-webkit-app-region: drag">
|
||||||
|
</body>
|
||||||
|
```
|
||||||
|
|
||||||
|
And note that if you have made the whole window draggable, you must also mark
|
||||||
|
buttons as non-draggable, otherwise it would be impossible for users to click on
|
||||||
|
them:
|
||||||
|
|
||||||
|
```css
|
||||||
|
button {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're only using a custom titlebar, you also need to make buttons in
|
||||||
|
titlebar non-draggable.
|
||||||
|
|
||||||
|
## Text selection
|
||||||
|
|
||||||
|
One thing on frameless window is that the dragging behaviour may conflict with
|
||||||
|
selecting text, for example, when you drag the titlebar, you may accidentally
|
||||||
|
select the text on titlebar. To prevent this, you need to disable text
|
||||||
|
selection on dragging area like this:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.titlebar {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##Context menu
|
||||||
|
|
||||||
|
On some platforms, the draggable area would be treated as non-client frame, so
|
||||||
|
when you right click on it a system menu would be popuped. To make context menu
|
||||||
|
behave correctly on all platforms, you should never custom context menu on
|
||||||
|
draggable areas.
|
|
@ -12,6 +12,8 @@
|
||||||
#include "ipc/ipc_message_macros.h"
|
#include "ipc/ipc_message_macros.h"
|
||||||
#include "renderer/api/atom_renderer_bindings.h"
|
#include "renderer/api/atom_renderer_bindings.h"
|
||||||
#include "renderer/atom_renderer_client.h"
|
#include "renderer/atom_renderer_client.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDraggableRegion.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
||||||
#include "v8/include/v8.h"
|
#include "v8/include/v8.h"
|
||||||
|
|
||||||
|
@ -76,6 +78,19 @@ void AtomRenderViewObserver::FrameWillClose(WebFrame* frame) {
|
||||||
vec.erase(std::remove(vec.begin(), vec.end(), frame), vec.end());
|
vec.erase(std::remove(vec.begin(), vec.end(), frame), vec.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AtomRenderViewObserver::DraggableRegionsChanged(WebKit::WebFrame* frame) {
|
||||||
|
WebKit::WebVector<WebKit::WebDraggableRegion> webregions =
|
||||||
|
frame->document().draggableRegions();
|
||||||
|
std::vector<DraggableRegion> regions;
|
||||||
|
for (size_t i = 0; i < webregions.size(); ++i) {
|
||||||
|
DraggableRegion region;
|
||||||
|
region.bounds = webregions[i].bounds;
|
||||||
|
region.draggable = webregions[i].draggable;
|
||||||
|
regions.push_back(region);
|
||||||
|
}
|
||||||
|
Send(new AtomViewHostMsg_UpdateDraggableRegions(routing_id(), regions));
|
||||||
|
}
|
||||||
|
|
||||||
bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
|
bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
|
IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
|
||||||
|
|
|
@ -32,6 +32,7 @@ class AtomRenderViewObserver : content::RenderViewObserver {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// content::RenderViewObserver implementation.
|
// content::RenderViewObserver implementation.
|
||||||
|
virtual void DraggableRegionsChanged(WebKit::WebFrame* frame) OVERRIDE;
|
||||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||||
|
|
||||||
void OnBrowserMessage(const std::string& channel,
|
void OnBrowserMessage(const std::string& channel,
|
||||||
|
|
Loading…
Reference in a new issue