OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/win/hwnd_message_handler.h" | 5 #include "ui/views/win/hwnd_message_handler.h" |
6 | 6 |
7 #include <dwmapi.h> | 7 #include <dwmapi.h> |
8 #include <oleacc.h> | 8 #include <oleacc.h> |
9 #include <shellapi.h> | 9 #include <shellapi.h> |
10 #include <tchar.h> | 10 #include <tchar.h> |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 const int kAutoHideTaskbarThicknessPx = 2; | 214 const int kAutoHideTaskbarThicknessPx = 2; |
215 | 215 |
216 bool IsTopLevelWindow(HWND window) { | 216 bool IsTopLevelWindow(HWND window) { |
217 long style = ::GetWindowLong(window, GWL_STYLE); | 217 long style = ::GetWindowLong(window, GWL_STYLE); |
218 if (!(style & WS_CHILD)) | 218 if (!(style & WS_CHILD)) |
219 return true; | 219 return true; |
220 HWND parent = ::GetParent(window); | 220 HWND parent = ::GetParent(window); |
221 return !parent || (parent == ::GetDesktopWindow()); | 221 return !parent || (parent == ::GetDesktopWindow()); |
222 } | 222 } |
223 | 223 |
224 void AddScrollStylesToWindow(HWND window) { | |
225 if (::IsWindow(window)) { | |
226 long current_style = ::GetWindowLong(window, GWL_STYLE); | |
227 ::SetWindowLong(window, GWL_STYLE, | |
228 current_style | WS_VSCROLL | WS_HSCROLL); | |
229 } | |
230 } | |
231 | |
232 const int kTouchDownContextResetTimeout = 500; | 224 const int kTouchDownContextResetTimeout = 500; |
233 | 225 |
234 // Windows does not flag synthesized mouse messages from touch in all cases. | 226 // Windows does not flag synthesized mouse messages from touch in all cases. |
235 // This causes us grief as we don't want to process touch and mouse messages | 227 // This causes us grief as we don't want to process touch and mouse messages |
236 // concurrently. Hack as per msdn is to check if the time difference between | 228 // concurrently. Hack as per msdn is to check if the time difference between |
237 // the touch message and the mouse move is within 500 ms and at the same | 229 // the touch message and the mouse move is within 500 ms and at the same |
238 // location as the cursor. | 230 // location as the cursor. |
239 const int kSynthesizedMouseTouchMessagesTimeDifference = 500; | 231 const int kSynthesizedMouseTouchMessagesTimeDifference = 500; |
240 | 232 |
241 } // namespace | 233 } // namespace |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 current_cursor_(NULL), | 315 current_cursor_(NULL), |
324 previous_cursor_(NULL), | 316 previous_cursor_(NULL), |
325 active_mouse_tracking_flags_(0), | 317 active_mouse_tracking_flags_(0), |
326 is_right_mouse_pressed_on_caption_(false), | 318 is_right_mouse_pressed_on_caption_(false), |
327 lock_updates_count_(0), | 319 lock_updates_count_(0), |
328 ignore_window_pos_changes_(false), | 320 ignore_window_pos_changes_(false), |
329 last_monitor_(NULL), | 321 last_monitor_(NULL), |
330 is_first_nccalc_(true), | 322 is_first_nccalc_(true), |
331 menu_depth_(0), | 323 menu_depth_(0), |
332 id_generator_(0), | 324 id_generator_(0), |
333 needs_scroll_styles_(false), | |
334 in_size_loop_(false), | 325 in_size_loop_(false), |
335 touch_down_contexts_(0), | 326 touch_down_contexts_(0), |
336 last_mouse_hwheel_time_(0), | 327 last_mouse_hwheel_time_(0), |
337 dwm_transition_desired_(false), | 328 dwm_transition_desired_(false), |
338 sent_window_size_changing_(false), | 329 sent_window_size_changing_(false), |
339 left_button_down_on_caption_(false), | 330 left_button_down_on_caption_(false), |
340 background_fullscreen_hack_(false), | 331 background_fullscreen_hack_(false), |
341 autohide_factory_(this), | 332 autohide_factory_(this), |
342 weak_factory_(this) {} | 333 weak_factory_(this) {} |
343 | 334 |
344 HWNDMessageHandler::~HWNDMessageHandler() { | 335 HWNDMessageHandler::~HWNDMessageHandler() { |
345 delegate_ = NULL; | 336 delegate_ = NULL; |
346 // Prevent calls back into this class via WNDPROC now that we've been | 337 // Prevent calls back into this class via WNDPROC now that we've been |
347 // destroyed. | 338 // destroyed. |
348 ClearUserData(); | 339 ClearUserData(); |
349 } | 340 } |
350 | 341 |
351 void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { | 342 void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { |
352 TRACE_EVENT0("views", "HWNDMessageHandler::Init"); | 343 TRACE_EVENT0("views", "HWNDMessageHandler::Init"); |
353 GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, | 344 GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, |
354 &last_work_area_); | 345 &last_work_area_); |
355 | 346 |
356 // Create the window. | 347 // Create the window. |
357 WindowImpl::Init(parent, bounds); | 348 WindowImpl::Init(parent, bounds); |
358 // TODO(ananta) | |
359 // Remove the scrolling hack code once we have scrolling working well. | |
360 #if defined(ENABLE_SCROLL_HACK) | |
361 // Certain trackpad drivers on Windows have bugs where in they don't generate | |
362 // WM_MOUSEWHEEL messages for the trackpoint and trackpad scrolling gestures | |
363 // unless there is an entry for Chrome with the class name of the Window. | |
364 // These drivers check if the window under the trackpoint has the WS_VSCROLL/ | |
365 // WS_HSCROLL style and if yes they generate the legacy WM_VSCROLL/WM_HSCROLL | |
366 // messages. We add these styles to ensure that trackpad/trackpoint scrolling | |
367 // work. | |
368 // TODO(ananta) | |
369 // Look into moving the WS_VSCROLL and WS_HSCROLL style setting logic to the | |
370 // CalculateWindowStylesFromInitParams function. Doing it there seems to | |
371 // cause some interactive tests to fail. Investigation needed. | |
372 if (IsTopLevelWindow(hwnd())) { | |
373 long current_style = ::GetWindowLong(hwnd(), GWL_STYLE); | |
374 if (!(current_style & WS_POPUP)) { | |
375 AddScrollStylesToWindow(hwnd()); | |
376 needs_scroll_styles_ = true; | |
377 } | |
378 } | |
379 #endif | |
380 | 349 |
381 prop_window_target_.reset(new ui::ViewProp(hwnd(), | 350 prop_window_target_.reset(new ui::ViewProp(hwnd(), |
382 ui::WindowEventTarget::kWin32InputEventTarget, | 351 ui::WindowEventTarget::kWin32InputEventTarget, |
383 static_cast<ui::WindowEventTarget*>(this))); | 352 static_cast<ui::WindowEventTarget*>(this))); |
384 | 353 |
385 // Direct Manipulation is enabled on Windows 10+. The CreateInstance function | 354 // Direct Manipulation is enabled on Windows 10+. The CreateInstance function |
386 // returns NULL if Direct Manipulation is not available. | 355 // returns NULL if Direct Manipulation is not available. |
387 direct_manipulation_helper_ = | 356 direct_manipulation_helper_ = |
388 gfx::win::DirectManipulationHelper::CreateInstance(); | 357 gfx::win::DirectManipulationHelper::CreateInstance(); |
389 if (direct_manipulation_helper_) | 358 if (direct_manipulation_helper_) |
(...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 display::win::GetScalingFactorFromDPI(LOWORD(w_param))); | 1386 display::win::GetScalingFactorFromDPI(LOWORD(w_param))); |
1418 return 0; | 1387 return 0; |
1419 } | 1388 } |
1420 | 1389 |
1421 void HWNDMessageHandler::OnEnterMenuLoop(BOOL from_track_popup_menu) { | 1390 void HWNDMessageHandler::OnEnterMenuLoop(BOOL from_track_popup_menu) { |
1422 if (menu_depth_++ == 0) | 1391 if (menu_depth_++ == 0) |
1423 delegate_->HandleMenuLoop(true); | 1392 delegate_->HandleMenuLoop(true); |
1424 } | 1393 } |
1425 | 1394 |
1426 void HWNDMessageHandler::OnEnterSizeMove() { | 1395 void HWNDMessageHandler::OnEnterSizeMove() { |
1427 // Please refer to the comments in the OnSize function about the scrollbar | |
1428 // hack. | |
1429 // Hide the Windows scrollbar if the scroll styles are present to ensure | |
1430 // that a paint flicker does not occur while sizing. | |
1431 if (in_size_loop_ && needs_scroll_styles_) | |
1432 ShowScrollBar(hwnd(), SB_BOTH, FALSE); | |
1433 | |
1434 delegate_->HandleBeginWMSizeMove(); | 1396 delegate_->HandleBeginWMSizeMove(); |
1435 SetMsgHandled(FALSE); | 1397 SetMsgHandled(FALSE); |
1436 } | 1398 } |
1437 | 1399 |
1438 LRESULT HWNDMessageHandler::OnEraseBkgnd(HDC dc) { | 1400 LRESULT HWNDMessageHandler::OnEraseBkgnd(HDC dc) { |
1439 // Needed to prevent resize flicker. | 1401 // Needed to prevent resize flicker. |
1440 return 1; | 1402 return 1; |
1441 } | 1403 } |
1442 | 1404 |
1443 void HWNDMessageHandler::OnExitMenuLoop(BOOL is_shortcut_menu) { | 1405 void HWNDMessageHandler::OnExitMenuLoop(BOOL is_shortcut_menu) { |
1444 if (--menu_depth_ == 0) | 1406 if (--menu_depth_ == 0) |
1445 delegate_->HandleMenuLoop(false); | 1407 delegate_->HandleMenuLoop(false); |
1446 DCHECK_GE(0, menu_depth_); | 1408 DCHECK_GE(0, menu_depth_); |
1447 } | 1409 } |
1448 | 1410 |
1449 void HWNDMessageHandler::OnExitSizeMove() { | 1411 void HWNDMessageHandler::OnExitSizeMove() { |
1450 delegate_->HandleEndWMSizeMove(); | 1412 delegate_->HandleEndWMSizeMove(); |
1451 SetMsgHandled(FALSE); | 1413 SetMsgHandled(FALSE); |
1452 // Please refer to the notes in the OnSize function for information about | |
1453 // the scrolling hack. | |
1454 // We hide the Windows scrollbar in the OnEnterSizeMove function. We need | |
1455 // to add the scroll styles back to ensure that scrolling works in legacy | |
1456 // trackpoint drivers. | |
1457 if (in_size_loop_ && needs_scroll_styles_) | |
1458 AddScrollStylesToWindow(hwnd()); | |
1459 // If the window was moved to a monitor which has a fullscreen window active, | 1414 // If the window was moved to a monitor which has a fullscreen window active, |
1460 // we need to reduce the size of the fullscreen window by 1px. | 1415 // we need to reduce the size of the fullscreen window by 1px. |
1461 CheckAndHandleBackgroundFullscreenOnMonitor(hwnd()); | 1416 CheckAndHandleBackgroundFullscreenOnMonitor(hwnd()); |
1462 } | 1417 } |
1463 | 1418 |
1464 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { | 1419 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { |
1465 gfx::Size min_window_size; | 1420 gfx::Size min_window_size; |
1466 gfx::Size max_window_size; | 1421 gfx::Size max_window_size; |
1467 delegate_->GetMinMaxSize(&min_window_size, &max_window_size); | 1422 delegate_->GetMinMaxSize(&min_window_size, &max_window_size); |
1468 min_window_size = delegate_->DIPToScreenSize(min_window_size); | 1423 min_window_size = delegate_->DIPToScreenSize(min_window_size); |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1832 } | 1787 } |
1833 | 1788 |
1834 // If the point is specified as custom or system nonclient item, return it. | 1789 // If the point is specified as custom or system nonclient item, return it. |
1835 if (component != HTNOWHERE) | 1790 if (component != HTNOWHERE) |
1836 return component; | 1791 return component; |
1837 | 1792 |
1838 // Otherwise, we let Windows do all the native frame non-client handling for | 1793 // Otherwise, we let Windows do all the native frame non-client handling for |
1839 // us. | 1794 // us. |
1840 LRESULT hit_test_code = DefWindowProc(hwnd(), WM_NCHITTEST, 0, | 1795 LRESULT hit_test_code = DefWindowProc(hwnd(), WM_NCHITTEST, 0, |
1841 MAKELPARAM(point.x(), point.y())); | 1796 MAKELPARAM(point.x(), point.y())); |
1842 if (needs_scroll_styles_) { | |
1843 switch (hit_test_code) { | |
1844 // If we faked the WS_VSCROLL and WS_HSCROLL styles for this window, then | |
1845 // Windows returns the HTVSCROLL or HTHSCROLL hit test codes if we hover | |
1846 // or click on the non client portions of the window where the OS | |
1847 // scrollbars would be drawn. These hittest codes are returned even when | |
1848 // the scrollbars are hidden, which is the case in Aura. We fake the | |
1849 // hittest code as HTCLIENT in this case to ensure that we receive client | |
1850 // mouse messages as opposed to non client mouse messages. | |
1851 case HTVSCROLL: | |
1852 case HTHSCROLL: | |
1853 hit_test_code = HTCLIENT; | |
1854 break; | |
1855 | |
1856 case HTBOTTOMRIGHT: { | |
1857 // Normally the HTBOTTOMRIGHT hittest code is received when we hover | |
1858 // near the bottom right of the window. However due to our fake scroll | |
1859 // styles, we get this code even when we hover around the area where | |
1860 // the vertical scrollar down arrow would be drawn. | |
1861 // We check if the hittest coordinates lie in this region and if yes | |
1862 // we return HTCLIENT. | |
1863 int border_width = ::GetSystemMetrics(SM_CXSIZEFRAME); | |
1864 int border_height = ::GetSystemMetrics(SM_CYSIZEFRAME); | |
1865 int scroll_width = ::GetSystemMetrics(SM_CXVSCROLL); | |
1866 int scroll_height = ::GetSystemMetrics(SM_CYVSCROLL); | |
1867 RECT window_rect; | |
1868 ::GetWindowRect(hwnd(), &window_rect); | |
1869 window_rect.bottom -= border_height; | |
1870 window_rect.right -= border_width; | |
1871 window_rect.left = window_rect.right - scroll_width; | |
1872 window_rect.top = window_rect.bottom - scroll_height; | |
1873 POINT pt; | |
1874 pt.x = point.x(); | |
1875 pt.y = point.y(); | |
1876 if (::PtInRect(&window_rect, pt)) | |
1877 hit_test_code = HTCLIENT; | |
1878 break; | |
1879 } | |
1880 | |
1881 default: | |
1882 break; | |
1883 } | |
1884 } | |
1885 return hit_test_code; | 1797 return hit_test_code; |
1886 } | 1798 } |
1887 | 1799 |
1888 void HWNDMessageHandler::OnNCPaint(HRGN rgn) { | 1800 void HWNDMessageHandler::OnNCPaint(HRGN rgn) { |
1889 RECT window_rect; | 1801 RECT window_rect; |
1890 GetWindowRect(hwnd(), &window_rect); | 1802 GetWindowRect(hwnd(), &window_rect); |
1891 RECT dirty_region; | 1803 RECT dirty_region; |
1892 // A value of 1 indicates paint all. | 1804 // A value of 1 indicates paint all. |
1893 if (!rgn || rgn == reinterpret_cast<HRGN>(1)) { | 1805 if (!rgn || rgn == reinterpret_cast<HRGN>(1)) { |
1894 dirty_region.left = 0; | 1806 dirty_region.left = 0; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 // this correctly. | 2034 // this correctly. |
2123 if (flags == SPI_SETWORKAREA) | 2035 if (flags == SPI_SETWORKAREA) |
2124 SendFrameChanged(); | 2036 SendFrameChanged(); |
2125 } | 2037 } |
2126 | 2038 |
2127 void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) { | 2039 void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) { |
2128 RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); | 2040 RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); |
2129 // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've | 2041 // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've |
2130 // invoked OnSize we ensure the RootView has been laid out. | 2042 // invoked OnSize we ensure the RootView has been laid out. |
2131 ResetWindowRegion(false, true); | 2043 ResetWindowRegion(false, true); |
2132 | |
2133 // We add the WS_VSCROLL and WS_HSCROLL styles to top level windows to ensure | |
2134 // that legacy trackpad/trackpoint drivers generate the WM_VSCROLL and | |
2135 // WM_HSCROLL messages and scrolling works. | |
2136 // We want the scroll styles to be present on the window. However we don't | |
2137 // want Windows to draw the scrollbars. To achieve this we hide the scroll | |
2138 // bars and readd them to the window style in a posted task to ensure that we | |
2139 // don't get nested WM_SIZE messages. | |
2140 if (needs_scroll_styles_ && !in_size_loop_) { | |
2141 ShowScrollBar(hwnd(), SB_BOTH, FALSE); | |
2142 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
2143 FROM_HERE, base::Bind(&AddScrollStylesToWindow, hwnd())); | |
2144 } | |
2145 } | 2044 } |
2146 | 2045 |
2147 void HWNDMessageHandler::OnSysCommand(UINT notification_code, | 2046 void HWNDMessageHandler::OnSysCommand(UINT notification_code, |
2148 const gfx::Point& point) { | 2047 const gfx::Point& point) { |
2149 if (!delegate_->ShouldHandleSystemCommands()) | 2048 if (!delegate_->ShouldHandleSystemCommands()) |
2150 return; | 2049 return; |
2151 | 2050 |
2152 // Windows uses the 4 lower order bits of |notification_code| for type- | 2051 // Windows uses the 4 lower order bits of |notification_code| for type- |
2153 // specific information so we must exclude this when comparing. | 2052 // specific information so we must exclude this when comparing. |
2154 static const int sc_mask = 0xFFF0; | 2053 static const int sc_mask = 0xFFF0; |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2423 LPARAM l_param, | 2322 LPARAM l_param, |
2424 bool track_mouse) { | 2323 bool track_mouse) { |
2425 // We handle touch events on Windows Aura. Windows generates synthesized | 2324 // We handle touch events on Windows Aura. Windows generates synthesized |
2426 // mouse messages in response to touch which we should ignore. However touch | 2325 // mouse messages in response to touch which we should ignore. However touch |
2427 // messages are only received for the client area. We need to ignore the | 2326 // messages are only received for the client area. We need to ignore the |
2428 // synthesized mouse messages for all points in the client area and places | 2327 // synthesized mouse messages for all points in the client area and places |
2429 // which return HTNOWHERE. | 2328 // which return HTNOWHERE. |
2430 // TODO(ananta) | 2329 // TODO(ananta) |
2431 // Windows does not reliably set the touch flag on mouse messages. Look into | 2330 // Windows does not reliably set the touch flag on mouse messages. Look into |
2432 // a better way of identifying mouse messages originating from touch. | 2331 // a better way of identifying mouse messages originating from touch. |
2433 if (ui::IsMouseEventFromTouch(message)) { | 2332 if ((message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) && |
| 2333 (ui::IsMouseEventFromTouch(message))) { |
2434 LPARAM l_param_ht = l_param; | 2334 LPARAM l_param_ht = l_param; |
2435 // For mouse events (except wheel events), location is in window coordinates | 2335 // For mouse events (except wheel events), location is in window coordinates |
2436 // and should be converted to screen coordinates for WM_NCHITTEST. | 2336 // and should be converted to screen coordinates for WM_NCHITTEST. |
2437 if (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) { | 2337 POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param_ht); |
2438 POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param_ht); | 2338 MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1); |
2439 MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1); | 2339 l_param_ht = MAKELPARAM(screen_point.x, screen_point.y); |
2440 l_param_ht = MAKELPARAM(screen_point.x, screen_point.y); | 2340 |
2441 } | |
2442 LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht); | 2341 LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht); |
2443 if (hittest == HTCLIENT || hittest == HTNOWHERE) | 2342 if (hittest == HTCLIENT || hittest == HTNOWHERE) |
2444 return 0; | 2343 return 0; |
2445 } | 2344 } |
2446 | 2345 |
2447 // Certain logitech drivers send the WM_MOUSEHWHEEL message to the parent | 2346 // Certain logitech drivers send the WM_MOUSEHWHEEL message to the parent |
2448 // followed by WM_MOUSEWHEEL messages to the child window causing a vertical | 2347 // followed by WM_MOUSEWHEEL messages to the child window causing a vertical |
2449 // scroll. We treat these WM_MOUSEWHEEL messages as WM_MOUSEHWHEEL | 2348 // scroll. We treat these WM_MOUSEWHEEL messages as WM_MOUSEHWHEEL |
2450 // messages. | 2349 // messages. |
2451 if (message == WM_MOUSEHWHEEL) | 2350 if (message == WM_MOUSEHWHEEL) |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2758 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 2657 MONITORINFO monitor_info = {sizeof(monitor_info)}; |
2759 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 2658 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
2760 &monitor_info); | 2659 &monitor_info); |
2761 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | 2660 gfx::Rect shrunk_rect(monitor_info.rcMonitor); |
2762 shrunk_rect.set_height(shrunk_rect.height() - 1); | 2661 shrunk_rect.set_height(shrunk_rect.height() - 1); |
2763 background_fullscreen_hack_ = true; | 2662 background_fullscreen_hack_ = true; |
2764 SetBoundsInternal(shrunk_rect, false); | 2663 SetBoundsInternal(shrunk_rect, false); |
2765 } | 2664 } |
2766 | 2665 |
2767 } // namespace views | 2666 } // namespace views |
OLD | NEW |