win: Implement frameless window.
This commit is contained in:
parent
db6c37bfbc
commit
6de595f036
8 changed files with 192 additions and 80 deletions
2
atom.gyp
2
atom.gyp
|
@ -135,6 +135,8 @@
|
|||
'atom/browser/ui/tray_icon_cocoa.mm',
|
||||
'atom/browser/ui/tray_icon_observer.h',
|
||||
'atom/browser/ui/tray_icon_win.cc',
|
||||
'atom/browser/ui/views/frameless_view.cc',
|
||||
'atom/browser/ui/views/frameless_view.h',
|
||||
'atom/browser/ui/views/global_menu_bar_x11.cc',
|
||||
'atom/browser/ui/views/global_menu_bar_x11.h',
|
||||
'atom/browser/ui/views/linux_frame_view.cc',
|
||||
|
|
|
@ -81,6 +81,9 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
|
|||
#if defined(USE_X11)
|
||||
// In X11 the window frame is drawn by the application.
|
||||
params.remove_standard_frame = true;
|
||||
#elif defined(OS_WIN)
|
||||
if (!has_frame_)
|
||||
params.remove_standard_frame = true;
|
||||
#endif
|
||||
|
||||
bool skip_taskbar = false;
|
||||
|
@ -370,18 +373,16 @@ bool NativeWindowViews::ShouldDescendIntoChildForEventHandling(
|
|||
gfx::NativeView child,
|
||||
const gfx::Point& location) {
|
||||
// App window should claim mouse events that fall within the draggable region.
|
||||
if (draggable_region_.get() &&
|
||||
if (draggable_region_ &&
|
||||
draggable_region_->contains(location.x(), location.y()))
|
||||
return false;
|
||||
|
||||
#if defined(USE_X11)
|
||||
// And the events on border for dragging resizable frameless window.
|
||||
if (!has_frame_ && CanResize()) {
|
||||
LinuxFrameView* frame = static_cast<LinuxFrameView*>(
|
||||
FramelessView* frame = static_cast<FramelessView*>(
|
||||
window_->non_client_view()->frame_view());
|
||||
return frame->ResizingBorderHitTest(location) == HTNOWHERE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -394,13 +395,11 @@ views::NonClientFrameView* NativeWindowViews::CreateNonClientFrameView(
|
|||
views::Widget* widget) {
|
||||
#if defined(USE_X11)
|
||||
LinuxFrameView* frame_view = new LinuxFrameView;
|
||||
#else defined(OS_WIN)
|
||||
WinFrameView* frame_view = new WinFrameView;
|
||||
#endif
|
||||
frame_view->Init(this, widget);
|
||||
return frame_view;
|
||||
#elif defined(OS_WIN)
|
||||
return new WinFrameView(widget);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::HandleKeyboardEvent(
|
||||
|
|
113
atom/browser/ui/views/frameless_view.cc
Normal file
113
atom/browser/ui/views/frameless_view.cc
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/ui/views/frameless_view.h"
|
||||
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "ui/aura/window.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
#include "ui/views/widget/widget_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kResizeInsideBoundsSize = 5;
|
||||
const int kResizeAreaCornerSize = 16;
|
||||
const char kViewClassName[] = "FramelessView";
|
||||
|
||||
} // namespace
|
||||
|
||||
FramelessView::FramelessView() : window_(NULL), frame_(NULL) {
|
||||
}
|
||||
|
||||
FramelessView::~FramelessView() {
|
||||
}
|
||||
|
||||
void FramelessView::Init(NativeWindowViews* window, views::Widget* frame) {
|
||||
window_ = window;
|
||||
frame_ = frame;
|
||||
}
|
||||
|
||||
int FramelessView::ResizingBorderHitTest(const gfx::Point& point) {
|
||||
// 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;
|
||||
return GetHTComponentForFrame(point, resize_border, resize_border,
|
||||
kResizeAreaCornerSize, kResizeAreaCornerSize, can_ever_resize);
|
||||
}
|
||||
|
||||
gfx::Rect FramelessView::GetBoundsForClientView() const {
|
||||
return bounds();
|
||||
}
|
||||
|
||||
gfx::Rect FramelessView::GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const {
|
||||
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;
|
||||
}
|
||||
|
||||
int FramelessView::NonClientHitTest(const gfx::Point& cursor) {
|
||||
if (frame_->IsFullscreen())
|
||||
return HTCLIENT;
|
||||
|
||||
// Check for possible draggable region in the client area for the frameless
|
||||
// window.
|
||||
SkRegion* draggable_region = window_->draggable_region();
|
||||
if (draggable_region && draggable_region->contains(cursor.x(), cursor.y()))
|
||||
return HTCAPTION;
|
||||
|
||||
// Support resizing frameless window by dragging the border.
|
||||
int frame_component = ResizingBorderHitTest(cursor);
|
||||
if (frame_component != HTNOWHERE)
|
||||
return frame_component;
|
||||
|
||||
return HTCLIENT;
|
||||
}
|
||||
|
||||
void FramelessView::GetWindowMask(const gfx::Size& size,
|
||||
gfx::Path* window_mask) {
|
||||
}
|
||||
|
||||
void FramelessView::ResetWindowControls() {
|
||||
}
|
||||
|
||||
void FramelessView::UpdateWindowIcon() {
|
||||
}
|
||||
|
||||
void FramelessView::UpdateWindowTitle() {
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetPreferredSize() {
|
||||
return frame_->non_client_view()->GetWindowBoundsForClientBounds(
|
||||
gfx::Rect(frame_->client_view()->GetPreferredSize())).size();
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetMinimumSize() {
|
||||
return window_->GetMinimumSize();
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetMaximumSize() {
|
||||
return window_->GetMaximumSize();
|
||||
}
|
||||
|
||||
const char* FramelessView::GetClassName() const {
|
||||
return kViewClassName;
|
||||
}
|
||||
|
||||
} // namespace atom
|
56
atom/browser/ui/views/frameless_view.h
Normal file
56
atom/browser/ui/views/frameless_view.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_UI_VIEWS_FRAMELESS_VIEW_H_
|
||||
#define ATOM_BROWSER_UI_VIEWS_FRAMELESS_VIEW_H_
|
||||
|
||||
#include "ui/views/window/non_client_view.h"
|
||||
|
||||
namespace views {
|
||||
class Widget;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeWindowViews;
|
||||
|
||||
class FramelessView : public views::NonClientFrameView {
|
||||
public:
|
||||
FramelessView();
|
||||
virtual ~FramelessView();
|
||||
|
||||
virtual void Init(NativeWindowViews* window, views::Widget* frame);
|
||||
|
||||
// Returns whether the |point| is on frameless window's resizing border.
|
||||
int ResizingBorderHitTest(const gfx::Point& point);
|
||||
|
||||
protected:
|
||||
// views::NonClientFrameView:
|
||||
virtual gfx::Rect GetBoundsForClientView() const OVERRIDE;
|
||||
virtual gfx::Rect GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const OVERRIDE;
|
||||
virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE;
|
||||
virtual void GetWindowMask(const gfx::Size& size,
|
||||
gfx::Path* window_mask) OVERRIDE;
|
||||
virtual void ResetWindowControls() OVERRIDE;
|
||||
virtual void UpdateWindowIcon() OVERRIDE;
|
||||
virtual void UpdateWindowTitle() OVERRIDE;
|
||||
|
||||
// Overridden from View:
|
||||
virtual gfx::Size GetPreferredSize() OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() OVERRIDE;
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
|
||||
// Not owned.
|
||||
NativeWindowViews* window_;
|
||||
views::Widget* frame_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FramelessView);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_UI_VIEWS_FRAMELESS_VIEW_H_
|
|
@ -91,8 +91,7 @@ LinuxFrameView::~LinuxFrameView() {
|
|||
}
|
||||
|
||||
void LinuxFrameView::Init(NativeWindowViews* window, views::Widget* frame) {
|
||||
window_ = window;
|
||||
frame_ = frame;
|
||||
FramelessView::Init(window, frame);
|
||||
|
||||
close_button_ = new views::ImageButton(this);
|
||||
close_button_->SetAccessibleName(
|
||||
|
|
|
@ -5,12 +5,10 @@
|
|||
#ifndef ATOM_BROWSER_UI_VIEWS_LINUX_FRAME_VIEW_H_
|
||||
#define ATOM_BROWSER_UI_VIEWS_LINUX_FRAME_VIEW_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "atom/browser/ui/views/frameless_view.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "ui/views/controls/button/button.h"
|
||||
#include "ui/views/window/frame_buttons.h"
|
||||
#include "ui/views/window/non_client_view.h"
|
||||
|
||||
namespace gfx {
|
||||
class ImageSkia;
|
||||
|
@ -19,20 +17,17 @@ class ImageSkia;
|
|||
namespace views {
|
||||
class FrameBackground;
|
||||
class ImageButton;
|
||||
class Widget;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeWindowViews;
|
||||
|
||||
class LinuxFrameView : public views::NonClientFrameView,
|
||||
class LinuxFrameView : public FramelessView
|
||||
public views::ButtonListener {
|
||||
public:
|
||||
LinuxFrameView();
|
||||
virtual ~LinuxFrameView();
|
||||
|
||||
void Init(NativeWindowViews* window, views::Widget* frame);
|
||||
void Init(NativeWindowViews* window, views::Widget* frame) OVERRIDE;
|
||||
|
||||
// Overridden from NonClientFrameView:
|
||||
virtual gfx::Rect GetBoundsForClientView() const OVERRIDE;
|
||||
|
@ -123,10 +118,6 @@ class LinuxFrameView : public views::NonClientFrameView,
|
|||
// The layout rect of the title, if visible.
|
||||
gfx::Rect title_bounds_;
|
||||
|
||||
// Not owned.
|
||||
NativeWindowViews* window_;
|
||||
views::Widget* frame_;
|
||||
|
||||
// The icon of this window. May be NULL.
|
||||
views::ImageButton* window_icon_;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "atom/browser/ui/views/win_frame_view.h"
|
||||
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
#include "ui/views/win/hwnd_util.h"
|
||||
|
||||
|
@ -16,18 +17,13 @@ const char kViewClassName[] = "WinFrameView";
|
|||
} // namespace
|
||||
|
||||
|
||||
WinFrameView::WinFrameView(views::Widget* frame)
|
||||
: frame_(frame) {
|
||||
WinFrameView::WinFrameView() {
|
||||
}
|
||||
|
||||
WinFrameView::~WinFrameView() {
|
||||
}
|
||||
|
||||
|
||||
gfx::Rect WinFrameView::GetBoundsForClientView() const {
|
||||
return gfx::Rect(0, 0, width(), height());
|
||||
}
|
||||
|
||||
gfx::Rect WinFrameView::GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const {
|
||||
gfx::Size size(client_bounds.size());
|
||||
|
@ -36,38 +32,10 @@ gfx::Rect WinFrameView::GetWindowBoundsForClientBounds(
|
|||
}
|
||||
|
||||
int WinFrameView::NonClientHitTest(const gfx::Point& point) {
|
||||
return frame_->client_view()->NonClientHitTest(point);
|
||||
}
|
||||
|
||||
void WinFrameView::GetWindowMask(const gfx::Size& size,
|
||||
gfx::Path* window_mask) {
|
||||
// Nothing to do, we use the default window mask.
|
||||
}
|
||||
|
||||
void WinFrameView::ResetWindowControls() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
void WinFrameView::UpdateWindowIcon() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
void WinFrameView::UpdateWindowTitle() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
gfx::Size WinFrameView::GetPreferredSize() {
|
||||
gfx::Size client_preferred_size = frame_->client_view()->GetPreferredSize();
|
||||
return frame_->non_client_view()->GetWindowBoundsForClientBounds(
|
||||
gfx::Rect(client_preferred_size)).size();
|
||||
}
|
||||
|
||||
gfx::Size WinFrameView::GetMinimumSize() {
|
||||
return frame_->client_view()->GetMinimumSize();
|
||||
}
|
||||
|
||||
gfx::Size WinFrameView::GetMaximumSize() {
|
||||
return frame_->client_view()->GetMaximumSize();
|
||||
if (window_->has_frame())
|
||||
return frame_->client_view()->NonClientHitTest(point);
|
||||
else
|
||||
return FramelessView::NonClientHitTest(point);
|
||||
}
|
||||
|
||||
const char* WinFrameView::GetClassName() const {
|
||||
|
|
|
@ -5,42 +5,26 @@
|
|||
#ifndef ATOM_BROWSER_UI_VIEWS_WIN_FRAME_VIEW_H_
|
||||
#define ATOM_BROWSER_UI_VIEWS_WIN_FRAME_VIEW_H_
|
||||
|
||||
#include "ui/views/window/non_client_view.h"
|
||||
|
||||
namespace views {
|
||||
class Widget;
|
||||
}
|
||||
#include "atom/browser/ui/views/frameless_view.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class WinFrameView : public views::NonClientFrameView {
|
||||
class WinFrameView : public FramelessView {
|
||||
public:
|
||||
explicit WinFrameView(views::Widget* widget);
|
||||
WinFrameView();
|
||||
virtual ~WinFrameView();
|
||||
|
||||
// views::NonClientFrameView:
|
||||
virtual gfx::Rect GetBoundsForClientView() const OVERRIDE;
|
||||
virtual gfx::Rect GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const OVERRIDE;
|
||||
virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE;
|
||||
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:
|
||||
virtual gfx::Size GetPreferredSize() OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() OVERRIDE;
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
|
||||
private:
|
||||
void ClientAreaSizeToWindowSize(gfx::Size* size) const;
|
||||
|
||||
// Our containing frame.
|
||||
views::Widget* frame_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WinFrameView);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue