native_window_views.cc 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790
  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. // FIXME(ckerr) this incorrect #include order is a temporary
  5. // fix to unblock the roll. Will fix in an upgrade followup.
  6. #include "ui/base/ozone_buildflags.h"
  7. #if BUILDFLAG(IS_OZONE_X11)
  8. #include "ui/base/x/x11_util.h"
  9. #endif
  10. #include "shell/browser/native_window_views.h"
  11. #if BUILDFLAG(IS_WIN)
  12. #include <dwmapi.h>
  13. #include <wrl/client.h>
  14. #endif
  15. #include <memory>
  16. #include <utility>
  17. #include <vector>
  18. #include "base/containers/contains.h"
  19. #include "base/memory/raw_ref.h"
  20. #include "base/strings/utf_string_conversions.h"
  21. #include "content/public/browser/desktop_media_id.h"
  22. #include "content/public/common/color_parser.h"
  23. #include "shell/browser/api/electron_api_web_contents.h"
  24. #include "shell/browser/ui/views/root_view.h"
  25. #include "shell/browser/web_contents_preferences.h"
  26. #include "shell/browser/web_view_manager.h"
  27. #include "shell/browser/window_list.h"
  28. #include "shell/common/electron_constants.h"
  29. #include "shell/common/gin_converters/image_converter.h"
  30. #include "shell/common/gin_helper/dictionary.h"
  31. #include "shell/common/options_switches.h"
  32. #include "ui/aura/window_tree_host.h"
  33. #include "ui/base/hit_test.h"
  34. #include "ui/display/screen.h"
  35. #include "ui/gfx/image/image.h"
  36. #include "ui/gfx/native_widget_types.h"
  37. #include "ui/ozone/public/ozone_platform.h"
  38. #include "ui/views/background.h"
  39. #include "ui/views/controls/webview/webview.h"
  40. #include "ui/views/widget/native_widget_private.h"
  41. #include "ui/views/widget/widget.h"
  42. #include "ui/views/window/client_view.h"
  43. #include "ui/wm/core/shadow_types.h"
  44. #include "ui/wm/core/window_util.h"
  45. #if BUILDFLAG(IS_LINUX)
  46. #include "base/strings/string_util.h"
  47. #include "shell/browser/browser.h"
  48. #include "shell/browser/linux/unity_service.h"
  49. #include "shell/browser/ui/electron_desktop_window_tree_host_linux.h"
  50. #include "shell/browser/ui/views/client_frame_view_linux.h"
  51. #include "shell/browser/ui/views/native_frame_view.h"
  52. #include "shell/browser/ui/views/opaque_frame_view.h"
  53. #include "shell/common/platform_util.h"
  54. #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
  55. #include "ui/views/window/native_frame_view.h"
  56. #if BUILDFLAG(IS_OZONE_X11)
  57. #include "shell/browser/ui/views/global_menu_bar_x11.h"
  58. #include "shell/browser/ui/x/event_disabler.h"
  59. #include "shell/browser/ui/x/x_window_utils.h"
  60. #include "ui/gfx/x/atom_cache.h"
  61. #include "ui/gfx/x/connection.h"
  62. #include "ui/gfx/x/shape.h"
  63. #include "ui/gfx/x/xproto.h"
  64. #endif
  65. #elif BUILDFLAG(IS_WIN)
  66. #include "base/win/win_util.h"
  67. #include "base/win/windows_version.h"
  68. #include "shell/browser/ui/views/win_frame_view.h"
  69. #include "shell/browser/ui/win/electron_desktop_native_widget_aura.h"
  70. #include "skia/ext/skia_utils_win.h"
  71. #include "ui/display/win/screen_win.h"
  72. #include "ui/gfx/color_utils.h"
  73. #include "ui/gfx/win/hwnd_util.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. [[maybe_unused]] bool IsX11() {
  145. return ui::OzonePlatform::GetInstance()
  146. ->GetPlatformProperties()
  147. .electron_can_call_x11;
  148. }
  149. class NativeWindowClientView : public views::ClientView {
  150. public:
  151. NativeWindowClientView(views::Widget* widget,
  152. views::View* root_view,
  153. NativeWindowViews* window)
  154. : views::ClientView{widget, root_view},
  155. window_{raw_ref<NativeWindowViews>::from_ptr(window)} {}
  156. ~NativeWindowClientView() override = default;
  157. // disable copy
  158. NativeWindowClientView(const NativeWindowClientView&) = delete;
  159. NativeWindowClientView& operator=(const NativeWindowClientView&) = delete;
  160. // views::ClientView
  161. views::CloseRequestResult OnWindowCloseRequested() override {
  162. window_->NotifyWindowCloseButtonClicked();
  163. return views::CloseRequestResult::kCannotClose;
  164. }
  165. private:
  166. const raw_ref<NativeWindowViews> window_;
  167. };
  168. } // namespace
  169. NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
  170. NativeWindow* parent)
  171. : NativeWindow(options, parent) {
  172. options.Get(options::kTitle, &title_);
  173. bool menu_bar_autohide;
  174. if (options.Get(options::kAutoHideMenuBar, &menu_bar_autohide))
  175. root_view_.SetAutoHideMenuBar(menu_bar_autohide);
  176. #if BUILDFLAG(IS_WIN)
  177. // On Windows we rely on the CanResize() to indicate whether window can be
  178. // resized, and it should be set before window is created.
  179. options.Get(options::kResizable, &resizable_);
  180. options.Get(options::kMinimizable, &minimizable_);
  181. options.Get(options::kMaximizable, &maximizable_);
  182. // Transparent window must not have thick frame.
  183. options.Get("thickFrame", &thick_frame_);
  184. if (transparent())
  185. thick_frame_ = false;
  186. overlay_button_color_ = color_utils::GetSysSkColor(COLOR_BTNFACE);
  187. overlay_symbol_color_ = color_utils::GetSysSkColor(COLOR_BTNTEXT);
  188. #endif
  189. v8::Local<v8::Value> titlebar_overlay;
  190. if (options.Get(options::ktitleBarOverlay, &titlebar_overlay) &&
  191. titlebar_overlay->IsObject()) {
  192. auto titlebar_overlay_obj =
  193. gin_helper::Dictionary::CreateEmpty(options.isolate());
  194. options.Get(options::ktitleBarOverlay, &titlebar_overlay_obj);
  195. std::string overlay_color_string;
  196. if (titlebar_overlay_obj.Get(options::kOverlayButtonColor,
  197. &overlay_color_string)) {
  198. bool success = content::ParseCssColorString(overlay_color_string,
  199. &overlay_button_color_);
  200. DCHECK(success);
  201. }
  202. std::string overlay_symbol_color_string;
  203. if (titlebar_overlay_obj.Get(options::kOverlaySymbolColor,
  204. &overlay_symbol_color_string)) {
  205. bool success = content::ParseCssColorString(overlay_symbol_color_string,
  206. &overlay_symbol_color_);
  207. DCHECK(success);
  208. }
  209. }
  210. // |hidden| is the only non-default titleBarStyle valid on Windows and Linux.
  211. if (title_bar_style_ == TitleBarStyle::kHidden)
  212. set_has_frame(false);
  213. #if BUILDFLAG(IS_WIN)
  214. // If the taskbar is re-created after we start up, we have to rebuild all of
  215. // our buttons.
  216. taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));
  217. #endif
  218. if (enable_larger_than_screen())
  219. // We need to set a default maximum window size here otherwise Windows
  220. // will not allow us to resize the window larger than scree.
  221. // Setting directly to INT_MAX somehow doesn't work, so we just divide
  222. // by 10, which should still be large enough.
  223. SetContentSizeConstraints(extensions::SizeConstraints(
  224. gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10)));
  225. int width = 800, height = 600;
  226. options.Get(options::kWidth, &width);
  227. options.Get(options::kHeight, &height);
  228. gfx::Rect bounds(0, 0, width, height);
  229. widget_size_ = bounds.size();
  230. widget()->AddObserver(this);
  231. using InitParams = views::Widget::InitParams;
  232. auto params = InitParams{InitParams::WIDGET_OWNS_NATIVE_WIDGET,
  233. InitParams::TYPE_WINDOW};
  234. params.bounds = bounds;
  235. params.delegate = this;
  236. params.remove_standard_frame = !has_frame() || has_client_frame();
  237. // If a client frame, we need to draw our own shadows.
  238. if (IsTranslucent() || has_client_frame())
  239. params.opacity = InitParams::WindowOpacity::kTranslucent;
  240. // The given window is most likely not rectangular since it is translucent and
  241. // has no standard frame, don't show a shadow for it.
  242. if (IsTranslucent() && !has_frame())
  243. params.shadow_type = InitParams::ShadowType::kNone;
  244. bool focusable;
  245. if (options.Get(options::kFocusable, &focusable) && !focusable)
  246. params.activatable = InitParams::Activatable::kNo;
  247. #if BUILDFLAG(IS_WIN)
  248. if (parent)
  249. params.parent = parent->GetNativeWindow();
  250. params.native_widget = new ElectronDesktopNativeWidgetAura(this);
  251. #elif BUILDFLAG(IS_LINUX)
  252. std::string name = Browser::Get()->GetName();
  253. // Set WM_WINDOW_ROLE.
  254. params.wm_role_name = "browser-window";
  255. // Set WM_CLASS.
  256. params.wm_class_name = base::ToLowerASCII(name);
  257. params.wm_class_class = name;
  258. // Set Wayland application ID.
  259. params.wayland_app_id = platform_util::GetXdgAppId();
  260. auto* native_widget = new views::DesktopNativeWidgetAura(widget());
  261. params.native_widget = native_widget;
  262. params.desktop_window_tree_host =
  263. new ElectronDesktopWindowTreeHostLinux(this, native_widget);
  264. #endif
  265. widget()->Init(std::move(params));
  266. widget()->SetNativeWindowProperty(kElectronNativeWindowKey, this);
  267. SetCanResize(resizable_);
  268. bool fullscreen = false;
  269. options.Get(options::kFullscreen, &fullscreen);
  270. std::string window_type;
  271. options.Get(options::kType, &window_type);
  272. #if BUILDFLAG(IS_LINUX)
  273. // Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
  274. bool use_dark_theme = false;
  275. if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
  276. SetGTKDarkThemeEnabled(use_dark_theme);
  277. }
  278. if (parent)
  279. SetParentWindow(parent);
  280. if (IsX11()) {
  281. // Before the window is mapped the SetWMSpecState can not work, so we have
  282. // to manually set the _NET_WM_STATE.
  283. std::vector<x11::Atom> state_atom_list;
  284. // Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
  285. if (fullscreen) {
  286. state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_FULLSCREEN"));
  287. }
  288. if (parent) {
  289. // Force using dialog type for child window.
  290. window_type = "dialog";
  291. // Modal window needs the _NET_WM_STATE_MODAL hint.
  292. if (is_modal())
  293. state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_MODAL"));
  294. }
  295. if (!state_atom_list.empty()) {
  296. auto* connection = x11::Connection::Get();
  297. connection->SetArrayProperty(
  298. static_cast<x11::Window>(GetAcceleratedWidget()),
  299. x11::GetAtom("_NET_WM_STATE"), x11::Atom::ATOM, state_atom_list);
  300. }
  301. // Set the _NET_WM_WINDOW_TYPE.
  302. if (!window_type.empty())
  303. SetWindowType(static_cast<x11::Window>(GetAcceleratedWidget()),
  304. window_type);
  305. }
  306. #endif
  307. #if BUILDFLAG(IS_WIN)
  308. if (!has_frame()) {
  309. // Set Window style so that we get a minimize and maximize animation when
  310. // frameless.
  311. DWORD frame_style = WS_CAPTION | WS_OVERLAPPED;
  312. if (resizable_)
  313. frame_style |= WS_THICKFRAME;
  314. if (minimizable_)
  315. frame_style |= WS_MINIMIZEBOX;
  316. if (maximizable_)
  317. frame_style |= WS_MAXIMIZEBOX;
  318. // We should not show a frame for transparent window.
  319. if (!thick_frame_)
  320. frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
  321. ::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
  322. }
  323. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  324. if (window_type == "toolbar")
  325. ex_style |= WS_EX_TOOLWINDOW;
  326. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  327. #endif
  328. if (has_frame() && !has_client_frame()) {
  329. // TODO(zcbenz): This was used to force using native frame on Windows 2003,
  330. // we should check whether setting it in InitParams can work.
  331. widget()->set_frame_type(views::Widget::FrameType::kForceNative);
  332. widget()->FrameTypeChanged();
  333. #if BUILDFLAG(IS_WIN)
  334. // thickFrame also works for normal window.
  335. if (!thick_frame_)
  336. FlipWindowStyle(GetAcceleratedWidget(), false, WS_THICKFRAME);
  337. #endif
  338. }
  339. // Default content view.
  340. SetContentView(new views::View());
  341. gfx::Size size = bounds.size();
  342. if (has_frame() &&
  343. options.Get(options::kUseContentSize, &use_content_size_) &&
  344. use_content_size_)
  345. size = ContentBoundsToWindowBounds(gfx::Rect(size)).size();
  346. widget()->CenterWindow(size);
  347. #if BUILDFLAG(IS_WIN)
  348. // Save initial window state.
  349. if (fullscreen)
  350. last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
  351. else
  352. last_window_state_ = ui::SHOW_STATE_NORMAL;
  353. #endif
  354. // Listen to mouse events.
  355. aura::Window* window = GetNativeWindow();
  356. if (window)
  357. window->AddPreTargetHandler(this);
  358. #if BUILDFLAG(IS_LINUX)
  359. // On linux after the widget is initialized we might have to force set the
  360. // bounds if the bounds are smaller than the current display
  361. SetBounds(gfx::Rect(GetPosition(), bounds.size()), false);
  362. #endif
  363. SetOwnedByWidget(false);
  364. RegisterDeleteDelegateCallback(base::BindOnce(
  365. [](NativeWindowViews* window) {
  366. if (window->is_modal() && window->parent()) {
  367. auto* parent = window->parent();
  368. // Enable parent window after current window gets closed.
  369. static_cast<NativeWindowViews*>(parent)->DecrementChildModals();
  370. // Focus on parent window.
  371. parent->Focus(true);
  372. }
  373. window->NotifyWindowClosed();
  374. },
  375. this));
  376. }
  377. NativeWindowViews::~NativeWindowViews() {
  378. widget()->RemoveObserver(this);
  379. #if BUILDFLAG(IS_WIN)
  380. // Disable mouse forwarding to relinquish resources, should any be held.
  381. SetForwardMouseMessages(false);
  382. #endif
  383. aura::Window* window = GetNativeWindow();
  384. if (window)
  385. window->RemovePreTargetHandler(this);
  386. }
  387. void NativeWindowViews::SetGTKDarkThemeEnabled(bool use_dark_theme) {
  388. #if BUILDFLAG(IS_LINUX)
  389. if (IsX11()) {
  390. const std::string color = use_dark_theme ? "dark" : "light";
  391. auto* connection = x11::Connection::Get();
  392. connection->SetStringProperty(
  393. static_cast<x11::Window>(GetAcceleratedWidget()),
  394. x11::GetAtom("_GTK_THEME_VARIANT"), x11::GetAtom("UTF8_STRING"), color);
  395. }
  396. #endif
  397. }
  398. void NativeWindowViews::SetContentView(views::View* view) {
  399. if (content_view()) {
  400. root_view_.GetMainView()->RemoveChildView(content_view());
  401. }
  402. set_content_view(view);
  403. focused_view_ = view;
  404. root_view_.GetMainView()->AddChildView(content_view());
  405. root_view_.GetMainView()->DeprecatedLayoutImmediately();
  406. }
  407. void NativeWindowViews::Close() {
  408. if (!IsClosable()) {
  409. WindowList::WindowCloseCancelled(this);
  410. return;
  411. }
  412. widget()->Close();
  413. }
  414. void NativeWindowViews::CloseImmediately() {
  415. widget()->CloseNow();
  416. }
  417. void NativeWindowViews::Focus(bool focus) {
  418. // For hidden window focus() should do nothing.
  419. if (!IsVisible())
  420. return;
  421. if (focus) {
  422. widget()->Activate();
  423. } else {
  424. widget()->Deactivate();
  425. }
  426. }
  427. bool NativeWindowViews::IsFocused() const {
  428. return widget()->IsActive();
  429. }
  430. void NativeWindowViews::Show() {
  431. if (is_modal() && NativeWindow::parent() &&
  432. !widget()->native_widget_private()->IsVisible())
  433. static_cast<NativeWindowViews*>(parent())->IncrementChildModals();
  434. widget()->native_widget_private()->Show(GetRestoredState(), gfx::Rect());
  435. // explicitly focus the window
  436. widget()->Activate();
  437. NotifyWindowShow();
  438. #if BUILDFLAG(IS_LINUX)
  439. if (global_menu_bar_)
  440. global_menu_bar_->OnWindowMapped();
  441. // On X11, setting Z order before showing the window doesn't take effect,
  442. // so we have to call it again.
  443. if (IsX11())
  444. widget()->SetZOrderLevel(widget()->GetZOrderLevel());
  445. #endif
  446. }
  447. void NativeWindowViews::ShowInactive() {
  448. widget()->ShowInactive();
  449. NotifyWindowShow();
  450. #if BUILDFLAG(IS_LINUX)
  451. if (global_menu_bar_)
  452. global_menu_bar_->OnWindowMapped();
  453. #endif
  454. }
  455. void NativeWindowViews::Hide() {
  456. if (is_modal() && NativeWindow::parent())
  457. static_cast<NativeWindowViews*>(parent())->DecrementChildModals();
  458. widget()->Hide();
  459. NotifyWindowHide();
  460. #if BUILDFLAG(IS_LINUX)
  461. if (global_menu_bar_)
  462. global_menu_bar_->OnWindowUnmapped();
  463. #endif
  464. #if BUILDFLAG(IS_WIN)
  465. // When the window is removed from the taskbar via win.hide(),
  466. // the thumbnail buttons need to be set up again.
  467. // Ensure that when the window is hidden,
  468. // the taskbar host is notified that it should re-add them.
  469. taskbar_host_.SetThumbarButtonsAdded(false);
  470. #endif
  471. }
  472. bool NativeWindowViews::IsVisible() const {
  473. #if BUILDFLAG(IS_WIN)
  474. // widget()->IsVisible() calls ::IsWindowVisible, which returns non-zero if a
  475. // window or any of its parent windows are visible. We want to only check the
  476. // current window.
  477. bool visible =
  478. ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_VISIBLE;
  479. // WS_VISIBLE is true even if a window is miminized - explicitly check that.
  480. return visible && !IsMinimized();
  481. #else
  482. return widget()->IsVisible();
  483. #endif
  484. }
  485. bool NativeWindowViews::IsEnabled() const {
  486. #if BUILDFLAG(IS_WIN)
  487. return ::IsWindowEnabled(GetAcceleratedWidget());
  488. #elif BUILDFLAG(IS_LINUX)
  489. if (IsX11())
  490. return !event_disabler_.get();
  491. NOTIMPLEMENTED();
  492. return true;
  493. #endif
  494. }
  495. void NativeWindowViews::IncrementChildModals() {
  496. num_modal_children_++;
  497. SetEnabledInternal(ShouldBeEnabled());
  498. }
  499. void NativeWindowViews::DecrementChildModals() {
  500. if (num_modal_children_ > 0) {
  501. num_modal_children_--;
  502. }
  503. SetEnabledInternal(ShouldBeEnabled());
  504. }
  505. void NativeWindowViews::SetEnabled(bool enable) {
  506. if (enable != is_enabled_) {
  507. is_enabled_ = enable;
  508. SetEnabledInternal(ShouldBeEnabled());
  509. }
  510. }
  511. bool NativeWindowViews::ShouldBeEnabled() const {
  512. return is_enabled_ && (num_modal_children_ == 0);
  513. }
  514. void NativeWindowViews::SetEnabledInternal(bool enable) {
  515. if (enable && IsEnabled()) {
  516. return;
  517. } else if (!enable && !IsEnabled()) {
  518. return;
  519. }
  520. #if BUILDFLAG(IS_WIN)
  521. ::EnableWindow(GetAcceleratedWidget(), enable);
  522. #else
  523. if (IsX11()) {
  524. views::DesktopWindowTreeHostPlatform* tree_host =
  525. views::DesktopWindowTreeHostLinux::GetHostForWidget(
  526. GetAcceleratedWidget());
  527. if (enable) {
  528. tree_host->RemoveEventRewriter(event_disabler_.get());
  529. event_disabler_.reset();
  530. } else {
  531. event_disabler_ = std::make_unique<EventDisabler>();
  532. tree_host->AddEventRewriter(event_disabler_.get());
  533. }
  534. }
  535. #endif
  536. }
  537. #if BUILDFLAG(IS_LINUX)
  538. void NativeWindowViews::Maximize() {
  539. if (IsVisible()) {
  540. widget()->Maximize();
  541. } else {
  542. widget()->native_widget_private()->Show(ui::SHOW_STATE_MAXIMIZED,
  543. gfx::Rect());
  544. NotifyWindowShow();
  545. }
  546. }
  547. #endif
  548. void NativeWindowViews::Unmaximize() {
  549. if (IsMaximized()) {
  550. #if BUILDFLAG(IS_WIN)
  551. if (transparent()) {
  552. SetBounds(restore_bounds_, false);
  553. NotifyWindowUnmaximize();
  554. UpdateThickFrame();
  555. return;
  556. }
  557. #endif
  558. widget()->Restore();
  559. #if BUILDFLAG(IS_WIN)
  560. UpdateThickFrame();
  561. #endif
  562. }
  563. }
  564. bool NativeWindowViews::IsMaximized() const {
  565. if (widget()->IsMaximized()) {
  566. return true;
  567. } else {
  568. #if BUILDFLAG(IS_WIN)
  569. if (transparent() && !IsMinimized()) {
  570. // Compare the size of the window with the size of the display
  571. auto display = display::Screen::GetScreen()->GetDisplayNearestWindow(
  572. GetNativeWindow());
  573. // Maximized if the window is the same dimensions and placement as the
  574. // display
  575. return GetBounds() == display.work_area();
  576. }
  577. #endif
  578. return false;
  579. }
  580. }
  581. void NativeWindowViews::Minimize() {
  582. if (IsVisible())
  583. widget()->Minimize();
  584. else
  585. widget()->native_widget_private()->Show(ui::SHOW_STATE_MINIMIZED,
  586. gfx::Rect());
  587. }
  588. void NativeWindowViews::Restore() {
  589. widget()->Restore();
  590. #if BUILDFLAG(IS_WIN)
  591. UpdateThickFrame();
  592. #endif
  593. }
  594. bool NativeWindowViews::IsMinimized() const {
  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() const {
  669. #if BUILDFLAG(IS_WIN)
  670. if (IsMinimized())
  671. return widget()->GetRestoredBounds();
  672. #endif
  673. return widget()->GetWindowBoundsInScreen();
  674. }
  675. gfx::Rect NativeWindowViews::GetContentBounds() const {
  676. return content_view() ? content_view()->GetBoundsInScreen() : gfx::Rect();
  677. }
  678. gfx::Size NativeWindowViews::GetContentSize() const {
  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() const {
  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. resizable_ = resizable;
  746. SetCanResize(resizable_);
  747. #if BUILDFLAG(IS_WIN)
  748. UpdateThickFrame();
  749. #endif
  750. }
  751. bool NativeWindowViews::MoveAbove(const std::string& sourceId) {
  752. const content::DesktopMediaID id = content::DesktopMediaID::Parse(sourceId);
  753. if (id.type != content::DesktopMediaID::TYPE_WINDOW)
  754. return false;
  755. #if BUILDFLAG(IS_WIN)
  756. const HWND otherWindow = reinterpret_cast<HWND>(id.id);
  757. if (!::IsWindow(otherWindow))
  758. return false;
  759. ::SetWindowPos(GetAcceleratedWidget(), GetWindow(otherWindow, GW_HWNDPREV), 0,
  760. 0, 0, 0,
  761. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  762. #else
  763. if (IsX11()) {
  764. if (!IsWindowValid(static_cast<x11::Window>(id.id)))
  765. return false;
  766. electron::MoveWindowAbove(static_cast<x11::Window>(GetAcceleratedWidget()),
  767. static_cast<x11::Window>(id.id));
  768. }
  769. #endif
  770. return true;
  771. }
  772. void NativeWindowViews::MoveTop() {
  773. // TODO(julien.isorce): fix chromium in order to use existing
  774. // widget()->StackAtTop().
  775. #if BUILDFLAG(IS_WIN)
  776. gfx::Point pos = GetPosition();
  777. gfx::Size size = GetSize();
  778. ::SetWindowPos(GetAcceleratedWidget(), HWND_TOP, pos.x(), pos.y(),
  779. size.width(), size.height(),
  780. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  781. #else
  782. if (IsX11())
  783. electron::MoveWindowToForeground(
  784. static_cast<x11::Window>(GetAcceleratedWidget()));
  785. #endif
  786. }
  787. bool NativeWindowViews::IsResizable() const {
  788. #if BUILDFLAG(IS_WIN)
  789. if (has_frame())
  790. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
  791. #endif
  792. return resizable_;
  793. }
  794. void NativeWindowViews::SetAspectRatio(double aspect_ratio,
  795. const gfx::Size& extra_size) {
  796. NativeWindow::SetAspectRatio(aspect_ratio, extra_size);
  797. gfx::SizeF aspect(aspect_ratio, 1.0);
  798. // Scale up because SetAspectRatio() truncates aspect value to int
  799. aspect.Scale(100);
  800. widget()->SetAspectRatio(aspect);
  801. }
  802. void NativeWindowViews::SetMovable(bool movable) {
  803. movable_ = movable;
  804. }
  805. bool NativeWindowViews::IsMovable() const {
  806. #if BUILDFLAG(IS_WIN)
  807. return movable_;
  808. #else
  809. return true; // Not implemented on Linux.
  810. #endif
  811. }
  812. void NativeWindowViews::SetMinimizable(bool minimizable) {
  813. #if BUILDFLAG(IS_WIN)
  814. FlipWindowStyle(GetAcceleratedWidget(), minimizable, WS_MINIMIZEBOX);
  815. if (IsWindowControlsOverlayEnabled()) {
  816. auto* frame_view =
  817. static_cast<WinFrameView*>(widget()->non_client_view()->frame_view());
  818. frame_view->caption_button_container()->UpdateButtons();
  819. }
  820. #endif
  821. minimizable_ = minimizable;
  822. }
  823. bool NativeWindowViews::IsMinimizable() const {
  824. #if BUILDFLAG(IS_WIN)
  825. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MINIMIZEBOX;
  826. #else
  827. return true; // Not implemented on Linux.
  828. #endif
  829. }
  830. void NativeWindowViews::SetMaximizable(bool maximizable) {
  831. #if BUILDFLAG(IS_WIN)
  832. FlipWindowStyle(GetAcceleratedWidget(), maximizable, WS_MAXIMIZEBOX);
  833. if (IsWindowControlsOverlayEnabled()) {
  834. auto* frame_view =
  835. static_cast<WinFrameView*>(widget()->non_client_view()->frame_view());
  836. frame_view->caption_button_container()->UpdateButtons();
  837. }
  838. #endif
  839. maximizable_ = maximizable;
  840. }
  841. bool NativeWindowViews::IsMaximizable() const {
  842. #if BUILDFLAG(IS_WIN)
  843. return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_MAXIMIZEBOX;
  844. #else
  845. return true; // Not implemented on Linux.
  846. #endif
  847. }
  848. void NativeWindowViews::SetExcludedFromShownWindowsMenu(bool excluded) {}
  849. bool NativeWindowViews::IsExcludedFromShownWindowsMenu() const {
  850. // return false on unsupported platforms
  851. return false;
  852. }
  853. void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
  854. fullscreenable_ = fullscreenable;
  855. }
  856. bool NativeWindowViews::IsFullScreenable() const {
  857. return fullscreenable_;
  858. }
  859. void NativeWindowViews::SetClosable(bool closable) {
  860. #if BUILDFLAG(IS_WIN)
  861. HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
  862. if (closable) {
  863. EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
  864. } else {
  865. EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  866. }
  867. if (IsWindowControlsOverlayEnabled()) {
  868. auto* frame_view =
  869. static_cast<WinFrameView*>(widget()->non_client_view()->frame_view());
  870. frame_view->caption_button_container()->UpdateButtons();
  871. }
  872. #endif
  873. }
  874. bool NativeWindowViews::IsClosable() const {
  875. #if BUILDFLAG(IS_WIN)
  876. HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
  877. MENUITEMINFO info;
  878. memset(&info, 0, sizeof(info));
  879. info.cbSize = sizeof(info);
  880. info.fMask = MIIM_STATE;
  881. if (!GetMenuItemInfo(menu, SC_CLOSE, false, &info)) {
  882. return false;
  883. }
  884. return !(info.fState & MFS_DISABLED);
  885. #elif BUILDFLAG(IS_LINUX)
  886. return true;
  887. #endif
  888. }
  889. void NativeWindowViews::SetAlwaysOnTop(ui::ZOrderLevel z_order,
  890. const std::string& level,
  891. int relativeLevel) {
  892. bool level_changed = z_order != widget()->GetZOrderLevel();
  893. widget()->SetZOrderLevel(z_order);
  894. #if BUILDFLAG(IS_WIN)
  895. // Reset the placement flag.
  896. behind_task_bar_ = false;
  897. if (z_order != ui::ZOrderLevel::kNormal) {
  898. // On macOS the window is placed behind the Dock for the following levels.
  899. // Re-use the same names on Windows to make it easier for the user.
  900. static const std::vector<std::string> levels = {
  901. "floating", "torn-off-menu", "modal-panel", "main-menu", "status"};
  902. behind_task_bar_ = base::Contains(levels, level);
  903. }
  904. #endif
  905. MoveBehindTaskBarIfNeeded();
  906. // This must be notified at the very end or IsAlwaysOnTop
  907. // will not yet have been updated to reflect the new status
  908. if (level_changed)
  909. NativeWindow::NotifyWindowAlwaysOnTopChanged();
  910. }
  911. ui::ZOrderLevel NativeWindowViews::GetZOrderLevel() const {
  912. return widget()->GetZOrderLevel();
  913. }
  914. // We previous called widget()->CenterWindow() here, but in
  915. // Chromium CL 4916277 behavior was changed to center relative to the
  916. // parent window if there is one. We want to keep the old behavior
  917. // for now to avoid breaking API contract, but should consider the long
  918. // term plan for this aligning with upstream.
  919. void NativeWindowViews::Center() {
  920. #if BUILDFLAG(IS_LINUX)
  921. auto display =
  922. display::Screen::GetScreen()->GetDisplayNearestWindow(GetNativeWindow());
  923. gfx::Rect window_bounds_in_screen = display.work_area();
  924. window_bounds_in_screen.ClampToCenteredSize(GetSize());
  925. widget()->SetBounds(window_bounds_in_screen);
  926. #else
  927. HWND hwnd = GetAcceleratedWidget();
  928. gfx::Size size = display::win::ScreenWin::DIPToScreenSize(hwnd, GetSize());
  929. gfx::CenterAndSizeWindow(nullptr, hwnd, size);
  930. #endif
  931. }
  932. void NativeWindowViews::Invalidate() {
  933. widget()->SchedulePaintInRect(gfx::Rect(GetBounds().size()));
  934. }
  935. void NativeWindowViews::SetTitle(const std::string& title) {
  936. title_ = title;
  937. widget()->UpdateWindowTitle();
  938. }
  939. std::string NativeWindowViews::GetTitle() const {
  940. return title_;
  941. }
  942. void NativeWindowViews::FlashFrame(bool flash) {
  943. #if BUILDFLAG(IS_WIN)
  944. // The Chromium's implementation has a bug stopping flash.
  945. if (!flash) {
  946. FLASHWINFO fwi;
  947. fwi.cbSize = sizeof(fwi);
  948. fwi.hwnd = GetAcceleratedWidget();
  949. fwi.dwFlags = FLASHW_STOP;
  950. fwi.uCount = 0;
  951. FlashWindowEx(&fwi);
  952. return;
  953. }
  954. #endif
  955. widget()->FlashFrame(flash);
  956. }
  957. void NativeWindowViews::SetSkipTaskbar(bool skip) {
  958. #if BUILDFLAG(IS_WIN)
  959. Microsoft::WRL::ComPtr<ITaskbarList> taskbar;
  960. if (FAILED(::CoCreateInstance(CLSID_TaskbarList, nullptr,
  961. CLSCTX_INPROC_SERVER,
  962. IID_PPV_ARGS(&taskbar))) ||
  963. FAILED(taskbar->HrInit()))
  964. return;
  965. if (skip) {
  966. taskbar->DeleteTab(GetAcceleratedWidget());
  967. } else {
  968. taskbar->AddTab(GetAcceleratedWidget());
  969. taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget());
  970. }
  971. #endif
  972. }
  973. void NativeWindowViews::SetSimpleFullScreen(bool simple_fullscreen) {
  974. SetFullScreen(simple_fullscreen);
  975. }
  976. bool NativeWindowViews::IsSimpleFullScreen() const {
  977. return IsFullscreen();
  978. }
  979. void NativeWindowViews::SetKiosk(bool kiosk) {
  980. SetFullScreen(kiosk);
  981. }
  982. bool NativeWindowViews::IsKiosk() const {
  983. return IsFullscreen();
  984. }
  985. bool NativeWindowViews::IsTabletMode() const {
  986. #if BUILDFLAG(IS_WIN)
  987. return base::win::IsWindows10OrGreaterTabletMode(GetAcceleratedWidget());
  988. #else
  989. return false;
  990. #endif
  991. }
  992. SkColor NativeWindowViews::GetBackgroundColor() const {
  993. auto* background = root_view_.background();
  994. if (!background)
  995. return SK_ColorTRANSPARENT;
  996. return background->get_color();
  997. }
  998. void NativeWindowViews::SetBackgroundColor(SkColor background_color) {
  999. // web views' background color.
  1000. root_view_.SetBackground(views::CreateSolidBackground(background_color));
  1001. #if BUILDFLAG(IS_WIN)
  1002. // Set the background color of native window.
  1003. HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color));
  1004. ULONG_PTR previous_brush =
  1005. SetClassLongPtr(GetAcceleratedWidget(), GCLP_HBRBACKGROUND,
  1006. reinterpret_cast<LONG_PTR>(brush));
  1007. if (previous_brush)
  1008. DeleteObject((HBRUSH)previous_brush);
  1009. InvalidateRect(GetAcceleratedWidget(), nullptr, 1);
  1010. #endif
  1011. }
  1012. void NativeWindowViews::SetHasShadow(bool has_shadow) {
  1013. wm::SetShadowElevation(GetNativeWindow(),
  1014. has_shadow ? wm::kShadowElevationInactiveWindow
  1015. : wm::kShadowElevationNone);
  1016. }
  1017. bool NativeWindowViews::HasShadow() const {
  1018. return GetNativeWindow()->GetProperty(wm::kShadowElevationKey) !=
  1019. wm::kShadowElevationNone;
  1020. }
  1021. void NativeWindowViews::SetOpacity(const double opacity) {
  1022. #if BUILDFLAG(IS_WIN)
  1023. const double boundedOpacity = std::clamp(opacity, 0.0, 1.0);
  1024. HWND hwnd = GetAcceleratedWidget();
  1025. if (!layered_) {
  1026. LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  1027. ex_style |= WS_EX_LAYERED;
  1028. ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
  1029. layered_ = true;
  1030. }
  1031. ::SetLayeredWindowAttributes(hwnd, 0, boundedOpacity * 255, LWA_ALPHA);
  1032. opacity_ = boundedOpacity;
  1033. #else
  1034. opacity_ = 1.0; // setOpacity unsupported on Linux
  1035. #endif
  1036. }
  1037. double NativeWindowViews::GetOpacity() const {
  1038. return opacity_;
  1039. }
  1040. void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
  1041. #if BUILDFLAG(IS_WIN)
  1042. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  1043. if (ignore)
  1044. ex_style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
  1045. else
  1046. ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
  1047. if (layered_)
  1048. ex_style |= WS_EX_LAYERED;
  1049. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  1050. // Forwarding is always disabled when not ignoring mouse messages.
  1051. if (!ignore) {
  1052. SetForwardMouseMessages(false);
  1053. } else {
  1054. SetForwardMouseMessages(forward);
  1055. }
  1056. #else
  1057. if (IsX11()) {
  1058. auto* connection = x11::Connection::Get();
  1059. if (ignore) {
  1060. x11::Rectangle r{0, 0, 1, 1};
  1061. connection->shape().Rectangles({
  1062. .operation = x11::Shape::So::Set,
  1063. .destination_kind = x11::Shape::Sk::Input,
  1064. .ordering = x11::ClipOrdering::YXBanded,
  1065. .destination_window =
  1066. static_cast<x11::Window>(GetAcceleratedWidget()),
  1067. .rectangles = {r},
  1068. });
  1069. } else {
  1070. connection->shape().Mask({
  1071. .operation = x11::Shape::So::Set,
  1072. .destination_kind = x11::Shape::Sk::Input,
  1073. .destination_window =
  1074. static_cast<x11::Window>(GetAcceleratedWidget()),
  1075. .source_bitmap = x11::Pixmap::None,
  1076. });
  1077. }
  1078. }
  1079. #endif
  1080. }
  1081. void NativeWindowViews::SetContentProtection(bool enable) {
  1082. #if BUILDFLAG(IS_WIN)
  1083. HWND hwnd = GetAcceleratedWidget();
  1084. DWORD affinity = enable ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE;
  1085. ::SetWindowDisplayAffinity(hwnd, affinity);
  1086. if (!layered_) {
  1087. // Workaround to prevent black window on screen capture after hiding and
  1088. // showing the BrowserWindow.
  1089. LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
  1090. ex_style |= WS_EX_LAYERED;
  1091. ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
  1092. layered_ = true;
  1093. }
  1094. #endif
  1095. }
  1096. void NativeWindowViews::SetFocusable(bool focusable) {
  1097. widget()->widget_delegate()->SetCanActivate(focusable);
  1098. #if BUILDFLAG(IS_WIN)
  1099. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  1100. if (focusable)
  1101. ex_style &= ~WS_EX_NOACTIVATE;
  1102. else
  1103. ex_style |= WS_EX_NOACTIVATE;
  1104. ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
  1105. SetSkipTaskbar(!focusable);
  1106. Focus(false);
  1107. #endif
  1108. }
  1109. bool NativeWindowViews::IsFocusable() const {
  1110. bool can_activate = widget()->widget_delegate()->CanActivate();
  1111. #if BUILDFLAG(IS_WIN)
  1112. LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
  1113. bool no_activate = ex_style & WS_EX_NOACTIVATE;
  1114. return !no_activate && can_activate;
  1115. #else
  1116. return can_activate;
  1117. #endif
  1118. }
  1119. void NativeWindowViews::SetMenu(ElectronMenuModel* menu_model) {
  1120. #if BUILDFLAG(IS_LINUX)
  1121. // Remove global menu bar.
  1122. if (global_menu_bar_ && menu_model == nullptr) {
  1123. global_menu_bar_.reset();
  1124. root_view_.UnregisterAcceleratorsWithFocusManager();
  1125. return;
  1126. }
  1127. // Use global application menu bar when possible.
  1128. bool can_use_global_menus = ui::OzonePlatform::GetInstance()
  1129. ->GetPlatformProperties()
  1130. .supports_global_application_menus;
  1131. if (can_use_global_menus && ShouldUseGlobalMenuBar()) {
  1132. if (!global_menu_bar_)
  1133. global_menu_bar_ = std::make_unique<GlobalMenuBarX11>(this);
  1134. if (global_menu_bar_->IsServerStarted()) {
  1135. root_view_.RegisterAcceleratorsWithFocusManager(menu_model);
  1136. global_menu_bar_->SetMenu(menu_model);
  1137. return;
  1138. }
  1139. }
  1140. #endif
  1141. // Should reset content size when setting menu.
  1142. gfx::Size content_size = GetContentSize();
  1143. bool should_reset_size = use_content_size_ && has_frame() &&
  1144. !IsMenuBarAutoHide() &&
  1145. ((!!menu_model) != root_view_.HasMenu());
  1146. root_view_.SetMenu(menu_model);
  1147. if (should_reset_size) {
  1148. // Enlarge the size constraints for the menu.
  1149. int menu_bar_height = root_view_.GetMenuBarHeight();
  1150. extensions::SizeConstraints constraints = GetContentSizeConstraints();
  1151. if (constraints.HasMinimumSize()) {
  1152. gfx::Size min_size = constraints.GetMinimumSize();
  1153. min_size.set_height(min_size.height() + menu_bar_height);
  1154. constraints.set_minimum_size(min_size);
  1155. }
  1156. if (constraints.HasMaximumSize()) {
  1157. gfx::Size max_size = constraints.GetMaximumSize();
  1158. max_size.set_height(max_size.height() + menu_bar_height);
  1159. constraints.set_maximum_size(max_size);
  1160. }
  1161. SetContentSizeConstraints(constraints);
  1162. // Resize the window to make sure content size is not changed.
  1163. SetContentSize(content_size);
  1164. }
  1165. }
  1166. void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
  1167. NativeWindow::SetParentWindow(parent);
  1168. #if BUILDFLAG(IS_LINUX)
  1169. if (IsX11()) {
  1170. auto* connection = x11::Connection::Get();
  1171. connection->SetProperty(
  1172. static_cast<x11::Window>(GetAcceleratedWidget()),
  1173. x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW,
  1174. parent ? static_cast<x11::Window>(parent->GetAcceleratedWidget())
  1175. : ui::GetX11RootWindow());
  1176. }
  1177. #elif BUILDFLAG(IS_WIN)
  1178. // To set parentship between windows into Windows is better to play with the
  1179. // owner instead of the parent, as Windows natively seems to do if a parent
  1180. // is specified at window creation time.
  1181. // For do this we must NOT use the ::SetParent function, instead we must use
  1182. // the ::GetWindowLongPtr or ::SetWindowLongPtr functions with "nIndex" set
  1183. // to "GWLP_HWNDPARENT" which actually means the window owner.
  1184. HWND hwndParent = parent ? parent->GetAcceleratedWidget() : nullptr;
  1185. if (hwndParent ==
  1186. (HWND)::GetWindowLongPtr(GetAcceleratedWidget(), GWLP_HWNDPARENT))
  1187. return;
  1188. ::SetWindowLongPtr(GetAcceleratedWidget(), GWLP_HWNDPARENT,
  1189. (LONG_PTR)hwndParent);
  1190. // Ensures the visibility
  1191. if (IsVisible()) {
  1192. WINDOWPLACEMENT wp;
  1193. wp.length = sizeof(WINDOWPLACEMENT);
  1194. ::GetWindowPlacement(GetAcceleratedWidget(), &wp);
  1195. ::ShowWindow(GetAcceleratedWidget(), SW_HIDE);
  1196. ::ShowWindow(GetAcceleratedWidget(), wp.showCmd);
  1197. ::BringWindowToTop(GetAcceleratedWidget());
  1198. }
  1199. #endif
  1200. }
  1201. gfx::NativeView NativeWindowViews::GetNativeView() const {
  1202. return widget()->GetNativeView();
  1203. }
  1204. gfx::NativeWindow NativeWindowViews::GetNativeWindow() const {
  1205. return widget()->GetNativeWindow();
  1206. }
  1207. void NativeWindowViews::SetProgressBar(double progress,
  1208. NativeWindow::ProgressState state) {
  1209. #if BUILDFLAG(IS_WIN)
  1210. taskbar_host_.SetProgressBar(GetAcceleratedWidget(), progress, state);
  1211. #elif BUILDFLAG(IS_LINUX)
  1212. if (unity::IsRunning()) {
  1213. unity::SetProgressFraction(progress);
  1214. }
  1215. #endif
  1216. }
  1217. void NativeWindowViews::SetOverlayIcon(const gfx::Image& overlay,
  1218. const std::string& description) {
  1219. #if BUILDFLAG(IS_WIN)
  1220. SkBitmap overlay_bitmap = overlay.AsBitmap();
  1221. taskbar_host_.SetOverlayIcon(GetAcceleratedWidget(), overlay_bitmap,
  1222. description);
  1223. #endif
  1224. }
  1225. void NativeWindowViews::SetAutoHideMenuBar(bool auto_hide) {
  1226. root_view_.SetAutoHideMenuBar(auto_hide);
  1227. }
  1228. bool NativeWindowViews::IsMenuBarAutoHide() const {
  1229. return root_view_.is_menu_bar_auto_hide();
  1230. }
  1231. void NativeWindowViews::SetMenuBarVisibility(bool visible) {
  1232. root_view_.SetMenuBarVisibility(visible);
  1233. }
  1234. bool NativeWindowViews::IsMenuBarVisible() const {
  1235. return root_view_.is_menu_bar_visible();
  1236. }
  1237. void NativeWindowViews::SetBackgroundMaterial(const std::string& material) {
  1238. NativeWindow::SetBackgroundMaterial(material);
  1239. #if BUILDFLAG(IS_WIN)
  1240. // DWMWA_USE_HOSTBACKDROPBRUSH is only supported on Windows 11 22H2 and up.
  1241. if (base::win::GetVersion() < base::win::Version::WIN11_22H2)
  1242. return;
  1243. DWM_SYSTEMBACKDROP_TYPE backdrop_type = GetBackdropFromString(material);
  1244. HRESULT result =
  1245. DwmSetWindowAttribute(GetAcceleratedWidget(), DWMWA_SYSTEMBACKDROP_TYPE,
  1246. &backdrop_type, sizeof(backdrop_type));
  1247. if (FAILED(result))
  1248. LOG(WARNING) << "Failed to set background material to " << material;
  1249. // For frameless windows with a background material set, we also need to
  1250. // remove the caption color so it doesn't render a caption bar (since the
  1251. // window is frameless)
  1252. COLORREF caption_color = DWMWA_COLOR_DEFAULT;
  1253. if (backdrop_type != DWMSBT_NONE && backdrop_type != DWMSBT_AUTO &&
  1254. !has_frame()) {
  1255. caption_color = DWMWA_COLOR_NONE;
  1256. }
  1257. result = DwmSetWindowAttribute(GetAcceleratedWidget(), DWMWA_CAPTION_COLOR,
  1258. &caption_color, sizeof(caption_color));
  1259. if (FAILED(result))
  1260. LOG(WARNING) << "Failed to set caption color to transparent";
  1261. #endif
  1262. }
  1263. void NativeWindowViews::SetVisibleOnAllWorkspaces(
  1264. bool visible,
  1265. bool visibleOnFullScreen,
  1266. bool skipTransformProcessType) {
  1267. widget()->SetVisibleOnAllWorkspaces(visible);
  1268. }
  1269. bool NativeWindowViews::IsVisibleOnAllWorkspaces() const {
  1270. #if BUILDFLAG(IS_LINUX)
  1271. if (IsX11()) {
  1272. // Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to
  1273. // determine whether the current window is visible on all workspaces.
  1274. x11::Atom sticky_atom = x11::GetAtom("_NET_WM_STATE_STICKY");
  1275. std::vector<x11::Atom> wm_states;
  1276. auto* connection = x11::Connection::Get();
  1277. connection->GetArrayProperty(
  1278. 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_.is_menu_bar_visible()) {
  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_.is_menu_bar_visible()) {
  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. #if BUILDFLAG(IS_WIN)
  1386. void NativeWindowViews::UpdateThickFrame() {
  1387. if (!thick_frame_)
  1388. return;
  1389. if (IsMaximized() && !transparent()) {
  1390. // For maximized window add thick frame always, otherwise it will be removed
  1391. // in HWNDMessageHandler::SizeConstraintsChanged() which will result in
  1392. // maximized window bounds change.
  1393. FlipWindowStyle(GetAcceleratedWidget(), true, WS_THICKFRAME);
  1394. } else if (has_frame()) {
  1395. FlipWindowStyle(GetAcceleratedWidget(), resizable_, WS_THICKFRAME);
  1396. }
  1397. }
  1398. #endif
  1399. void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
  1400. bool active) {
  1401. if (changed_widget != widget())
  1402. return;
  1403. if (active) {
  1404. MoveBehindTaskBarIfNeeded();
  1405. NativeWindow::NotifyWindowFocus();
  1406. } else {
  1407. NativeWindow::NotifyWindowBlur();
  1408. }
  1409. // Hide menu bar when window is blurred.
  1410. if (!active && IsMenuBarAutoHide() && IsMenuBarVisible())
  1411. SetMenuBarVisibility(false);
  1412. root_view_.ResetAltState();
  1413. }
  1414. void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
  1415. const gfx::Rect& bounds) {
  1416. if (changed_widget != widget())
  1417. return;
  1418. // Note: We intentionally use `GetBounds()` instead of `bounds` to properly
  1419. // handle minimized windows on Windows.
  1420. const auto new_bounds = GetBounds();
  1421. if (widget_size_ != new_bounds.size()) {
  1422. NotifyWindowResize();
  1423. widget_size_ = new_bounds.size();
  1424. }
  1425. }
  1426. void NativeWindowViews::OnWidgetDestroying(views::Widget* widget) {
  1427. aura::Window* window = GetNativeWindow();
  1428. if (window)
  1429. window->RemovePreTargetHandler(this);
  1430. }
  1431. void NativeWindowViews::OnWidgetDestroyed(views::Widget* changed_widget) {
  1432. widget_destroyed_ = true;
  1433. }
  1434. views::View* NativeWindowViews::GetInitiallyFocusedView() {
  1435. return focused_view_;
  1436. }
  1437. bool NativeWindowViews::CanMaximize() const {
  1438. return resizable_ && maximizable_;
  1439. }
  1440. bool NativeWindowViews::CanMinimize() const {
  1441. #if BUILDFLAG(IS_WIN)
  1442. return minimizable_;
  1443. #elif BUILDFLAG(IS_LINUX)
  1444. return true;
  1445. #endif
  1446. }
  1447. std::u16string NativeWindowViews::GetWindowTitle() const {
  1448. return base::UTF8ToUTF16(title_);
  1449. }
  1450. views::View* NativeWindowViews::GetContentsView() {
  1451. return root_view_.GetMainView();
  1452. }
  1453. bool NativeWindowViews::ShouldDescendIntoChildForEventHandling(
  1454. gfx::NativeView child,
  1455. const gfx::Point& location) {
  1456. return NonClientHitTest(location) == HTNOWHERE;
  1457. }
  1458. views::ClientView* NativeWindowViews::CreateClientView(views::Widget* widget) {
  1459. return new NativeWindowClientView{widget, &root_view_, this};
  1460. }
  1461. std::unique_ptr<views::NonClientFrameView>
  1462. NativeWindowViews::CreateNonClientFrameView(views::Widget* widget) {
  1463. #if BUILDFLAG(IS_WIN)
  1464. auto frame_view = std::make_unique<WinFrameView>();
  1465. frame_view->Init(this, widget);
  1466. return frame_view;
  1467. #else
  1468. if (has_frame() && !has_client_frame()) {
  1469. return std::make_unique<NativeFrameView>(this, widget);
  1470. } else {
  1471. if (has_frame() && has_client_frame()) {
  1472. auto frame_view = std::make_unique<ClientFrameViewLinux>();
  1473. frame_view->Init(this, widget);
  1474. return frame_view;
  1475. } else {
  1476. auto frame_view = std::make_unique<OpaqueFrameView>();
  1477. frame_view->Init(this, widget);
  1478. return frame_view;
  1479. }
  1480. }
  1481. #endif
  1482. }
  1483. void NativeWindowViews::OnWidgetMove() {
  1484. NotifyWindowMove();
  1485. }
  1486. void NativeWindowViews::HandleKeyboardEvent(
  1487. content::WebContents*,
  1488. const input::NativeWebKeyboardEvent& event) {
  1489. if (widget_destroyed_)
  1490. return;
  1491. #if BUILDFLAG(IS_LINUX)
  1492. if (event.windows_key_code == ui::VKEY_BROWSER_BACK)
  1493. NotifyWindowExecuteAppCommand(kBrowserBackward);
  1494. else if (event.windows_key_code == ui::VKEY_BROWSER_FORWARD)
  1495. NotifyWindowExecuteAppCommand(kBrowserForward);
  1496. #endif
  1497. keyboard_event_handler_.HandleKeyboardEvent(event,
  1498. root_view_.GetFocusManager());
  1499. root_view_.HandleKeyEvent(event);
  1500. }
  1501. void NativeWindowViews::OnMouseEvent(ui::MouseEvent* event) {
  1502. if (event->type() != ui::EventType::kMousePressed)
  1503. return;
  1504. // Alt+Click should not toggle menu bar.
  1505. root_view_.ResetAltState();
  1506. #if BUILDFLAG(IS_LINUX)
  1507. if (event->changed_button_flags() == ui::EF_BACK_MOUSE_BUTTON)
  1508. NotifyWindowExecuteAppCommand(kBrowserBackward);
  1509. else if (event->changed_button_flags() == ui::EF_FORWARD_MOUSE_BUTTON)
  1510. NotifyWindowExecuteAppCommand(kBrowserForward);
  1511. #endif
  1512. }
  1513. ui::WindowShowState NativeWindowViews::GetRestoredState() {
  1514. if (IsMaximized()) {
  1515. #if BUILDFLAG(IS_WIN)
  1516. // Only restore Maximized state when window is NOT transparent style
  1517. if (!transparent()) {
  1518. return ui::SHOW_STATE_MAXIMIZED;
  1519. }
  1520. #else
  1521. return ui::SHOW_STATE_MAXIMIZED;
  1522. #endif
  1523. }
  1524. if (IsFullscreen())
  1525. return ui::SHOW_STATE_FULLSCREEN;
  1526. return ui::SHOW_STATE_NORMAL;
  1527. }
  1528. void NativeWindowViews::MoveBehindTaskBarIfNeeded() {
  1529. #if BUILDFLAG(IS_WIN)
  1530. if (behind_task_bar_) {
  1531. const HWND task_bar_hwnd = ::FindWindow(kUniqueTaskBarClassName, nullptr);
  1532. ::SetWindowPos(GetAcceleratedWidget(), task_bar_hwnd, 0, 0, 0, 0,
  1533. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1534. }
  1535. #endif
  1536. // TODO(julien.isorce): Implement X11 case.
  1537. }
  1538. // static
  1539. NativeWindow* NativeWindow::Create(const gin_helper::Dictionary& options,
  1540. NativeWindow* parent) {
  1541. return new NativeWindowViews(options, parent);
  1542. }
  1543. } // namespace electron