native_window_views.cc 55 KB

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