Merge pull request #12008 from electron/window-refactor-1

Refactor NativeWindow (Part 1): Remove WebContentsObserver methods
This commit is contained in:
Cheng Zhao 2018-02-23 10:06:34 +09:00 committed by GitHub
commit 15ce235eed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 435 additions and 461 deletions

View file

@ -9,7 +9,10 @@
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/unresponsive_suppressor.h"
#include "atom/browser/web_contents_preferences.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
@ -20,11 +23,14 @@
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_switches.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gl/gpu_switching_manager.h"
#if defined(TOOLKIT_VIEWS)
#include "atom/browser/native_window_views.h"
@ -77,7 +83,8 @@ v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
BrowserWindow::BrowserWindow(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options) {
const mate::Dictionary& options)
: weak_factory_(this) {
mate::Handle<class WebContents> web_contents;
// Use options.webPreferences in WebContents.
@ -129,6 +136,8 @@ void BrowserWindow::Init(v8::Isolate* isolate,
mate::Handle<class WebContents> web_contents) {
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
api_web_contents_->AddObserver(this);
Observe(api_web_contents_->web_contents());
// Keep a copy of the options for later use.
mate::Dictionary(isolate, web_contents->GetWrapper()).Set(
@ -147,6 +156,10 @@ void BrowserWindow::Init(v8::Isolate* isolate,
web_contents->SetOwnerWindow(window_.get());
window_->set_is_offscreen_dummy(api_web_contents_->IsOffScreen());
// Tell the content module to initialize renderer widget with transparent
// mode.
ui::GpuSwitchingManager::SetTransparent(window_->transparent());
#if defined(TOOLKIT_VIEWS)
// Sets the window icon.
mate::Handle<NativeImage> icon;
@ -164,22 +177,107 @@ void BrowserWindow::Init(v8::Isolate* isolate,
// window's JS wrapper gets initialized.
if (!parent.IsEmpty())
parent->child_windows_.Set(isolate, ID(), wrapper);
auto* host = web_contents->web_contents()->GetRenderViewHost();
if (host)
host->GetWidget()->AddInputEventObserver(this);
}
BrowserWindow::~BrowserWindow() {
if (!window_->IsClosed())
window_->CloseContents(nullptr);
window_->CloseImmediately();
api_web_contents_->RemoveObserver(this);
// Destroy the native window in next tick because the native code might be
// iterating all windows.
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release());
}
void BrowserWindow::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close");
void BrowserWindow::OnInputEvent(const blink::WebInputEvent& event) {
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
case blink::WebInputEvent::kGestureScrollUpdate:
case blink::WebInputEvent::kGestureScrollEnd:
Emit("scroll-touch-edge");
break;
default:
break;
}
}
void BrowserWindow::WillDestroyNativeObject() {
void BrowserWindow::RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) {
if (old_host)
old_host->GetWidget()->RemoveInputEventObserver(this);
if (new_host)
new_host->GetWidget()->AddInputEventObserver(this);
}
void BrowserWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) {
if (!window_->transparent())
return;
content::RenderWidgetHostImpl* impl = content::RenderWidgetHostImpl::FromID(
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
if (impl)
impl->SetBackgroundOpaque(false);
}
void BrowserWindow::DidFirstVisuallyNonEmptyPaint() {
if (window_->IsVisible())
return;
// When there is a non-empty first paint, resize the RenderWidget to force
// Chromium to draw.
const auto view = web_contents()->GetRenderWidgetHostView();
view->Show();
view->SetSize(window_->GetContentSize());
// Emit the ReadyToShow event in next tick in case of pending drawing work.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind([](base::WeakPtr<BrowserWindow> self) {
if (self)
self->Emit("ready-to-show");
}, GetWeakPtr()));
}
void BrowserWindow::BeforeUnloadDialogCancelled() {
WindowList::WindowCloseCancelled(window_.get());
// Cancel unresponsive event when window close is cancelled.
window_unresponsive_closure_.Cancel();
}
void BrowserWindow::OnRendererUnresponsive(content::RenderWidgetHost*) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
// blocked for a while.
// Also notice that when closing this event would be ignored because we have
// explicitly started a close timeout counter. This is on purpose because we
// don't want the unresponsive event to be sent too early when user is closing
// the window.
ScheduleUnresponsiveEvent(50);
}
bool BrowserWindow::OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserWindow, message, rfh)
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_UpdateDraggableRegions,
UpdateDraggableRegions)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void BrowserWindow::OnCloseContents() {
if (!web_contents())
return;
Observe(nullptr);
// Close all child windows before closing current window.
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
@ -188,6 +286,48 @@ void BrowserWindow::WillDestroyNativeObject() {
if (mate::ConvertFromV8(isolate(), value, &child) && !child.IsEmpty())
child->window_->CloseImmediately();
}
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
window_->CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
window_unresponsive_closure_.Cancel();
}
void BrowserWindow::OnRendererResponsive() {
window_unresponsive_closure_.Cancel();
Emit("responsive");
}
void BrowserWindow::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close");
}
void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
// When user tries to close the window by clicking the close button, we do
// not close the window immediately, instead we try to close the web page
// first, and when the web page is closed the window will also be closed.
*prevent_default = true;
// Assume the window is not responding if it doesn't cancel the close and is
// not closed in 5s, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for
// the unresponsive timeout.
if (window_unresponsive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(5000);
if (!web_contents())
// Already closed by renderer
return;
if (web_contents()->NeedToFireBeforeUnload())
web_contents()->DispatchBeforeUnload();
else
web_contents()->Close();
}
void BrowserWindow::OnWindowClosed() {
@ -231,10 +371,6 @@ void BrowserWindow::OnWindowHide() {
Emit("hide");
}
void BrowserWindow::OnReadyToShow() {
Emit("ready-to-show");
}
void BrowserWindow::OnWindowMaximize() {
Emit("maximize");
}
@ -279,10 +415,6 @@ void BrowserWindow::OnWindowScrollTouchEnd() {
Emit("scroll-touch-end");
}
void BrowserWindow::OnWindowScrollTouchEdge() {
Emit("scroll-touch-edge");
}
void BrowserWindow::OnWindowSwipe(const std::string& direction) {
Emit("swipe", direction);
}
@ -303,14 +435,6 @@ void BrowserWindow::OnWindowLeaveHtmlFullScreen() {
Emit("leave-html-full-screen");
}
void BrowserWindow::OnRendererUnresponsive() {
Emit("unresponsive");
}
void BrowserWindow::OnRendererResponsive() {
Emit("responsive");
}
void BrowserWindow::OnExecuteWindowsCommand(const std::string& command_name) {
Emit("app-command", command_name);
}
@ -1008,6 +1132,32 @@ void BrowserWindow::RemoveFromParentChildWindows() {
parent->child_windows_.Remove(ID());
}
void BrowserWindow::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
window_->UpdateDraggableRegions(regions);
}
void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresponsive_closure_.IsCancelled())
return;
window_unresponsive_closure_.Reset(
base::Bind(&BrowserWindow::NotifyWindowUnresponsive, GetWeakPtr()));
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
window_unresponsive_closure_.callback(),
base::TimeDelta::FromMilliseconds(ms));
}
void BrowserWindow::NotifyWindowUnresponsive() {
window_unresponsive_closure_.Cancel();
if (!window_->IsClosed() && window_->IsEnabled() &&
!IsUnresponsiveEventSuppressed()) {
Emit("unresponsive");
}
}
// static
void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {

View file

@ -10,14 +10,15 @@
#include <string>
#include <vector>
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/native_window.h"
#include "atom/browser/native_window_observer.h"
#include "atom/common/api/atom_api_native_image.h"
#include "atom/common/key_weak_map.h"
#include "native_mate/handle.h"
#include "base/cancelable_callback.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/render_widget_host.h"
#include "native_mate/persistent_dictionary.h"
#include "ui/gfx/image/image.h"
class GURL;
@ -36,9 +37,10 @@ class NativeWindow;
namespace api {
class WebContents;
class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
public content::RenderWidgetHost::InputEventObserver,
public content::WebContentsObserver,
public ExtendedWebContentsObserver,
public NativeWindowObserver {
public:
static mate::WrappableBase* New(mate::Arguments* args);
@ -60,16 +62,32 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
const mate::Dictionary& options);
~BrowserWindow() override;
// content::RenderWidgetHost::InputEventObserver:
void OnInputEvent(const blink::WebInputEvent& event) override;
// content::WebContentsObserver:
void RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) override;
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void DidFirstVisuallyNonEmptyPaint() override;
void BeforeUnloadDialogCancelled() override;
void OnRendererUnresponsive(content::RenderWidgetHost*) override;
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) override;
// ExtendedWebContentsObserver:
void OnCloseContents() override;
void OnRendererResponsive() override;
// NativeWindowObserver:
void WillCloseWindow(bool* prevent_default) override;
void WillDestroyNativeObject() override;
void OnCloseButtonClicked(bool* prevent_default) override;
void OnWindowClosed() override;
void OnWindowEndSession() override;
void OnWindowBlur() override;
void OnWindowFocus() override;
void OnWindowShow() override;
void OnWindowHide() override;
void OnReadyToShow() override;
void OnWindowMaximize() override;
void OnWindowUnmaximize() override;
void OnWindowMinimize() override;
@ -79,7 +97,6 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
void OnWindowMoved() override;
void OnWindowScrollTouchBegin() override;
void OnWindowScrollTouchEnd() override;
void OnWindowScrollTouchEdge() override;
void OnWindowSwipe(const std::string& direction) override;
void OnWindowSheetBegin() override;
void OnWindowSheetEnd() override;
@ -87,8 +104,6 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
void OnWindowLeaveFullScreen() override;
void OnWindowEnterHtmlFullScreen() override;
void OnWindowLeaveHtmlFullScreen() override;
void OnRendererUnresponsive() override;
void OnRendererResponsive() override;
void OnExecuteWindowsCommand(const std::string& command_name) override;
void OnTouchBarItemResult(const std::string& item_id,
const base::DictionaryValue& details) override;
@ -98,11 +113,16 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
#endif
base::WeakPtr<BrowserWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
void Init(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options,
mate::Handle<class WebContents> web_contents);
// APIs for NativeWindow.
void Close();
void Focus();
@ -235,11 +255,26 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
// Remove this window from parent window's |child_windows_|.
void RemoveFromParentChildWindows();
// Called when the window needs to update its draggable region.
void UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions);
// Schedule a notification unresponsive event.
void ScheduleUnresponsiveEvent(int ms);
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();
#if defined(OS_WIN)
typedef std::map<UINT, MessageCallback> MessageCallbackMap;
MessageCallbackMap messages_callback_map_;
#endif
// Closure that would be called when window is unresponsive when closing,
// it should be cancelled when we can prove that the window is responsive.
base::CancelableClosure window_unresponsive_closure_;
v8::Global<v8::Value> browser_view_;
v8::Global<v8::Value> web_contents_;
v8::Global<v8::Value> menu_;
@ -250,6 +285,8 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
std::unique_ptr<NativeWindow> window_;
base::WeakPtrFactory<BrowserWindow> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
};

