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) {
 | 
				
			||||||
  return new NativeWindowFrameView(widget, this);
 | 
					  if (has_frame_)
 | 
				
			||||||
 | 
					    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…
	
	Add table
		Add a link
		
	
		Reference in a new issue