native_window_views.cc 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747
  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 BUILDFLAG(IS_WIN)
  6. #include <wrl/client.h>
  7. #endif
  8. #include <memory>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/cxx17_backports.h"
  12. #include "base/stl_util.h"
  13. #include "base/strings/utf_string_conversions.h"
  14. #include "content/public/browser/browser_thread.h"
  15. #include "content/public/browser/desktop_media_id.h"
  16. #include "shell/browser/api/electron_api_web_contents.h"
  17. #include "shell/browser/native_browser_view_views.h"
  18. #include "shell/browser/ui/drag_util.h"
  19. #include "shell/browser/ui/inspectable_web_contents.h"
  20. #include "shell/browser/ui/inspectable_web_contents_view.h"
  21. #include "shell/browser/ui/views/root_view.h"
  22. #include "shell/browser/web_contents_preferences.h"
  23. #include "shell/browser/web_view_manager.h"
  24. #include "shell/browser/window_list.h"
  25. #include "shell/common/electron_constants.h"
  26. #include "shell/common/gin_converters/image_converter.h"
  27. #include "shell/common/gin_helper/dictionary.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 BUILDFLAG(IS_LINUX)
  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/electron_desktop_window_tree_host_linux.h"
  46. #include "shell/browser/ui/views/client_frame_view_linux.h"
  47. #include "shell/browser/ui/views/frameless_view.h"
  48. #include "shell/browser/ui/views/native_frame_view.h"
  49. #include "shell/common/platform_util.h"
  50. #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
  51. #include "ui/views/window/native_frame_view.h"
  52. #if defined(USE_OZONE)
  53. #include "shell/browser/ui/views/global_menu_bar_x11.h"
  54. #include "shell/browser/ui/x/event_disabler.h"
  55. #include "shell/browser/ui/x/x_window_utils.h"
  56. #include "ui/base/x/x11_util.h"
  57. #include "ui/gfx/x/shape.h"
  58. #include "ui/gfx/x/x11_atom_cache.h"
  59. #include "ui/gfx/x/xproto.h"
  60. #include "ui/gfx/x/xproto_util.h"
  61. #include "ui/ozone/public/ozone_platform.h"
  62. #endif
  63. #elif BUILDFLAG(IS_WIN)
  64. #include "base/win/win_util.h"
  65. #include "content/public/common/color_parser.h"
  66. #include "shell/browser/ui/views/win_frame_view.h"
  67. #include "shell/browser/ui/win/electron_desktop_native_widget_aura.h"
  68. #include "skia/ext/skia_utils_win.h"
  69. #include "ui/base/win/shell.h"
  70. #include "ui/display/screen.h"
  71. #include "ui/display/win/screen_win.h"
  72. #include "ui/gfx/color_utils.h"
  73. #endif
  74. namespace electron {
  75. #if BUILDFLAG(IS_WIN)
  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. #endif
  88. namespace {
  89. #if BUILDFLAG(IS_WIN)
  90. const LPCWSTR kUniqueTaskBarClassName = L"Shell_TrayWnd";
  91. void FlipWindowStyle(HWND handle, bool on, DWORD flag) {
  92. DWORD style = ::GetWindowLong(handle, GWL_STYLE);
  93. if (on)
  94. style |= flag;
  95. else
  96. style &= ~flag;
  97. ::SetWindowLong(handle, GWL_STYLE, style);
  98. // Window's frame styles are cached so we need to call SetWindowPos
  99. // with the SWP_FRAMECHANGED flag to update cache properly.
  100. ::SetWindowPos(handle, 0, 0, 0, 0, 0, // ignored
  101. SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
  102. SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  103. }
  104. gfx::Rect DIPToScreenRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
  105. float scale_factor = display::win::ScreenWin::GetScaleFactorForHWND(hwnd);
  106. gfx::Rect screen_rect = ScaleToRoundedRect(pixel_bounds, scale_factor);
  107. screen_rect.set_origin(
  108. display::win::ScreenWin::DIPToScreenRect(hwnd, pixel_bounds).origin());
  109. return screen_rect;
  110. }
  111. #endif
  112. #if defined(USE_OZONE)
  113. bool CreateGlobalMenuBar() {
  114. return ui::OzonePlatform::GetInstance()
  115. ->GetPlatformProperties()
  116. .supports_global_application_menus;
  117. }
  118. #endif
  119. #if defined(USE_OZONE_PLATFORM_X11)
  120. bool IsX11() {
  121. return ui::OzonePlatform::GetInstance()
  122. ->GetPlatformProperties()
  123. .electron_can_call_x11;
  124. }
  125. #endif
  126. class NativeWindowClientView : public views::ClientView {
  127. public:
  128. NativeWindowClientView(views::Widget* widget,
  129. views::View* root_view,
  130. NativeWindowViews* window)
  131. : views::ClientView(widget, root_view), window_(window) {}
  132. ~NativeWindowClientView() override = default;
  133. // disable copy
  134. NativeWindowClientView(const NativeWindowClientView&) = delete;
  135. NativeWindowClientView& operator=(const NativeWindowClientView&) = delete;
  136. views::CloseRequestResult OnWindowCloseRequested() override {
  137. window_->NotifyWindowCloseButtonClicked();
  138. return views::CloseRequestResult::kCannotClose;
  139. }
  140. private:
  141. NativeWindowViews* window_;
  142. };
  143. } // namespace
  144. NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
  145. NativeWindow* parent)
  146. : NativeWindow(options, parent),
  147. root_view_(std::make_unique<RootView>(this)),
  148. keyboard_event_handler_(
  149. std::make_unique<views::UnhandledKeyboardEventHandler>()) {
  150. options.Get(options::kTitle, &title_);
  151. bool menu_bar_autohide;
  152. if (options.Get(options::kAutoHideMenuBar, &menu_bar_autohide))
  153. root_view_->SetAutoHideMenuBar(menu_bar_autohide);
  154. #if BUILDFLAG(IS_WIN)
  155. // On Windows we rely on the CanResize() to indicate whether window can be
  156. // resized, and it should be set before window is created.
  157. options.Get(options::kResizable, &resizable_);
  158. options.Get(options::kMinimizable, &minimizable_);
  159. options.Get(options::kMaximizable, &maximizable_);
  160. // Transparent window must not have thick frame.
  161. options.Get("thickFrame", &thick_frame_);
  162. if (transparent())
  163. thick_frame_ = false;
  164. overlay_button_color_ = color_utils::GetSysSkColor(COLOR_BTNFACE);
  165. overlay_symbol_color_ = color_utils::GetSysSkColor(COLOR_BTNTEXT);
  166. v8::Local<v8::Value> titlebar_overlay;
  167. if (options.Get(options::ktitleBarOverlay, &titlebar_overlay) &&
  168. titlebar_overlay->IsObject()) {
  169. gin_helper::Dictionary titlebar_overlay_obj =
  170. gin::Dictionary::CreateEmpty(options.isolate());
  171. options.Get(options::ktitleBarOverlay, &titlebar_overlay_obj);
  172. std::string overlay_color_string;
  173. if (titlebar_overlay_obj.Get(options::kOverlayButtonColor,
  174. &overlay_color_string)) {
  175. bool success = content::ParseCssColorString(overlay_color_string,
  176. &overlay_button_color_);
  177. DCHECK(success);
  178. }
  179. std::string overlay_symbol_color_string;
  180. if (titlebar_overlay_obj.Get(options::kOverlaySymbolColor,
  181. &overlay_symbol_color_string)) {
  182. bool success = content::ParseCssColorString(overlay_symbol_color_string,
  183. &overlay_symbol_color_);
  184. DCHECK(success);
  185. }
  186. }
  187. if (title_bar_style_ != TitleBarStyle::kNormal)
  188. set_has_frame(false);
  189. #endif
  190. if (enable_larger_than_screen())
  191. // We need to set a default maximum window size here otherwise Windows
  192. // will not allow us to resize the window larger than scree.
  193. // Setting directly to INT_MAX somehow doesn't work, so we just divide
  194. // by 10, which should still be large enough.
  195. SetContentSizeConstraints(extensions::SizeConstraints(
  196. gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10)));
  197. int width = 800, height = 600;
  198. options.Get(options::kWidth, &width);
  199. options.Get(options::kHeight, &height);
  200. gfx::Rect bounds(0, 0, width, height);
  201. widget_size_ = bounds.size();
  202. widget()->AddObserver(this);
  203. views::Widget::InitParams params;
  204. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  205. params.bounds = bounds;
  206. params.delegate = this;
  207. params.type = views::Widget::InitParams::TYPE_WINDOW;
  208. params.remove_standard_frame = !has_frame() || has_client_frame();
  209. // If a client frame, we need to draw our own shadows.
  210. if (transparent() || has_client_frame())
  211. params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
  212. // The given window is most likely not rectangular since it uses
  213. // transparency and has no standard frame, don't show a shadow for it.
  214. if (transparent() && !has_frame())
  215. params.shadow_type = views::Widget::InitParams::ShadowType::kNone;
  216. bool focusable;
  217. if (options.Get(options::kFocusable, &focusable) && !focusable)
  218. params.activatable = views::Widget::InitParams::Activatable::kNo;
  219. #if BUILDFLAG(IS_WIN)
  220. if (parent)
  221. params.parent = parent->GetNativeWindow();
  222. params.native_widget = new ElectronDesktopNativeWidgetAura(this);
  223. #elif BUILDFLAG(IS_LINUX)
  224. std::string name = Browser::Get()->GetName();
  225. // Set WM_WINDOW_ROLE.
  226. params.wm_role_name = "browser-window";
  227. // Set WM_CLASS.
  228. params.wm_class_name = base::ToLowerASCII(name);
  229. params.wm_class_class = name;
  230. // Set Wayland application ID.
  231. params.wayland_app_id = platform_util::GetXdgAppId();
  232. auto* native_widget = new views::DesktopNativeWidgetAura(widget());
  233. params.native_widget = native_widget;
  234. params.desktop_window_tree_host =
  235. new ElectronDesktopWindowTreeHostLinux(this, native_widget);
  236. #endif
  237. // Ref https://github.com/electron/electron/issues/30760
  238. // Set the can_resize param before initializing the widget.
  239. // When resizable_ is true, this causes the WS_THICKFRAME style
  240. // to be passed into CreateWindowEx and SetWindowLong calls in
  241. // WindowImpl::Init and HwndMessageHandler::SizeConstraintsChanged
  242. // respectively. As a result, the Windows 7 frame doesn't show,
  243. // but it isn't clear why this is the case.
  244. // When resizable_ is false, WS_THICKFRAME is not passed into the
  245. // SetWindowLong call, so the Windows 7 frame still shows.
  246. // One workaround would be to call set_can_resize(true) here,
  247. // and then move the SetCanResize(resizable_) call after the
  248. // SetWindowLong call around line 365, but that's a much larger change.
  249. set_can_resize(true);
  250. widget()->Init(std::move(params));
  251. // When the workaround above is not needed anymore, only this
  252. // call should be necessary.
  253. // With the workaround in place, this call doesn't do anything.
  254. SetCanResize(resizable_);
  255. bool fullscreen = false;
  256. options.Get(options::kFullscreen, &fullscreen);
  257. std::string window_type;
  258. options.Get(options::kType, &window_type);
  259. #if BUILDFLAG(IS_LINUX)
  260. // Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
  261. bool use_dark_theme = false;
  262. if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
  263. SetGTKDarkThemeEnabled(use_dark_theme);
  264. }
  265. if (parent)
  266. SetParentWindow(parent);
  267. #endif
  268. #if defined(USE_OZONE_PLATFORM_X11)
  269. if (IsX11()) {
  270. // TODO(ckerr): remove in Electron v20.0.0
  271. // Before the window is mapped the SetWMSpecState can not work, so we have
  272. // to manually set the _NET_WM_STATE.
  273. std::vector<x11::Atom> state_atom_list;
  274. bool skip_taskbar = false;
  275. if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
  276. state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
  277. }
  278. // Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
  279. if (fullscreen) {
  280. state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_FULLSCREEN"));
  281. }
  282. if (parent) {
  283. // Force using dialog type for child window.
  284. window_type = "dialog";
  285. // Modal window needs the _NET_WM_STATE_MODAL hint.
  286. if (is_modal())
  287. state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_MODAL"));
  288. }
  289. if (!state_atom_list.empty())
  290. SetArrayProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
  291. x11::GetAtom("_NET_WM_STATE"), x11::Atom::ATOM,
  292. state_atom_list);
  293. // Set the _NET_WM_WINDOW_TYPE.
  294. if (!window_type.empty())
  295. SetWindowType(static_cast<x11::Window>(GetAcceleratedWidget()),
  296. window_type);
  297. }
  298. #endif
  299. #if BUILDFLAG(IS_WIN)
  300. if (!has_frame()) {
  301. // Set Window style so that we get a minimize and maximize animation when
  302. // frameless.
  303. DWORD frame_style = WS_CAPTION | WS_OVERLAPPED;
  304. if (resizable_)
  305. frame_style |= WS_THICKFRAME;
  306. if (minimizable_)
  307. frame_style |= WS_MINIMIZEBOX;
  308. if (maximizable_)
  309. frame_style |= WS_MAXIMIZEBOX;
  310. // We should not show a frame for transparent window.
  311. if (!thick_frame_)
  312. frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
  313. ::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
  314. }
  315. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  316. if (window_type == "toolbar")
  317. ex_style |= WS_EX_TOOLWINDOW;
  318. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  319. #endif
  320. if (has_frame() && !has_client_frame()) {
  321. // TODO(zcbenz): This was used to force using native frame on Windows 2003,
  322. // we should check whether setting it in InitParams can work.
  323. widget()->set_frame_type(views::Widget::FrameType::kForceNative);
  324. widget()->FrameTypeChanged();
  325. #if BUILDFLAG(IS_WIN)
  326. // thickFrame also works for normal window.
  327. if (!thick_frame_)
  328. FlipWindowStyle(GetAcceleratedWidget(), false, WS_THICKFRAME);
  329. #endif
  330. }
  331. // Default content view.
  332. SetContentView(new views::View());
  333. gfx::Size size = bounds.size();
  334. if (has_frame() &&
  335. options.Get(options::kUseContentSize, &use_content_size_) &&
  336. use_content_size_)
  337. size = ContentBoundsToWindowBounds(gfx::Rect(size)).size();
  338. widget()->CenterWindow(size);
  339. #if BUILDFLAG(IS_WIN)
  340. // Save initial window state.
  341. if (fullscreen)
  342. last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
  343. else
  344. last_window_state_ = ui::SHOW_STATE_NORMAL;
  345. #endif
  346. // Listen to mouse events.
  347. aura::Window* window = GetNativeWindow();
  348. if (window)
  349. window->AddPreTargetHandler(this);
  350. #if BUILDFLAG(IS_LINUX)
  351. // On linux after the widget is initialized we might have to force set the
  352. // bounds if the bounds are smaller than the current display
  353. SetBounds(gfx::Rect(GetPosition(), bounds.size()), false);
  354. #endif
  355. SetOwnedByWidget(false);
  356. RegisterDeleteDelegateCallback(base::BindOnce(
  357. [](NativeWindowViews* window) {
  358. if (window->is_modal() && window->parent()) {
  359. auto* parent = window->parent();
  360. // Enable parent window after current window gets closed.
  361. static_cast<NativeWindowViews*>(parent)->DecrementChildModals();
  362. // Focus on parent window.
  363. parent->Focus(true);
  364. }
  365. window->NotifyWindowClosed();
  366. },
  367. this));
  368. }
  369. NativeWindowViews::~NativeWindowViews() {
  370. widget()->RemoveObserver(this);
  371. #if BUILDFLAG(IS_WIN)
  372. // Disable mouse forwarding to relinquish resources, should any be held.
  373. SetForwardMouseMessages(false);
  374. #endif
  375. aura::Window* window = GetNativeWindow();
  376. if (window)
  377. window->RemovePreTargetHandler(this);
  378. }
  379. void NativeWindowViews::SetGTKDarkThemeEnabled(bool use_dark_theme) {
  380. #if defined(USE_OZONE_PLATFORM_X11)
  381. if (IsX11()) {
  382. const std::string color = use_dark_theme ? "dark" : "light";
  383. x11::SetStringProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
  384. x11::GetAtom("_GTK_THEME_VARIANT"),
  385. x11::GetAtom("UTF8_STRING"), color);
  386. }
  387. #endif
  388. }
  389. void NativeWindowViews::SetContentView(views::View* view) {
  390. if (content_view()) {
  391. root_view_->RemoveChildView(content_view());
  392. }
  393. set_content_view(view);
  394. focused_view_ = view;
  395. root_view_->AddChildView(content_view());
  396. root_view_->Layout();
  397. }
  398. void NativeWindowViews::Close() {
  399. if (!IsClosable()) {
  400. WindowList::WindowCloseCancelled(this);
  401. return;
  402. }
  403. widget()->Close();
  404. }
  405. void NativeWindowViews::CloseImmediately() {
  406. widget()->CloseNow();
  407. }
  408. void NativeWindowViews::Focus(bool focus) {
  409. // For hidden window focus() should do nothing.
  410. if (!IsVisible())
  411. return;
  412. if (focus) {
  413. widget()->Activate();
  414. } else {
  415. widget()->Deactivate();
  416. }
  417. }
  418. bool NativeWindowViews::IsFocused() {
  419. return widget()->IsActive();
  420. }
  421. void NativeWindowViews::Show() {
  422. if (is_modal() && NativeWindow::parent() &&
  423. !widget()->native_widget_private()->IsVisible())
  424. static_cast<NativeWindowViews*>(parent())->IncrementChildModals();
  425. widget()->native_widget_private()->Show(GetRestoredState(), gfx::Rect());
  426. // explicitly focus the window
  427. widget()->Activate();
  428. NotifyWindowShow();
  429. #if defined(USE_OZONE)
  430. if (global_menu_bar_)
  431. global_menu_bar_->OnWindowMapped();
  432. #endif
  433. #if defined(USE_OZONE_PLATFORM_X11)
  434. // On X11, setting Z order before showing the window doesn't take effect,
  435. // so we have to call it again.
  436. if (IsX11())
  437. widget()->SetZOrderLevel(widget()->GetZOrderLevel());
  438. #endif
  439. }
  440. void NativeWindowViews::ShowInactive() {
  441. widget()->ShowInactive();
  442. NotifyWindowShow();
  443. #if defined(USE_OZONE)
  444. if (global_menu_bar_)
  445. global_menu_bar_->OnWindowMapped();
  446. #endif
  447. }
  448. void NativeWindowViews::Hide() {
  449. if (is_modal() && NativeWindow::parent())
  450. static_cast<NativeWindowViews*>(parent())->DecrementChildModals();
  451. widget()->Hide();
  452. NotifyWindowHide();
  453. #if defined(USE_OZONE)
  454. if (global_menu_bar_)
  455. global_menu_bar_->OnWindowUnmapped();
  456. #endif
  457. #if BUILDFLAG(IS_WIN)
  458. // When the window is removed from the taskbar via win.hide(),
  459. // the thumbnail buttons need to be set up again.
  460. // Ensure that when the window is hidden,
  461. // the taskbar host is notified that it should re-add them.
  462. taskbar_host_.SetThumbarButtonsAdded(false);
  463. #endif
  464. }
  465. bool NativeWindowViews::IsVisible() {
  466. return widget()->IsVisible();
  467. }
  468. bool NativeWindowViews::IsEnabled() {
  469. #if BUILDFLAG(IS_WIN)
  470. return ::IsWindowEnabled(GetAcceleratedWidget());
  471. #elif BUILDFLAG(IS_LINUX)
  472. #if defined(USE_OZONE_PLATFORM_X11)
  473. if (IsX11())
  474. return !event_disabler_.get();
  475. #endif
  476. NOTIMPLEMENTED();
  477. return true;
  478. #endif
  479. }
  480. void NativeWindowViews::IncrementChildModals() {
  481. num_modal_children_++;
  482. SetEnabledInternal(ShouldBeEnabled());
  483. }
  484. void NativeWindowViews::DecrementChildModals() {
  485. if (num_modal_children_ > 0) {
  486. num_modal_children_--;
  487. }
  488. SetEnabledInternal(ShouldBeEnabled());
  489. }
  490. void NativeWindowViews::SetEnabled(bool enable) {
  491. if (enable != is_enabled_) {
  492. is_enabled_ = enable;
  493. SetEnabledInternal(ShouldBeEnabled());
  494. }
  495. }
  496. bool NativeWindowViews::ShouldBeEnabled() {
  497. return is_enabled_ && (num_modal_children_ == 0);
  498. }
  499. void NativeWindowViews::SetEnabledInternal(bool enable) {
  500. if (enable && IsEnabled()) {
  501. return;
  502. } else if (!enable && !IsEnabled()) {
  503. return;
  504. }
  505. #if BUILDFLAG(IS_WIN)
  506. ::EnableWindow(GetAcceleratedWidget(), enable);
  507. #elif defined(USE_OZONE_PLATFORM_X11)
  508. if (IsX11()) {
  509. views::DesktopWindowTreeHostPlatform* tree_host =
  510. views::DesktopWindowTreeHostLinux::GetHostForWidget(
  511. GetAcceleratedWidget());
  512. if (enable) {
  513. tree_host->RemoveEventRewriter(event_disabler_.get());
  514. event_disabler_.reset();
  515. } else {
  516. event_disabler_ = std::make_unique<EventDisabler>();
  517. tree_host->AddEventRewriter(event_disabler_.get());
  518. }
  519. }
  520. #endif
  521. }
  522. #if BUILDFLAG(IS_LINUX)
  523. void NativeWindowViews::Maximize() {
  524. if (IsVisible()) {
  525. widget()->Maximize();
  526. } else {
  527. widget()->native_widget_private()->Show(ui::SHOW_STATE_MAXIMIZED,
  528. gfx::Rect());
  529. NotifyWindowShow();
  530. }
  531. }
  532. #endif
  533. void NativeWindowViews::Unmaximize() {
  534. if (IsMaximized()) {
  535. #if BUILDFLAG(IS_WIN)
  536. if (transparent()) {
  537. SetBounds(restore_bounds_, false);
  538. NotifyWindowUnmaximize();
  539. return;
  540. }
  541. #endif
  542. widget()->Restore();
  543. }
  544. }
  545. bool NativeWindowViews::IsMaximized() {
  546. if (widget()->IsMaximized()) {
  547. return true;
  548. } else {
  549. #if BUILDFLAG(IS_WIN)
  550. if (transparent()) {
  551. // Compare the size of the window with the size of the display
  552. auto display = display::Screen::GetScreen()->GetDisplayNearestWindow(
  553. GetNativeWindow());
  554. // Maximized if the window is the same dimensions and placement as the
  555. // display
  556. return GetBounds() == display.work_area();
  557. }
  558. #endif
  559. return false;
  560. }
  561. }
  562. void NativeWindowViews::Minimize() {
  563. if (IsVisible())
  564. widget()->Minimize();
  565. else
  566. widget()->native_widget_private()->Show(ui::SHOW_STATE_MINIMIZED,
  567. gfx::Rect());
  568. }
  569. void NativeWindowViews::Restore() {
  570. widget()->Restore();
  571. }
  572. bool NativeWindowViews::IsMinimized() {
  573. return widget()->IsMinimized();
  574. }
  575. void NativeWindowViews::SetFullScreen(bool fullscreen) {
  576. if (!IsFullScreenable())
  577. return;
  578. #if BUILDFLAG(IS_WIN)
  579. // There is no native fullscreen state on Windows.
  580. bool leaving_fullscreen = IsFullscreen() && !fullscreen;
  581. if (fullscreen) {
  582. last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
  583. NotifyWindowEnterFullScreen();
  584. } else {
  585. last_window_state_ = ui::SHOW_STATE_NORMAL;
  586. NotifyWindowLeaveFullScreen();
  587. }
  588. // For window without WS_THICKFRAME style, we can not call SetFullscreen().
  589. // This path will be used for transparent windows as well.
  590. if (!thick_frame_) {
  591. if (fullscreen) {
  592. restore_bounds_ = GetBounds();
  593. auto display =
  594. display::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
  595. SetBounds(display.bounds(), false);
  596. } else {
  597. SetBounds(restore_bounds_, false);
  598. }
  599. return;
  600. }
  601. // We set the new value after notifying, so we can handle the size event
  602. // correctly.
  603. widget()->SetFullscreen(fullscreen);
  604. // If restoring from fullscreen and the window isn't visible, force visible,
  605. // else a non-responsive window shell could be rendered.
  606. // (this situation may arise when app starts with fullscreen: true)
  607. // Note: the following must be after "widget()->SetFullscreen(fullscreen);"
  608. if (leaving_fullscreen && !IsVisible())
  609. FlipWindowStyle(GetAcceleratedWidget(), true, WS_VISIBLE);
  610. #else
  611. if (IsVisible())
  612. widget()->SetFullscreen(fullscreen);
  613. else if (fullscreen)
  614. widget()->native_widget_private()->Show(ui::SHOW_STATE_FULLSCREEN,
  615. gfx::Rect());
  616. // Auto-hide menubar when in fullscreen.
  617. if (fullscreen)
  618. SetMenuBarVisibility(false);
  619. else
  620. SetMenuBarVisibility(!IsMenuBarAutoHide());
  621. #endif
  622. }
  623. bool NativeWindowViews::IsFullscreen() const {
  624. return widget()->IsFullscreen();
  625. }
  626. void NativeWindowViews::SetBounds(const gfx::Rect& bounds, bool animate) {
  627. #if BUILDFLAG(IS_WIN)
  628. if (is_moving_ || is_resizing_) {
  629. pending_bounds_change_ = bounds;
  630. }
  631. #endif
  632. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
  633. // On Linux and Windows the minimum and maximum size should be updated with
  634. // window size when window is not resizable.
  635. if (!resizable_) {
  636. SetMaximumSize(bounds.size());
  637. SetMinimumSize(bounds.size());
  638. }
  639. #endif
  640. widget()->SetBounds(bounds);
  641. }
  642. gfx::Rect NativeWindowViews::GetBounds() {
  643. #if BUILDFLAG(IS_WIN)
  644. if (IsMinimized())
  645. return widget()->GetRestoredBounds();
  646. #endif
  647. return widget()->GetWindowBoundsInScreen();
  648. }
  649. gfx::Rect NativeWindowViews::GetContentBounds() {
  650. return content_view() ? content_view()->GetBoundsInScreen() : gfx::Rect();
  651. }
  652. gfx::Size NativeWindowViews::GetContentSize() {
  653. #if BUILDFLAG(IS_WIN)
  654. if (IsMinimized())
  655. return NativeWindow::GetContentSize();
  656. #endif
  657. return content_view() ? content_view()->size() : gfx::Size();
  658. }
  659. gfx::Rect NativeWindowViews::GetNormalBounds() {
  660. return widget()->GetRestoredBounds();
  661. }
  662. void NativeWindowViews::SetContentSizeConstraints(
  663. const extensions::SizeConstraints& size_constraints) {
  664. NativeWindow::SetContentSizeConstraints(size_constraints);
  665. #if BUILDFLAG(IS_WIN)
  666. // Changing size constraints would force adding the WS_THICKFRAME style, so
  667. // do nothing if thickFrame is false.
  668. if (!thick_frame_)
  669. return;
  670. #endif
  671. // widget_delegate() is only available after Init() is called, we make use of
  672. // this to determine whether native widget has initialized.
  673. if (widget() && widget()->widget_delegate())
  674. widget()->OnSizeConstraintsChanged();
  675. if (resizable_)
  676. old_size_constraints_ = size_constraints;
  677. }
  678. void NativeWindowViews::SetResizable(bool resizable) {
  679. if (resizable != resizable_) {
  680. // On Linux there is no "resizable" property of a window, we have to set
  681. // both the minimum and maximum size to the window size to achieve it.
  682. if (resizable) {
  683. SetContentSizeConstraints(old_size_constraints_);
  684. SetMaximizable(maximizable_);
  685. } else {
  686. old_size_constraints_ = GetContentSizeConstraints();
  687. resizable_ = false;
  688. gfx::Size content_size = GetContentSize();
  689. SetContentSizeConstraints(
  690. extensions::SizeConstraints(content_size, content_size));
  691. }
  692. }
  693. #if BUILDFLAG(IS_WIN)
  694. if (has_frame() && thick_frame_)
  695. FlipWindowStyle(GetAcceleratedWidget(), resizable, WS_THICKFRAME);
  696. #endif
  697. resizable_ = resizable;
  698. SetCanResize(resizable_);
  699. }
  700. bool NativeWindowViews::MoveAbove(const std::string& sourceId) {
  701. const content::DesktopMediaID id = content::DesktopMediaID::Parse(sourceId);
  702. if (id.type != content::DesktopMediaID::TYPE_WINDOW)
  703. return false;
  704. #if BUILDFLAG(IS_WIN)
  705. const HWND otherWindow = reinterpret_cast<HWND>(id.id);
  706. if (!::IsWindow(otherWindow))
  707. return false;
  708. ::SetWindowPos(GetAcceleratedWidget(), GetWindow(otherWindow, GW_HWNDPREV), 0,
  709. 0, 0, 0,
  710. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  711. #elif defined(USE_OZONE_PLATFORM_X11)
  712. if (IsX11()) {
  713. if (!IsWindowValid(static_cast<x11::Window>(id.id)))
  714. return false;
  715. electron::MoveWindowAbove(static_cast<x11::Window>(GetAcceleratedWidget()),
  716. static_cast<x11::Window>(id.id));
  717. }
  718. #endif
  719. return true;
  720. }
  721. void NativeWindowViews::MoveTop() {
  722. // TODO(julien.isorce): fix chromium in order to use existing
  723. // widget()->StackAtTop().
  724. #if BUILDFLAG(IS_WIN)
  725. gfx::Point pos = GetPosition();
  726. gfx::Size size = GetSize();
  727. ::SetWindowPos(GetAcceleratedWidget(), HWND_TOP, pos.x(), pos.y(),
  728. size.width(), size.height(),
  729. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  730. #elif defined(USE_OZONE_PLATFORM_X11)
  731. if (IsX11())
  732. electron::MoveWindowToForeground(
  733. static_cast<x11::Window>(GetAcceleratedWidget()));
  734. #endif
  735. }
  736. bool NativeWindowViews::IsResizable() {
  737. #if BUILDFLAG(IS_WIN)
  738. if (has_frame())
  739. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
  740. #endif
  741. return resizable_;
  742. }
  743. void NativeWindowViews::SetAspectRatio(double aspect_ratio,
  744. const gfx::Size& extra_size) {
  745. NativeWindow::SetAspectRatio(aspect_ratio, extra_size);
  746. gfx::SizeF aspect(aspect_ratio, 1.0);
  747. // Scale up because SetAspectRatio() truncates aspect value to int
  748. aspect.Scale(100);
  749. widget()->SetAspectRatio(aspect);
  750. }
  751. void NativeWindowViews::SetMovable(bool movable) {
  752. movable_ = movable;
  753. }
  754. bool NativeWindowViews::IsMovable() {
  755. #if BUILDFLAG(IS_WIN)
  756. return movable_;
  757. #else
  758. return true; // Not implemented on Linux.
  759. #endif
  760. }
  761. void NativeWindowViews::SetMinimizable(bool minimizable) {
  762. #if BUILDFLAG(IS_WIN)
  763. FlipWindowStyle(GetAcceleratedWidget(), minimizable, WS_MINIMIZEBOX);
  764. if (IsWindowControlsOverlayEnabled()) {
  765. auto* frame_view =
  766. static_cast<WinFrameView*>(widget()->non_client_view()->frame_view());
  767. frame_view->caption_button_container()->UpdateButtons();
  768. }
  769. #endif
  770. minimizable_ = minimizable;
  771. }
  772. bool NativeWindowViews::IsMinimizable() {
  773. #if BUILDFLAG(IS_WIN)
  774. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MINIMIZEBOX;
  775. #else
  776. return true; // Not implemented on Linux.
  777. #endif
  778. }
  779. void NativeWindowViews::SetMaximizable(bool maximizable) {
  780. #if BUILDFLAG(IS_WIN)
  781. FlipWindowStyle(GetAcceleratedWidget(), maximizable, WS_MAXIMIZEBOX);
  782. if (IsWindowControlsOverlayEnabled()) {
  783. auto* frame_view =
  784. static_cast<WinFrameView*>(widget()->non_client_view()->frame_view());
  785. frame_view->caption_button_container()->UpdateButtons();
  786. }
  787. #endif
  788. maximizable_ = maximizable;
  789. }
  790. bool NativeWindowViews::IsMaximizable() {
  791. #if BUILDFLAG(IS_WIN)
  792. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MAXIMIZEBOX;
  793. #else
  794. return true; // Not implemented on Linux.
  795. #endif
  796. }
  797. void NativeWindowViews::SetExcludedFromShownWindowsMenu(bool excluded) {}
  798. bool NativeWindowViews::IsExcludedFromShownWindowsMenu() {
  799. // return false on unsupported platforms
  800. return false;
  801. }
  802. void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
  803. fullscreenable_ = fullscreenable;
  804. }
  805. bool NativeWindowViews::IsFullScreenable() {
  806. return fullscreenable_;
  807. }
  808. void NativeWindowViews::SetClosable(bool closable) {
  809. #if BUILDFLAG(IS_WIN)
  810. HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
  811. if (closable) {
  812. EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
  813. } else {
  814. EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  815. }
  816. if (IsWindowControlsOverlayEnabled()) {
  817. auto* frame_view =
  818. static_cast<WinFrameView*>(widget()->non_client_view()->frame_view());
  819. frame_view->caption_button_container()->UpdateButtons();
  820. }
  821. #endif
  822. }
  823. bool NativeWindowViews::IsClosable() {
  824. #if BUILDFLAG(IS_WIN)
  825. HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
  826. MENUITEMINFO info;
  827. memset(&info, 0, sizeof(info));
  828. info.cbSize = sizeof(info);
  829. info.fMask = MIIM_STATE;
  830. if (!GetMenuItemInfo(menu, SC_CLOSE, false, &info)) {
  831. return false;
  832. }
  833. return !(info.fState & MFS_DISABLED);
  834. #elif BUILDFLAG(IS_LINUX)
  835. return true;
  836. #endif
  837. }
  838. void NativeWindowViews::SetAlwaysOnTop(ui::ZOrderLevel z_order,
  839. const std::string& level,
  840. int relativeLevel) {
  841. bool level_changed = z_order != widget()->GetZOrderLevel();
  842. widget()->SetZOrderLevel(z_order);
  843. #if BUILDFLAG(IS_WIN)
  844. // Reset the placement flag.
  845. behind_task_bar_ = false;
  846. if (z_order != ui::ZOrderLevel::kNormal) {
  847. // On macOS the window is placed behind the Dock for the following levels.
  848. // Re-use the same names on Windows to make it easier for the user.
  849. static const std::vector<std::string> levels = {
  850. "floating", "torn-off-menu", "modal-panel", "main-menu", "status"};
  851. behind_task_bar_ = base::Contains(levels, level);
  852. }
  853. #endif
  854. MoveBehindTaskBarIfNeeded();
  855. // This must be notified at the very end or IsAlwaysOnTop
  856. // will not yet have been updated to reflect the new status
  857. if (level_changed)
  858. NativeWindow::NotifyWindowAlwaysOnTopChanged();
  859. }
  860. ui::ZOrderLevel NativeWindowViews::GetZOrderLevel() {
  861. return widget()->GetZOrderLevel();
  862. }
  863. void NativeWindowViews::Center() {
  864. widget()->CenterWindow(GetSize());
  865. }
  866. void NativeWindowViews::Invalidate() {
  867. widget()->SchedulePaintInRect(gfx::Rect(GetBounds().size()));
  868. }
  869. void NativeWindowViews::SetTitle(const std::string& title) {
  870. title_ = title;
  871. widget()->UpdateWindowTitle();
  872. }
  873. std::string NativeWindowViews::GetTitle() {
  874. return title_;
  875. }
  876. void NativeWindowViews::FlashFrame(bool flash) {
  877. #if BUILDFLAG(IS_WIN)
  878. // The Chromium's implementation has a bug stopping flash.
  879. if (!flash) {
  880. FLASHWINFO fwi;
  881. fwi.cbSize = sizeof(fwi);
  882. fwi.hwnd = GetAcceleratedWidget();
  883. fwi.dwFlags = FLASHW_STOP;
  884. fwi.uCount = 0;
  885. FlashWindowEx(&fwi);
  886. return;
  887. }
  888. #endif
  889. widget()->FlashFrame(flash);
  890. }
  891. void NativeWindowViews::SetSkipTaskbar(bool skip) {
  892. #if BUILDFLAG(IS_WIN)
  893. Microsoft::WRL::ComPtr<ITaskbarList> taskbar;
  894. if (FAILED(::CoCreateInstance(CLSID_TaskbarList, nullptr,
  895. CLSCTX_INPROC_SERVER,
  896. IID_PPV_ARGS(&taskbar))) ||
  897. FAILED(taskbar->HrInit()))
  898. return;
  899. if (skip) {
  900. taskbar->DeleteTab(GetAcceleratedWidget());
  901. } else {
  902. taskbar->AddTab(GetAcceleratedWidget());
  903. taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget());
  904. }
  905. #elif defined(USE_OZONE_PLATFORM_X11)
  906. if (IsX11())
  907. SetWMSpecState(static_cast<x11::Window>(GetAcceleratedWidget()), skip,
  908. x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
  909. #endif
  910. }
  911. void NativeWindowViews::SetSimpleFullScreen(bool simple_fullscreen) {
  912. SetFullScreen(simple_fullscreen);
  913. }
  914. bool NativeWindowViews::IsSimpleFullScreen() {
  915. return IsFullscreen();
  916. }
  917. void NativeWindowViews::SetKiosk(bool kiosk) {
  918. SetFullScreen(kiosk);
  919. }
  920. bool NativeWindowViews::IsKiosk() {
  921. return IsFullscreen();
  922. }
  923. bool NativeWindowViews::IsTabletMode() const {
  924. #if BUILDFLAG(IS_WIN)
  925. return base::win::IsWindows10OrGreaterTabletMode(GetAcceleratedWidget());
  926. #else
  927. return false;
  928. #endif
  929. }
  930. SkColor NativeWindowViews::GetBackgroundColor() {
  931. auto* background = root_view_->background();
  932. if (!background)
  933. return SK_ColorTRANSPARENT;
  934. return background->get_color();
  935. }
  936. void NativeWindowViews::SetBackgroundColor(SkColor background_color) {
  937. // web views' background color.
  938. root_view_->SetBackground(views::CreateSolidBackground(background_color));
  939. #if BUILDFLAG(IS_WIN)
  940. // Set the background color of native window.
  941. HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color));
  942. ULONG_PTR previous_brush =
  943. SetClassLongPtr(GetAcceleratedWidget(), GCLP_HBRBACKGROUND,
  944. reinterpret_cast<LONG_PTR>(brush));
  945. if (previous_brush)
  946. DeleteObject((HBRUSH)previous_brush);
  947. InvalidateRect(GetAcceleratedWidget(), NULL, 1);
  948. #endif
  949. }
  950. void NativeWindowViews::SetHasShadow(bool has_shadow) {
  951. wm::SetShadowElevation(GetNativeWindow(),
  952. has_shadow ? wm::kShadowElevationInactiveWindow
  953. : wm::kShadowElevationNone);
  954. }
  955. bool NativeWindowViews::HasShadow() {
  956. return GetNativeWindow()->GetProperty(wm::kShadowElevationKey) !=
  957. wm::kShadowElevationNone;
  958. }
  959. void NativeWindowViews::SetOpacity(const double opacity) {
  960. #if BUILDFLAG(IS_WIN)
  961. const double boundedOpacity = base::clamp(opacity, 0.0, 1.0);
  962. HWND hwnd = GetAcceleratedWidget();
  963. if (!layered_) {
  964. LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  965. ex_style |= WS_EX_LAYERED;
  966. ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
  967. layered_ = true;
  968. }
  969. ::SetLayeredWindowAttributes(hwnd, 0, boundedOpacity * 255, LWA_ALPHA);
  970. opacity_ = boundedOpacity;
  971. #else
  972. opacity_ = 1.0; // setOpacity unsupported on Linux
  973. #endif
  974. }
  975. double NativeWindowViews::GetOpacity() {
  976. return opacity_;
  977. }
  978. void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
  979. #if BUILDFLAG(IS_WIN)
  980. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  981. if (ignore)
  982. ex_style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
  983. else
  984. ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
  985. if (layered_)
  986. ex_style |= WS_EX_LAYERED;
  987. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  988. // Forwarding is always disabled when not ignoring mouse messages.
  989. if (!ignore) {
  990. SetForwardMouseMessages(false);
  991. } else {
  992. SetForwardMouseMessages(forward);
  993. }
  994. #elif defined(USE_OZONE_PLATFORM_X11)
  995. if (IsX11()) {
  996. auto* connection = x11::Connection::Get();
  997. if (ignore) {
  998. x11::Rectangle r{0, 0, 1, 1};
  999. connection->shape().Rectangles({
  1000. .operation = x11::Shape::So::Set,
  1001. .destination_kind = x11::Shape::Sk::Input,
  1002. .ordering = x11::ClipOrdering::YXBanded,
  1003. .destination_window =
  1004. static_cast<x11::Window>(GetAcceleratedWidget()),
  1005. .rectangles = {r},
  1006. });
  1007. } else {
  1008. connection->shape().Mask({
  1009. .operation = x11::Shape::So::Set,
  1010. .destination_kind = x11::Shape::Sk::Input,
  1011. .destination_window =
  1012. static_cast<x11::Window>(GetAcceleratedWidget()),
  1013. .source_bitmap = x11::Pixmap::None,
  1014. });
  1015. }
  1016. }
  1017. #endif
  1018. }
  1019. void NativeWindowViews::SetContentProtection(bool enable) {
  1020. #if BUILDFLAG(IS_WIN)
  1021. HWND hwnd = GetAcceleratedWidget();
  1022. DWORD affinity = enable ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE;
  1023. ::SetWindowDisplayAffinity(hwnd, affinity);
  1024. if (!layered_) {
  1025. // Workaround to prevent black window on screen capture after hiding and
  1026. // showing the BrowserWindow.
  1027. LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  1028. ex_style |= WS_EX_LAYERED;
  1029. ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
  1030. layered_ = true;
  1031. }
  1032. #endif
  1033. }
  1034. void NativeWindowViews::SetFocusable(bool focusable) {
  1035. widget()->widget_delegate()->SetCanActivate(focusable);
  1036. #if BUILDFLAG(IS_WIN)
  1037. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  1038. if (focusable)
  1039. ex_style &= ~WS_EX_NOACTIVATE;
  1040. else
  1041. ex_style |= WS_EX_NOACTIVATE;
  1042. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  1043. SetSkipTaskbar(!focusable);
  1044. Focus(false);
  1045. #endif
  1046. }
  1047. bool NativeWindowViews::IsFocusable() {
  1048. bool can_activate = widget()->widget_delegate()->CanActivate();
  1049. #if BUILDFLAG(IS_WIN)
  1050. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  1051. bool no_activate = ex_style & WS_EX_NOACTIVATE;
  1052. return !no_activate && can_activate;
  1053. #else
  1054. return can_activate;
  1055. #endif
  1056. }
  1057. void NativeWindowViews::SetMenu(ElectronMenuModel* menu_model) {
  1058. #if defined(USE_OZONE)
  1059. // Remove global menu bar.
  1060. if (global_menu_bar_ && menu_model == nullptr) {
  1061. global_menu_bar_.reset();
  1062. root_view_->UnregisterAcceleratorsWithFocusManager();
  1063. return;
  1064. }
  1065. // Use global application menu bar when possible.
  1066. if (CreateGlobalMenuBar() && ShouldUseGlobalMenuBar()) {
  1067. if (!global_menu_bar_)
  1068. global_menu_bar_ = std::make_unique<GlobalMenuBarX11>(this);
  1069. if (global_menu_bar_->IsServerStarted()) {
  1070. root_view_->RegisterAcceleratorsWithFocusManager(menu_model);
  1071. global_menu_bar_->SetMenu(menu_model);
  1072. return;
  1073. }
  1074. }
  1075. #endif
  1076. // Should reset content size when setting menu.
  1077. gfx::Size content_size = GetContentSize();
  1078. bool should_reset_size = use_content_size_ && has_frame() &&
  1079. !IsMenuBarAutoHide() &&
  1080. ((!!menu_model) != root_view_->HasMenu());
  1081. root_view_->SetMenu(menu_model);
  1082. if (should_reset_size) {
  1083. // Enlarge the size constraints for the menu.
  1084. int menu_bar_height = root_view_->GetMenuBarHeight();
  1085. extensions::SizeConstraints constraints = GetContentSizeConstraints();
  1086. if (constraints.HasMinimumSize()) {
  1087. gfx::Size min_size = constraints.GetMinimumSize();
  1088. min_size.set_height(min_size.height() + menu_bar_height);
  1089. constraints.set_minimum_size(min_size);
  1090. }
  1091. if (constraints.HasMaximumSize()) {
  1092. gfx::Size max_size = constraints.GetMaximumSize();
  1093. max_size.set_height(max_size.height() + menu_bar_height);
  1094. constraints.set_maximum_size(max_size);
  1095. }
  1096. SetContentSizeConstraints(constraints);
  1097. // Resize the window to make sure content size is not changed.
  1098. SetContentSize(content_size);
  1099. }
  1100. }
  1101. void NativeWindowViews::AddBrowserView(NativeBrowserView* view) {
  1102. if (!content_view())
  1103. return;
  1104. if (!view) {
  1105. return;
  1106. }
  1107. add_browser_view(view);
  1108. if (view->GetInspectableWebContentsView())
  1109. content_view()->AddChildView(
  1110. view->GetInspectableWebContentsView()->GetView());
  1111. }
  1112. void NativeWindowViews::RemoveBrowserView(NativeBrowserView* view) {
  1113. if (!content_view())
  1114. return;
  1115. if (!view) {
  1116. return;
  1117. }
  1118. if (view->GetInspectableWebContentsView())
  1119. content_view()->RemoveChildView(
  1120. view->GetInspectableWebContentsView()->GetView());
  1121. remove_browser_view(view);
  1122. }
  1123. void NativeWindowViews::SetTopBrowserView(NativeBrowserView* view) {
  1124. if (!content_view())
  1125. return;
  1126. if (!view) {
  1127. return;
  1128. }
  1129. remove_browser_view(view);
  1130. add_browser_view(view);
  1131. if (view->GetInspectableWebContentsView())
  1132. content_view()->ReorderChildView(
  1133. view->GetInspectableWebContentsView()->GetView(), -1);
  1134. }
  1135. void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
  1136. NativeWindow::SetParentWindow(parent);
  1137. #if defined(USE_OZONE_PLATFORM_X11)
  1138. if (IsX11())
  1139. x11::SetProperty(
  1140. static_cast<x11::Window>(GetAcceleratedWidget()),
  1141. x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW,
  1142. parent ? static_cast<x11::Window>(parent->GetAcceleratedWidget())
  1143. : ui::GetX11RootWindow());
  1144. #elif BUILDFLAG(IS_WIN)
  1145. // To set parentship between windows into Windows is better to play with the
  1146. // owner instead of the parent, as Windows natively seems to do if a parent
  1147. // is specified at window creation time.
  1148. // For do this we must NOT use the ::SetParent function, instead we must use
  1149. // the ::GetWindowLongPtr or ::SetWindowLongPtr functions with "nIndex" set
  1150. // to "GWLP_HWNDPARENT" which actually means the window owner.
  1151. HWND hwndParent = parent ? parent->GetAcceleratedWidget() : NULL;
  1152. if (hwndParent ==
  1153. (HWND)::GetWindowLongPtr(GetAcceleratedWidget(), GWLP_HWNDPARENT))
  1154. return;
  1155. ::SetWindowLongPtr(GetAcceleratedWidget(), GWLP_HWNDPARENT,
  1156. (LONG_PTR)hwndParent);
  1157. // Ensures the visibility
  1158. if (IsVisible()) {
  1159. WINDOWPLACEMENT wp;
  1160. wp.length = sizeof(WINDOWPLACEMENT);
  1161. ::GetWindowPlacement(GetAcceleratedWidget(), &wp);
  1162. ::ShowWindow(GetAcceleratedWidget(), SW_HIDE);
  1163. ::ShowWindow(GetAcceleratedWidget(), wp.showCmd);
  1164. ::BringWindowToTop(GetAcceleratedWidget());
  1165. }
  1166. #endif
  1167. }
  1168. gfx::NativeView NativeWindowViews::GetNativeView() const {
  1169. return widget()->GetNativeView();
  1170. }
  1171. gfx::NativeWindow NativeWindowViews::GetNativeWindow() const {
  1172. return widget()->GetNativeWindow();
  1173. }
  1174. void NativeWindowViews::SetProgressBar(double progress,
  1175. NativeWindow::ProgressState state) {
  1176. #if BUILDFLAG(IS_WIN)
  1177. taskbar_host_.SetProgressBar(GetAcceleratedWidget(), progress, state);
  1178. #elif BUILDFLAG(IS_LINUX)
  1179. if (unity::IsRunning()) {
  1180. unity::SetProgressFraction(progress);
  1181. }
  1182. #endif
  1183. }
  1184. void NativeWindowViews::SetOverlayIcon(const gfx::Image& overlay,
  1185. const std::string& description) {
  1186. #if BUILDFLAG(IS_WIN)
  1187. SkBitmap overlay_bitmap = overlay.AsBitmap();
  1188. taskbar_host_.SetOverlayIcon(GetAcceleratedWidget(), overlay_bitmap,
  1189. description);
  1190. #endif
  1191. }
  1192. void NativeWindowViews::SetAutoHideMenuBar(bool auto_hide) {
  1193. root_view_->SetAutoHideMenuBar(auto_hide);
  1194. }
  1195. bool NativeWindowViews::IsMenuBarAutoHide() {
  1196. return root_view_->IsMenuBarAutoHide();
  1197. }
  1198. void NativeWindowViews::SetMenuBarVisibility(bool visible) {
  1199. root_view_->SetMenuBarVisibility(visible);
  1200. }
  1201. bool NativeWindowViews::IsMenuBarVisible() {
  1202. return root_view_->IsMenuBarVisible();
  1203. }
  1204. void NativeWindowViews::SetVisibleOnAllWorkspaces(
  1205. bool visible,
  1206. bool visibleOnFullScreen,
  1207. bool skipTransformProcessType) {
  1208. widget()->SetVisibleOnAllWorkspaces(visible);
  1209. }
  1210. bool NativeWindowViews::IsVisibleOnAllWorkspaces() {
  1211. #if defined(USE_OZONE_PLATFORM_X11)
  1212. if (IsX11()) {
  1213. // Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to
  1214. // determine whether the current window is visible on all workspaces.
  1215. x11::Atom sticky_atom = x11::GetAtom("_NET_WM_STATE_STICKY");
  1216. std::vector<x11::Atom> wm_states;
  1217. GetArrayProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
  1218. x11::GetAtom("_NET_WM_STATE"), &wm_states);
  1219. return std::find(wm_states.begin(), wm_states.end(), sticky_atom) !=
  1220. wm_states.end();
  1221. }
  1222. #endif
  1223. return false;
  1224. }
  1225. content::DesktopMediaID NativeWindowViews::GetDesktopMediaID() const {
  1226. const gfx::AcceleratedWidget accelerated_widget = GetAcceleratedWidget();
  1227. content::DesktopMediaID::Id window_handle = content::DesktopMediaID::kNullId;
  1228. content::DesktopMediaID::Id aura_id = content::DesktopMediaID::kNullId;
  1229. #if BUILDFLAG(IS_WIN)
  1230. window_handle =
  1231. reinterpret_cast<content::DesktopMediaID::Id>(accelerated_widget);
  1232. #elif BUILDFLAG(IS_LINUX)
  1233. window_handle = static_cast<uint32_t>(accelerated_widget);
  1234. #endif
  1235. aura::WindowTreeHost* const host =
  1236. aura::WindowTreeHost::GetForAcceleratedWidget(accelerated_widget);
  1237. aura::Window* const aura_window = host ? host->window() : nullptr;
  1238. if (aura_window) {
  1239. aura_id = content::DesktopMediaID::RegisterNativeWindow(
  1240. content::DesktopMediaID::TYPE_WINDOW, aura_window)
  1241. .window_id;
  1242. }
  1243. // No constructor to pass the aura_id. Make sure to not use the other
  1244. // constructor that has a third parameter, it is for yet another purpose.
  1245. content::DesktopMediaID result = content::DesktopMediaID(
  1246. content::DesktopMediaID::TYPE_WINDOW, window_handle);
  1247. // Confusing but this is how content::DesktopMediaID is designed. The id
  1248. // property is the window handle whereas the window_id property is an id
  1249. // given by a map containing all aura instances.
  1250. result.window_id = aura_id;
  1251. return result;
  1252. }
  1253. gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
  1254. if (GetNativeWindow() && GetNativeWindow()->GetHost())
  1255. return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
  1256. else
  1257. return gfx::kNullAcceleratedWidget;
  1258. }
  1259. NativeWindowHandle NativeWindowViews::GetNativeWindowHandle() const {
  1260. return GetAcceleratedWidget();
  1261. }
  1262. gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
  1263. const gfx::Rect& bounds) const {
  1264. if (!has_frame())
  1265. return bounds;
  1266. gfx::Rect window_bounds(bounds);
  1267. #if BUILDFLAG(IS_WIN)
  1268. if (widget()->non_client_view()) {
  1269. HWND hwnd = GetAcceleratedWidget();
  1270. gfx::Rect dpi_bounds = DIPToScreenRect(hwnd, bounds);
  1271. window_bounds = ScreenToDIPRect(
  1272. hwnd, widget()->non_client_view()->GetWindowBoundsForClientBounds(
  1273. dpi_bounds));
  1274. }
  1275. #endif
  1276. if (root_view_->HasMenu() && root_view_->IsMenuBarVisible()) {
  1277. int menu_bar_height = root_view_->GetMenuBarHeight();
  1278. window_bounds.set_y(window_bounds.y() - menu_bar_height);
  1279. window_bounds.set_height(window_bounds.height() + menu_bar_height);
  1280. }
  1281. return window_bounds;
  1282. }
  1283. gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
  1284. const gfx::Rect& bounds) const {
  1285. if (!has_frame())
  1286. return bounds;
  1287. gfx::Rect content_bounds(bounds);
  1288. #if BUILDFLAG(IS_WIN)
  1289. HWND hwnd = GetAcceleratedWidget();
  1290. content_bounds.set_size(DIPToScreenRect(hwnd, content_bounds).size());
  1291. RECT rect;
  1292. SetRectEmpty(&rect);
  1293. DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
  1294. DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  1295. AdjustWindowRectEx(&rect, style, FALSE, ex_style);
  1296. content_bounds.set_width(content_bounds.width() - (rect.right - rect.left));
  1297. content_bounds.set_height(content_bounds.height() - (rect.bottom - rect.top));
  1298. content_bounds.set_size(ScreenToDIPRect(hwnd, content_bounds).size());
  1299. #endif
  1300. if (root_view_->HasMenu() && root_view_->IsMenuBarVisible()) {
  1301. int menu_bar_height = root_view_->GetMenuBarHeight();
  1302. content_bounds.set_y(content_bounds.y() + menu_bar_height);
  1303. content_bounds.set_height(content_bounds.height() - menu_bar_height);
  1304. }
  1305. return content_bounds;
  1306. }
  1307. void NativeWindowViews::UpdateDraggableRegions(
  1308. const std::vector<mojom::DraggableRegionPtr>& regions) {
  1309. draggable_region_ = DraggableRegionsToSkRegion(regions);
  1310. }
  1311. #if BUILDFLAG(IS_WIN)
  1312. void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) {
  1313. // We are responsible for storing the images.
  1314. window_icon_ = base::win::ScopedHICON(CopyIcon(window_icon));
  1315. app_icon_ = base::win::ScopedHICON(CopyIcon(app_icon));
  1316. HWND hwnd = GetAcceleratedWidget();
  1317. SendMessage(hwnd, WM_SETICON, ICON_SMALL,
  1318. reinterpret_cast<LPARAM>(window_icon_.get()));
  1319. SendMessage(hwnd, WM_SETICON, ICON_BIG,
  1320. reinterpret_cast<LPARAM>(app_icon_.get()));
  1321. }
  1322. #elif BUILDFLAG(IS_LINUX)
  1323. void NativeWindowViews::SetIcon(const gfx::ImageSkia& icon) {
  1324. auto* tree_host = views::DesktopWindowTreeHostLinux::GetHostForWidget(
  1325. GetAcceleratedWidget());
  1326. tree_host->SetWindowIcons(icon, {});
  1327. }
  1328. #endif
  1329. void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
  1330. bool active) {
  1331. if (changed_widget != widget())
  1332. return;
  1333. if (active) {
  1334. MoveBehindTaskBarIfNeeded();
  1335. NativeWindow::NotifyWindowFocus();
  1336. } else {
  1337. NativeWindow::NotifyWindowBlur();
  1338. }
  1339. // Hide menu bar when window is blured.
  1340. if (!active && IsMenuBarAutoHide() && IsMenuBarVisible())
  1341. SetMenuBarVisibility(false);
  1342. root_view_->ResetAltState();
  1343. }
  1344. void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
  1345. const gfx::Rect& bounds) {
  1346. if (changed_widget != widget())
  1347. return;
  1348. // Note: We intentionally use `GetBounds()` instead of `bounds` to properly
  1349. // handle minimized windows on Windows.
  1350. const auto new_bounds = GetBounds();
  1351. if (widget_size_ != new_bounds.size()) {
  1352. int width_delta = new_bounds.width() - widget_size_.width();
  1353. int height_delta = new_bounds.height() - widget_size_.height();
  1354. for (NativeBrowserView* item : browser_views()) {
  1355. auto* native_view = static_cast<NativeBrowserViewViews*>(item);
  1356. native_view->SetAutoResizeProportions(widget_size_);
  1357. native_view->AutoResize(new_bounds, width_delta, height_delta);
  1358. }
  1359. NotifyWindowResize();
  1360. widget_size_ = new_bounds.size();
  1361. }
  1362. }
  1363. void NativeWindowViews::OnWidgetDestroying(views::Widget* widget) {
  1364. aura::Window* window = GetNativeWindow();
  1365. if (window)
  1366. window->RemovePreTargetHandler(this);
  1367. }
  1368. void NativeWindowViews::OnWidgetDestroyed(views::Widget* changed_widget) {
  1369. widget_destroyed_ = true;
  1370. }
  1371. views::View* NativeWindowViews::GetInitiallyFocusedView() {
  1372. return focused_view_;
  1373. }
  1374. bool NativeWindowViews::CanMaximize() const {
  1375. return resizable_ && maximizable_;
  1376. }
  1377. bool NativeWindowViews::CanMinimize() const {
  1378. #if BUILDFLAG(IS_WIN)
  1379. return minimizable_;
  1380. #elif BUILDFLAG(IS_LINUX)
  1381. return true;
  1382. #endif
  1383. }
  1384. std::u16string NativeWindowViews::GetWindowTitle() const {
  1385. return base::UTF8ToUTF16(title_);
  1386. }
  1387. views::View* NativeWindowViews::GetContentsView() {
  1388. return root_view_.get();
  1389. }
  1390. bool NativeWindowViews::ShouldDescendIntoChildForEventHandling(
  1391. gfx::NativeView child,
  1392. const gfx::Point& location) {
  1393. // App window should claim mouse events that fall within any BrowserViews'
  1394. // draggable region.
  1395. for (auto* view : browser_views()) {
  1396. auto* native_view = static_cast<NativeBrowserViewViews*>(view);
  1397. auto* view_draggable_region = native_view->draggable_region();
  1398. if (view_draggable_region &&
  1399. view_draggable_region->contains(location.x(), location.y()))
  1400. return false;
  1401. }
  1402. // App window should claim mouse events that fall within the draggable region.
  1403. if (draggable_region() &&
  1404. draggable_region()->contains(location.x(), location.y()))
  1405. return false;
  1406. // And the events on border for dragging resizable frameless window.
  1407. if ((!has_frame() || has_client_frame()) && resizable_) {
  1408. auto* frame =
  1409. static_cast<FramelessView*>(widget()->non_client_view()->frame_view());
  1410. return frame->ResizingBorderHitTest(location) == HTNOWHERE;
  1411. }
  1412. return true;
  1413. }
  1414. views::ClientView* NativeWindowViews::CreateClientView(views::Widget* widget) {
  1415. return new NativeWindowClientView(widget, root_view_.get(), this);
  1416. }
  1417. std::unique_ptr<views::NonClientFrameView>
  1418. NativeWindowViews::CreateNonClientFrameView(views::Widget* widget) {
  1419. #if BUILDFLAG(IS_WIN)
  1420. auto frame_view = std::make_unique<WinFrameView>();
  1421. frame_view->Init(this, widget);
  1422. return frame_view;
  1423. #else
  1424. if (has_frame() && !has_client_frame()) {
  1425. return std::make_unique<NativeFrameView>(this, widget);
  1426. } else {
  1427. auto frame_view = has_frame() && has_client_frame()
  1428. ? std::make_unique<ClientFrameViewLinux>()
  1429. : std::make_unique<FramelessView>();
  1430. frame_view->Init(this, widget);
  1431. return frame_view;
  1432. }
  1433. #endif
  1434. }
  1435. void NativeWindowViews::OnWidgetMove() {
  1436. NotifyWindowMove();
  1437. }
  1438. void NativeWindowViews::HandleKeyboardEvent(
  1439. content::WebContents*,
  1440. const content::NativeWebKeyboardEvent& event) {
  1441. if (widget_destroyed_)
  1442. return;
  1443. #if BUILDFLAG(IS_LINUX)
  1444. if (event.windows_key_code == ui::VKEY_BROWSER_BACK)
  1445. NotifyWindowExecuteAppCommand(kBrowserBackward);
  1446. else if (event.windows_key_code == ui::VKEY_BROWSER_FORWARD)
  1447. NotifyWindowExecuteAppCommand(kBrowserForward);
  1448. #endif
  1449. keyboard_event_handler_->HandleKeyboardEvent(event,
  1450. root_view_->GetFocusManager());
  1451. root_view_->HandleKeyEvent(event);
  1452. }
  1453. void NativeWindowViews::OnMouseEvent(ui::MouseEvent* event) {
  1454. if (event->type() != ui::ET_MOUSE_PRESSED)
  1455. return;
  1456. // Alt+Click should not toggle menu bar.
  1457. root_view_->ResetAltState();
  1458. #if BUILDFLAG(IS_LINUX)
  1459. if (event->changed_button_flags() == ui::EF_BACK_MOUSE_BUTTON)
  1460. NotifyWindowExecuteAppCommand(kBrowserBackward);
  1461. else if (event->changed_button_flags() == ui::EF_FORWARD_MOUSE_BUTTON)
  1462. NotifyWindowExecuteAppCommand(kBrowserForward);
  1463. #endif
  1464. }
  1465. ui::WindowShowState NativeWindowViews::GetRestoredState() {
  1466. if (IsMaximized()) {
  1467. #if BUILDFLAG(IS_WIN)
  1468. // Only restore Maximized state when window is NOT transparent style
  1469. if (!transparent()) {
  1470. return ui::SHOW_STATE_MAXIMIZED;
  1471. }
  1472. #else
  1473. return ui::SHOW_STATE_MAXIMIZED;
  1474. #endif
  1475. }
  1476. if (IsFullscreen())
  1477. return ui::SHOW_STATE_FULLSCREEN;
  1478. return ui::SHOW_STATE_NORMAL;
  1479. }
  1480. void NativeWindowViews::MoveBehindTaskBarIfNeeded() {
  1481. #if BUILDFLAG(IS_WIN)
  1482. if (behind_task_bar_) {
  1483. const HWND task_bar_hwnd = ::FindWindow(kUniqueTaskBarClassName, nullptr);
  1484. ::SetWindowPos(GetAcceleratedWidget(), task_bar_hwnd, 0, 0, 0, 0,
  1485. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1486. }
  1487. #endif
  1488. // TODO(julien.isorce): Implement X11 case.
  1489. }
  1490. // static
  1491. NativeWindow* NativeWindow::Create(const gin_helper::Dictionary& options,
  1492. NativeWindow* parent) {
  1493. return new NativeWindowViews(options, parent);
  1494. }
  1495. } // namespace electron