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/window_tree_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/window_event_dispatcher.h" 14 #include "ui/base/cursor/cursor_loader_win.h" 15 #include "ui/base/view_prop.h" 16 #include "ui/compositor/compositor.h" 17 #include "ui/events/event.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 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { 34 return new WindowTreeHostWin(bounds); 35 } 36 37 // static 38 gfx::Size WindowTreeHost::GetNativeScreenSize() { 39 return gfx::Size(GetSystemMetrics(SM_CXSCREEN), 40 GetSystemMetrics(SM_CYSCREEN)); 41 } 42 43 WindowTreeHostWin::WindowTreeHostWin(const gfx::Rect& bounds) 44 : has_capture_(false) { 45 if (use_popup_as_root_window_for_test) 46 set_window_style(WS_POPUP); 47 Init(NULL, bounds); 48 SetWindowText(hwnd(), L"aura::RootWindow!"); 49 CreateCompositor(GetAcceleratedWidget()); 50 } 51 52 WindowTreeHostWin::~WindowTreeHostWin() { 53 DestroyCompositor(); 54 DestroyDispatcher(); 55 DestroyWindow(hwnd()); 56 } 57 58 ui::EventSource* WindowTreeHostWin::GetEventSource() { 59 return this; 60 } 61 62 gfx::AcceleratedWidget WindowTreeHostWin::GetAcceleratedWidget() { 63 return hwnd(); 64 } 65 66 void WindowTreeHostWin::Show() { 67 ShowWindow(hwnd(), SW_SHOWNORMAL); 68 } 69 70 void WindowTreeHostWin::Hide() { 71 NOTIMPLEMENTED(); 72 } 73 74 gfx::Rect WindowTreeHostWin::GetBounds() const { 75 RECT r; 76 GetClientRect(hwnd(), &r); 77 return gfx::Rect(r); 78 } 79 80 void WindowTreeHostWin::SetBounds(const gfx::Rect& bounds) { 81 RECT window_rect; 82 window_rect.left = bounds.x(); 83 window_rect.top = bounds.y(); 84 window_rect.right = bounds.right() ; 85 window_rect.bottom = bounds.bottom(); 86 AdjustWindowRectEx(&window_rect, 87 GetWindowLong(hwnd(), GWL_STYLE), 88 FALSE, 89 GetWindowLong(hwnd(), GWL_EXSTYLE)); 90 SetWindowPos( 91 hwnd(), 92 NULL, 93 window_rect.left, 94 window_rect.top, 95 window_rect.right - window_rect.left, 96 window_rect.bottom - window_rect.top, 97 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION); 98 99 // Explicity call OnHostResized when the scale has changed because 100 // the window size may not have changed. 101 float current_scale = compositor()->device_scale_factor(); 102 float new_scale = gfx::Screen::GetScreenFor(window())-> 103 GetDisplayNearestWindow(window()).device_scale_factor(); 104 if (current_scale != new_scale) 105 OnHostResized(bounds.size()); 106 } 107 108 gfx::Point WindowTreeHostWin::GetLocationOnNativeScreen() const { 109 RECT r; 110 GetClientRect(hwnd(), &r); 111 return gfx::Point(r.left, r.top); 112 } 113 114 115 void WindowTreeHostWin::SetCapture() { 116 if (!has_capture_) { 117 has_capture_ = true; 118 ::SetCapture(hwnd()); 119 } 120 } 121 122 void WindowTreeHostWin::ReleaseCapture() { 123 if (has_capture_) { 124 has_capture_ = false; 125 ::ReleaseCapture(); 126 } 127 } 128 129 void WindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) { 130 // Custom web cursors are handled directly. 131 if (native_cursor == ui::kCursorCustom) 132 return; 133 134 ui::CursorLoaderWin cursor_loader; 135 cursor_loader.SetPlatformCursor(&native_cursor); 136 ::SetCursor(native_cursor.platform()); 137 } 138 139 void WindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) { 140 // Deliberately not implemented. 141 } 142 143 void WindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) { 144 NOTIMPLEMENTED(); 145 } 146 147 void WindowTreeHostWin::PostNativeEvent(const base::NativeEvent& native_event) { 148 ::PostMessage( 149 hwnd(), native_event.message, native_event.wParam, native_event.lParam); 150 } 151 152 void WindowTreeHostWin::OnDeviceScaleFactorChanged( 153 float device_scale_factor) { 154 NOTIMPLEMENTED(); 155 } 156 157 ui::EventProcessor* WindowTreeHostWin::GetEventProcessor() { 158 return dispatcher(); 159 } 160 161 void WindowTreeHostWin::OnClose() { 162 // TODO: this obviously shouldn't be here. 163 base::MessageLoopForUI::current()->Quit(); 164 } 165 166 LRESULT WindowTreeHostWin::OnKeyEvent(UINT message, 167 WPARAM w_param, 168 LPARAM l_param) { 169 MSG msg = { hwnd(), message, w_param, l_param }; 170 ui::KeyEvent keyev(msg, message == WM_CHAR); 171 ui::EventDispatchDetails details = SendEventToProcessor(&keyev); 172 SetMsgHandled(keyev.handled() || details.dispatcher_destroyed); 173 return 0; 174 } 175 176 LRESULT WindowTreeHostWin::OnMouseRange(UINT message, 177 WPARAM w_param, 178 LPARAM l_param) { 179 MSG msg = { hwnd(), message, w_param, l_param, 0, 180 { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } }; 181 ui::MouseEvent event(msg); 182 bool handled = false; 183 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) { 184 ui::EventDispatchDetails details = SendEventToProcessor(&event); 185 handled = event.handled() || details.dispatcher_destroyed; 186 } 187 SetMsgHandled(handled); 188 return 0; 189 } 190 191 LRESULT WindowTreeHostWin::OnCaptureChanged(UINT message, 192 WPARAM w_param, 193 LPARAM l_param) { 194 if (has_capture_) { 195 has_capture_ = false; 196 OnHostLostWindowCapture(); 197 } 198 return 0; 199 } 200 201 LRESULT WindowTreeHostWin::OnNCActivate(UINT message, 202 WPARAM w_param, 203 LPARAM l_param) { 204 if (!!w_param) 205 OnHostActivated(); 206 return DefWindowProc(hwnd(), message, w_param, l_param); 207 } 208 209 void WindowTreeHostWin::OnMove(const gfx::Point& point) { 210 OnHostMoved(point); 211 } 212 213 void WindowTreeHostWin::OnPaint(HDC dc) { 214 gfx::Rect damage_rect; 215 RECT update_rect = {0}; 216 if (GetUpdateRect(hwnd(), &update_rect, FALSE)) 217 damage_rect = gfx::Rect(update_rect); 218 compositor()->ScheduleRedrawRect(damage_rect); 219 ValidateRect(hwnd(), NULL); 220 } 221 222 void WindowTreeHostWin::OnSize(UINT param, const gfx::Size& size) { 223 // Minimizing resizes the window to 0x0 which causes our layout to go all 224 // screwy, so we just ignore it. 225 if (dispatcher() && param != SIZE_MINIMIZED) 226 OnHostResized(size); 227 } 228 229 namespace test { 230 231 // static 232 void SetUsePopupAsRootWindowForTest(bool use) { 233 use_popup_as_root_window_for_test = use; 234 } 235 236 } // namespace test 237 238 } // namespace aura 239