native_window_views.cc 44 KB

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