View file

@ -89,6 +89,11 @@
#include "ui/aura/window.h"
#endif
#if defined(OS_LINUX) || defined(OS_WIN)
#include "content/public/common/renderer_preferences.h"
#include "ui/gfx/font_render_params.h"
#endif
#include "atom/common/node_includes.h"
namespace {
@ -412,6 +417,19 @@ void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
managed_web_contents()->GetView()->SetDelegate(this);
#if defined(OS_LINUX) || defined(OS_WIN)
// Update font settings.
auto* prefs = web_contents->GetMutableRendererPrefs();
CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params,
(gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
prefs->should_antialias_text = params.antialiasing;
prefs->use_subpixel_positioning = params.subpixel_positioning;
prefs->hinting = params.hinting;
prefs->use_autohinter = params.autohinter;
prefs->use_bitmaps = params.use_bitmaps;
prefs->subpixel_rendering = params.subpixel_rendering;
#endif
// Save the preferences in C++.
new WebContentsPreferences(web_contents, options);
@ -446,6 +464,8 @@ void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
WebContents::~WebContents() {
// The destroy() is called.
if (managed_web_contents()) {
managed_web_contents()->GetView()->SetDelegate(nullptr);
// For webview we need to tell content module to do some cleanup work before
// destroying it.
if (type_ == WEB_VIEW)
@ -457,7 +477,8 @@ WebContents::~WebContents() {
DestroyWebContents(false /* async */);
} else {
if (type_ == BROWSER_WINDOW && owner_window()) {
owner_window()->CloseContents(nullptr);
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnCloseContents();
} else {
DestroyWebContents(true /* async */);
}
@ -565,9 +586,10 @@ void WebContents::MoveContents(content::WebContents* source,
void WebContents::CloseContents(content::WebContents* source) {
Emit("close");
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
owner_window()->CloseContents(source);
if (managed_web_contents())
managed_web_contents()->GetView()->SetDelegate(nullptr);
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnCloseContents();
}
void WebContents::ActivateContents(content::WebContents* source) {
@ -636,14 +658,12 @@ void WebContents::RendererUnresponsive(
content::WebContents* source,
const content::WebContentsUnresponsiveState& unresponsive_state) {
Emit("unresponsive");
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
owner_window()->RendererUnresponsive(source);
}
void WebContents::RendererResponsive(content::WebContents* source) {
Emit("responsive");
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
owner_window()->RendererResponsive(source);
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnRendererResponsive();
}
bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) {

View file

@ -13,6 +13,7 @@
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/ui/autofill_popup.h"
#include "base/observer_list.h"
#include "content/common/cursors/webcursor.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/web_contents.h"
@ -49,6 +50,15 @@ class WebViewGuestDelegate;
namespace api {
// Certain events are only in WebContentsDelegate, provide our own Observer to
// dispatch those events.
class ExtendedWebContentsObserver {
public:
virtual void OnCloseContents() {}
virtual void OnRendererResponsive() {}
};
// Wrapper around the content::WebContents.
class WebContents : public mate::TrackableObject<WebContents>,
public CommonWebContentsDelegate,
public content::WebContentsObserver {
@ -231,6 +241,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
WebContentsZoomController* GetZoomController() { return zoom_controller_; }
void AddObserver(ExtendedWebContentsObserver* obs) {
observers_.AddObserver(obs);
}
void RemoveObserver(ExtendedWebContentsObserver* obs) {
observers_.RemoveObserver(obs);
}
protected:
WebContents(v8::Isolate* isolate,
content::WebContents* web_contents,
@ -421,6 +438,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Whether to enable devtools.
bool enable_devtools_;
// Observers of this WebContents.
base::ObserverList<ExtendedWebContentsObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(WebContents);
};

View file

@ -11,9 +11,8 @@
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/browser.h"
#include "atom/browser/unresponsive_suppressor.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/draggable_region.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/options_switches.h"
#include "base/files/file_util.h"
@ -24,7 +23,6 @@
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "components/prefs/pref_service.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
@ -40,12 +38,6 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gl/gpu_switching_manager.h"
#if defined(OS_LINUX) || defined(OS_WIN)
#include "content/public/common/renderer_preferences.h"
#include "ui/gfx/font_render_params.h"
#endif
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
@ -75,24 +67,6 @@ NativeWindow::NativeWindow(
if (parent)
options.Get("modal", &is_modal_);
#if defined(OS_LINUX) || defined(OS_WIN)
auto* prefs = web_contents()->GetMutableRendererPrefs();
// Update font settings.
CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params,
(gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
prefs->should_antialias_text = params.antialiasing;
prefs->use_subpixel_positioning = params.subpixel_positioning;
prefs->hinting = params.hinting;
prefs->use_autohinter = params.autohinter;
prefs->use_bitmaps = params.use_bitmaps;
prefs->subpixel_rendering = params.subpixel_rendering;
#endif
// Tell the content module to initialize renderer widget with transparent
// mode.
ui::GpuSwitchingManager::SetTransparent(transparent_);
WindowList::AddWindow(this);
}
@ -427,7 +401,8 @@ void NativeWindow::PreviewFile(const std::string& path,
void NativeWindow::CloseFilePreview() {
}
void NativeWindow::RequestToClosePage() {
void NativeWindow::NotifyWindowCloseButtonClicked() {
// First ask the observers whether we want to close.
bool prevent_default = false;
for (NativeWindowObserver& observer : observers_)
observer.WillCloseWindow(&prevent_default);
@ -436,60 +411,13 @@ void NativeWindow::RequestToClosePage() {
return;
}
// Assume the window is not responding if it doesn't cancel the close and is
// not closed in 5s, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for
// the unresponsive timeout.
if (window_unresposive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(5000);
if (!web_contents())
// Already closed by renderer
return;
if (web_contents()->NeedToFireBeforeUnload())
web_contents()->DispatchBeforeUnload();
else
web_contents()->Close();
}
void NativeWindow::CloseContents(content::WebContents* source) {
if (!inspectable_web_contents_)
return;
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
inspectable_web_contents_ = nullptr;
Observe(nullptr);
// Then ask the observers how should we close the window.
for (NativeWindowObserver& observer : observers_)
observer.WillDestroyNativeObject();
observer.OnCloseButtonClicked(&prevent_default);
if (prevent_default)
return;
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
window_unresposive_closure_.Cancel();
}
void NativeWindow::RendererUnresponsive(content::WebContents* source) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
// blocked for a while.
// Also notice that when closing this event would be ignored because we have
// explicitly started a close timeout counter. This is on purpose because we
// don't want the unresponsive event to be sent too early when user is closing
// the window.
ScheduleUnresponsiveEvent(50);
}
void NativeWindow::RendererResponsive(content::WebContents* source) {
window_unresposive_closure_.Cancel();
for (NativeWindowObserver& observer : observers_)
observer.OnRendererResponsive();
}
void NativeWindow::NotifyWindowClosed() {
@ -578,11 +506,6 @@ void NativeWindow::NotifyWindowScrollTouchEnd() {
observer.OnWindowScrollTouchEnd();
}
void NativeWindow::NotifyWindowScrollTouchEdge() {
for (NativeWindowObserver& observer : observers_)
observer.OnWindowScrollTouchEdge();
}
void NativeWindow::NotifyWindowSwipe(const std::string& direction) {
for (NativeWindowObserver& observer : observers_)
observer.OnWindowSwipe(direction);
@ -653,87 +576,4 @@ std::unique_ptr<SkRegion> NativeWindow::DraggableRegionsToSkRegion(
return sk_region;
}
void NativeWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) {
if (!transparent_)
return;
content::RenderWidgetHostImpl* impl = content::RenderWidgetHostImpl::FromID(
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
if (impl)
impl->SetBackgroundOpaque(false);
}
void NativeWindow::BeforeUnloadDialogCancelled() {
WindowList::WindowCloseCancelled(this);
// Cancel unresponsive event when window close is cancelled.
window_unresposive_closure_.Cancel();
}
void NativeWindow::DidFirstVisuallyNonEmptyPaint() {
if (IsVisible())
return;
// When there is a non-empty first paint, resize the RenderWidget to force
// Chromium to draw.
const auto view = web_contents()->GetRenderWidgetHostView();
view->Show();
view->SetSize(GetContentSize());
// Emit the ReadyToShow event in next tick in case of pending drawing work.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&NativeWindow::NotifyReadyToShow, GetWeakPtr()));
}
bool NativeWindow::OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(NativeWindow, message, rfh)
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_UpdateDraggableRegions,
UpdateDraggableRegions)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void NativeWindow::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
// Draggable region is not supported for non-frameless window.
if (has_frame_)
return;
draggable_region_ = DraggableRegionsToSkRegion(regions);
}
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresposive_closure_.IsCancelled())
return;
window_unresposive_closure_.Reset(
base::Bind(&NativeWindow::NotifyWindowUnresponsive,
weak_factory_.GetWeakPtr()));
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
window_unresposive_closure_.callback(),
base::TimeDelta::FromMilliseconds(ms));
}
void NativeWindow::NotifyWindowUnresponsive() {
window_unresposive_closure_.Cancel();
if (!is_closed_ && !IsUnresponsiveEventSuppressed() && IsEnabled()) {
for (NativeWindowObserver& observer : observers_)
observer.OnRendererUnresponsive();
}
}
void NativeWindow::NotifyReadyToShow() {
for (NativeWindowObserver& observer : observers_)
observer.OnReadyToShow();
}
} // namespace atom

View file

@ -13,7 +13,6 @@
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h"
#include "atom/browser/ui/atom_menu_model.h"
#include "base/cancelable_callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/supports_user_data.h"
@ -216,17 +215,21 @@ class NativeWindow : public base::SupportsUserData,
const std::string& display_name);
virtual void CloseFilePreview();
// Converts between content bounds and window bounds.
virtual gfx::Rect ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const = 0;
virtual gfx::Rect WindowBoundsToContentBounds(
const gfx::Rect& bounds) const = 0;
// Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) = 0;
base::WeakPtr<NativeWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
// Requests the WebContents to close, can be cancelled by the page.
virtual void RequestToClosePage();
// Methods called by the WebContents.
virtual void CloseContents(content::WebContents* source);
virtual void RendererUnresponsive(content::WebContents* source);
virtual void RendererResponsive(content::WebContents* source);
virtual void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {}
@ -240,6 +243,7 @@ class NativeWindow : public base::SupportsUserData,
// Public API used by platform-dependent delegates and observers to send UI
// related notifications.
void NotifyWindowCloseButtonClicked();
void NotifyWindowClosed();
void NotifyWindowEndSession();
void NotifyWindowBlur();
@ -255,7 +259,6 @@ class NativeWindow : public base::SupportsUserData,
void NotifyWindowMoved();
void NotifyWindowScrollTouchBegin();
void NotifyWindowScrollTouchEnd();
void NotifyWindowScrollTouchEdge();
void NotifyWindowSwipe(const std::string& direction);
void NotifyWindowSheetBegin();
void NotifyWindowSheetEnd();
@ -287,7 +290,6 @@ class NativeWindow : public base::SupportsUserData,
void set_has_frame(bool has_frame) { has_frame_ = has_frame; }
bool transparent() const { return transparent_; }
SkRegion* draggable_region() const { return draggable_region_.get(); }
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
void set_is_offscreen_dummy(bool is_dummy) { is_osr_dummy_ = is_dummy; }
@ -306,44 +308,13 @@ class NativeWindow : public base::SupportsUserData,
std::unique_ptr<SkRegion> DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions);
// Converts between content bounds and window bounds.
virtual gfx::Rect ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const = 0;
virtual gfx::Rect WindowBoundsToContentBounds(
const gfx::Rect& bounds) const = 0;
// Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions);
// content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadDialogCancelled() override;
void DidFirstVisuallyNonEmptyPaint() override;
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) override;
private:
// Schedule a notification unresponsive event.
void ScheduleUnresponsiveEvent(int ms);
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();
// Dispatch ReadyToShow event to observers.
void NotifyReadyToShow();
// Whether window has standard frame.
bool has_frame_;
// Whether window is transparent.
bool transparent_;
// For custom drag, the whole window is non-draggable and the draggable region
// has to been explicitly provided.
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
// Minimum and maximum size, stored as content size.
extensions::SizeConstraints size_constraints_;
@ -353,10 +324,6 @@ class NativeWindow : public base::SupportsUserData,
// The windows has been closed.
bool is_closed_;
// Closure that would be called when window is unresponsive when closing,
// it should be cancelled when we can prove that the window is responsive.
base::CancelableClosure window_unresposive_closure_;
// Used to display sheets at the appropriate horizontal and vertical offsets
// on macOS.
double sheet_offset_x_;

View file

@ -12,7 +12,6 @@
#include "atom/browser/native_window.h"
#include "base/mac/scoped_nsobject.h"
#include "content/public/browser/render_widget_host.h"
@class AtomNSWindow;
@class AtomNSWindowDelegate;
@ -20,8 +19,7 @@
namespace atom {
class NativeWindowMac : public NativeWindow,
public content::RenderWidgetHost::InputEventObserver {
class NativeWindowMac : public NativeWindow {
public:
NativeWindowMac(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
@ -119,17 +117,10 @@ class NativeWindowMac : public NativeWindow,
void RefreshTouchBarItem(const std::string& item_id) override;
void SetEscapeTouchBarItem(const mate::PersistentDictionary& item) override;
// content::RenderWidgetHost::InputEventObserver:
void OnInputEvent(const blink::WebInputEvent& event) override;
// content::WebContentsObserver:
void RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) override;
// Refresh the DraggableRegion views.
void UpdateDraggableRegionViews() {
UpdateDraggableRegionViews(draggable_regions_);
}
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const;
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;
// Set the attribute of NSWindow while work around a bug of zoom button.
void SetStyleMask(bool on, NSUInteger flag);
@ -144,10 +135,11 @@ class NativeWindowMac : public NativeWindow,
TitleBarStyle title_bar_style() const { return title_bar_style_; }
bool zoom_to_page_width() const { return zoom_to_page_width_; }
bool fullscreen_window_title() const { return fullscreen_window_title_; }
bool simple_fullscreen() const { return always_simple_fullscreen_; }
const std::vector<DraggableRegion>& draggable_regions() const {
return draggable_regions_;
}
protected:
// Return a vector of non-draggable regions that fill a window of size
@ -156,26 +148,12 @@ class NativeWindowMac : public NativeWindow,
const std::vector<DraggableRegion>& regions, int width, int height);
private:
// NativeWindow:
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const;
void UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) override;
void InternalSetParentWindow(NativeWindow* parent, bool attach);
void ShowWindowButton(NSWindowButton button);
void InstallView();
void UninstallView();
// Install the drag view, which will cover the whole window and decides
// whether we can drag.
void UpdateDraggableRegionViews(const std::vector<DraggableRegion>& regions);
void RegisterInputEventObserver(content::RenderViewHost* host);
void UnregisterInputEventObserver(content::RenderViewHost* host);
void SetRenderWidgetHostOpaque(bool opaque);
base::scoped_nsobject<AtomNSWindow> window_;

View file

@ -296,7 +296,7 @@ bool ScopedDisableResize::disable_resize_ = false;
}
- (void)windowDidResize:(NSNotification*)notification {
shell_->UpdateDraggableRegionViews();
shell_->UpdateDraggableRegions(shell_->draggable_regions());
shell_->NotifyWindowResize();
}
@ -415,10 +415,7 @@ bool ScopedDisableResize::disable_resize_ = false;
}
- (BOOL)windowShouldClose:(id)window {
// When user tries to close the window by clicking the close button, we do
// not close the window immediately, instead we try to close the web page
// first, and when the web page is closed the window will also be closed.
shell_->RequestToClosePage();
shell_->NotifyWindowCloseButtonClicked();
return NO;
}
@ -1041,9 +1038,6 @@ NativeWindowMac::NativeWindowMac(
// Set maximizable state last to ensure zoom button does not get reset
// by calls to other APIs.
SetMaximizable(maximizable);
RegisterInputEventObserver(
web_contents->GetWebContents()->GetRenderViewHost());
}
NativeWindowMac::~NativeWindowMac() {
@ -1789,42 +1783,6 @@ void NativeWindowMac::SetEscapeTouchBarItem(const mate::PersistentDictionary& it
[window_ setEscapeTouchBarItem:item];
}
void NativeWindowMac::OnInputEvent(const blink::WebInputEvent& event) {
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
case blink::WebInputEvent::kGestureScrollUpdate:
case blink::WebInputEvent::kGestureScrollEnd:
this->NotifyWindowScrollTouchEdge();
break;
default:
break;
}
}
void NativeWindowMac::RenderViewHostChanged(
content::RenderViewHost* old_host,
content::RenderViewHost* new_host) {
UnregisterInputEventObserver(old_host);
RegisterInputEventObserver(new_host);
}
std::vector<gfx::Rect> NativeWindowMac::CalculateNonDraggableRegions(
const std::vector<DraggableRegion>& regions, int width, int height) {
std::vector<gfx::Rect> result;
if (regions.empty()) {
result.push_back(gfx::Rect(0, 0, width, height));
} else {
std::unique_ptr<SkRegion> draggable(DraggableRegionsToSkRegion(regions));
std::unique_ptr<SkRegion> non_draggable(new SkRegion);
non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op);
non_draggable->op(*draggable, SkRegion::kDifference_Op);
for (SkRegion::Iterator it(*non_draggable); !it.done(); it.next()) {
result.push_back(gfx::SkIRectToRect(it.rect()));
}
}
return result;
}
gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const {
if (has_frame()) {
@ -1852,11 +1810,77 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
}
void NativeWindowMac::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
NativeWindow::UpdateDraggableRegions(rfh, regions);
if (has_frame())
return;
// 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 = web_contents()->GetNativeView();
NSInteger webViewWidth = NSWidth([webView bounds]);
NSInteger webViewHeight = NSHeight([webView bounds]);
if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
[webView setMouseDownCanMoveWindow:YES];
}
// 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.
base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
for (NSView* subview in subviews.get())
if ([subview isKindOfClass:[ControlRegionView class]])
[subview removeFromSuperview];
// Draggable regions is implemented by having the whole web view draggable
// (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
draggable_regions_ = regions;
UpdateDraggableRegionViews(regions);
std::vector<gfx::Rect> system_drag_exclude_areas =
CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight);
if (browser_view_)
browser_view_->UpdateDraggableRegions(system_drag_exclude_areas);
// Create and add a 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) {
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
[controlRegion setFrame:NSMakeRect(iter->x(),
webViewHeight - iter->bottom(),
iter->width(),
iter->height())];
[webView addSubview:controlRegion];
}
// AppKit will not update its cache of mouseDownCanMoveWindow unless something
// changes. Previously we tried adding an NSView and removing it, but for some
// reason it required reposting the mouse-down event, and didn't always work.
// Calling the below seems to be an effective solution.
[window_ setMovableByWindowBackground:NO];
[window_ setMovableByWindowBackground:YES];
}
std::vector<gfx::Rect> NativeWindowMac::CalculateNonDraggableRegions(
const std::vector<DraggableRegion>& regions, int width, int height) {
std::vector<gfx::Rect> result;
if (regions.empty()) {
result.push_back(gfx::Rect(0, 0, width, height));
} else {
std::unique_ptr<SkRegion> draggable(DraggableRegionsToSkRegion(regions));
std::unique_ptr<SkRegion> non_draggable(new SkRegion);
non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op);
non_draggable->op(*draggable, SkRegion::kDifference_Op);
for (SkRegion::Iterator it(*non_draggable); !it.done(); it.next()) {
result.push_back(gfx::SkIRectToRect(it.rect()));
}
}
return result;
}
void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent, bool attach) {
@ -1944,63 +1968,6 @@ void NativeWindowMac::UninstallView() {
[view removeFromSuperview];
}
void NativeWindowMac::UpdateDraggableRegionViews(
const std::vector<DraggableRegion>& regions) {
if (has_frame())
return;
// 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 = web_contents()->GetNativeView();
NSInteger webViewWidth = NSWidth([webView bounds]);
NSInteger webViewHeight = NSHeight([webView bounds]);
if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
[webView setMouseDownCanMoveWindow:YES];
}
// 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.
base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
for (NSView* subview in subviews.get())
if ([subview isKindOfClass:[ControlRegionView class]])
[subview removeFromSuperview];
// Draggable regions is implemented by having the whole web view draggable
// (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
std::vector<gfx::Rect> system_drag_exclude_areas =
CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight);
if (browser_view_) {
browser_view_->UpdateDraggableRegions(system_drag_exclude_areas);
}
// Create and add a 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) {
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
[controlRegion setFrame:NSMakeRect(iter->x(),
webViewHeight - iter->bottom(),
iter->width(),
iter->height())];
[webView addSubview:controlRegion];
}
// AppKit will not update its cache of mouseDownCanMoveWindow unless something
// changes. Previously we tried adding an NSView and removing it, but for some
// reason it required reposting the mouse-down event, and didn't always work.
// Calling the below seems to be an effective solution.
[window_ setMovableByWindowBackground:NO];
[window_ setMovableByWindowBackground:YES];
}
void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) {
// Changing the styleMask of a frameless windows causes it to change size so
// we explicitly disable resizing while setting it.
@ -2027,18 +1994,6 @@ void NativeWindowMac::SetCollectionBehavior(bool on, NSUInteger flag) {
SetMaximizable(was_maximizable);
}
void NativeWindowMac::RegisterInputEventObserver(
content::RenderViewHost* host) {
if (host)
host->GetWidget()->AddInputEventObserver(this);
}
void NativeWindowMac::UnregisterInputEventObserver(
content::RenderViewHost* host) {
if (host)
host->GetWidget()->RemoveInputEventObserver(this);
}
// static
NativeWindow* NativeWindow::Create(
brightray::InspectableWebContents* inspectable_web_contents,

View file

@ -34,8 +34,8 @@ class NativeWindowObserver {
// Called when the window is gonna closed.
virtual void WillCloseWindow(bool* prevent_default) {}
// Called before the native window object is going to be destroyed.
virtual void WillDestroyNativeObject() {}
// Called when closed button is clicked.
virtual void OnCloseButtonClicked(bool* prevent_default) {}
// Called when the window is closed.
virtual void OnWindowClosed() {}
@ -55,9 +55,6 @@ class NativeWindowObserver {
// Called when window is hidden.
virtual void OnWindowHide() {}
// Called when window is ready to show.
virtual void OnReadyToShow() {}
// Called when window state changed.
virtual void OnWindowMaximize() {}
virtual void OnWindowUnmaximize() {}
@ -68,7 +65,6 @@ class NativeWindowObserver {
virtual void OnWindowMoved() {}
virtual void OnWindowScrollTouchBegin() {}
virtual void OnWindowScrollTouchEnd() {}
virtual void OnWindowScrollTouchEdge() {}
virtual void OnWindowSwipe(const std::string& direction) {}
virtual void OnWindowSheetBegin() {}
virtual void OnWindowSheetEnd() {}
@ -85,12 +81,6 @@ class NativeWindowObserver {
virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {}
#endif
// Called when renderer is hung.
virtual void OnRendererUnresponsive() {}
// Called when renderer recovers.
virtual void OnRendererResponsive() {}
// Called on Windows when App Commands arrive (WM_APPCOMMAND)
virtual void OnExecuteWindowsCommand(const std::string& command_name) {}
};

View file

@ -124,7 +124,8 @@ class NativeWindowClientView : public views::ClientView {
virtual ~NativeWindowClientView() {}
bool CanClose() override {
static_cast<NativeWindowViews*>(contents_view())->RequestToClosePage();
static_cast<NativeWindowViews*>(contents_view())->
NotifyWindowCloseButtonClicked();
return false;
}
@ -1072,6 +1073,63 @@ gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
}
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
gfx::Rect window_bounds(bounds);
#if defined(OS_WIN)
HWND hwnd = GetAcceleratedWidget();
gfx::Rect dpi_bounds = display::win::ScreenWin::DIPToScreenRect(hwnd, bounds);
window_bounds = display::win::ScreenWin::ScreenToDIPRect(
hwnd,
window_->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds));
#endif
if (menu_bar_ && menu_bar_visible_) {
window_bounds.set_y(window_bounds.y() - kMenuBarHeight);
window_bounds.set_height(window_bounds.height() + kMenuBarHeight);
}
return window_bounds;
}
gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
gfx::Rect content_bounds(bounds);
#if defined(OS_WIN)
HWND hwnd = GetAcceleratedWidget();
content_bounds.set_size(
display::win::ScreenWin::DIPToScreenSize(hwnd, content_bounds.size()));
RECT rect;
SetRectEmpty(&rect);
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
AdjustWindowRectEx(&rect, style, FALSE, ex_style);
content_bounds.set_width(content_bounds.width() - (rect.right - rect.left));
content_bounds.set_height(content_bounds.height() - (rect.bottom - rect.top));
content_bounds.set_size(
display::win::ScreenWin::ScreenToDIPSize(hwnd, content_bounds.size()));
#endif
if (menu_bar_ && menu_bar_visible_) {
content_bounds.set_y(content_bounds.y() + kMenuBarHeight);
content_bounds.set_height(content_bounds.height() - kMenuBarHeight);
}
return content_bounds;
}
void NativeWindowViews::UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) {
// Draggable region is not supported for non-frameless window.
if (has_frame())
return;
draggable_region_ = DraggableRegionsToSkRegion(regions);
}
#if defined(OS_WIN)
void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) {
// We are responsible for storing the images.
@ -1270,55 +1328,6 @@ void NativeWindowViews::OnWidgetMove() {
NotifyWindowMove();
}
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
gfx::Rect window_bounds(bounds);
#if defined(OS_WIN)
HWND hwnd = GetAcceleratedWidget();
gfx::Rect dpi_bounds = display::win::ScreenWin::DIPToScreenRect(hwnd, bounds);
window_bounds = display::win::ScreenWin::ScreenToDIPRect(
hwnd,
window_->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds));
#endif
if (menu_bar_ && menu_bar_visible_) {
window_bounds.set_y(window_bounds.y() - kMenuBarHeight);
window_bounds.set_height(window_bounds.height() + kMenuBarHeight);
}
return window_bounds;
}
gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
gfx::Rect content_bounds(bounds);
#if defined(OS_WIN)
HWND hwnd = GetAcceleratedWidget();
content_bounds.set_size(
display::win::ScreenWin::DIPToScreenSize(hwnd, content_bounds.size()));
RECT rect;
SetRectEmpty(&rect);
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
AdjustWindowRectEx(&rect, style, FALSE, ex_style);
content_bounds.set_width(content_bounds.width() - (rect.right - rect.left));
content_bounds.set_height(content_bounds.height() - (rect.bottom - rect.top));
content_bounds.set_size(
display::win::ScreenWin::ScreenToDIPSize(hwnd, content_bounds.size()));
#endif
if (menu_bar_ && menu_bar_visible_) {
content_bounds.set_y(content_bounds.y() + kMenuBarHeight);
content_bounds.set_height(content_bounds.height() - kMenuBarHeight);
}
return content_bounds;
}
void NativeWindowViews::HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {

View file

@ -126,6 +126,11 @@ class NativeWindowViews : public NativeWindow,
gfx::AcceleratedWidget GetAcceleratedWidget() const override;
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;
#if defined(OS_WIN)
void SetIcon(HICON small_icon, HICON app_icon);
#elif defined(USE_X11)
@ -135,6 +140,7 @@ class NativeWindowViews : public NativeWindow,
void SetEnabled(bool enable) override;
views::Widget* widget() const { return window_.get(); }
SkRegion* draggable_region() const { return draggable_region_.get(); }
#if defined(OS_WIN)
TaskbarHost& taskbar_host() { return taskbar_host_; }
@ -183,8 +189,6 @@ class NativeWindowViews : public NativeWindow,
#endif
// NativeWindow:
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) override;
@ -289,6 +293,10 @@ class NativeWindowViews : public NativeWindow,
// Map from accelerator to menu item's command id.
accelerator_util::AcceleratorTable accelerator_table_;
// For custom drag, the whole window is non-draggable and the draggable region
// has to been explicitly provided.
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
// How many times the Disable has been called.
int disable_count_;

View file

@ -93,7 +93,7 @@ void WindowList::CloseAllWindows() {
void WindowList::DestroyAllWindows() {
WindowVector windows = GetInstance()->windows_;
for (const auto& window : windows)
window->CloseContents(nullptr); // e.g. Destroy()
window->CloseImmediately(); // e.g. Destroy()
}
WindowList::WindowList() {