native_window_views.cc 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299
  1. // Copyright (c) 2014 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/native_window_views.h"
  5. #if defined(OS_WIN)
  6. #include <objbase.h>
  7. #include <wrl/client.h>
  8. #endif
  9. #include <memory>
  10. #include <tuple>
  11. #include <utility>
  12. #include <vector>
  13. #include "atom/browser/api/atom_api_web_contents.h"
  14. #include "atom/browser/native_browser_view_views.h"
  15. #include "atom/browser/ui/views/root_view.h"
  16. #include "atom/browser/web_contents_preferences.h"
  17. #include "atom/browser/web_view_manager.h"
  18. #include "atom/browser/window_list.h"
  19. #include "atom/common/draggable_region.h"
  20. #include "atom/common/native_mate_converters/image_converter.h"
  21. #include "atom/common/options_switches.h"
  22. #include "base/strings/utf_string_conversions.h"
  23. #include "brightray/browser/inspectable_web_contents.h"
  24. #include "brightray/browser/inspectable_web_contents_view.h"
  25. #include "content/public/browser/browser_thread.h"
  26. #include "native_mate/dictionary.h"
  27. #include "ui/aura/window_tree_host.h"
  28. #include "ui/base/hit_test.h"
  29. #include "ui/gfx/image/image.h"
  30. #include "ui/views/background.h"
  31. #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
  32. #include "ui/views/controls/webview/webview.h"
  33. #include "ui/views/widget/native_widget_private.h"
  34. #include "ui/views/widget/widget.h"
  35. #include "ui/views/window/client_view.h"
  36. #include "ui/wm/core/shadow_types.h"
  37. #include "ui/wm/core/window_util.h"
  38. #if defined(USE_X11)
  39. #include "atom/browser/browser.h"
  40. #include "atom/browser/ui/views/frameless_view.h"
  41. #include "atom/browser/ui/views/global_menu_bar_x11.h"
  42. #include "atom/browser/ui/views/native_frame_view.h"
  43. #include "atom/browser/ui/x/event_disabler.h"
  44. #include "atom/browser/ui/x/window_state_watcher.h"
  45. #include "atom/browser/ui/x/x_window_utils.h"
  46. #include "base/strings/string_util.h"
  47. #include "chrome/browser/ui/libgtkui/unity_service.h"
  48. #include "ui/base/x/x11_util.h"
  49. #include "ui/gfx/x/x11_types.h"
  50. #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
  51. #include "ui/views/window/native_frame_view.h"
  52. #elif defined(OS_WIN)
  53. #include "atom/browser/ui/views/win_frame_view.h"
  54. #include "atom/browser/ui/win/atom_desktop_native_widget_aura.h"
  55. #include "atom/browser/ui/win/atom_desktop_window_tree_host_win.h"
  56. #include "skia/ext/skia_utils_win.h"
  57. #include "ui/base/win/shell.h"
  58. #include "ui/display/display.h"
  59. #include "ui/display/screen.h"
  60. #include "ui/display/win/screen_win.h"
  61. #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
  62. #endif
  63. namespace atom {
  64. namespace {
  65. #if defined(OS_WIN)
  66. void FlipWindowStyle(HWND handle, bool on, DWORD flag) {
  67. DWORD style = ::GetWindowLong(handle, GWL_STYLE);
  68. if (on)
  69. style |= flag;
  70. else
  71. style &= ~flag;
  72. ::SetWindowLong(handle, GWL_STYLE, style);
  73. }
  74. #endif
  75. class NativeWindowClientView : public views::ClientView {
  76. public:
  77. NativeWindowClientView(views::Widget* widget,
  78. views::View* root_view,
  79. NativeWindowViews* window)
  80. : views::ClientView(widget, root_view), window_(window) {}
  81. ~NativeWindowClientView() override = default;
  82. bool CanClose() override {
  83. window_->NotifyWindowCloseButtonClicked();
  84. return false;
  85. }
  86. private:
  87. NativeWindowViews* window_;
  88. DISALLOW_COPY_AND_ASSIGN(NativeWindowClientView);
  89. };
  90. } // namespace
  91. NativeWindowViews::NativeWindowViews(const mate::Dictionary& options,
  92. NativeWindow* parent)
  93. : NativeWindow(options, parent),
  94. root_view_(new RootView(this)),
  95. keyboard_event_handler_(new views::UnhandledKeyboardEventHandler) {
  96. options.Get(options::kTitle, &title_);
  97. bool menu_bar_autohide;
  98. if (options.Get(options::kAutoHideMenuBar, &menu_bar_autohide))
  99. root_view_->SetAutoHideMenuBar(menu_bar_autohide);
  100. #if defined(OS_WIN)
  101. // On Windows we rely on the CanResize() to indicate whether window can be
  102. // resized, and it should be set before window is created.
  103. options.Get(options::kResizable, &resizable_);
  104. options.Get(options::kMinimizable, &minimizable_);
  105. options.Get(options::kMaximizable, &maximizable_);
  106. // Transparent window must not have thick frame.
  107. options.Get("thickFrame", &thick_frame_);
  108. if (transparent())
  109. thick_frame_ = false;
  110. #endif
  111. if (enable_larger_than_screen())
  112. // We need to set a default maximum window size here otherwise Windows
  113. // will not allow us to resize the window larger than scree.
  114. // Setting directly to INT_MAX somehow doesn't work, so we just devide
  115. // by 10, which should still be large enough.
  116. SetContentSizeConstraints(extensions::SizeConstraints(
  117. gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10)));
  118. int width = 800, height = 600;
  119. options.Get(options::kWidth, &width);
  120. options.Get(options::kHeight, &height);
  121. gfx::Rect bounds(0, 0, width, height);
  122. widget_size_ = bounds.size();
  123. widget()->AddObserver(this);
  124. views::Widget::InitParams params;
  125. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  126. params.bounds = bounds;
  127. params.delegate = this;
  128. params.type = views::Widget::InitParams::TYPE_WINDOW;
  129. params.remove_standard_frame = !has_frame();
  130. if (transparent())
  131. params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
  132. // The given window is most likely not rectangular since it uses
  133. // transparency and has no standard frame, don't show a shadow for it.
  134. if (transparent() && !has_frame())
  135. params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
  136. bool focusable;
  137. if (options.Get(options::kFocusable, &focusable) && !focusable)
  138. params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
  139. #if defined(OS_WIN)
  140. if (parent)
  141. params.parent = parent->GetNativeWindow();
  142. params.native_widget = new AtomDesktopNativeWidgetAura(widget());
  143. atom_desktop_window_tree_host_win_ = new AtomDesktopWindowTreeHostWin(
  144. this, widget(),
  145. static_cast<views::DesktopNativeWidgetAura*>(params.native_widget));
  146. params.desktop_window_tree_host = atom_desktop_window_tree_host_win_;
  147. #elif defined(USE_X11)
  148. std::string name = Browser::Get()->GetName();
  149. // Set WM_WINDOW_ROLE.
  150. params.wm_role_name = "browser-window";
  151. // Set WM_CLASS.
  152. params.wm_class_name = base::ToLowerASCII(name);
  153. params.wm_class_class = name;
  154. #endif
  155. widget()->Init(params);
  156. bool fullscreen = false;
  157. options.Get(options::kFullscreen, &fullscreen);
  158. std::string window_type;
  159. options.Get(options::kType, &window_type);
  160. #if defined(USE_X11)
  161. // Start monitoring window states.
  162. window_state_watcher_.reset(new WindowStateWatcher(this));
  163. // Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
  164. bool use_dark_theme = false;
  165. if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
  166. XDisplay* xdisplay = gfx::GetXDisplay();
  167. XChangeProperty(xdisplay, GetAcceleratedWidget(),
  168. XInternAtom(xdisplay, "_GTK_THEME_VARIANT", x11::False),
  169. XInternAtom(xdisplay, "UTF8_STRING", x11::False), 8,
  170. PropModeReplace,
  171. reinterpret_cast<const unsigned char*>("dark"), 4);
  172. }
  173. // Before the window is mapped the SetWMSpecState can not work, so we have
  174. // to manually set the _NET_WM_STATE.
  175. std::vector<::Atom> state_atom_list;
  176. bool skip_taskbar = false;
  177. if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
  178. state_atom_list.push_back(GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
  179. }
  180. // Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
  181. if (fullscreen) {
  182. state_atom_list.push_back(GetAtom("_NET_WM_STATE_FULLSCREEN"));
  183. }
  184. if (parent) {
  185. SetParentWindow(parent);
  186. // Force using dialog type for child window.
  187. window_type = "dialog";
  188. // Modal window needs the _NET_WM_STATE_MODAL hint.
  189. if (is_modal())
  190. state_atom_list.push_back(GetAtom("_NET_WM_STATE_MODAL"));
  191. }
  192. if (!state_atom_list.empty())
  193. ui::SetAtomArrayProperty(GetAcceleratedWidget(), "_NET_WM_STATE", "ATOM",
  194. state_atom_list);
  195. // Set the _NET_WM_WINDOW_TYPE.
  196. if (!window_type.empty())
  197. SetWindowType(GetAcceleratedWidget(), window_type);
  198. #endif
  199. #if defined(OS_WIN)
  200. if (!has_frame()) {
  201. // Set Window style so that we get a minimize and maximize animation when
  202. // frameless.
  203. DWORD frame_style = WS_CAPTION;
  204. if (resizable_)
  205. frame_style |= WS_THICKFRAME;
  206. if (minimizable_)
  207. frame_style |= WS_MINIMIZEBOX;
  208. if (maximizable_)
  209. frame_style |= WS_MAXIMIZEBOX;
  210. // We should not show a frame for transparent window.
  211. if (!thick_frame_)
  212. frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
  213. ::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
  214. }
  215. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  216. if (window_type == "toolbar")
  217. ex_style |= WS_EX_TOOLWINDOW;
  218. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  219. #endif
  220. if (has_frame()) {
  221. // TODO(zcbenz): This was used to force using native frame on Windows 2003,
  222. // we should check whether setting it in InitParams can work.
  223. widget()->set_frame_type(views::Widget::FrameType::FRAME_TYPE_FORCE_NATIVE);
  224. widget()->FrameTypeChanged();
  225. #if defined(OS_WIN)
  226. // thickFrame also works for normal window.
  227. if (!thick_frame_)
  228. FlipWindowStyle(GetAcceleratedWidget(), false, WS_THICKFRAME);
  229. #endif
  230. }
  231. // Default content view.
  232. SetContentView(new views::View());
  233. gfx::Size size = bounds.size();
  234. if (has_frame() &&
  235. options.Get(options::kUseContentSize, &use_content_size_) &&
  236. use_content_size_)
  237. size = ContentBoundsToWindowBounds(gfx::Rect(size)).size();
  238. widget()->CenterWindow(size);
  239. #if defined(OS_WIN)
  240. // Save initial window state.
  241. if (fullscreen)
  242. last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
  243. else
  244. last_window_state_ = ui::SHOW_STATE_NORMAL;
  245. last_normal_bounds_ = GetBounds();
  246. #endif
  247. }
  248. NativeWindowViews::~NativeWindowViews() {
  249. widget()->RemoveObserver(this);
  250. #if defined(OS_WIN)
  251. // Disable mouse forwarding to relinquish resources, should any be held.
  252. SetForwardMouseMessages(false);
  253. #endif
  254. }
  255. void NativeWindowViews::SetContentView(views::View* view) {
  256. if (content_view()) {
  257. root_view_->RemoveChildView(content_view());
  258. if (browser_view()) {
  259. content_view()->RemoveChildView(
  260. browser_view()->GetInspectableWebContentsView()->GetView());
  261. set_browser_view(nullptr);
  262. }
  263. }
  264. set_content_view(view);
  265. focused_view_ = view;
  266. root_view_->AddChildView(content_view());
  267. root_view_->Layout();
  268. }
  269. void NativeWindowViews::Close() {
  270. if (!IsClosable()) {
  271. WindowList::WindowCloseCancelled(this);
  272. return;
  273. }
  274. widget()->Close();
  275. }
  276. void NativeWindowViews::CloseImmediately() {
  277. widget()->CloseNow();
  278. }
  279. void NativeWindowViews::Focus(bool focus) {
  280. // For hidden window focus() should do nothing.
  281. if (!IsVisible())
  282. return;
  283. if (focus) {
  284. widget()->Activate();
  285. } else {
  286. widget()->Deactivate();
  287. }
  288. }
  289. bool NativeWindowViews::IsFocused() {
  290. return widget()->IsActive();
  291. }
  292. void NativeWindowViews::Show() {
  293. if (is_modal() && NativeWindow::parent() &&
  294. !widget()->native_widget_private()->IsVisible())
  295. static_cast<NativeWindowViews*>(parent())->IncrementChildModals();
  296. widget()->native_widget_private()->ShowWithWindowState(GetRestoredState());
  297. // explicitly focus the window
  298. widget()->Activate();
  299. NotifyWindowShow();
  300. #if defined(USE_X11)
  301. if (global_menu_bar_)
  302. global_menu_bar_->OnWindowMapped();
  303. #endif
  304. }
  305. void NativeWindowViews::ShowInactive() {
  306. widget()->ShowInactive();
  307. NotifyWindowShow();
  308. #if defined(USE_X11)
  309. if (global_menu_bar_)
  310. global_menu_bar_->OnWindowMapped();
  311. #endif
  312. }
  313. void NativeWindowViews::Hide() {
  314. if (is_modal() && NativeWindow::parent())
  315. static_cast<NativeWindowViews*>(parent())->DecrementChildModals();
  316. widget()->Hide();
  317. NotifyWindowHide();
  318. #if defined(USE_X11)
  319. if (global_menu_bar_)
  320. global_menu_bar_->OnWindowUnmapped();
  321. #endif
  322. }
  323. bool NativeWindowViews::IsVisible() {
  324. return widget()->IsVisible();
  325. }
  326. bool NativeWindowViews::IsEnabled() {
  327. #if defined(OS_WIN)
  328. return ::IsWindowEnabled(GetAcceleratedWidget());
  329. #elif defined(USE_X11)
  330. return !event_disabler_.get();
  331. #endif
  332. }
  333. void NativeWindowViews::IncrementChildModals() {
  334. num_modal_children_++;
  335. SetEnabledInternal(ShouldBeEnabled());
  336. }
  337. void NativeWindowViews::DecrementChildModals() {
  338. if (num_modal_children_ > 0) {
  339. num_modal_children_--;
  340. }
  341. SetEnabledInternal(ShouldBeEnabled());
  342. }
  343. void NativeWindowViews::SetEnabled(bool enable) {
  344. if (enable != is_enabled_) {
  345. is_enabled_ = enable;
  346. SetEnabledInternal(ShouldBeEnabled());
  347. }
  348. }
  349. bool NativeWindowViews::ShouldBeEnabled() {
  350. return is_enabled_ && (num_modal_children_ == 0);
  351. }
  352. void NativeWindowViews::SetEnabledInternal(bool enable) {
  353. if (enable && IsEnabled()) {
  354. return;
  355. } else if (!enable && !IsEnabled()) {
  356. return;
  357. }
  358. #if defined(OS_WIN)
  359. ::EnableWindow(GetAcceleratedWidget(), enable);
  360. #elif defined(USE_X11)
  361. views::DesktopWindowTreeHostX11* tree_host =
  362. views::DesktopWindowTreeHostX11::GetHostForXID(GetAcceleratedWidget());
  363. if (enable) {
  364. tree_host->RemoveEventRewriter(event_disabler_.get());
  365. event_disabler_.reset();
  366. } else {
  367. event_disabler_.reset(new EventDisabler);
  368. tree_host->AddEventRewriter(event_disabler_.get());
  369. }
  370. #endif
  371. }
  372. void NativeWindowViews::Maximize() {
  373. #if defined(OS_WIN)
  374. // For window without WS_THICKFRAME style, we can not call Maximize().
  375. if (!(::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME)) {
  376. restore_bounds_ = GetBounds();
  377. auto display =
  378. display::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
  379. SetBounds(display.work_area(), false);
  380. return;
  381. }
  382. #endif
  383. if (IsVisible())
  384. widget()->Maximize();
  385. else
  386. widget()->native_widget_private()->ShowWithWindowState(
  387. ui::SHOW_STATE_MAXIMIZED);
  388. }
  389. void NativeWindowViews::Unmaximize() {
  390. #if defined(OS_WIN)
  391. if (!(::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME)) {
  392. SetBounds(restore_bounds_, false);
  393. return;
  394. }
  395. #endif
  396. widget()->Restore();
  397. }
  398. bool NativeWindowViews::IsMaximized() {
  399. return widget()->IsMaximized();
  400. }
  401. void NativeWindowViews::Minimize() {
  402. if (IsVisible())
  403. widget()->Minimize();
  404. else
  405. widget()->native_widget_private()->ShowWithWindowState(
  406. ui::SHOW_STATE_MINIMIZED);
  407. }
  408. void NativeWindowViews::Restore() {
  409. widget()->Restore();
  410. }
  411. bool NativeWindowViews::IsMinimized() {
  412. return widget()->IsMinimized();
  413. }
  414. void NativeWindowViews::SetFullScreen(bool fullscreen) {
  415. if (!IsFullScreenable())
  416. return;
  417. #if defined(OS_WIN)
  418. // There is no native fullscreen state on Windows.
  419. bool leaving_fullscreen = IsFullscreen() && !fullscreen;
  420. if (fullscreen) {
  421. last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
  422. NotifyWindowEnterFullScreen();
  423. } else {
  424. last_window_state_ = ui::SHOW_STATE_NORMAL;
  425. NotifyWindowLeaveFullScreen();
  426. }
  427. // For window without WS_THICKFRAME style, we can not call SetFullscreen().
  428. // This path will be used for transparent windows as well.
  429. if (!thick_frame_) {
  430. if (fullscreen) {
  431. restore_bounds_ = GetBounds();
  432. auto display =
  433. display::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
  434. SetBounds(display.bounds(), false);
  435. } else {
  436. SetBounds(restore_bounds_, false);
  437. }
  438. return;
  439. }
  440. // We set the new value after notifying, so we can handle the size event
  441. // correctly.
  442. widget()->SetFullscreen(fullscreen);
  443. // If restoring from fullscreen and the window isn't visible, force visible,
  444. // else a non-responsive window shell could be rendered.
  445. // (this situation may arise when app starts with fullscreen: true)
  446. // Note: the following must be after "widget()->SetFullscreen(fullscreen);"
  447. if (leaving_fullscreen && !IsVisible())
  448. FlipWindowStyle(GetAcceleratedWidget(), true, WS_VISIBLE);
  449. #else
  450. if (IsVisible())
  451. widget()->SetFullscreen(fullscreen);
  452. else if (fullscreen)
  453. widget()->native_widget_private()->ShowWithWindowState(
  454. ui::SHOW_STATE_FULLSCREEN);
  455. // Auto-hide menubar when in fullscreen.
  456. if (fullscreen)
  457. SetMenuBarVisibility(false);
  458. else
  459. SetMenuBarVisibility(!IsMenuBarAutoHide());
  460. #endif
  461. }
  462. bool NativeWindowViews::IsFullscreen() const {
  463. return widget()->IsFullscreen();
  464. }
  465. void NativeWindowViews::SetBounds(const gfx::Rect& bounds, bool animate) {
  466. #if defined(OS_WIN) || defined(USE_X11)
  467. // On Linux and Windows the minimum and maximum size should be updated with
  468. // window size when window is not resizable.
  469. if (!resizable_) {
  470. SetMaximumSize(bounds.size());
  471. SetMinimumSize(bounds.size());
  472. }
  473. #endif
  474. widget()->SetBounds(bounds);
  475. }
  476. gfx::Rect NativeWindowViews::GetBounds() {
  477. #if defined(OS_WIN)
  478. if (IsMinimized())
  479. return widget()->GetRestoredBounds();
  480. #endif
  481. return widget()->GetWindowBoundsInScreen();
  482. }
  483. gfx::Rect NativeWindowViews::GetContentBounds() {
  484. return content_view() ? content_view()->GetBoundsInScreen() : gfx::Rect();
  485. }
  486. gfx::Size NativeWindowViews::GetContentSize() {
  487. #if defined(OS_WIN)
  488. if (IsMinimized())
  489. return NativeWindow::GetContentSize();
  490. #endif
  491. return content_view() ? content_view()->size() : gfx::Size();
  492. }
  493. gfx::Rect NativeWindowViews::GetNormalBounds() {
  494. return widget()->GetRestoredBounds();
  495. }
  496. void NativeWindowViews::SetContentSizeConstraints(
  497. const extensions::SizeConstraints& size_constraints) {
  498. NativeWindow::SetContentSizeConstraints(size_constraints);
  499. #if defined(OS_WIN)
  500. // Changing size constraints would force adding the WS_THICKFRAME style, so
  501. // do nothing if thickFrame is false.
  502. if (!thick_frame_)
  503. return;
  504. #endif
  505. // widget_delegate() is only available after Init() is called, we make use of
  506. // this to determine whether native widget has initialized.
  507. if (widget() && widget()->widget_delegate())
  508. widget()->OnSizeConstraintsChanged();
  509. if (resizable_)
  510. old_size_constraints_ = size_constraints;
  511. }
  512. void NativeWindowViews::SetResizable(bool resizable) {
  513. if (resizable != resizable_) {
  514. // On Linux there is no "resizable" property of a window, we have to set
  515. // both the minimum and maximum size to the window size to achieve it.
  516. if (resizable) {
  517. SetContentSizeConstraints(old_size_constraints_);
  518. SetMaximizable(maximizable_);
  519. } else {
  520. old_size_constraints_ = GetContentSizeConstraints();
  521. resizable_ = false;
  522. gfx::Size content_size = GetContentSize();
  523. SetContentSizeConstraints(
  524. extensions::SizeConstraints(content_size, content_size));
  525. }
  526. }
  527. #if defined(OS_WIN)
  528. if (has_frame() && thick_frame_)
  529. FlipWindowStyle(GetAcceleratedWidget(), resizable, WS_THICKFRAME);
  530. #endif
  531. resizable_ = resizable;
  532. }
  533. #if defined(OS_WIN)
  534. void NativeWindowViews::MoveTop() {
  535. gfx::Point pos = GetPosition();
  536. gfx::Size size = GetSize();
  537. ::SetWindowPos(GetAcceleratedWidget(), HWND_TOP, pos.x(), pos.y(),
  538. size.width(), size.height(),
  539. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  540. }
  541. #endif
  542. bool NativeWindowViews::IsResizable() {
  543. #if defined(OS_WIN)
  544. if (has_frame())
  545. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
  546. #endif
  547. return CanResize();
  548. }
  549. void NativeWindowViews::SetMovable(bool movable) {
  550. movable_ = movable;
  551. }
  552. bool NativeWindowViews::IsMovable() {
  553. #if defined(OS_WIN)
  554. return movable_;
  555. #else
  556. return true; // Not implemented on Linux.
  557. #endif
  558. }
  559. void NativeWindowViews::SetMinimizable(bool minimizable) {
  560. #if defined(OS_WIN)
  561. FlipWindowStyle(GetAcceleratedWidget(), minimizable, WS_MINIMIZEBOX);
  562. #endif
  563. minimizable_ = minimizable;
  564. }
  565. bool NativeWindowViews::IsMinimizable() {
  566. #if defined(OS_WIN)
  567. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MINIMIZEBOX;
  568. #else
  569. return true; // Not implemented on Linux.
  570. #endif
  571. }
  572. void NativeWindowViews::SetMaximizable(bool maximizable) {
  573. #if defined(OS_WIN)
  574. FlipWindowStyle(GetAcceleratedWidget(), maximizable, WS_MAXIMIZEBOX);
  575. #endif
  576. maximizable_ = maximizable;
  577. }
  578. bool NativeWindowViews::IsMaximizable() {
  579. #if defined(OS_WIN)
  580. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MAXIMIZEBOX;
  581. #else
  582. return true; // Not implemented on Linux.
  583. #endif
  584. }
  585. void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
  586. fullscreenable_ = fullscreenable;
  587. }
  588. bool NativeWindowViews::IsFullScreenable() {
  589. return fullscreenable_;
  590. }
  591. void NativeWindowViews::SetClosable(bool closable) {
  592. #if defined(OS_WIN)
  593. HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
  594. if (closable) {
  595. EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
  596. } else {
  597. EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  598. }
  599. #endif
  600. }
  601. bool NativeWindowViews::IsClosable() {
  602. #if defined(OS_WIN)
  603. HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
  604. MENUITEMINFO info;
  605. memset(&info, 0, sizeof(info));
  606. info.cbSize = sizeof(info);
  607. info.fMask = MIIM_STATE;
  608. if (!GetMenuItemInfo(menu, SC_CLOSE, false, &info)) {
  609. return false;
  610. }
  611. return !(info.fState & MFS_DISABLED);
  612. #elif defined(USE_X11)
  613. return true;
  614. #endif
  615. }
  616. void NativeWindowViews::SetAlwaysOnTop(bool top,
  617. const std::string& level,
  618. int relativeLevel,
  619. std::string* error) {
  620. if (top != widget()->IsAlwaysOnTop())
  621. NativeWindow::NotifyWindowAlwaysOnTopChanged();
  622. widget()->SetAlwaysOnTop(top);
  623. }
  624. bool NativeWindowViews::IsAlwaysOnTop() {
  625. return widget()->IsAlwaysOnTop();
  626. }
  627. void NativeWindowViews::Center() {
  628. widget()->CenterWindow(GetSize());
  629. }
  630. void NativeWindowViews::Invalidate() {
  631. widget()->SchedulePaintInRect(gfx::Rect(GetBounds().size()));
  632. }
  633. void NativeWindowViews::SetTitle(const std::string& title) {
  634. title_ = title;
  635. widget()->UpdateWindowTitle();
  636. }
  637. std::string NativeWindowViews::GetTitle() {
  638. return title_;
  639. }
  640. void NativeWindowViews::FlashFrame(bool flash) {
  641. #if defined(OS_WIN)
  642. // The Chromium's implementation has a bug stopping flash.
  643. if (!flash) {
  644. FLASHWINFO fwi;
  645. fwi.cbSize = sizeof(fwi);
  646. fwi.hwnd = GetAcceleratedWidget();
  647. fwi.dwFlags = FLASHW_STOP;
  648. fwi.uCount = 0;
  649. FlashWindowEx(&fwi);
  650. return;
  651. }
  652. #endif
  653. widget()->FlashFrame(flash);
  654. }
  655. void NativeWindowViews::SetSkipTaskbar(bool skip) {
  656. #if defined(OS_WIN)
  657. Microsoft::WRL::ComPtr<ITaskbarList> taskbar;
  658. if (FAILED(::CoCreateInstance(CLSID_TaskbarList, nullptr,
  659. CLSCTX_INPROC_SERVER,
  660. IID_PPV_ARGS(&taskbar))) ||
  661. FAILED(taskbar->HrInit()))
  662. return;
  663. if (skip) {
  664. taskbar->DeleteTab(GetAcceleratedWidget());
  665. } else {
  666. taskbar->AddTab(GetAcceleratedWidget());
  667. taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget());
  668. }
  669. #elif defined(USE_X11)
  670. SetWMSpecState(GetAcceleratedWidget(), skip,
  671. GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
  672. #endif
  673. }
  674. void NativeWindowViews::SetSimpleFullScreen(bool simple_fullscreen) {
  675. SetFullScreen(simple_fullscreen);
  676. }
  677. bool NativeWindowViews::IsSimpleFullScreen() {
  678. return IsFullscreen();
  679. }
  680. void NativeWindowViews::SetKiosk(bool kiosk) {
  681. SetFullScreen(kiosk);
  682. }
  683. bool NativeWindowViews::IsKiosk() {
  684. return IsFullscreen();
  685. }
  686. void NativeWindowViews::SetBackgroundColor(SkColor background_color) {
  687. // web views' background color.
  688. root_view_->SetBackground(views::CreateSolidBackground(background_color));
  689. #if defined(OS_WIN)
  690. // Set the background color of native window.
  691. HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color));
  692. ULONG_PTR previous_brush =
  693. SetClassLongPtr(GetAcceleratedWidget(), GCLP_HBRBACKGROUND,
  694. reinterpret_cast<LONG_PTR>(brush));
  695. if (previous_brush)
  696. DeleteObject((HBRUSH)previous_brush);
  697. InvalidateRect(GetAcceleratedWidget(), NULL, 1);
  698. #endif
  699. }
  700. void NativeWindowViews::SetHasShadow(bool has_shadow) {
  701. wm::SetShadowElevation(GetNativeWindow(),
  702. has_shadow ? wm::kShadowElevationInactiveWindow
  703. : wm::kShadowElevationNone);
  704. }
  705. bool NativeWindowViews::HasShadow() {
  706. return GetNativeWindow()->GetProperty(wm::kShadowElevationKey) !=
  707. wm::kShadowElevationNone;
  708. }
  709. void NativeWindowViews::SetOpacity(const double opacity) {
  710. #if defined(OS_WIN)
  711. HWND hwnd = GetAcceleratedWidget();
  712. if (!layered_) {
  713. LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  714. ex_style |= WS_EX_LAYERED;
  715. ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
  716. layered_ = true;
  717. }
  718. ::SetLayeredWindowAttributes(hwnd, 0, opacity * 255, LWA_ALPHA);
  719. #endif
  720. opacity_ = opacity;
  721. }
  722. double NativeWindowViews::GetOpacity() {
  723. return opacity_;
  724. }
  725. void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
  726. #if defined(OS_WIN)
  727. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  728. if (ignore)
  729. ex_style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
  730. else
  731. ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
  732. if (layered_)
  733. ex_style |= WS_EX_LAYERED;
  734. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  735. // Forwarding is always disabled when not ignoring mouse messages.
  736. if (!ignore) {
  737. SetForwardMouseMessages(false);
  738. } else {
  739. SetForwardMouseMessages(forward);
  740. }
  741. #elif defined(USE_X11)
  742. if (ignore) {
  743. XRectangle r = {0, 0, 1, 1};
  744. XShapeCombineRectangles(gfx::GetXDisplay(), GetAcceleratedWidget(),
  745. ShapeInput, 0, 0, &r, 1, ShapeSet, YXBanded);
  746. } else {
  747. XShapeCombineMask(gfx::GetXDisplay(), GetAcceleratedWidget(), ShapeInput, 0,
  748. 0, x11::None, ShapeSet);
  749. }
  750. #endif
  751. }
  752. void NativeWindowViews::SetContentProtection(bool enable) {
  753. #if defined(OS_WIN)
  754. DWORD affinity = enable ? WDA_MONITOR : WDA_NONE;
  755. ::SetWindowDisplayAffinity(GetAcceleratedWidget(), affinity);
  756. #endif
  757. }
  758. void NativeWindowViews::SetFocusable(bool focusable) {
  759. #if defined(OS_WIN)
  760. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  761. if (focusable)
  762. ex_style &= ~WS_EX_NOACTIVATE;
  763. else
  764. ex_style |= WS_EX_NOACTIVATE;
  765. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  766. SetSkipTaskbar(!focusable);
  767. Focus(false);
  768. #endif
  769. }
  770. void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
  771. #if defined(USE_X11)
  772. if (menu_model == nullptr) {
  773. global_menu_bar_.reset();
  774. root_view_->UnregisterAcceleratorsWithFocusManager();
  775. return;
  776. }
  777. if (!global_menu_bar_ && ShouldUseGlobalMenuBar())
  778. global_menu_bar_.reset(new GlobalMenuBarX11(this));
  779. // Use global application menu bar when possible.
  780. if (global_menu_bar_ && global_menu_bar_->IsServerStarted()) {
  781. root_view_->RegisterAcceleratorsWithFocusManager(menu_model);
  782. global_menu_bar_->SetMenu(menu_model);
  783. return;
  784. }
  785. #endif
  786. // Should reset content size when setting menu.
  787. gfx::Size content_size = GetContentSize();
  788. bool should_reset_size = use_content_size_ && has_frame() &&
  789. !IsMenuBarAutoHide() &&
  790. ((!!menu_model) != root_view_->HasMenu());
  791. root_view_->SetMenu(menu_model);
  792. if (should_reset_size) {
  793. // Enlarge the size constraints for the menu.
  794. int menu_bar_height = root_view_->GetMenuBarHeight();
  795. extensions::SizeConstraints constraints = GetContentSizeConstraints();
  796. if (constraints.HasMinimumSize()) {
  797. gfx::Size min_size = constraints.GetMinimumSize();
  798. min_size.set_height(min_size.height() + menu_bar_height);
  799. constraints.set_minimum_size(min_size);
  800. }
  801. if (constraints.HasMaximumSize()) {
  802. gfx::Size max_size = constraints.GetMaximumSize();
  803. max_size.set_height(max_size.height() + menu_bar_height);
  804. constraints.set_maximum_size(max_size);
  805. }
  806. SetContentSizeConstraints(constraints);
  807. // Resize the window to make sure content size is not changed.
  808. SetContentSize(content_size);
  809. }
  810. }
  811. void NativeWindowViews::SetBrowserView(NativeBrowserView* view) {
  812. if (!content_view())
  813. return;
  814. if (browser_view()) {
  815. content_view()->RemoveChildView(
  816. browser_view()->GetInspectableWebContentsView()->GetView());
  817. set_browser_view(nullptr);
  818. }
  819. if (!view) {
  820. return;
  821. }
  822. // Add as child of the main web view to avoid (0, 0) origin from overlapping
  823. // with menu bar.
  824. set_browser_view(view);
  825. content_view()->AddChildView(
  826. view->GetInspectableWebContentsView()->GetView());
  827. }
  828. void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
  829. NativeWindow::SetParentWindow(parent);
  830. #if defined(USE_X11)
  831. XDisplay* xdisplay = gfx::GetXDisplay();
  832. XSetTransientForHint(
  833. xdisplay, GetAcceleratedWidget(),
  834. parent ? parent->GetAcceleratedWidget() : DefaultRootWindow(xdisplay));
  835. #elif defined(OS_WIN) && defined(DEBUG)
  836. // Should work, but does not, it seems that the views toolkit doesn't support
  837. // reparenting on desktop.
  838. if (parent) {
  839. ::SetParent(GetAcceleratedWidget(), parent->GetAcceleratedWidget());
  840. views::Widget::ReparentNativeView(GetNativeWindow(),
  841. parent->GetNativeWindow());
  842. wm::AddTransientChild(parent->GetNativeWindow(), GetNativeWindow());
  843. } else {
  844. if (!GetNativeWindow()->parent())
  845. return;
  846. ::SetParent(GetAcceleratedWidget(), NULL);
  847. views::Widget::ReparentNativeView(GetNativeWindow(), nullptr);
  848. wm::RemoveTransientChild(GetNativeWindow()->parent(), GetNativeWindow());
  849. }
  850. #endif
  851. }
  852. gfx::NativeView NativeWindowViews::GetNativeView() const {
  853. return widget()->GetNativeView();
  854. }
  855. gfx::NativeWindow NativeWindowViews::GetNativeWindow() const {
  856. return widget()->GetNativeWindow();
  857. }
  858. void NativeWindowViews::SetProgressBar(double progress,
  859. NativeWindow::ProgressState state) {
  860. #if defined(OS_WIN)
  861. taskbar_host_.SetProgressBar(GetAcceleratedWidget(), progress, state);
  862. #elif defined(USE_X11)
  863. if (unity::IsRunning()) {
  864. unity::SetProgressFraction(progress);
  865. }
  866. #endif
  867. }
  868. void NativeWindowViews::SetOverlayIcon(const gfx::Image& overlay,
  869. const std::string& description) {
  870. #if defined(OS_WIN)
  871. taskbar_host_.SetOverlayIcon(GetAcceleratedWidget(), overlay, description);
  872. #endif
  873. }
  874. void NativeWindowViews::SetAutoHideMenuBar(bool auto_hide) {
  875. root_view_->SetAutoHideMenuBar(auto_hide);
  876. }
  877. bool NativeWindowViews::IsMenuBarAutoHide() {
  878. return root_view_->IsMenuBarAutoHide();
  879. }
  880. void NativeWindowViews::SetMenuBarVisibility(bool visible) {
  881. root_view_->SetMenuBarVisibility(visible);
  882. }
  883. bool NativeWindowViews::IsMenuBarVisible() {
  884. return root_view_->IsMenuBarVisible();
  885. }
  886. void NativeWindowViews::SetVisibleOnAllWorkspaces(bool visible,
  887. bool visibleOnFullScreen) {
  888. widget()->SetVisibleOnAllWorkspaces(visible);
  889. }
  890. bool NativeWindowViews::IsVisibleOnAllWorkspaces() {
  891. #if defined(USE_X11)
  892. // Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to
  893. // determine whether the current window is visible on all workspaces.
  894. XAtom sticky_atom = GetAtom("_NET_WM_STATE_STICKY");
  895. std::vector<XAtom> wm_states;
  896. ui::GetAtomArrayProperty(GetAcceleratedWidget(), "_NET_WM_STATE", &wm_states);
  897. return std::find(wm_states.begin(), wm_states.end(), sticky_atom) !=
  898. wm_states.end();
  899. #endif
  900. return false;
  901. }
  902. gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
  903. return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
  904. }
  905. NativeWindowHandle NativeWindowViews::GetNativeWindowHandle() const {
  906. return GetAcceleratedWidget();
  907. }
  908. gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
  909. const gfx::Rect& bounds) const {
  910. if (!has_frame())
  911. return bounds;
  912. gfx::Rect window_bounds(bounds);
  913. #if defined(OS_WIN)
  914. HWND hwnd = GetAcceleratedWidget();
  915. gfx::Rect dpi_bounds = display::win::ScreenWin::DIPToScreenRect(hwnd, bounds);
  916. window_bounds = display::win::ScreenWin::ScreenToDIPRect(
  917. hwnd,
  918. widget()->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds));
  919. #endif
  920. if (root_view_->HasMenu() && root_view_->IsMenuBarVisible()) {
  921. int menu_bar_height = root_view_->GetMenuBarHeight();
  922. window_bounds.set_y(window_bounds.y() - menu_bar_height);
  923. window_bounds.set_height(window_bounds.height() + menu_bar_height);
  924. }
  925. return window_bounds;
  926. }
  927. gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
  928. const gfx::Rect& bounds) const {
  929. if (!has_frame())
  930. return bounds;
  931. gfx::Rect content_bounds(bounds);
  932. #if defined(OS_WIN)
  933. HWND hwnd = GetAcceleratedWidget();
  934. content_bounds.set_size(
  935. display::win::ScreenWin::DIPToScreenSize(hwnd, content_bounds.size()));
  936. RECT rect;
  937. SetRectEmpty(&rect);
  938. DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
  939. DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  940. AdjustWindowRectEx(&rect, style, FALSE, ex_style);
  941. content_bounds.set_width(content_bounds.width() - (rect.right - rect.left));
  942. content_bounds.set_height(content_bounds.height() - (rect.bottom - rect.top));
  943. content_bounds.set_size(
  944. display::win::ScreenWin::ScreenToDIPSize(hwnd, content_bounds.size()));
  945. #endif
  946. if (root_view_->HasMenu() && root_view_->IsMenuBarVisible()) {
  947. int menu_bar_height = root_view_->GetMenuBarHeight();
  948. content_bounds.set_y(content_bounds.y() + menu_bar_height);
  949. content_bounds.set_height(content_bounds.height() - menu_bar_height);
  950. }
  951. return content_bounds;
  952. }
  953. void NativeWindowViews::UpdateDraggableRegions(
  954. std::unique_ptr<SkRegion> region) {
  955. draggable_region_ = std::move(region);
  956. }
  957. #if defined(OS_WIN)
  958. void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) {
  959. // We are responsible for storing the images.
  960. window_icon_ = base::win::ScopedHICON(CopyIcon(window_icon));
  961. app_icon_ = base::win::ScopedHICON(CopyIcon(app_icon));
  962. HWND hwnd = GetAcceleratedWidget();
  963. SendMessage(hwnd, WM_SETICON, ICON_SMALL,
  964. reinterpret_cast<LPARAM>(window_icon_.get()));
  965. SendMessage(hwnd, WM_SETICON, ICON_BIG,
  966. reinterpret_cast<LPARAM>(app_icon_.get()));
  967. }
  968. #elif defined(USE_X11)
  969. void NativeWindowViews::SetIcon(const gfx::ImageSkia& icon) {
  970. auto* tree_host = static_cast<views::DesktopWindowTreeHost*>(
  971. views::DesktopWindowTreeHostX11::GetHostForXID(GetAcceleratedWidget()));
  972. tree_host->SetWindowIcons(icon, icon);
  973. }
  974. #endif
  975. void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
  976. bool active) {
  977. if (changed_widget != widget())
  978. return;
  979. if (active)
  980. NativeWindow::NotifyWindowFocus();
  981. else
  982. NativeWindow::NotifyWindowBlur();
  983. // Hide menu bar when window is blured.
  984. if (!active && IsMenuBarAutoHide() && IsMenuBarVisible())
  985. SetMenuBarVisibility(false);
  986. root_view_->ResetAltState();
  987. }
  988. void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
  989. const gfx::Rect& bounds) {
  990. if (changed_widget != widget())
  991. return;
  992. // Note: We intentionally use `GetBounds()` instead of `bounds` to properly
  993. // handle minimized windows on Windows.
  994. const auto new_bounds = GetBounds();
  995. if (widget_size_ != new_bounds.size()) {
  996. if (browser_view()) {
  997. const auto flags = static_cast<NativeBrowserViewViews*>(browser_view())
  998. ->GetAutoResizeFlags();
  999. int width_delta = 0;
  1000. int height_delta = 0;
  1001. if (flags & kAutoResizeWidth) {
  1002. width_delta = new_bounds.width() - widget_size_.width();
  1003. }
  1004. if (flags & kAutoResizeHeight) {
  1005. height_delta = new_bounds.height() - widget_size_.height();
  1006. }
  1007. auto* view = browser_view()->GetInspectableWebContentsView()->GetView();
  1008. auto new_view_size = view->size();
  1009. new_view_size.set_width(new_view_size.width() + width_delta);
  1010. new_view_size.set_height(new_view_size.height() + height_delta);
  1011. view->SetSize(new_view_size);
  1012. }
  1013. NotifyWindowResize();
  1014. widget_size_ = new_bounds.size();
  1015. }
  1016. }
  1017. void NativeWindowViews::DeleteDelegate() {
  1018. if (is_modal() && this->parent()) {
  1019. auto* parent = this->parent();
  1020. // Enable parent window after current window gets closed.
  1021. static_cast<NativeWindowViews*>(parent)->DecrementChildModals();
  1022. // Focus on parent window.
  1023. parent->Focus(true);
  1024. }
  1025. NotifyWindowClosed();
  1026. }
  1027. views::View* NativeWindowViews::GetInitiallyFocusedView() {
  1028. return focused_view_;
  1029. }
  1030. bool NativeWindowViews::CanResize() const {
  1031. return resizable_;
  1032. }
  1033. bool NativeWindowViews::CanMaximize() const {
  1034. return resizable_ && maximizable_;
  1035. }
  1036. bool NativeWindowViews::CanMinimize() const {
  1037. #if defined(OS_WIN)
  1038. return minimizable_;
  1039. #elif defined(USE_X11)
  1040. return true;
  1041. #endif
  1042. }
  1043. base::string16 NativeWindowViews::GetWindowTitle() const {
  1044. return base::UTF8ToUTF16(title_);
  1045. }
  1046. views::View* NativeWindowViews::GetContentsView() {
  1047. return root_view_.get();
  1048. }
  1049. bool NativeWindowViews::ShouldDescendIntoChildForEventHandling(
  1050. gfx::NativeView child,
  1051. const gfx::Point& location) {
  1052. // App window should claim mouse events that fall within the draggable region.
  1053. if (draggable_region() &&
  1054. draggable_region()->contains(location.x(), location.y()))
  1055. return false;
  1056. // And the events on border for dragging resizable frameless window.
  1057. if (!has_frame() && CanResize()) {
  1058. FramelessView* frame =
  1059. static_cast<FramelessView*>(widget()->non_client_view()->frame_view());
  1060. return frame->ResizingBorderHitTest(location) == HTNOWHERE;
  1061. }
  1062. return true;
  1063. }
  1064. views::ClientView* NativeWindowViews::CreateClientView(views::Widget* widget) {
  1065. return new NativeWindowClientView(widget, root_view_.get(), this);
  1066. }
  1067. views::NonClientFrameView* NativeWindowViews::CreateNonClientFrameView(
  1068. views::Widget* widget) {
  1069. #if defined(OS_WIN)
  1070. WinFrameView* frame_view = new WinFrameView;
  1071. frame_view->Init(this, widget);
  1072. return frame_view;
  1073. #else
  1074. if (has_frame()) {
  1075. return new NativeFrameView(this, widget);
  1076. } else {
  1077. FramelessView* frame_view = new FramelessView;
  1078. frame_view->Init(this, widget);
  1079. return frame_view;
  1080. }
  1081. #endif
  1082. }
  1083. void NativeWindowViews::OnWidgetMove() {
  1084. NotifyWindowMove();
  1085. }
  1086. void NativeWindowViews::HandleKeyboardEvent(
  1087. content::WebContents*,
  1088. const content::NativeWebKeyboardEvent& event) {
  1089. keyboard_event_handler_->HandleKeyboardEvent(event,
  1090. root_view_->GetFocusManager());
  1091. root_view_->HandleKeyEvent(event);
  1092. }
  1093. ui::WindowShowState NativeWindowViews::GetRestoredState() {
  1094. if (IsMaximized())
  1095. return ui::SHOW_STATE_MAXIMIZED;
  1096. if (IsFullscreen())
  1097. return ui::SHOW_STATE_FULLSCREEN;
  1098. return ui::SHOW_STATE_NORMAL;
  1099. }
  1100. // static
  1101. NativeWindow* NativeWindow::Create(const mate::Dictionary& options,
  1102. NativeWindow* parent) {
  1103. return new NativeWindowViews(options, parent);
  1104. }
  1105. } // namespace atom