1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/aura/window_tree_host_win.h"
11 #include "base/message_loop/message_loop.h"
12 #include "ui/aura/client/cursor_client.h"
13 #include "ui/aura/root_window.h"
14 #include "ui/base/cursor/cursor_loader_win.h"
15 #include "ui/base/view_prop.h"
16 #include "ui/events/event.h"
17 #include "ui/gfx/display.h"
18 #include "ui/gfx/insets.h"
19 #include "ui/gfx/screen.h"
27 bool use_popup_as_root_window_for_test
= false;
32 WindowTreeHost
* WindowTreeHost::Create(const gfx::Rect
& bounds
) {
33 return new WindowTreeHostWin(bounds
);
37 gfx::Size
WindowTreeHost::GetNativeScreenSize() {
38 return gfx::Size(GetSystemMetrics(SM_CXSCREEN
),
39 GetSystemMetrics(SM_CYSCREEN
));
42 WindowTreeHostWin::WindowTreeHostWin(const gfx::Rect
& bounds
)
45 saved_window_style_(0),
46 saved_window_ex_style_(0) {
47 if (use_popup_as_root_window_for_test
)
48 set_window_style(WS_POPUP
);
50 SetWindowText(hwnd(), L
"aura::RootWindow!");
51 CreateCompositor(GetAcceleratedWidget());
54 WindowTreeHostWin::~WindowTreeHostWin() {
56 DestroyWindow(hwnd());
59 RootWindow
* WindowTreeHostWin::GetRootWindow() {
60 return delegate_
->AsRootWindow();
63 gfx::AcceleratedWidget
WindowTreeHostWin::GetAcceleratedWidget() {
67 void WindowTreeHostWin::Show() {
68 ShowWindow(hwnd(), SW_SHOWNORMAL
);
71 void WindowTreeHostWin::Hide() {
75 void WindowTreeHostWin::ToggleFullScreen() {
76 gfx::Rect target_rect
;
79 saved_window_style_
= GetWindowLong(hwnd(), GWL_STYLE
);
80 saved_window_ex_style_
= GetWindowLong(hwnd(), GWL_EXSTYLE
);
81 GetWindowRect(hwnd(), &saved_window_rect_
);
82 SetWindowLong(hwnd(), GWL_STYLE
,
83 saved_window_style_
& ~(WS_CAPTION
| WS_THICKFRAME
));
84 SetWindowLong(hwnd(), GWL_EXSTYLE
,
85 saved_window_ex_style_
& ~(WS_EX_DLGMODALFRAME
|
86 WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
| WS_EX_STATICEDGE
));
89 mi
.cbSize
= sizeof(mi
);
90 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST
), &mi
);
91 target_rect
= gfx::Rect(mi
.rcMonitor
);
94 SetWindowLong(hwnd(), GWL_STYLE
, saved_window_style_
);
95 SetWindowLong(hwnd(), GWL_EXSTYLE
, saved_window_ex_style_
);
96 target_rect
= gfx::Rect(saved_window_rect_
);
103 target_rect
.height(),
104 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
107 gfx::Rect
WindowTreeHostWin::GetBounds() const {
109 GetClientRect(hwnd(), &r
);
113 void WindowTreeHostWin::SetBounds(const gfx::Rect
& bounds
) {
115 saved_window_rect_
.right
= saved_window_rect_
.left
+ bounds
.width();
116 saved_window_rect_
.bottom
= saved_window_rect_
.top
+ bounds
.height();
120 window_rect
.left
= bounds
.x();
121 window_rect
.top
= bounds
.y();
122 window_rect
.right
= bounds
.right() ;
123 window_rect
.bottom
= bounds
.bottom();
124 AdjustWindowRectEx(&window_rect
,
125 GetWindowLong(hwnd(), GWL_STYLE
),
127 GetWindowLong(hwnd(), GWL_EXSTYLE
));
133 window_rect
.right
- window_rect
.left
,
134 window_rect
.bottom
- window_rect
.top
,
135 SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOREDRAW
| SWP_NOREPOSITION
);
137 // Explicity call NotifyHostResized when the scale has changed because
138 // the window size may not have changed.
139 float current_scale
= compositor()->device_scale_factor();
140 float new_scale
= gfx::Screen::GetScreenFor(
141 delegate_
->AsRootWindow()->window())->GetDisplayNearestWindow(
142 delegate_
->AsRootWindow()->window()).device_scale_factor();
143 if (current_scale
!= new_scale
)
144 NotifyHostResized(bounds
.size());
147 gfx::Insets
WindowTreeHostWin::GetInsets() const {
148 return gfx::Insets();
151 void WindowTreeHostWin::SetInsets(const gfx::Insets
& insets
) {
154 gfx::Point
WindowTreeHostWin::GetLocationOnNativeScreen() const {
156 GetClientRect(hwnd(), &r
);
157 return gfx::Point(r
.left
, r
.top
);
161 void WindowTreeHostWin::SetCapture() {
164 ::SetCapture(hwnd());
168 void WindowTreeHostWin::ReleaseCapture() {
170 has_capture_
= false;
175 bool WindowTreeHostWin::QueryMouseLocation(gfx::Point
* location_return
) {
176 client::CursorClient
* cursor_client
=
177 client::GetCursorClient(GetRootWindow()->window());
178 if (cursor_client
&& !cursor_client
->IsMouseEventsEnabled()) {
179 *location_return
= gfx::Point(0, 0);
185 ScreenToClient(hwnd(), &pt
);
186 const gfx::Size size
= GetBounds().size();
188 gfx::Point(max(0, min(size
.width(), static_cast<int>(pt
.x
))),
189 max(0, min(size
.height(), static_cast<int>(pt
.y
))));
190 return (pt
.x
>= 0 && static_cast<int>(pt
.x
) < size
.width() &&
191 pt
.y
>= 0 && static_cast<int>(pt
.y
) < size
.height());
194 bool WindowTreeHostWin::ConfineCursorToRootWindow() {
196 GetWindowRect(hwnd(), &window_rect
);
197 return ClipCursor(&window_rect
) != 0;
200 void WindowTreeHostWin::UnConfineCursor() {
204 void WindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor
) {
205 // Custom web cursors are handled directly.
206 if (native_cursor
== ui::kCursorCustom
)
209 ui::CursorLoaderWin cursor_loader
;
210 cursor_loader
.SetPlatformCursor(&native_cursor
);
211 ::SetCursor(native_cursor
.platform());
214 void WindowTreeHostWin::MoveCursorToNative(const gfx::Point
& location
) {
215 // Deliberately not implemented.
218 void WindowTreeHostWin::OnCursorVisibilityChangedNative(bool show
) {
222 void WindowTreeHostWin::PostNativeEvent(const base::NativeEvent
& native_event
) {
224 hwnd(), native_event
.message
, native_event
.wParam
, native_event
.lParam
);
227 void WindowTreeHostWin::OnDeviceScaleFactorChanged(
228 float device_scale_factor
) {
232 void WindowTreeHostWin::PrepareForShutdown() {
236 ui::EventProcessor
* WindowTreeHostWin::GetEventProcessor() {
237 return delegate_
->GetEventProcessor();
240 void WindowTreeHostWin::OnClose() {
241 // TODO: this obviously shouldn't be here.
242 base::MessageLoopForUI::current()->Quit();
245 LRESULT
WindowTreeHostWin::OnKeyEvent(UINT message
,
248 MSG msg
= { hwnd(), message
, w_param
, l_param
};
249 ui::KeyEvent
keyev(msg
, message
== WM_CHAR
);
250 ui::EventDispatchDetails details
= SendEventToProcessor(&keyev
);
251 SetMsgHandled(keyev
.handled() || details
.dispatcher_destroyed
);
255 LRESULT
WindowTreeHostWin::OnMouseRange(UINT message
,
258 MSG msg
= { hwnd(), message
, w_param
, l_param
, 0,
259 { CR_GET_X_LPARAM(l_param
), CR_GET_Y_LPARAM(l_param
) } };
260 ui::MouseEvent
event(msg
);
261 bool handled
= false;
262 if (!(event
.flags() & ui::EF_IS_NON_CLIENT
)) {
263 ui::EventDispatchDetails details
= SendEventToProcessor(&event
);
264 handled
= event
.handled() || details
.dispatcher_destroyed
;
266 SetMsgHandled(handled
);
270 LRESULT
WindowTreeHostWin::OnCaptureChanged(UINT message
,
274 has_capture_
= false;
275 delegate_
->OnHostLostWindowCapture();
280 LRESULT
WindowTreeHostWin::OnNCActivate(UINT message
,
284 delegate_
->OnHostActivated();
285 return DefWindowProc(hwnd(), message
, w_param
, l_param
);
288 void WindowTreeHostWin::OnMove(const gfx::Point
& point
) {
290 delegate_
->OnHostMoved(point
);
293 void WindowTreeHostWin::OnPaint(HDC dc
) {
294 gfx::Rect damage_rect
;
295 RECT update_rect
= {0};
296 if (GetUpdateRect(hwnd(), &update_rect
, FALSE
))
297 damage_rect
= gfx::Rect(update_rect
);
298 compositor()->ScheduleRedrawRect(damage_rect
);
299 ValidateRect(hwnd(), NULL
);
302 void WindowTreeHostWin::OnSize(UINT param
, const gfx::Size
& size
) {
303 // Minimizing resizes the window to 0x0 which causes our layout to go all
304 // screwy, so we just ignore it.
305 if (delegate_
&& param
!= SIZE_MINIMIZED
)
306 NotifyHostResized(size
);
312 void SetUsePopupAsRootWindowForTest(bool use
) {
313 use_popup_as_root_window_for_test
= use
;