2014-10-31 18:17:05 +00:00
|
|
|
// Copyright (c) 2014 GitHub, Inc.
|
2014-07-03 17:30:36 +00:00
|
|
|
// Use of this source code is governed by the MIT license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "atom/browser/native_window_views.h"
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2015-02-11 01:14:26 +00:00
|
|
|
|
2017-05-26 01:38:27 +00:00
|
|
|
#include "atom/browser/api/atom_api_web_contents.h"
|
2017-04-12 11:40:31 +00:00
|
|
|
#include "atom/browser/native_browser_view_views.h"
|
2014-07-16 14:10:10 +00:00
|
|
|
#include "atom/browser/ui/views/menu_bar.h"
|
2017-11-02 21:50:04 +00:00
|
|
|
#include "atom/browser/web_contents_preferences.h"
|
2016-05-25 23:25:51 +00:00
|
|
|
#include "atom/browser/window_list.h"
|
2016-04-02 11:35:57 +00:00
|
|
|
#include "atom/common/color_util.h"
|
2014-07-07 07:35:16 +00:00
|
|
|
#include "atom/common/draggable_region.h"
|
2016-05-20 13:22:15 +00:00
|
|
|
#include "atom/common/native_mate_converters/image_converter.h"
|
2014-07-03 17:30:36 +00:00
|
|
|
#include "atom/common/options_switches.h"
|
|
|
|
#include "base/strings/utf_string_conversions.h"
|
2015-06-25 05:08:11 +00:00
|
|
|
#include "brightray/browser/inspectable_web_contents.h"
|
|
|
|
#include "brightray/browser/inspectable_web_contents_view.h"
|
2016-04-13 02:02:34 +00:00
|
|
|
#include "content/public/browser/browser_thread.h"
|
2014-07-04 08:54:10 +00:00
|
|
|
#include "content/public/browser/native_web_keyboard_event.h"
|
2014-07-03 17:30:36 +00:00
|
|
|
#include "native_mate/dictionary.h"
|
2014-07-21 14:03:58 +00:00
|
|
|
#include "ui/aura/window_tree_host.h"
|
2014-07-07 14:39:39 +00:00
|
|
|
#include "ui/base/hit_test.h"
|
2015-02-07 01:00:26 +00:00
|
|
|
#include "ui/gfx/image/image.h"
|
2014-07-03 17:30:36 +00:00
|
|
|
#include "ui/views/background.h"
|
2014-07-07 15:02:46 +00:00
|
|
|
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
|
2014-07-03 17:30:36 +00:00
|
|
|
#include "ui/views/controls/webview/webview.h"
|
2014-12-16 01:28:51 +00:00
|
|
|
#include "ui/views/widget/native_widget_private.h"
|
2014-07-03 17:30:36 +00:00
|
|
|
#include "ui/views/widget/widget.h"
|
2016-08-26 22:30:02 +00:00
|
|
|
#include "ui/views/window/client_view.h"
|
2014-12-24 00:55:57 +00:00
|
|
|
#include "ui/wm/core/shadow_types.h"
|
2016-08-26 22:30:02 +00:00
|
|
|
#include "ui/wm/core/window_util.h"
|
2014-07-03 17:30:36 +00:00
|
|
|
|
2014-07-07 07:35:16 +00:00
|
|
|
#if defined(USE_X11)
|
2014-08-26 02:34:48 +00:00
|
|
|
#include "atom/browser/browser.h"
|
2014-07-24 10:06:27 +00:00
|
|
|
#include "atom/browser/ui/views/frameless_view.h"
|
2016-08-26 22:30:02 +00:00
|
|
|
#include "atom/browser/ui/views/global_menu_bar_x11.h"
|
2015-07-24 08:04:54 +00:00
|
|
|
#include "atom/browser/ui/views/native_frame_view.h"
|
2016-06-19 08:35:56 +00:00
|
|
|
#include "atom/browser/ui/x/event_disabler.h"
|
2014-11-25 05:05:04 +00:00
|
|
|
#include "atom/browser/ui/x/window_state_watcher.h"
|
2014-08-26 05:37:37 +00:00
|
|
|
#include "atom/browser/ui/x/x_window_utils.h"
|
2014-11-24 07:27:36 +00:00
|
|
|
#include "base/strings/string_util.h"
|
2017-01-26 10:55:19 +00:00
|
|
|
#include "chrome/browser/ui/libgtkui/unity_service.h"
|
2014-08-26 04:15:22 +00:00
|
|
|
#include "ui/base/x/x11_util.h"
|
2014-07-24 10:22:10 +00:00
|
|
|
#include "ui/gfx/x/x11_types.h"
|
2016-05-20 13:22:15 +00:00
|
|
|
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
|
2014-07-24 10:06:27 +00:00
|
|
|
#include "ui/views/window/native_frame_view.h"
|
2014-07-12 03:36:08 +00:00
|
|
|
#elif defined(OS_WIN)
|
|
|
|
#include "atom/browser/ui/views/win_frame_view.h"
|
2017-02-13 23:21:55 +00:00
|
|
|
#include "atom/browser/ui/win/atom_desktop_native_widget_aura.h"
|
2015-08-05 05:04:21 +00:00
|
|
|
#include "atom/browser/ui/win/atom_desktop_window_tree_host_win.h"
|
2015-10-23 03:17:14 +00:00
|
|
|
#include "skia/ext/skia_utils_win.h"
|
2014-08-05 10:17:14 +00:00
|
|
|
#include "ui/base/win/shell.h"
|
2016-07-22 14:37:20 +00:00
|
|
|
#include "ui/display/display.h"
|
2016-07-21 17:20:43 +00:00
|
|
|
#include "ui/display/screen.h"
|
2016-08-26 22:30:02 +00:00
|
|
|
#include "ui/display/win/screen_win.h"
|
2015-08-05 05:47:59 +00:00
|
|
|
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
|
2014-07-07 07:35:16 +00:00
|
|
|
#endif
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
namespace atom {
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-07-16 14:10:10 +00:00
|
|
|
// The menu bar height in pixels.
|
2014-07-25 07:05:18 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
const int kMenuBarHeight = 20;
|
|
|
|
#else
|
2014-07-16 14:10:10 +00:00
|
|
|
const int kMenuBarHeight = 25;
|
2014-07-25 07:05:18 +00:00
|
|
|
#endif
|
2014-07-16 14:10:10 +00:00
|
|
|
|
2016-01-23 10:23:18 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
void FlipWindowStyle(HWND handle, bool on, DWORD flag) {
|
|
|
|
DWORD style = ::GetWindowLong(handle, GWL_STYLE);
|
|
|
|
if (on)
|
|
|
|
style |= flag;
|
|
|
|
else
|
|
|
|
style &= ~flag;
|
|
|
|
::SetWindowLong(handle, GWL_STYLE, style);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-08-07 07:54:05 +00:00
|
|
|
bool IsAltKey(const content::NativeWebKeyboardEvent& event) {
|
2017-06-28 14:58:47 +00:00
|
|
|
return event.windows_key_code == ui::VKEY_MENU;
|
2014-08-07 07:54:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsAltModifier(const content::NativeWebKeyboardEvent& event) {
|
|
|
|
typedef content::NativeWebKeyboardEvent::Modifiers Modifiers;
|
2017-06-28 14:58:47 +00:00
|
|
|
int modifiers = event.GetModifiers();
|
|
|
|
modifiers &= ~Modifiers::kNumLockOn;
|
|
|
|
modifiers &= ~Modifiers::kCapsLockOn;
|
|
|
|
return (modifiers == Modifiers::kAltKey) ||
|
|
|
|
(modifiers == (Modifiers::kAltKey | Modifiers::kIsLeft)) ||
|
|
|
|
(modifiers == (Modifiers::kAltKey | Modifiers::kIsRight));
|
2014-08-07 07:54:05 +00:00
|
|
|
}
|
|
|
|
|
2016-06-06 07:53:32 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
int SendClientEvent(XDisplay* display, ::Window window, const char* msg) {
|
|
|
|
XEvent event = {};
|
|
|
|
event.xclient.type = ClientMessage;
|
|
|
|
event.xclient.send_event = True;
|
|
|
|
event.xclient.message_type = XInternAtom(display, msg, False);
|
|
|
|
event.xclient.window = window;
|
|
|
|
event.xclient.format = 32;
|
|
|
|
XSendEvent(display, DefaultRootWindow(display), False,
|
|
|
|
SubstructureRedirectMask | SubstructureNotifyMask, &event);
|
|
|
|
XFlush(display);
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
class NativeWindowClientView : public views::ClientView {
|
|
|
|
public:
|
|
|
|
NativeWindowClientView(views::Widget* widget,
|
|
|
|
NativeWindowViews* contents_view)
|
|
|
|
: views::ClientView(widget, contents_view) {
|
|
|
|
}
|
|
|
|
virtual ~NativeWindowClientView() {}
|
|
|
|
|
2015-01-10 01:24:36 +00:00
|
|
|
bool CanClose() override {
|
2015-06-25 05:27:51 +00:00
|
|
|
static_cast<NativeWindowViews*>(contents_view())->RequestToClosePage();
|
2014-07-03 17:30:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NativeWindowClientView);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2015-06-25 01:47:57 +00:00
|
|
|
NativeWindowViews::NativeWindowViews(
|
|
|
|
brightray::InspectableWebContents* web_contents,
|
2016-06-19 03:06:08 +00:00
|
|
|
const mate::Dictionary& options,
|
|
|
|
NativeWindow* parent)
|
2016-06-20 06:44:50 +00:00
|
|
|
: NativeWindow(web_contents, options, parent),
|
2014-07-03 17:30:36 +00:00
|
|
|
window_(new views::Widget),
|
2014-07-04 08:54:10 +00:00
|
|
|
web_view_(inspectable_web_contents()->GetView()->GetView()),
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
browser_view_(nullptr),
|
2014-08-07 05:47:58 +00:00
|
|
|
menu_bar_autohide_(false),
|
2014-08-07 08:48:30 +00:00
|
|
|
menu_bar_visible_(false),
|
2014-08-07 07:54:05 +00:00
|
|
|
menu_bar_alt_pressed_(false),
|
2016-07-09 12:49:15 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-10-14 19:17:32 +00:00
|
|
|
checked_for_a11y_support_(false),
|
2016-07-09 12:49:15 +00:00
|
|
|
thick_frame_(true),
|
|
|
|
#endif
|
2014-07-07 15:02:46 +00:00
|
|
|
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
|
2016-06-20 06:44:50 +00:00
|
|
|
disable_count_(0),
|
2014-07-21 12:58:15 +00:00
|
|
|
use_content_size_(false),
|
2016-01-23 10:23:18 +00:00
|
|
|
movable_(true),
|
2016-01-18 22:46:35 +00:00
|
|
|
resizable_(true),
|
|
|
|
maximizable_(true),
|
2016-02-22 09:23:56 +00:00
|
|
|
minimizable_(true),
|
2017-02-14 20:52:19 +00:00
|
|
|
fullscreenable_(true) {
|
2015-11-13 05:58:31 +00:00
|
|
|
options.Get(options::kTitle, &title_);
|
|
|
|
options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_);
|
2014-07-03 17:30:36 +00:00
|
|
|
|
2014-08-26 05:37:37 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
// On Windows we rely on the CanResize() to indicate whether window can be
|
|
|
|
// resized, and it should be set before window is created.
|
2015-11-13 05:58:31 +00:00
|
|
|
options.Get(options::kResizable, &resizable_);
|
2016-01-18 22:46:35 +00:00
|
|
|
options.Get(options::kMinimizable, &minimizable_);
|
2016-01-22 21:24:33 +00:00
|
|
|
options.Get(options::kMaximizable, &maximizable_);
|
2016-07-09 12:49:15 +00:00
|
|
|
|
|
|
|
// Transparent window must not have thick frame.
|
|
|
|
options.Get("thickFrame", &thick_frame_);
|
|
|
|
if (transparent())
|
|
|
|
thick_frame_ = false;
|
2014-08-26 05:37:37 +00:00
|
|
|
#endif
|
|
|
|
|
2015-08-05 04:46:32 +00:00
|
|
|
if (enable_larger_than_screen())
|
2014-08-17 04:23:00 +00:00
|
|
|
// We need to set a default maximum window size here otherwise Windows
|
|
|
|
// will not allow us to resize the window larger than scree.
|
|
|
|
// Setting directly to INT_MAX somehow doesn't work, so we just devide
|
|
|
|
// by 10, which should still be large enough.
|
2015-10-05 11:05:59 +00:00
|
|
|
SetContentSizeConstraints(extensions::SizeConstraints(
|
|
|
|
gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10)));
|
2014-08-17 04:23:00 +00:00
|
|
|
|
2014-07-12 03:36:08 +00:00
|
|
|
int width = 800, height = 600;
|
2015-11-13 05:58:31 +00:00
|
|
|
options.Get(options::kWidth, &width);
|
|
|
|
options.Get(options::kHeight, &height);
|
2014-07-12 03:36:08 +00:00
|
|
|
gfx::Rect bounds(0, 0, width, height);
|
2015-05-20 08:37:13 +00:00
|
|
|
widget_size_ = bounds.size();
|
2014-07-12 03:36:08 +00:00
|
|
|
|
2014-07-08 04:55:33 +00:00
|
|
|
window_->AddObserver(this);
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
views::Widget::InitParams params;
|
2014-07-04 09:24:49 +00:00
|
|
|
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
2014-07-12 03:36:08 +00:00
|
|
|
params.bounds = bounds;
|
2014-07-03 17:30:36 +00:00
|
|
|
params.delegate = this;
|
2017-04-05 09:02:06 +00:00
|
|
|
params.type = views::Widget::InitParams::TYPE_WINDOW;
|
2015-08-05 04:46:32 +00:00
|
|
|
params.remove_standard_frame = !has_frame();
|
2014-07-07 09:22:22 +00:00
|
|
|
|
2015-08-05 04:46:32 +00:00
|
|
|
if (transparent())
|
2014-12-24 00:55:57 +00:00
|
|
|
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
|
|
|
|
|
2016-01-23 10:55:12 +00:00
|
|
|
// The given window is most likely not rectangular since it uses
|
|
|
|
// transparency and has no standard frame, don't show a shadow for it.
|
|
|
|
if (transparent() && !has_frame())
|
2016-01-23 12:03:56 +00:00
|
|
|
params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
|
2016-01-23 10:55:12 +00:00
|
|
|
|
2017-02-14 20:52:19 +00:00
|
|
|
bool focusable;
|
|
|
|
if (options.Get(options::kFocusable, &focusable) && !focusable)
|
2016-06-13 08:24:45 +00:00
|
|
|
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
|
|
|
|
|
2016-06-19 06:47:27 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-06-19 03:18:48 +00:00
|
|
|
if (parent)
|
|
|
|
params.parent = parent->GetNativeWindow();
|
|
|
|
|
2017-02-14 21:14:35 +00:00
|
|
|
params.native_widget = new AtomDesktopNativeWidgetAura(window_.get());
|
2015-08-02 03:11:29 +00:00
|
|
|
atom_desktop_window_tree_host_win_ = new AtomDesktopWindowTreeHostWin(
|
2015-08-06 02:15:27 +00:00
|
|
|
this,
|
2015-08-02 03:11:29 +00:00
|
|
|
window_.get(),
|
|
|
|
static_cast<views::DesktopNativeWidgetAura*>(params.native_widget));
|
|
|
|
params.desktop_window_tree_host = atom_desktop_window_tree_host_win_;
|
2015-08-06 02:15:27 +00:00
|
|
|
#elif defined(USE_X11)
|
2014-11-24 07:27:36 +00:00
|
|
|
std::string name = Browser::Get()->GetName();
|
2014-08-26 02:34:48 +00:00
|
|
|
// Set WM_WINDOW_ROLE.
|
2014-11-24 07:27:36 +00:00
|
|
|
params.wm_role_name = "browser-window";
|
2014-08-26 02:34:48 +00:00
|
|
|
// Set WM_CLASS.
|
2015-12-07 11:56:23 +00:00
|
|
|
params.wm_class_name = base::ToLowerASCII(name);
|
2014-11-24 07:27:36 +00:00
|
|
|
params.wm_class_class = name;
|
2014-07-21 14:03:58 +00:00
|
|
|
#endif
|
2014-07-07 09:22:22 +00:00
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
window_->Init(params);
|
|
|
|
|
2015-09-28 23:20:09 +00:00
|
|
|
bool fullscreen = false;
|
2015-11-13 05:58:31 +00:00
|
|
|
options.Get(options::kFullscreen, &fullscreen);
|
2015-09-28 23:20:09 +00:00
|
|
|
|
2016-07-11 03:46:50 +00:00
|
|
|
std::string window_type;
|
|
|
|
options.Get(options::kType, &window_type);
|
|
|
|
|
2014-11-25 05:05:04 +00:00
|
|
|
#if defined(USE_X11)
|
2014-11-25 03:46:30 +00:00
|
|
|
// Start monitoring window states.
|
|
|
|
window_state_watcher_.reset(new WindowStateWatcher(this));
|
|
|
|
|
2014-08-26 02:34:48 +00:00
|
|
|
// Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
|
2014-08-21 04:24:55 +00:00
|
|
|
bool use_dark_theme = false;
|
2015-11-13 05:58:31 +00:00
|
|
|
if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
|
2014-08-21 04:24:55 +00:00
|
|
|
XDisplay* xdisplay = gfx::GetXDisplay();
|
|
|
|
XChangeProperty(xdisplay, GetAcceleratedWidget(),
|
|
|
|
XInternAtom(xdisplay, "_GTK_THEME_VARIANT", False),
|
|
|
|
XInternAtom(xdisplay, "UTF8_STRING", False),
|
|
|
|
8, PropModeReplace,
|
|
|
|
reinterpret_cast<const unsigned char*>("dark"),
|
|
|
|
4);
|
|
|
|
}
|
2014-08-26 04:15:22 +00:00
|
|
|
|
|
|
|
// Before the window is mapped the SetWMSpecState can not work, so we have
|
|
|
|
// to manually set the _NET_WM_STATE.
|
2015-06-29 13:53:33 +00:00
|
|
|
std::vector<::Atom> state_atom_list;
|
2014-08-26 04:15:22 +00:00
|
|
|
bool skip_taskbar = false;
|
2015-11-13 05:58:31 +00:00
|
|
|
if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
|
2014-08-26 04:15:22 +00:00
|
|
|
state_atom_list.push_back(GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
|
|
|
}
|
2015-02-11 04:12:22 +00:00
|
|
|
|
2015-06-29 13:53:33 +00:00
|
|
|
// Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
|
2015-09-28 23:20:09 +00:00
|
|
|
if (fullscreen) {
|
2015-06-29 13:53:33 +00:00
|
|
|
state_atom_list.push_back(GetAtom("_NET_WM_STATE_FULLSCREEN"));
|
|
|
|
}
|
|
|
|
|
2016-06-20 06:44:50 +00:00
|
|
|
if (parent) {
|
|
|
|
SetParentWindow(parent);
|
|
|
|
// Force using dialog type for child window.
|
|
|
|
window_type = "dialog";
|
|
|
|
// Modal window needs the _NET_WM_STATE_MODAL hint.
|
|
|
|
if (is_modal())
|
|
|
|
state_atom_list.push_back(GetAtom("_NET_WM_STATE_MODAL"));
|
|
|
|
}
|
|
|
|
|
2015-06-29 13:53:33 +00:00
|
|
|
ui::SetAtomArrayProperty(GetAcceleratedWidget(), "_NET_WM_STATE", "ATOM",
|
|
|
|
state_atom_list);
|
|
|
|
|
2015-02-11 04:12:22 +00:00
|
|
|
// Set the _NET_WM_WINDOW_TYPE.
|
2016-06-20 06:44:50 +00:00
|
|
|
if (!window_type.empty())
|
2015-02-11 04:12:22 +00:00
|
|
|
SetWindowType(GetAcceleratedWidget(), window_type);
|
2014-08-21 04:24:55 +00:00
|
|
|
#endif
|
|
|
|
|
2014-07-04 04:32:03 +00:00
|
|
|
AddChildView(web_view_);
|
|
|
|
|
2014-11-07 18:34:52 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-01-23 10:23:18 +00:00
|
|
|
if (!has_frame()) {
|
|
|
|
// Set Window style so that we get a minimize and maximize animation when
|
|
|
|
// frameless.
|
|
|
|
DWORD frame_style = WS_CAPTION;
|
|
|
|
if (resizable_)
|
|
|
|
frame_style |= WS_THICKFRAME;
|
|
|
|
if (minimizable_)
|
|
|
|
frame_style |= WS_MINIMIZEBOX;
|
|
|
|
if (maximizable_)
|
|
|
|
frame_style |= WS_MAXIMIZEBOX;
|
|
|
|
// We should not show a frame for transparent window.
|
2016-07-09 12:49:15 +00:00
|
|
|
if (!thick_frame_)
|
2016-01-23 10:23:18 +00:00
|
|
|
frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
|
|
|
|
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
|
|
|
|
}
|
2014-12-24 00:55:57 +00:00
|
|
|
|
2016-07-11 03:46:50 +00:00
|
|
|
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
|
|
|
|
// Window without thick frame has to have WS_EX_COMPOSITED style.
|
|
|
|
if (!thick_frame_)
|
2014-12-24 00:55:57 +00:00
|
|
|
ex_style |= WS_EX_COMPOSITED;
|
2016-07-11 03:46:50 +00:00
|
|
|
if (window_type == "toolbar")
|
|
|
|
ex_style |= WS_EX_TOOLWINDOW;
|
|
|
|
::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
|
2014-11-07 18:34:52 +00:00
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
|
2015-08-05 04:46:32 +00:00
|
|
|
if (has_frame()) {
|
2017-08-21 08:21:59 +00:00
|
|
|
// TODO(zcbenz): This was used to force using native frame on Windows 2003,
|
|
|
|
// we should check whether setting it in InitParams can work.
|
2014-11-12 05:45:21 +00:00
|
|
|
window_->set_frame_type(views::Widget::FrameType::FRAME_TYPE_FORCE_NATIVE);
|
|
|
|
window_->FrameTypeChanged();
|
2017-08-21 08:42:45 +00:00
|
|
|
#if defined(OS_WIN)
|
2017-08-21 08:21:59 +00:00
|
|
|
// thickFrame also works for normal window.
|
|
|
|
if (!thick_frame_)
|
|
|
|
FlipWindowStyle(GetAcceleratedWidget(), false, WS_THICKFRAME);
|
2017-08-21 08:42:45 +00:00
|
|
|
#endif
|
2014-11-12 05:45:21 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:05:59 +00:00
|
|
|
gfx::Size size = bounds.size();
|
|
|
|
if (has_frame() &&
|
2015-11-13 05:58:31 +00:00
|
|
|
options.Get(options::kUseContentSize, &use_content_size_) &&
|
2015-10-05 11:05:59 +00:00
|
|
|
use_content_size_)
|
2016-08-04 17:58:59 +00:00
|
|
|
size = ContentBoundsToWindowBounds(gfx::Rect(size)).size();
|
2015-10-05 11:05:59 +00:00
|
|
|
|
|
|
|
window_->CenterWindow(size);
|
2014-07-12 03:36:08 +00:00
|
|
|
Layout();
|
2016-07-09 14:10:36 +00:00
|
|
|
|
2017-05-26 01:38:27 +00:00
|
|
|
autofill_popup_.reset(new AutofillPopup(GetNativeView()));
|
|
|
|
|
2016-07-09 14:10:36 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
// Save initial window state.
|
|
|
|
if (fullscreen)
|
|
|
|
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
|
|
|
else
|
|
|
|
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
2016-11-22 04:49:56 +00:00
|
|
|
last_normal_bounds_ = GetBounds();
|
2016-07-09 14:10:36 +00:00
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NativeWindowViews::~NativeWindowViews() {
|
2014-07-08 04:55:33 +00:00
|
|
|
window_->RemoveObserver(this);
|
2017-08-15 23:03:33 +00:00
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
// Disable mouse forwarding to relinquish resources, should any be held.
|
|
|
|
SetForwardMouseMessages(false);
|
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Close() {
|
2016-05-25 23:25:51 +00:00
|
|
|
if (!IsClosable()) {
|
|
|
|
WindowList::WindowCloseCancelled(this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
window_->Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::CloseImmediately() {
|
|
|
|
window_->CloseNow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Focus(bool focus) {
|
2016-07-05 01:34:52 +00:00
|
|
|
// For hidden window focus() should do nothing.
|
|
|
|
if (!IsVisible())
|
|
|
|
return;
|
|
|
|
|
2016-06-06 07:53:32 +00:00
|
|
|
if (focus) {
|
|
|
|
#if defined(OS_WIN)
|
2014-07-03 17:30:36 +00:00
|
|
|
window_->Activate();
|
2016-06-06 07:53:32 +00:00
|
|
|
#elif defined(USE_X11)
|
|
|
|
// The "Activate" implementation of Chromium is not reliable on Linux.
|
|
|
|
::Window window = GetAcceleratedWidget();
|
|
|
|
XDisplay* xdisplay = gfx::GetXDisplay();
|
|
|
|
SendClientEvent(xdisplay, window, "_NET_ACTIVE_WINDOW");
|
|
|
|
XMapRaised(xdisplay, window);
|
|
|
|
#endif
|
|
|
|
} else {
|
2014-07-03 17:30:36 +00:00
|
|
|
window_->Deactivate();
|
2016-06-06 07:53:32 +00:00
|
|
|
}
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsFocused() {
|
|
|
|
return window_->IsActive();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Show() {
|
2017-06-29 04:37:54 +00:00
|
|
|
if (is_modal() && NativeWindow::parent() &&
|
|
|
|
!window_->native_widget_private()->IsVisible())
|
2016-06-20 06:44:50 +00:00
|
|
|
static_cast<NativeWindowViews*>(NativeWindow::parent())->SetEnabled(false);
|
|
|
|
|
2015-03-26 08:39:03 +00:00
|
|
|
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
2016-02-23 07:43:32 +00:00
|
|
|
|
2016-03-08 17:36:41 +00:00
|
|
|
NotifyWindowShow();
|
|
|
|
|
2016-02-23 07:43:32 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
if (global_menu_bar_)
|
|
|
|
global_menu_bar_->OnWindowMapped();
|
|
|
|
#endif
|
2014-10-17 14:51:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::ShowInactive() {
|
2014-09-08 07:28:34 +00:00
|
|
|
window_->ShowInactive();
|
2016-02-23 07:43:32 +00:00
|
|
|
|
2016-03-08 17:36:41 +00:00
|
|
|
NotifyWindowShow();
|
|
|
|
|
2016-02-23 07:43:32 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
if (global_menu_bar_)
|
|
|
|
global_menu_bar_->OnWindowMapped();
|
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Hide() {
|
2016-06-20 06:44:50 +00:00
|
|
|
if (is_modal() && NativeWindow::parent())
|
|
|
|
static_cast<NativeWindowViews*>(NativeWindow::parent())->SetEnabled(true);
|
|
|
|
|
2015-10-05 11:57:14 +00:00
|
|
|
window_->Hide();
|
2016-02-23 07:43:32 +00:00
|
|
|
|
2016-03-08 17:36:41 +00:00
|
|
|
NotifyWindowHide();
|
|
|
|
|
2016-02-23 07:43:32 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
if (global_menu_bar_)
|
|
|
|
global_menu_bar_->OnWindowUnmapped();
|
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsVisible() {
|
|
|
|
return window_->IsVisible();
|
|
|
|
}
|
|
|
|
|
2016-06-17 08:38:44 +00:00
|
|
|
bool NativeWindowViews::IsEnabled() {
|
2016-06-19 06:47:27 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-06-19 03:18:48 +00:00
|
|
|
return ::IsWindowEnabled(GetAcceleratedWidget());
|
2016-06-19 08:35:56 +00:00
|
|
|
#elif defined(USE_X11)
|
|
|
|
return !event_disabler_.get();
|
2016-06-19 06:47:27 +00:00
|
|
|
#endif
|
2016-06-17 08:38:44 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
void NativeWindowViews::Maximize() {
|
2016-07-09 13:49:55 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
// For window without WS_THICKFRAME style, we can not call Maximize().
|
2016-12-15 06:01:03 +00:00
|
|
|
if (!(::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME)) {
|
2016-07-09 14:16:57 +00:00
|
|
|
restore_bounds_ = GetBounds();
|
2016-07-09 13:49:55 +00:00
|
|
|
auto display =
|
2016-07-21 17:20:43 +00:00
|
|
|
display::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
|
2016-07-09 13:49:55 +00:00
|
|
|
SetBounds(display.work_area(), false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-12-16 00:37:46 +00:00
|
|
|
if (IsVisible())
|
|
|
|
window_->Maximize();
|
|
|
|
else
|
2014-12-16 00:57:04 +00:00
|
|
|
window_->native_widget_private()->ShowWithWindowState(
|
|
|
|
ui::SHOW_STATE_MAXIMIZED);
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Unmaximize() {
|
2016-07-09 14:04:42 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-12-15 06:01:03 +00:00
|
|
|
if (!(::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME)) {
|
2016-07-09 14:16:57 +00:00
|
|
|
SetBounds(restore_bounds_, false);
|
2016-07-09 14:04:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
window_->Restore();
|
|
|
|
}
|
|
|
|
|
2014-07-07 15:49:28 +00:00
|
|
|
bool NativeWindowViews::IsMaximized() {
|
|
|
|
return window_->IsMaximized();
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
void NativeWindowViews::Minimize() {
|
2014-12-16 00:37:46 +00:00
|
|
|
if (IsVisible())
|
|
|
|
window_->Minimize();
|
|
|
|
else
|
2014-12-16 00:57:04 +00:00
|
|
|
window_->native_widget_private()->ShowWithWindowState(
|
|
|
|
ui::SHOW_STATE_MINIMIZED);
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Restore() {
|
|
|
|
window_->Restore();
|
|
|
|
}
|
|
|
|
|
2014-07-26 05:58:26 +00:00
|
|
|
bool NativeWindowViews::IsMinimized() {
|
|
|
|
return window_->IsMinimized();
|
|
|
|
}
|
|
|
|
|
2014-11-25 06:34:14 +00:00
|
|
|
void NativeWindowViews::SetFullScreen(bool fullscreen) {
|
2016-03-05 12:38:06 +00:00
|
|
|
if (!IsFullScreenable())
|
|
|
|
return;
|
|
|
|
|
2014-11-25 06:28:34 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
// There is no native fullscreen state on Windows.
|
2017-06-14 00:47:15 +00:00
|
|
|
bool leaving_fullscreen = IsFullscreen() && !fullscreen;
|
2017-06-01 04:38:51 +00:00
|
|
|
|
2015-09-28 23:20:09 +00:00
|
|
|
if (fullscreen) {
|
2016-03-05 12:38:06 +00:00
|
|
|
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
|
|
|
NotifyWindowEnterFullScreen();
|
2015-09-28 23:20:09 +00:00
|
|
|
} else {
|
|
|
|
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
2014-11-25 06:28:34 +00:00
|
|
|
NotifyWindowLeaveFullScreen();
|
2015-09-28 23:20:09 +00:00
|
|
|
}
|
2016-07-09 13:49:55 +00:00
|
|
|
|
2017-01-18 22:40:42 +00:00
|
|
|
// For window without WS_THICKFRAME style, we can not call SetFullscreen().
|
|
|
|
// This path will be used for transparent windows as well.
|
|
|
|
if (!thick_frame_) {
|
|
|
|
if (fullscreen) {
|
|
|
|
restore_bounds_ = GetBounds();
|
|
|
|
auto display =
|
|
|
|
display::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
|
|
|
|
SetBounds(display.bounds(), false);
|
|
|
|
} else {
|
|
|
|
SetBounds(restore_bounds_, false);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-28 23:20:09 +00:00
|
|
|
// We set the new value after notifying, so we can handle the size event
|
|
|
|
// correctly.
|
2016-03-05 12:38:06 +00:00
|
|
|
window_->SetFullscreen(fullscreen);
|
2017-06-01 04:38:51 +00:00
|
|
|
|
|
|
|
// If restoring from fullscreen and the window isn't visible, force visible,
|
|
|
|
// else a non-responsive window shell could be rendered.
|
|
|
|
// (this situation may arise when app starts with fullscreen: true)
|
|
|
|
// Note: the following must be after "window_->SetFullscreen(fullscreen);"
|
2017-06-14 00:55:55 +00:00
|
|
|
if (leaving_fullscreen && !IsVisible())
|
2017-06-14 00:47:15 +00:00
|
|
|
FlipWindowStyle(GetAcceleratedWidget(), true, WS_VISIBLE);
|
2016-02-09 00:17:05 +00:00
|
|
|
#else
|
2016-03-05 12:38:06 +00:00
|
|
|
if (IsVisible())
|
|
|
|
window_->SetFullscreen(fullscreen);
|
2016-08-24 21:30:29 +00:00
|
|
|
else if (fullscreen)
|
2016-03-05 12:38:06 +00:00
|
|
|
window_->native_widget_private()->ShowWithWindowState(
|
|
|
|
ui::SHOW_STATE_FULLSCREEN);
|
2016-07-11 04:10:19 +00:00
|
|
|
|
|
|
|
// Auto-hide menubar when in fullscreen.
|
|
|
|
if (fullscreen)
|
|
|
|
SetMenuBarVisibility(false);
|
|
|
|
else
|
|
|
|
SetMenuBarVisibility(!menu_bar_autohide_);
|
2014-11-25 06:28:34 +00:00
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
2015-04-21 13:35:36 +00:00
|
|
|
bool NativeWindowViews::IsFullscreen() const {
|
2014-07-03 17:30:36 +00:00
|
|
|
return window_->IsFullscreen();
|
|
|
|
}
|
|
|
|
|
2016-07-09 13:49:55 +00:00
|
|
|
void NativeWindowViews::SetBounds(const gfx::Rect& bounds, bool animate) {
|
2015-05-01 14:40:46 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
// On Linux the minimum and maximum size should be updated with window size
|
|
|
|
// when window is not resizable.
|
|
|
|
if (!resizable_) {
|
|
|
|
SetMaximumSize(bounds.size());
|
|
|
|
SetMinimumSize(bounds.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
window_->SetBounds(bounds);
|
2015-05-01 10:50:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Rect NativeWindowViews::GetBounds() {
|
2015-05-01 14:40:46 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
if (IsMinimized())
|
|
|
|
return window_->GetRestoredBounds();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return window_->GetWindowBoundsInScreen();
|
2015-05-01 10:50:53 +00:00
|
|
|
}
|
|
|
|
|
2016-07-29 01:19:17 +00:00
|
|
|
gfx::Rect NativeWindowViews::GetContentBounds() {
|
2016-07-29 17:03:35 +00:00
|
|
|
return web_view_->GetBoundsInScreen();
|
2016-07-29 01:19:17 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 12:03:43 +00:00
|
|
|
gfx::Size NativeWindowViews::GetContentSize() {
|
2015-10-05 13:06:57 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
if (IsMinimized())
|
|
|
|
return NativeWindow::GetContentSize();
|
|
|
|
#endif
|
|
|
|
|
2015-10-05 12:03:43 +00:00
|
|
|
return web_view_->size();
|
|
|
|
}
|
|
|
|
|
2015-10-06 08:06:39 +00:00
|
|
|
void NativeWindowViews::SetContentSizeConstraints(
|
|
|
|
const extensions::SizeConstraints& size_constraints) {
|
|
|
|
NativeWindow::SetContentSizeConstraints(size_constraints);
|
2017-08-21 08:42:45 +00:00
|
|
|
#if defined(OS_WIN)
|
2017-08-21 08:21:59 +00:00
|
|
|
// Changing size constraints would force adding the WS_THICKFRAME style, so
|
|
|
|
// do nothing if thickFrame is false.
|
2017-08-21 08:42:45 +00:00
|
|
|
if (!thick_frame_)
|
|
|
|
return;
|
|
|
|
#endif
|
2015-10-15 08:19:45 +00:00
|
|
|
// widget_delegate() is only available after Init() is called, we make use of
|
|
|
|
// this to determine whether native widget has initialized.
|
2017-08-21 08:42:45 +00:00
|
|
|
if (window_ && window_->widget_delegate())
|
2015-10-15 08:19:45 +00:00
|
|
|
window_->OnSizeConstraintsChanged();
|
2015-10-06 08:06:39 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
if (resizable_)
|
|
|
|
old_size_constraints_ = size_constraints;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
void NativeWindowViews::SetResizable(bool resizable) {
|
2014-08-05 12:41:26 +00:00
|
|
|
#if defined(OS_WIN)
|
2017-08-21 08:21:59 +00:00
|
|
|
if (has_frame() && thick_frame_)
|
2016-01-23 10:23:18 +00:00
|
|
|
FlipWindowStyle(GetAcceleratedWidget(), resizable, WS_THICKFRAME);
|
2014-08-26 05:37:37 +00:00
|
|
|
#elif defined(USE_X11)
|
|
|
|
if (resizable != resizable_) {
|
|
|
|
// On Linux there is no "resizable" property of a window, we have to set
|
|
|
|
// both the minimum and maximum size to the window size to achieve it.
|
|
|
|
if (resizable) {
|
2015-10-06 08:06:39 +00:00
|
|
|
SetContentSizeConstraints(old_size_constraints_);
|
2014-08-26 05:37:37 +00:00
|
|
|
} else {
|
2015-10-06 08:06:39 +00:00
|
|
|
old_size_constraints_ = GetContentSizeConstraints();
|
|
|
|
resizable_ = false;
|
|
|
|
gfx::Size content_size = GetContentSize();
|
|
|
|
SetContentSizeConstraints(
|
|
|
|
extensions::SizeConstraints(content_size, content_size));
|
2014-08-26 05:37:37 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-05 12:41:26 +00:00
|
|
|
#endif
|
|
|
|
|
2014-08-26 05:37:37 +00:00
|
|
|
resizable_ = resizable;
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsResizable() {
|
2016-01-23 12:03:56 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-11-15 05:23:59 +00:00
|
|
|
if (has_frame())
|
2016-07-09 12:49:15 +00:00
|
|
|
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
|
2016-11-15 05:23:59 +00:00
|
|
|
else
|
2016-07-09 12:49:15 +00:00
|
|
|
return CanResize();
|
2016-01-23 12:03:56 +00:00
|
|
|
#else
|
2016-01-23 10:23:18 +00:00
|
|
|
return CanResize();
|
2016-01-23 12:03:56 +00:00
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
2016-01-18 22:46:35 +00:00
|
|
|
void NativeWindowViews::SetMovable(bool movable) {
|
|
|
|
movable_ = movable;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsMovable() {
|
2016-01-19 15:43:52 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-01-18 22:46:35 +00:00
|
|
|
return movable_;
|
2016-01-23 10:23:18 +00:00
|
|
|
#else
|
|
|
|
return true; // Not implemented on Linux.
|
2016-01-19 15:43:52 +00:00
|
|
|
#endif
|
2016-01-18 22:46:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::SetMinimizable(bool minimizable) {
|
|
|
|
#if defined(OS_WIN)
|
2016-01-23 10:23:18 +00:00
|
|
|
FlipWindowStyle(GetAcceleratedWidget(), minimizable, WS_MINIMIZEBOX);
|
2016-01-18 22:46:35 +00:00
|
|
|
#endif
|
|
|
|
minimizable_ = minimizable;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsMinimizable() {
|
|
|
|
#if defined(OS_WIN)
|
2016-01-23 11:35:30 +00:00
|
|
|
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MINIMIZEBOX;
|
2016-01-23 10:23:18 +00:00
|
|
|
#else
|
2016-01-23 11:35:30 +00:00
|
|
|
return true; // Not implemented on Linux.
|
2016-01-18 22:46:35 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-01-22 21:24:33 +00:00
|
|
|
void NativeWindowViews::SetMaximizable(bool maximizable) {
|
|
|
|
#if defined(OS_WIN)
|
2016-01-23 10:23:18 +00:00
|
|
|
FlipWindowStyle(GetAcceleratedWidget(), maximizable, WS_MAXIMIZEBOX);
|
2016-01-22 21:24:33 +00:00
|
|
|
#endif
|
2016-01-23 10:23:18 +00:00
|
|
|
maximizable_ = maximizable;
|
2016-01-22 21:24:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsMaximizable() {
|
|
|
|
#if defined(OS_WIN)
|
2016-01-23 11:35:30 +00:00
|
|
|
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MAXIMIZEBOX;
|
2016-01-23 10:23:18 +00:00
|
|
|
#else
|
2016-01-23 11:35:30 +00:00
|
|
|
return true; // Not implemented on Linux.
|
2016-01-22 21:24:33 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-02-22 09:23:56 +00:00
|
|
|
void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
|
|
|
|
fullscreenable_ = fullscreenable;
|
2016-01-22 21:24:33 +00:00
|
|
|
}
|
|
|
|
|
2016-01-23 07:47:37 +00:00
|
|
|
bool NativeWindowViews::IsFullScreenable() {
|
2016-02-22 09:23:56 +00:00
|
|
|
return fullscreenable_;
|
2016-01-22 21:24:33 +00:00
|
|
|
}
|
|
|
|
|
2016-01-18 22:46:35 +00:00
|
|
|
void NativeWindowViews::SetClosable(bool closable) {
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
|
|
|
|
if (closable) {
|
|
|
|
EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
|
|
|
|
} else {
|
|
|
|
EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsClosable() {
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
|
|
|
|
MENUITEMINFO info;
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
info.cbSize = sizeof(info);
|
|
|
|
info.fMask = MIIM_STATE;
|
|
|
|
if (!GetMenuItemInfo(menu, SC_CLOSE, false, &info)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !(info.fState & MFS_DISABLED);
|
|
|
|
#elif defined(USE_X11)
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-01-24 04:36:09 +00:00
|
|
|
void NativeWindowViews::SetAlwaysOnTop(bool top, const std::string& level,
|
2017-01-25 04:08:08 +00:00
|
|
|
int relativeLevel, std::string* error) {
|
2016-09-22 16:38:04 +00:00
|
|
|
window_->SetAlwaysOnTop(top);
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsAlwaysOnTop() {
|
2014-07-04 04:32:03 +00:00
|
|
|
return window_->IsAlwaysOnTop();
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::Center() {
|
|
|
|
window_->CenterWindow(GetSize());
|
|
|
|
}
|
|
|
|
|
2017-02-14 03:41:24 +00:00
|
|
|
void NativeWindowViews::Invalidate() {
|
2017-02-14 19:09:15 +00:00
|
|
|
window_->SchedulePaintInRect(gfx::Rect(GetBounds().size()));
|
2017-02-14 03:41:24 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
void NativeWindowViews::SetTitle(const std::string& title) {
|
|
|
|
title_ = title;
|
|
|
|
window_->UpdateWindowTitle();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string NativeWindowViews::GetTitle() {
|
|
|
|
return title_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::FlashFrame(bool flash) {
|
2014-12-16 01:27:58 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
// The Chromium's implementation has a bug stopping flash.
|
|
|
|
if (!flash) {
|
|
|
|
FLASHWINFO fwi;
|
|
|
|
fwi.cbSize = sizeof(fwi);
|
|
|
|
fwi.hwnd = GetAcceleratedWidget();
|
|
|
|
fwi.dwFlags = FLASHW_STOP;
|
|
|
|
fwi.uCount = 0;
|
|
|
|
FlashWindowEx(&fwi);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
window_->FlashFrame(flash);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::SetSkipTaskbar(bool skip) {
|
2014-07-07 09:22:22 +00:00
|
|
|
#if defined(OS_WIN)
|
2014-07-21 14:03:58 +00:00
|
|
|
base::win::ScopedComPtr<ITaskbarList> taskbar;
|
|
|
|
if (FAILED(taskbar.CreateInstance(CLSID_TaskbarList, NULL,
|
|
|
|
CLSCTX_INPROC_SERVER)) ||
|
|
|
|
FAILED(taskbar->HrInit()))
|
|
|
|
return;
|
2016-08-12 15:55:42 +00:00
|
|
|
if (skip) {
|
2014-07-21 14:03:58 +00:00
|
|
|
taskbar->DeleteTab(GetAcceleratedWidget());
|
2016-08-12 15:55:42 +00:00
|
|
|
} else {
|
2014-07-21 14:03:58 +00:00
|
|
|
taskbar->AddTab(GetAcceleratedWidget());
|
2016-08-12 15:55:42 +00:00
|
|
|
taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget());
|
|
|
|
}
|
2014-08-26 04:15:22 +00:00
|
|
|
#elif defined(USE_X11)
|
|
|
|
SetWMSpecState(GetAcceleratedWidget(), skip,
|
|
|
|
GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
2014-07-07 09:22:22 +00:00
|
|
|
#endif
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
2017-08-13 06:28:33 +00:00
|
|
|
void NativeWindowViews::SetSimpleFullScreen(bool simple_fullscreen) {
|
|
|
|
SetFullScreen(simple_fullscreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsSimpleFullScreen() {
|
|
|
|
return IsFullscreen();
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
void NativeWindowViews::SetKiosk(bool kiosk) {
|
2014-11-25 06:34:14 +00:00
|
|
|
SetFullScreen(kiosk);
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsKiosk() {
|
|
|
|
return IsFullscreen();
|
|
|
|
}
|
|
|
|
|
2015-10-23 03:35:33 +00:00
|
|
|
void NativeWindowViews::SetBackgroundColor(const std::string& color_name) {
|
|
|
|
// web views' background color.
|
2016-04-02 11:35:57 +00:00
|
|
|
SkColor background_color = ParseHexColor(color_name);
|
2015-10-23 03:35:33 +00:00
|
|
|
set_background(views::Background::CreateSolidBackground(background_color));
|
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
// Set the background color of native window.
|
|
|
|
HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color));
|
|
|
|
ULONG_PTR previous_brush = SetClassLongPtr(
|
2016-05-10 04:09:41 +00:00
|
|
|
GetAcceleratedWidget(),
|
|
|
|
GCLP_HBRBACKGROUND,
|
|
|
|
reinterpret_cast<LONG_PTR>(brush));
|
2015-10-23 03:35:33 +00:00
|
|
|
if (previous_brush)
|
|
|
|
DeleteObject((HBRUSH)previous_brush);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-01-23 10:55:12 +00:00
|
|
|
void NativeWindowViews::SetHasShadow(bool has_shadow) {
|
2017-04-17 08:17:02 +00:00
|
|
|
wm::SetShadowElevation(
|
2016-01-23 12:03:56 +00:00
|
|
|
GetNativeWindow(),
|
2017-04-17 08:17:02 +00:00
|
|
|
has_shadow ? wm::ShadowElevation::MEDIUM : wm::ShadowElevation::NONE);
|
2016-01-23 10:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::HasShadow() {
|
2017-04-17 08:17:02 +00:00
|
|
|
return GetNativeWindow()->GetProperty(wm::kShadowElevationKey)
|
|
|
|
!= wm::ShadowElevation::NONE;
|
2016-01-23 10:55:12 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 02:26:02 +00:00
|
|
|
void NativeWindowViews::SetOpacity(const double opacity) {
|
|
|
|
#if defined(OS_WIN)
|
2017-10-02 00:52:27 +00:00
|
|
|
HWND hwnd = GetAcceleratedWidget();
|
2017-09-29 02:26:02 +00:00
|
|
|
if (!layered_) {
|
2017-10-02 00:52:27 +00:00
|
|
|
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
|
2017-09-29 02:26:02 +00:00
|
|
|
ex_style |= WS_EX_LAYERED;
|
2017-10-02 00:52:27 +00:00
|
|
|
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
|
2017-09-29 02:26:02 +00:00
|
|
|
layered_ = true;
|
|
|
|
}
|
2017-10-02 00:52:27 +00:00
|
|
|
::SetLayeredWindowAttributes(hwnd, 0, opacity * 255, LWA_ALPHA);
|
2017-09-29 02:26:02 +00:00
|
|
|
#endif
|
2017-10-02 15:08:10 +00:00
|
|
|
opacity_ = opacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
double NativeWindowViews::GetOpacity() {
|
|
|
|
return opacity_;
|
2017-09-29 02:26:02 +00:00
|
|
|
}
|
|
|
|
|
2017-08-14 18:21:00 +00:00
|
|
|
void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
|
2016-06-07 10:38:41 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
|
|
|
|
if (ignore)
|
|
|
|
ex_style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
|
|
|
else
|
|
|
|
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
2017-09-29 02:26:02 +00:00
|
|
|
if (layered_)
|
|
|
|
ex_style |= WS_EX_LAYERED;
|
2016-06-07 10:38:41 +00:00
|
|
|
::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
|
2017-08-14 18:21:00 +00:00
|
|
|
|
|
|
|
// Forwarding is always disabled when not ignoring mouse messages.
|
|
|
|
if (!ignore) {
|
|
|
|
SetForwardMouseMessages(false);
|
|
|
|
} else {
|
|
|
|
SetForwardMouseMessages(forward);
|
|
|
|
}
|
2016-06-07 11:23:29 +00:00
|
|
|
#elif defined(USE_X11)
|
|
|
|
if (ignore) {
|
|
|
|
XRectangle r = {0, 0, 1, 1};
|
|
|
|
XShapeCombineRectangles(gfx::GetXDisplay(), GetAcceleratedWidget(),
|
|
|
|
ShapeInput, 0, 0, &r, 1, ShapeSet, YXBanded);
|
|
|
|
} else {
|
|
|
|
XShapeCombineMask(gfx::GetXDisplay(), GetAcceleratedWidget(),
|
|
|
|
ShapeInput, 0, 0, None, ShapeSet);
|
|
|
|
}
|
2016-06-07 10:38:41 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-06-22 08:40:01 +00:00
|
|
|
void NativeWindowViews::SetContentProtection(bool enable) {
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
DWORD affinity = enable ? WDA_MONITOR : WDA_NONE;
|
|
|
|
::SetWindowDisplayAffinity(GetAcceleratedWidget(), affinity);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-06-13 08:10:28 +00:00
|
|
|
void NativeWindowViews::SetFocusable(bool focusable) {
|
2016-06-12 18:20:25 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
|
2016-06-13 08:10:28 +00:00
|
|
|
if (focusable)
|
2016-06-12 18:20:25 +00:00
|
|
|
ex_style &= ~WS_EX_NOACTIVATE;
|
2016-06-13 08:24:45 +00:00
|
|
|
else
|
|
|
|
ex_style |= WS_EX_NOACTIVATE;
|
2016-06-12 18:20:25 +00:00
|
|
|
::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
|
2016-06-13 08:24:45 +00:00
|
|
|
SetSkipTaskbar(!focusable);
|
|
|
|
Focus(false);
|
2016-06-12 18:20:25 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-07-06 23:04:18 +00:00
|
|
|
void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
|
2015-06-04 08:10:19 +00:00
|
|
|
if (menu_model == nullptr) {
|
|
|
|
// Remove accelerators
|
|
|
|
accelerator_table_.clear();
|
|
|
|
GetFocusManager()->UnregisterAccelerators(this);
|
|
|
|
// and menu bar.
|
|
|
|
#if defined(USE_X11)
|
|
|
|
global_menu_bar_.reset();
|
|
|
|
#endif
|
|
|
|
SetMenuBarVisibility(false);
|
|
|
|
menu_bar_.reset();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-04 08:54:10 +00:00
|
|
|
RegisterAccelerators(menu_model);
|
2014-07-11 00:57:19 +00:00
|
|
|
|
|
|
|
#if defined(USE_X11)
|
2014-08-06 15:34:16 +00:00
|
|
|
if (!global_menu_bar_ && ShouldUseGlobalMenuBar())
|
2014-07-11 00:57:19 +00:00
|
|
|
global_menu_bar_.reset(new GlobalMenuBarX11(this));
|
2014-07-16 14:10:10 +00:00
|
|
|
|
|
|
|
// Use global application menu bar when possible.
|
2014-07-31 05:09:31 +00:00
|
|
|
if (global_menu_bar_ && global_menu_bar_->IsServerStarted()) {
|
2014-07-16 14:10:10 +00:00
|
|
|
global_menu_bar_->SetMenu(menu_model);
|
|
|
|
return;
|
|
|
|
}
|
2014-07-11 00:57:19 +00:00
|
|
|
#endif
|
2014-07-16 14:10:10 +00:00
|
|
|
|
|
|
|
// Do not show menu bar in frameless window.
|
2015-08-05 04:46:32 +00:00
|
|
|
if (!has_frame())
|
2014-07-16 14:10:10 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!menu_bar_) {
|
|
|
|
gfx::Size content_size = GetContentSize();
|
2016-10-24 02:42:15 +00:00
|
|
|
menu_bar_.reset(new MenuBar(this));
|
2014-08-07 05:47:58 +00:00
|
|
|
menu_bar_->set_owned_by_client();
|
|
|
|
|
|
|
|
if (!menu_bar_autohide_) {
|
|
|
|
SetMenuBarVisibility(true);
|
2015-10-05 16:15:10 +00:00
|
|
|
if (use_content_size_) {
|
|
|
|
// Enlarge the size constraints for the menu.
|
|
|
|
extensions::SizeConstraints constraints = GetContentSizeConstraints();
|
|
|
|
if (constraints.HasMinimumSize()) {
|
|
|
|
gfx::Size min_size = constraints.GetMinimumSize();
|
|
|
|
min_size.set_height(min_size.height() + kMenuBarHeight);
|
|
|
|
constraints.set_minimum_size(min_size);
|
|
|
|
}
|
|
|
|
if (constraints.HasMaximumSize()) {
|
|
|
|
gfx::Size max_size = constraints.GetMaximumSize();
|
|
|
|
max_size.set_height(max_size.height() + kMenuBarHeight);
|
|
|
|
constraints.set_maximum_size(max_size);
|
|
|
|
}
|
|
|
|
SetContentSizeConstraints(constraints);
|
|
|
|
|
|
|
|
// Resize the window to make sure content size is not changed.
|
2016-01-15 16:31:31 +00:00
|
|
|
SetContentSize(content_size);
|
2015-10-05 16:15:10 +00:00
|
|
|
}
|
2014-08-07 05:47:58 +00:00
|
|
|
}
|
2014-07-16 14:10:10 +00:00
|
|
|
}
|
2014-07-17 06:23:28 +00:00
|
|
|
|
|
|
|
menu_bar_->SetMenu(menu_model);
|
|
|
|
Layout();
|
2014-07-04 08:54:10 +00:00
|
|
|
}
|
|
|
|
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
void NativeWindowViews::SetBrowserView(NativeBrowserView* browser_view) {
|
|
|
|
if (browser_view_) {
|
2017-04-12 11:40:31 +00:00
|
|
|
web_view_->RemoveChildView(
|
|
|
|
browser_view_->GetInspectableWebContentsView()->GetView());
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
browser_view_ = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!browser_view) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-12 11:40:31 +00:00
|
|
|
// Add as child of the main web view to avoid (0, 0) origin from overlapping
|
|
|
|
// with menu bar.
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
browser_view_ = browser_view;
|
2017-04-12 11:40:31 +00:00
|
|
|
web_view_->AddChildView(
|
|
|
|
browser_view->GetInspectableWebContentsView()->GetView());
|
Implement initial, experimental BrowserView API
Right now, `<webview>` is the only way to embed additional content in a
`BrowserWindow`. Unfortunately `<webview>` suffers from a [number of
problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20).
To make matters worse, many of these are upstream Chromium bugs instead
of Electron-specific bugs.
For us at [Figma](https://www.figma.com), the main issue is very slow
performance.
Despite the upstream improvements to `<webview>` through the OOPIF work, it is
probable that there will continue to be `<webview>`-specific bugs in the
future.
Therefore, this introduces a `<webview>` alternative to called `BrowserView`,
which...
- is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will
likely also be bugs in `BrowserWindow` web contents)
- is instantiated in the main process like `BrowserWindow` (and unlike
`<webview>`, which lives in the DOM of a `BrowserWindow` web contents)
- needs to be added to a `BrowserWindow` to display something on the screen
This implements the most basic API. The API is expected to evolve and change in
the near future and has consequently been marked as experimental. Please do not
use this API in production unless you are prepared to deal with breaking
changes.
In the future, we will want to change the API to support multiple
`BrowserView`s per window. We will also want to consider z-ordering
auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 06:28:43 +00:00
|
|
|
void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
|
2016-06-20 05:49:24 +00:00
|
|
|
NativeWindow::SetParentWindow(parent);
|
|
|
|
|
2016-06-19 06:47:27 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
XDisplay* xdisplay = gfx::GetXDisplay();
|
|
|
|
XSetTransientForHint(
|
|
|
|
xdisplay, GetAcceleratedWidget(),
|
|
|
|
parent? parent->GetAcceleratedWidget() : DefaultRootWindow(xdisplay));
|
|
|
|
#elif defined(OS_WIN) && defined(DEBUG)
|
2016-06-19 02:19:32 +00:00
|
|
|
// Should work, but does not, it seems that the views toolkit doesn't support
|
|
|
|
// reparenting on desktop.
|
|
|
|
if (parent) {
|
|
|
|
::SetParent(GetAcceleratedWidget(), parent->GetAcceleratedWidget());
|
|
|
|
views::Widget::ReparentNativeView(GetNativeWindow(),
|
|
|
|
parent->GetNativeWindow());
|
|
|
|
wm::AddTransientChild(parent->GetNativeWindow(), GetNativeWindow());
|
|
|
|
} else {
|
|
|
|
if (!GetNativeWindow()->parent())
|
|
|
|
return;
|
2016-06-19 06:47:27 +00:00
|
|
|
::SetParent(GetAcceleratedWidget(), NULL);
|
2016-06-19 02:19:32 +00:00
|
|
|
views::Widget::ReparentNativeView(GetNativeWindow(), nullptr);
|
|
|
|
wm::RemoveTransientChild(GetNativeWindow()->parent(), GetNativeWindow());
|
|
|
|
}
|
|
|
|
#endif
|
2016-06-17 06:28:43 +00:00
|
|
|
}
|
|
|
|
|
2017-05-21 18:57:19 +00:00
|
|
|
gfx::NativeView NativeWindowViews::GetNativeView() const {
|
2017-03-04 02:09:16 +00:00
|
|
|
return window_->GetNativeView();
|
|
|
|
}
|
|
|
|
|
2017-05-21 18:57:19 +00:00
|
|
|
gfx::NativeWindow NativeWindowViews::GetNativeWindow() const {
|
2014-07-03 17:30:36 +00:00
|
|
|
return window_->GetNativeWindow();
|
|
|
|
}
|
|
|
|
|
2016-08-08 22:44:48 +00:00
|
|
|
void NativeWindowViews::SetProgressBar(
|
2016-08-09 23:05:44 +00:00
|
|
|
double progress, NativeWindow::ProgressState state) {
|
2014-09-17 01:42:47 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-08-09 23:05:44 +00:00
|
|
|
taskbar_host_.SetProgressBar(GetAcceleratedWidget(), progress, state);
|
2014-09-18 11:12:24 +00:00
|
|
|
#elif defined(USE_X11)
|
|
|
|
if (unity::IsRunning()) {
|
|
|
|
unity::SetProgressFraction(progress);
|
|
|
|
}
|
2014-09-17 01:42:47 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-11 01:14:26 +00:00
|
|
|
void NativeWindowViews::SetOverlayIcon(const gfx::Image& overlay,
|
|
|
|
const std::string& description) {
|
2015-02-06 23:58:49 +00:00
|
|
|
#if defined(OS_WIN)
|
2015-08-06 05:07:00 +00:00
|
|
|
taskbar_host_.SetOverlayIcon(GetAcceleratedWidget(), overlay, description);
|
2015-02-06 23:58:49 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-11-12 12:32:14 +00:00
|
|
|
void NativeWindowViews::SetAutoHideMenuBar(bool auto_hide) {
|
|
|
|
menu_bar_autohide_ = auto_hide;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsMenuBarAutoHide() {
|
|
|
|
return menu_bar_autohide_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::SetMenuBarVisibility(bool visible) {
|
|
|
|
if (!menu_bar_ || menu_bar_visible_ == visible)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Always show the accelerator when the auto-hide menu bar shows.
|
|
|
|
if (menu_bar_autohide_)
|
|
|
|
menu_bar_->SetAcceleratorVisibility(visible);
|
|
|
|
|
|
|
|
menu_bar_visible_ = visible;
|
|
|
|
if (visible) {
|
|
|
|
DCHECK_EQ(child_count(), 1);
|
|
|
|
AddChildView(menu_bar_.get());
|
|
|
|
} else {
|
|
|
|
DCHECK_EQ(child_count(), 2);
|
|
|
|
RemoveChildView(menu_bar_.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
Layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsMenuBarVisible() {
|
|
|
|
return menu_bar_visible_;
|
|
|
|
}
|
|
|
|
|
2015-03-26 06:18:37 +00:00
|
|
|
void NativeWindowViews::SetVisibleOnAllWorkspaces(bool visible) {
|
|
|
|
window_->SetVisibleOnAllWorkspaces(visible);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::IsVisibleOnAllWorkspaces() {
|
2015-03-27 11:41:07 +00:00
|
|
|
#if defined(USE_X11)
|
|
|
|
// Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to
|
|
|
|
// determine whether the current window is visible on all workspaces.
|
2015-03-29 13:35:40 +00:00
|
|
|
XAtom sticky_atom = GetAtom("_NET_WM_STATE_STICKY");
|
|
|
|
std::vector<XAtom> wm_states;
|
|
|
|
ui::GetAtomArrayProperty(GetAcceleratedWidget(), "_NET_WM_STATE", &wm_states);
|
|
|
|
return std::find(wm_states.begin(),
|
|
|
|
wm_states.end(), sticky_atom) != wm_states.end();
|
2015-03-27 11:41:07 +00:00
|
|
|
#endif
|
|
|
|
return false;
|
2015-03-26 06:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-05-21 18:57:19 +00:00
|
|
|
gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
|
2014-07-21 14:03:58 +00:00
|
|
|
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
|
|
|
|
}
|
|
|
|
|
2016-05-20 13:28:07 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-05-31 08:47:45 +00:00
|
|
|
void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) {
|
|
|
|
// We are responsible for storing the images.
|
|
|
|
window_icon_ = base::win::ScopedHICON(CopyIcon(window_icon));
|
|
|
|
app_icon_ = base::win::ScopedHICON(CopyIcon(app_icon));
|
|
|
|
|
2016-05-20 13:28:07 +00:00
|
|
|
HWND hwnd = GetAcceleratedWidget();
|
|
|
|
SendMessage(hwnd, WM_SETICON, ICON_SMALL,
|
2016-05-31 08:47:45 +00:00
|
|
|
reinterpret_cast<LPARAM>(window_icon_.get()));
|
2016-05-20 13:28:07 +00:00
|
|
|
SendMessage(hwnd, WM_SETICON, ICON_BIG,
|
2016-05-31 08:47:45 +00:00
|
|
|
reinterpret_cast<LPARAM>(app_icon_.get()));
|
2016-05-20 13:28:07 +00:00
|
|
|
}
|
|
|
|
#elif defined(USE_X11)
|
2016-05-20 13:22:15 +00:00
|
|
|
void NativeWindowViews::SetIcon(const gfx::ImageSkia& icon) {
|
|
|
|
views::DesktopWindowTreeHostX11* tree_host =
|
|
|
|
views::DesktopWindowTreeHostX11::GetHostForXID(GetAcceleratedWidget());
|
|
|
|
static_cast<views::DesktopWindowTreeHost*>(tree_host)->SetWindowIcons(
|
|
|
|
icon, icon);
|
|
|
|
}
|
2016-05-20 13:28:07 +00:00
|
|
|
#endif
|
2016-05-20 13:22:15 +00:00
|
|
|
|
2016-06-20 06:44:50 +00:00
|
|
|
void NativeWindowViews::SetEnabled(bool enable) {
|
|
|
|
// Handle multiple calls of SetEnabled correctly.
|
|
|
|
if (enable) {
|
|
|
|
--disable_count_;
|
|
|
|
if (disable_count_ != 0)
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
++disable_count_;
|
|
|
|
if (disable_count_ != 1)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
::EnableWindow(GetAcceleratedWidget(), enable);
|
|
|
|
#elif defined(USE_X11)
|
|
|
|
views::DesktopWindowTreeHostX11* tree_host =
|
|
|
|
views::DesktopWindowTreeHostX11::GetHostForXID(GetAcceleratedWidget());
|
|
|
|
if (enable) {
|
|
|
|
tree_host->RemoveEventRewriter(event_disabler_.get());
|
|
|
|
event_disabler_.reset();
|
|
|
|
} else {
|
|
|
|
event_disabler_.reset(new EventDisabler);
|
|
|
|
tree_host->AddEventRewriter(event_disabler_.get());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-07-08 04:55:33 +00:00
|
|
|
void NativeWindowViews::OnWidgetActivationChanged(
|
|
|
|
views::Widget* widget, bool active) {
|
|
|
|
if (widget != window_.get())
|
|
|
|
return;
|
|
|
|
|
2016-04-13 02:02:34 +00:00
|
|
|
// Post the notification to next tick.
|
|
|
|
content::BrowserThread::PostTask(
|
|
|
|
content::BrowserThread::UI, FROM_HERE,
|
|
|
|
base::Bind(active ? &NativeWindow::NotifyWindowFocus :
|
|
|
|
&NativeWindow::NotifyWindowBlur,
|
|
|
|
GetWeakPtr()));
|
2014-08-07 06:02:03 +00:00
|
|
|
|
2015-06-25 06:54:00 +00:00
|
|
|
if (active && inspectable_web_contents() &&
|
2015-06-08 05:19:56 +00:00
|
|
|
!inspectable_web_contents()->IsDevToolsViewShowing())
|
2015-06-25 06:54:00 +00:00
|
|
|
web_contents()->Focus();
|
2014-08-07 08:04:14 +00:00
|
|
|
|
2014-08-07 06:48:02 +00:00
|
|
|
// Hide menu bar when window is blured.
|
2014-11-12 12:32:14 +00:00
|
|
|
if (!active && menu_bar_autohide_ && menu_bar_visible_)
|
2014-08-07 06:02:03 +00:00
|
|
|
SetMenuBarVisibility(false);
|
2014-07-08 04:55:33 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 15:55:10 +00:00
|
|
|
void NativeWindowViews::OnWidgetBoundsChanged(
|
|
|
|
views::Widget* widget, const gfx::Rect& bounds) {
|
|
|
|
if (widget != window_.get())
|
|
|
|
return;
|
|
|
|
|
2017-07-17 20:51:42 +00:00
|
|
|
// Note: We intentionally use `GetBounds()` instead of `bounds` to properly
|
|
|
|
// handle minimized windows on Windows.
|
|
|
|
const auto new_bounds = GetBounds();
|
|
|
|
if (widget_size_ != new_bounds.size()) {
|
2017-07-17 18:46:31 +00:00
|
|
|
if (browser_view_) {
|
|
|
|
const auto flags = static_cast<NativeBrowserViewViews*>(browser_view_)
|
|
|
|
->GetAutoResizeFlags();
|
|
|
|
int width_delta = 0;
|
|
|
|
int height_delta = 0;
|
|
|
|
if (flags & kAutoResizeWidth) {
|
2017-07-17 20:51:42 +00:00
|
|
|
width_delta = new_bounds.width() - widget_size_.width();
|
2017-07-17 18:46:31 +00:00
|
|
|
}
|
|
|
|
if (flags & kAutoResizeHeight) {
|
2017-07-17 20:51:42 +00:00
|
|
|
height_delta = new_bounds.height() - widget_size_.height();
|
2017-07-17 18:46:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto* view = browser_view_->GetInspectableWebContentsView()->GetView();
|
|
|
|
auto new_view_size = view->size();
|
|
|
|
new_view_size.set_width(new_view_size.width() + width_delta);
|
|
|
|
new_view_size.set_height(new_view_size.height() + height_delta);
|
|
|
|
view->SetSize(new_view_size);
|
|
|
|
}
|
|
|
|
|
2015-05-09 15:55:10 +00:00
|
|
|
NotifyWindowResize();
|
2017-07-17 20:51:42 +00:00
|
|
|
widget_size_ = new_bounds.size();
|
2015-05-09 15:55:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
void NativeWindowViews::DeleteDelegate() {
|
2016-06-20 06:44:50 +00:00
|
|
|
if (is_modal() && NativeWindow::parent()) {
|
|
|
|
NativeWindowViews* parent =
|
|
|
|
static_cast<NativeWindowViews*>(NativeWindow::parent());
|
|
|
|
// Enable parent window after current window gets closed.
|
|
|
|
parent->SetEnabled(true);
|
|
|
|
// Focus on parent window.
|
|
|
|
parent->Focus(true);
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
NotifyWindowClosed();
|
|
|
|
}
|
|
|
|
|
|
|
|
views::View* NativeWindowViews::GetInitiallyFocusedView() {
|
2014-07-04 08:54:10 +00:00
|
|
|
return inspectable_web_contents()->GetView()->GetWebView();
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::CanResize() const {
|
|
|
|
return resizable_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::CanMaximize() const {
|
2016-01-23 10:23:18 +00:00
|
|
|
return resizable_ && maximizable_;
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
2014-12-16 00:46:37 +00:00
|
|
|
bool NativeWindowViews::CanMinimize() const {
|
2016-01-19 15:57:14 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-01-18 22:46:35 +00:00
|
|
|
return minimizable_;
|
|
|
|
#elif defined(USE_X11)
|
2014-12-16 00:46:37 +00:00
|
|
|
return true;
|
2016-01-18 22:46:35 +00:00
|
|
|
#endif
|
2014-12-16 00:46:37 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
base::string16 NativeWindowViews::GetWindowTitle() const {
|
|
|
|
return base::UTF8ToUTF16(title_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowViews::ShouldHandleSystemCommands() const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
views::Widget* NativeWindowViews::GetWidget() {
|
|
|
|
return window_.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
const views::Widget* NativeWindowViews::GetWidget() const {
|
|
|
|
return window_.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
views::View* NativeWindowViews::GetContentsView() {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2014-07-07 07:35:16 +00:00
|
|
|
bool NativeWindowViews::ShouldDescendIntoChildForEventHandling(
|
|
|
|
gfx::NativeView child,
|
|
|
|
const gfx::Point& location) {
|
|
|
|
// App window should claim mouse events that fall within the draggable region.
|
2015-08-05 04:32:22 +00:00
|
|
|
if (draggable_region() &&
|
|
|
|
draggable_region()->contains(location.x(), location.y()))
|
2014-07-07 14:39:39 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// And the events on border for dragging resizable frameless window.
|
2015-08-05 04:46:32 +00:00
|
|
|
if (!has_frame() && CanResize()) {
|
2014-07-16 07:33:40 +00:00
|
|
|
FramelessView* frame = static_cast<FramelessView*>(
|
2014-07-07 14:39:39 +00:00
|
|
|
window_->non_client_view()->frame_view());
|
|
|
|
return frame->ResizingBorderHitTest(location) == HTNOWHERE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2014-07-07 07:35:16 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
views::ClientView* NativeWindowViews::CreateClientView(views::Widget* widget) {
|
|
|
|
return new NativeWindowClientView(widget, this);
|
|
|
|
}
|
|
|
|
|
2014-07-04 04:32:03 +00:00
|
|
|
views::NonClientFrameView* NativeWindowViews::CreateNonClientFrameView(
|
|
|
|
views::Widget* widget) {
|
2014-07-24 10:06:27 +00:00
|
|
|
#if defined(OS_WIN)
|
2014-11-12 06:33:30 +00:00
|
|
|
WinFrameView* frame_view = new WinFrameView;
|
|
|
|
frame_view->Init(this, widget);
|
|
|
|
return frame_view;
|
|
|
|
#else
|
2015-08-05 04:46:32 +00:00
|
|
|
if (has_frame()) {
|
2015-07-24 08:04:54 +00:00
|
|
|
return new NativeFrameView(this, widget);
|
2014-07-24 10:06:27 +00:00
|
|
|
} else {
|
2014-11-12 06:33:30 +00:00
|
|
|
FramelessView* frame_view = new FramelessView;
|
2014-07-24 10:06:27 +00:00
|
|
|
frame_view->Init(this, widget);
|
|
|
|
return frame_view;
|
|
|
|
}
|
|
|
|
#endif
|
2014-07-04 04:32:03 +00:00
|
|
|
}
|
|
|
|
|
2015-05-10 03:44:18 +00:00
|
|
|
void NativeWindowViews::OnWidgetMove() {
|
|
|
|
NotifyWindowMove();
|
|
|
|
}
|
|
|
|
|
2016-08-04 17:58:59 +00:00
|
|
|
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
|
2017-05-21 18:57:19 +00:00
|
|
|
const gfx::Rect& bounds) const {
|
2016-10-03 11:41:52 +00:00
|
|
|
if (!has_frame())
|
|
|
|
return bounds;
|
|
|
|
|
2016-08-04 17:58:59 +00:00
|
|
|
gfx::Rect window_bounds(bounds);
|
2015-10-05 11:05:59 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-07-05 00:31:29 +00:00
|
|
|
HWND hwnd = GetAcceleratedWidget();
|
2016-08-04 17:58:59 +00:00
|
|
|
gfx::Rect dpi_bounds = display::win::ScreenWin::DIPToScreenRect(hwnd, bounds);
|
|
|
|
window_bounds = display::win::ScreenWin::ScreenToDIPRect(
|
2016-07-05 00:31:29 +00:00
|
|
|
hwnd,
|
2015-10-05 11:05:59 +00:00
|
|
|
window_->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds));
|
|
|
|
#endif
|
|
|
|
|
2016-10-03 11:41:52 +00:00
|
|
|
if (menu_bar_ && menu_bar_visible_) {
|
2016-08-04 20:17:04 +00:00
|
|
|
window_bounds.set_y(window_bounds.y() - kMenuBarHeight);
|
2016-08-04 17:58:59 +00:00
|
|
|
window_bounds.set_height(window_bounds.height() + kMenuBarHeight);
|
2016-08-04 20:17:04 +00:00
|
|
|
}
|
2016-08-04 17:58:59 +00:00
|
|
|
return window_bounds;
|
2015-10-05 11:05:59 +00:00
|
|
|
}
|
|
|
|
|
2016-08-04 17:58:59 +00:00
|
|
|
gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
|
2017-05-21 18:57:19 +00:00
|
|
|
const gfx::Rect& bounds) const {
|
2016-10-03 11:41:52 +00:00
|
|
|
if (!has_frame())
|
|
|
|
return bounds;
|
|
|
|
|
2016-08-04 17:58:59 +00:00
|
|
|
gfx::Rect content_bounds(bounds);
|
2015-10-05 11:05:59 +00:00
|
|
|
#if defined(OS_WIN)
|
2016-07-05 00:31:29 +00:00
|
|
|
HWND hwnd = GetAcceleratedWidget();
|
2016-08-04 17:58:59 +00:00
|
|
|
content_bounds.set_size(
|
|
|
|
display::win::ScreenWin::DIPToScreenSize(hwnd, content_bounds.size()));
|
2015-10-05 11:05:59 +00:00
|
|
|
RECT rect;
|
|
|
|
SetRectEmpty(&rect);
|
|
|
|
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
|
|
|
|
DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
|
|
|
|
AdjustWindowRectEx(&rect, style, FALSE, ex_style);
|
2016-08-04 17:58:59 +00:00
|
|
|
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()));
|
2015-10-05 11:05:59 +00:00
|
|
|
#endif
|
|
|
|
|
2016-10-03 11:41:52 +00:00
|
|
|
if (menu_bar_ && menu_bar_visible_) {
|
2016-08-04 20:17:04 +00:00
|
|
|
content_bounds.set_y(content_bounds.y() + kMenuBarHeight);
|
2016-08-04 17:58:59 +00:00
|
|
|
content_bounds.set_height(content_bounds.height() - kMenuBarHeight);
|
2016-08-04 20:17:04 +00:00
|
|
|
}
|
2016-08-04 17:58:59 +00:00
|
|
|
return content_bounds;
|
2015-10-05 11:05:59 +00:00
|
|
|
}
|
|
|
|
|
2014-07-04 08:54:10 +00:00
|
|
|
void NativeWindowViews::HandleKeyboardEvent(
|
|
|
|
content::WebContents*,
|
|
|
|
const content::NativeWebKeyboardEvent& event) {
|
2014-08-08 06:30:43 +00:00
|
|
|
keyboard_event_handler_->HandleKeyboardEvent(event, GetFocusManager());
|
|
|
|
|
2014-08-18 08:14:28 +00:00
|
|
|
if (!menu_bar_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Show accelerator when "Alt" is pressed.
|
|
|
|
if (menu_bar_visible_ && IsAltKey(event))
|
|
|
|
menu_bar_->SetAcceleratorVisibility(
|
2017-06-28 14:58:47 +00:00
|
|
|
event.GetType() == blink::WebInputEvent::kRawKeyDown);
|
2014-08-18 08:14:28 +00:00
|
|
|
|
|
|
|
// Show the submenu when "Alt+Key" is pressed.
|
2017-06-28 14:58:47 +00:00
|
|
|
if (event.GetType() == blink::WebInputEvent::kRawKeyDown &&
|
|
|
|
!IsAltKey(event) && IsAltModifier(event)) {
|
2014-08-18 08:14:28 +00:00
|
|
|
if (!menu_bar_visible_ &&
|
2017-06-28 14:58:47 +00:00
|
|
|
(menu_bar_->GetAcceleratorIndex(event.windows_key_code) != -1))
|
2014-08-18 08:14:28 +00:00
|
|
|
SetMenuBarVisibility(true);
|
2017-06-28 14:58:47 +00:00
|
|
|
menu_bar_->ActivateAccelerator(event.windows_key_code);
|
2014-08-18 08:14:28 +00:00
|
|
|
return;
|
2014-08-18 06:12:12 +00:00
|
|
|
}
|
|
|
|
|
2014-08-08 06:30:43 +00:00
|
|
|
if (!menu_bar_autohide_)
|
|
|
|
return;
|
|
|
|
|
2014-08-07 07:54:05 +00:00
|
|
|
// Toggle the menu bar only when a single Alt is released.
|
2017-06-28 14:58:47 +00:00
|
|
|
if (event.GetType() == blink::WebInputEvent::kRawKeyDown && IsAltKey(event)) {
|
2014-08-07 07:54:05 +00:00
|
|
|
// When a single Alt is pressed:
|
|
|
|
menu_bar_alt_pressed_ = true;
|
2017-06-29 23:50:55 +00:00
|
|
|
} else if (event.GetType() == blink::WebInputEvent::kKeyUp &&
|
|
|
|
IsAltKey(event) && menu_bar_alt_pressed_) {
|
2014-08-07 07:54:05 +00:00
|
|
|
// When a single Alt is released right after a Alt is pressed:
|
|
|
|
menu_bar_alt_pressed_ = false;
|
2014-08-07 08:48:30 +00:00
|
|
|
SetMenuBarVisibility(!menu_bar_visible_);
|
2014-08-07 07:54:05 +00:00
|
|
|
} else {
|
|
|
|
// When any other keys except single Alt have been pressed/released:
|
|
|
|
menu_bar_alt_pressed_ = false;
|
2014-08-07 05:47:58 +00:00
|
|
|
}
|
2014-07-04 08:54:10 +00:00
|
|
|
}
|
|
|
|
|
2017-05-26 01:38:27 +00:00
|
|
|
void NativeWindowViews::ShowAutofillPopup(
|
|
|
|
content::RenderFrameHost* frame_host,
|
2017-11-03 02:01:26 +00:00
|
|
|
content::WebContents* web_contents,
|
2017-05-26 01:38:27 +00:00
|
|
|
const gfx::RectF& bounds,
|
|
|
|
const std::vector<base::string16>& values,
|
2017-11-02 23:42:30 +00:00
|
|
|
const std::vector<base::string16>& labels) {
|
2017-11-02 21:50:04 +00:00
|
|
|
WebContentsPreferences* web_preferences =
|
2017-11-13 07:13:54 +00:00
|
|
|
WebContentsPreferences::FromWebContents(web_contents);
|
2017-11-02 23:42:30 +00:00
|
|
|
|
2017-11-13 07:13:54 +00:00
|
|
|
bool is_offsceen = web_preferences->IsOffScreen(web_contents);
|
|
|
|
bool is_embedder_offscreen =
|
|
|
|
web_preferences->IsGuest(web_contents) &&
|
|
|
|
web_preferences->IsOffScreen(web_preferences->Embedder(web_contents));
|
2017-11-02 23:42:30 +00:00
|
|
|
|
2017-05-26 01:38:27 +00:00
|
|
|
autofill_popup_->CreateView(
|
2017-11-13 07:13:54 +00:00
|
|
|
frame_host,
|
|
|
|
is_offsceen || is_embedder_offscreen,
|
|
|
|
widget(),
|
|
|
|
bounds);
|
2017-05-26 01:38:27 +00:00
|
|
|
autofill_popup_->SetItems(values, labels);
|
2017-11-02 23:25:59 +00:00
|
|
|
autofill_popup_->UpdatePopupBounds(menu_bar_visible_ ? 0 : kMenuBarHeight);
|
2017-05-26 01:38:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowViews::HideAutofillPopup(
|
|
|
|
content::RenderFrameHost* frame_host) {
|
|
|
|
autofill_popup_->Hide();
|
|
|
|
}
|
|
|
|
|
2017-04-12 11:00:00 +00:00
|
|
|
void NativeWindowViews::Layout() {
|
|
|
|
const auto size = GetContentsBounds().size();
|
|
|
|
const auto menu_bar_bounds =
|
2017-04-17 09:29:42 +00:00
|
|
|
menu_bar_visible_ ? gfx::Rect(0, 0, size.width(), kMenuBarHeight)
|
|
|
|
: gfx::Rect();
|
2017-04-12 11:00:00 +00:00
|
|
|
if (menu_bar_) {
|
|
|
|
menu_bar_->SetBoundsRect(menu_bar_bounds);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (web_view_) {
|
|
|
|
web_view_->SetBoundsRect(
|
|
|
|
gfx::Rect(0, menu_bar_bounds.height(), size.width(),
|
|
|
|
size.height() - menu_bar_bounds.height()));
|
|
|
|
}
|
2017-11-02 23:42:30 +00:00
|
|
|
|
2017-11-02 23:25:59 +00:00
|
|
|
if (autofill_popup_.get())
|
|
|
|
autofill_popup_->UpdatePopupBounds(menu_bar_visible_ ? 0 : kMenuBarHeight);
|
2017-04-12 11:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-05-21 18:57:19 +00:00
|
|
|
gfx::Size NativeWindowViews::GetMinimumSize() const {
|
2015-10-05 11:05:59 +00:00
|
|
|
return NativeWindow::GetMinimumSize();
|
|
|
|
}
|
|
|
|
|
2017-05-21 18:57:19 +00:00
|
|
|
gfx::Size NativeWindowViews::GetMaximumSize() const {
|
2015-10-05 11:05:59 +00:00
|
|
|
return NativeWindow::GetMaximumSize();
|
|
|
|
}
|
|
|
|
|
2014-07-04 08:54:10 +00:00
|
|
|
bool NativeWindowViews::AcceleratorPressed(const ui::Accelerator& accelerator) {
|
|
|
|
return accelerator_util::TriggerAcceleratorTableCommand(
|
|
|
|
&accelerator_table_, accelerator);
|
|
|
|
}
|
|
|
|
|
2016-07-06 23:04:18 +00:00
|
|
|
void NativeWindowViews::RegisterAccelerators(AtomMenuModel* menu_model) {
|
2014-07-04 08:54:10 +00:00
|
|
|
// Clear previous accelerators.
|
|
|
|
views::FocusManager* focus_manager = GetFocusManager();
|
|
|
|
accelerator_table_.clear();
|
|
|
|
focus_manager->UnregisterAccelerators(this);
|
|
|
|
|
|
|
|
// Register accelerators with focus manager.
|
|
|
|
accelerator_util::GenerateAcceleratorTable(&accelerator_table_, menu_model);
|
|
|
|
accelerator_util::AcceleratorTable::const_iterator iter;
|
|
|
|
for (iter = accelerator_table_.begin();
|
|
|
|
iter != accelerator_table_.end();
|
|
|
|
++iter) {
|
|
|
|
focus_manager->RegisterAccelerator(
|
|
|
|
iter->first, ui::AcceleratorManager::kNormalPriority, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-26 08:39:03 +00:00
|
|
|
ui::WindowShowState NativeWindowViews::GetRestoredState() {
|
|
|
|
if (IsMaximized())
|
|
|
|
return ui::SHOW_STATE_MAXIMIZED;
|
|
|
|
if (IsFullscreen())
|
|
|
|
return ui::SHOW_STATE_FULLSCREEN;
|
|
|
|
|
|
|
|
return ui::SHOW_STATE_NORMAL;
|
|
|
|
}
|
|
|
|
|
2014-07-03 17:30:36 +00:00
|
|
|
// static
|
2015-06-25 01:47:57 +00:00
|
|
|
NativeWindow* NativeWindow::Create(
|
|
|
|
brightray::InspectableWebContents* inspectable_web_contents,
|
2016-06-19 03:06:08 +00:00
|
|
|
const mate::Dictionary& options,
|
|
|
|
NativeWindow* parent) {
|
|
|
|
return new NativeWindowViews(inspectable_web_contents, options, parent);
|
2014-07-03 17:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace atom
|