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