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. 4 5 #include "ui/aura/root_window_host_win.h" 6 7 #include <windows.h> 8 9 #include <algorithm> 10 11 #include "base/message_loop/message_loop.h" 12 #include "ui/aura/client/capture_client.h" 13 #include "ui/aura/client/cursor_client.h" 14 #include "ui/aura/root_window.h" 15 #include "ui/base/cursor/cursor_loader_win.h" 16 #include "ui/base/events/event.h" 17 #include "ui/base/view_prop.h" 18 #include "ui/gfx/display.h" 19 #include "ui/gfx/insets.h" 20 #include "ui/gfx/screen.h" 21 22 using std::max; 23 using std::min; 24 25 namespace aura { 26 namespace { 27 28 bool use_popup_as_root_window_for_test = false; 29 30 } // namespace 31 32 // static 33 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { 34 return new RootWindowHostWin(bounds); 35 } 36 37 // static 38 gfx::Size RootWindowHost::GetNativeScreenSize() { 39 return gfx::Size(GetSystemMetrics(SM_CXSCREEN), 40 GetSystemMetrics(SM_CYSCREEN)); 41 } 42 43 RootWindowHostWin::RootWindowHostWin(const gfx::Rect& bounds) 44 : delegate_(NULL), 45 fullscreen_(false), 46 has_capture_(false), 47 saved_window_style_(0), 48 saved_window_ex_style_(0) { 49 if (use_popup_as_root_window_for_test) 50 set_window_style(WS_POPUP); 51 Init(NULL, bounds); 52 SetWindowText(hwnd(), L"aura::RootWindow!"); 53 } 54 55 RootWindowHostWin::~RootWindowHostWin() { 56 DestroyWindow(hwnd()); 57 } 58 59 void RootWindowHostWin::SetDelegate(RootWindowHostDelegate* delegate) { 60 delegate_ = delegate; 61 } 62 63 RootWindow* RootWindowHostWin::GetRootWindow() { 64 return delegate_->AsRootWindow(); 65 } 66 67 gfx::AcceleratedWidget RootWindowHostWin::GetAcceleratedWidget() { 68 return hwnd(); 69 } 70 71 void RootWindowHostWin::Show() { 72 ShowWindow(hwnd(), SW_SHOWNORMAL); 73 } 74 75 void RootWindowHostWin::Hide() { 76 NOTIMPLEMENTED(); 77 } 78 79 void RootWindowHostWin::ToggleFullScreen() { 80 gfx::Rect target_rect; 81 if (!fullscreen_) { 82 fullscreen_ = true; 83 saved_window_style_ = GetWindowLong(hwnd(), GWL_STYLE); 84 saved_window_ex_style_ = GetWindowLong(hwnd(), GWL_EXSTYLE); 85 GetWindowRect(hwnd(), &saved_window_rect_); 86 SetWindowLong(hwnd(), GWL_STYLE, 87 saved_window_style_ & ~(WS_CAPTION | WS_THICKFRAME)); 88 SetWindowLong(hwnd(), GWL_EXSTYLE, 89 saved_window_ex_style_ & ~(WS_EX_DLGMODALFRAME | 90 WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); 91 92 MONITORINFO mi; 93 mi.cbSize = sizeof(mi); 94 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST), &mi); 95 target_rect = gfx::Rect(mi.rcMonitor); 96 } else { 97 fullscreen_ = false; 98 SetWindowLong(hwnd(), GWL_STYLE, saved_window_style_); 99 SetWindowLong(hwnd(), GWL_EXSTYLE, saved_window_ex_style_); 100 target_rect = gfx::Rect(saved_window_rect_); 101 } 102 SetWindowPos(hwnd(), 103 NULL, 104 target_rect.x(), 105 target_rect.y(), 106 target_rect.width(), 107 target_rect.height(), 108 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); 109 } 110 111 gfx::Rect RootWindowHostWin::GetBounds() const { 112 RECT r; 113 GetClientRect(hwnd(), &r); 114 return gfx::Rect(r); 115 } 116 117 void RootWindowHostWin::SetBounds(const gfx::Rect& bounds) { 118 if (fullscreen_) { 119 saved_window_rect_.right = saved_window_rect_.left + bounds.width(); 120 saved_window_rect_.bottom = saved_window_rect_.top + bounds.height(); 121 return; 122 } 123 RECT window_rect; 124 window_rect.left = bounds.x(); 125 window_rect.top = bounds.y(); 126 window_rect.right = bounds.right() ; 127 window_rect.bottom = bounds.bottom(); 128 AdjustWindowRectEx(&window_rect, 129 GetWindowLong(hwnd(), GWL_STYLE), 130 FALSE, 131 GetWindowLong(hwnd(), GWL_EXSTYLE)); 132 SetWindowPos( 133 hwnd(), 134 NULL, 135 window_rect.left, 136 window_rect.top, 137 window_rect.right - window_rect.left, 138 window_rect.bottom - window_rect.top, 139 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION); 140 141 // Explicity call OnHostResized when the scale has changed because 142 // the window size may not have changed. 143 float current_scale = delegate_->GetDeviceScaleFactor(); 144 float new_scale = gfx::Screen::GetScreenFor(delegate_->AsRootWindow())-> 145 GetDisplayNearestWindow(delegate_->AsRootWindow()).device_scale_factor(); 146 if (current_scale != new_scale) 147 delegate_->OnHostResized(bounds.size()); 148 } 149 150 gfx::Insets RootWindowHostWin::GetInsets() const { 151 return gfx::Insets(); 152 } 153 154 void RootWindowHostWin::SetInsets(const gfx::Insets& insets) { 155 } 156 157 gfx::Point RootWindowHostWin::GetLocationOnNativeScreen() const { 158 RECT r; 159 GetClientRect(hwnd(), &r); 160 return gfx::Point(r.left, r.top); 161 } 162 163 164 void RootWindowHostWin::SetCursor(gfx::NativeCursor native_cursor) { 165 // Custom web cursors are handled directly. 166 if (native_cursor == ui::kCursorCustom) 167 return; 168 169 ui::CursorLoaderWin cursor_loader; 170 cursor_loader.SetPlatformCursor(&native_cursor); 171 ::SetCursor(native_cursor.platform()); 172 } 173 174 void RootWindowHostWin::SetCapture() { 175 if (!has_capture_) { 176 has_capture_ = true; 177 ::SetCapture(hwnd()); 178 } 179 } 180 181 void RootWindowHostWin::ReleaseCapture() { 182 if (has_capture_) { 183 has_capture_ = false; 184 ::ReleaseCapture(); 185 } 186 } 187 188 bool RootWindowHostWin::QueryMouseLocation(gfx::Point* location_return) { 189 client::CursorClient* cursor_client = 190 client::GetCursorClient(GetRootWindow()); 191 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) { 192 *location_return = gfx::Point(0, 0); 193 return false; 194 } 195 196 POINT pt; 197 GetCursorPos(&pt); 198 ScreenToClient(hwnd(), &pt); 199 const gfx::Size size = GetBounds().size(); 200 *location_return = 201 gfx::Point(max(0, min(size.width(), static_cast<int>(pt.x))), 202 max(0, min(size.height(), static_cast<int>(pt.y)))); 203 return (pt.x >= 0 && static_cast<int>(pt.x) < size.width() && 204 pt.y >= 0 && static_cast<int>(pt.y) < size.height()); 205 } 206 207 bool RootWindowHostWin::ConfineCursorToRootWindow() { 208 RECT window_rect; 209 GetWindowRect(hwnd(), &window_rect); 210 return ClipCursor(&window_rect) != 0; 211 } 212 213 bool RootWindowHostWin::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, 214 const gfx::Point& dest_offset, 215 SkCanvas* canvas) { 216 NOTIMPLEMENTED(); 217 return false; 218 } 219 220 void RootWindowHostWin::UnConfineCursor() { 221 ClipCursor(NULL); 222 } 223 224 void RootWindowHostWin::OnCursorVisibilityChanged(bool show) { 225 NOTIMPLEMENTED(); 226 } 227 228 void RootWindowHostWin::MoveCursorTo(const gfx::Point& location) { 229 // Deliberately not implemented. 230 } 231 232 void RootWindowHostWin::SetFocusWhenShown(bool focus_when_shown) { 233 NOTIMPLEMENTED(); 234 } 235 236 void RootWindowHostWin::PostNativeEvent(const base::NativeEvent& native_event) { 237 ::PostMessage( 238 hwnd(), native_event.message, native_event.wParam, native_event.lParam); 239 } 240 241 void RootWindowHostWin::OnDeviceScaleFactorChanged( 242 float device_scale_factor) { 243 NOTIMPLEMENTED(); 244 } 245 246 void RootWindowHostWin::PrepareForShutdown() { 247 NOTIMPLEMENTED(); 248 } 249 250 void RootWindowHostWin::OnClose() { 251 // TODO: this obviously shouldn't be here. 252 base::MessageLoopForUI::current()->Quit(); 253 } 254 255 LRESULT RootWindowHostWin::OnKeyEvent(UINT message, 256 WPARAM w_param, 257 LPARAM l_param) { 258 MSG msg = { hwnd(), message, w_param, l_param }; 259 ui::KeyEvent keyev(msg, message == WM_CHAR); 260 SetMsgHandled(delegate_->OnHostKeyEvent(&keyev)); 261 return 0; 262 } 263 264 LRESULT RootWindowHostWin::OnMouseRange(UINT message, 265 WPARAM w_param, 266 LPARAM l_param) { 267 MSG msg = { hwnd(), message, w_param, l_param, 0, 268 { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } }; 269 ui::MouseEvent event(msg); 270 bool handled = false; 271 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) 272 handled = delegate_->OnHostMouseEvent(&event); 273 SetMsgHandled(handled); 274 return 0; 275 } 276 277 LRESULT RootWindowHostWin::OnCaptureChanged(UINT message, 278 WPARAM w_param, 279 LPARAM l_param) { 280 if (has_capture_) { 281 has_capture_ = false; 282 delegate_->OnHostLostWindowCapture(); 283 } 284 return 0; 285 } 286 287 LRESULT RootWindowHostWin::OnNCActivate(UINT message, 288 WPARAM w_param, 289 LPARAM l_param) { 290 if (!!w_param) 291 delegate_->OnHostActivated(); 292 return DefWindowProc(hwnd(), message, w_param, l_param); 293 } 294 295 void RootWindowHostWin::OnMove(const CPoint& point) { 296 if (delegate_) 297 delegate_->OnHostMoved(gfx::Point(point.x, point.y)); 298 } 299 300 void RootWindowHostWin::OnPaint(HDC dc) { 301 gfx::Rect damage_rect; 302 RECT update_rect = {0}; 303 if (GetUpdateRect(hwnd(), &update_rect, FALSE)) 304 damage_rect = gfx::Rect(update_rect); 305 delegate_->OnHostPaint(damage_rect); 306 ValidateRect(hwnd(), NULL); 307 } 308 309 void RootWindowHostWin::OnSize(UINT param, const CSize& size) { 310 // Minimizing resizes the window to 0x0 which causes our layout to go all 311 // screwy, so we just ignore it. 312 if (delegate_ && param != SIZE_MINIMIZED) 313 delegate_->OnHostResized(gfx::Size(size.cx, size.cy)); 314 } 315 316 namespace test { 317 318 // static 319 void SetUsePopupAsRootWindowForTest(bool use) { 320 use_popup_as_root_window_for_test = use; 321 } 322 323 } // namespace test 324 325 } // namespace aura 326