Chromium Code Reviews| 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 <wtsapi32.h> | 10 #include <wtsapi32.h> |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 352 layered_alpha_(255), | 352 layered_alpha_(255), |
| 353 waiting_for_redraw_layered_window_contents_(false), | 353 waiting_for_redraw_layered_window_contents_(false), |
| 354 is_first_nccalc_(true), | 354 is_first_nccalc_(true), |
| 355 menu_depth_(0), | 355 menu_depth_(0), |
| 356 autohide_factory_(this), | 356 autohide_factory_(this), |
| 357 id_generator_(0), | 357 id_generator_(0), |
| 358 needs_scroll_styles_(false), | 358 needs_scroll_styles_(false), |
| 359 in_size_loop_(false), | 359 in_size_loop_(false), |
| 360 touch_down_contexts_(0), | 360 touch_down_contexts_(0), |
| 361 last_mouse_hwheel_time_(0), | 361 last_mouse_hwheel_time_(0), |
| 362 msg_handled_(FALSE) { | 362 msg_handled_(FALSE), |
| 363 dwm_transition_desired_(false) { | |
| 363 } | 364 } |
| 364 | 365 |
| 365 HWNDMessageHandler::~HWNDMessageHandler() { | 366 HWNDMessageHandler::~HWNDMessageHandler() { |
| 366 delegate_ = NULL; | 367 delegate_ = NULL; |
| 367 // Prevent calls back into this class via WNDPROC now that we've been | 368 // Prevent calls back into this class via WNDPROC now that we've been |
| 368 // destroyed. | 369 // destroyed. |
| 369 ClearUserData(); | 370 ClearUserData(); |
| 370 } | 371 } |
| 371 | 372 |
| 372 void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { | 373 void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 if (cursor) { | 788 if (cursor) { |
| 788 previous_cursor_ = ::SetCursor(cursor); | 789 previous_cursor_ = ::SetCursor(cursor); |
| 789 current_cursor_ = cursor; | 790 current_cursor_ = cursor; |
| 790 } else if (previous_cursor_) { | 791 } else if (previous_cursor_) { |
| 791 ::SetCursor(previous_cursor_); | 792 ::SetCursor(previous_cursor_); |
| 792 previous_cursor_ = NULL; | 793 previous_cursor_ = NULL; |
| 793 } | 794 } |
| 794 } | 795 } |
| 795 | 796 |
| 796 void HWNDMessageHandler::FrameTypeChanged() { | 797 void HWNDMessageHandler::FrameTypeChanged() { |
| 797 // Called when the frame type could possibly be changing (theme change or | 798 if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
| 798 // DWM composition change). | 799 // Don't redraw the window here, because we invalidate the window later. |
| 799 UpdateDwmNcRenderingPolicy(); | 800 ResetWindowRegion(true, false); |
| 800 | 801 // The non-client view needs to update too. |
| 801 // Don't redraw the window here, because we need to hide and show the window | 802 delegate_->HandleFrameChanged(); |
| 802 // which will also trigger a redraw. | 803 InvalidateRect(hwnd(), NULL, FALSE); |
| 803 ResetWindowRegion(true, false); | 804 } else { |
| 804 | 805 dwm_transition_desired_ = true; |
|
sky
2014/08/20 15:25:56
Shouldn't this be conditional on whether you actua
ananta
2014/08/20 18:52:54
Done.
| |
| 805 // The non-client view needs to update too. | 806 // On Windows Vista and beyond, if we are transitioning from glass to |
|
sky
2014/08/20 15:25:56
I think this comment would be better in the header
ananta
2014/08/20 18:52:54
Done.
| |
| 806 delegate_->HandleFrameChanged(); | 807 // custom and vice versa we delay setting the DWM related properties in |
| 807 | 808 // full screen mode as DWM is not supported in full screen windows. We |
| 808 if (IsVisible() && !delegate_->IsUsingCustomFrame()) { | 809 // perform the DWM related operations when the window comes out of |
| 809 // For some reason, we need to hide the window after we change from a custom | 810 // fullscreen mode. |
| 810 // frame to a native frame. If we don't, the client area will be filled | 811 if (!fullscreen_handler_->fullscreen()) |
| 811 // with black. This seems to be related to an interaction between DWM and | 812 PerformDwmTransition(); |
| 812 // SetWindowRgn, but the details aren't clear. Additionally, we need to | |
| 813 // specify SWP_NOZORDER here, otherwise if you have multiple chrome windows | |
| 814 // open they will re-appear with a non-deterministic Z-order. | |
| 815 UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER; | |
| 816 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW); | |
| 817 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW); | |
| 818 } | 813 } |
| 819 | |
| 820 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want | |
| 821 // to notify our children too, since we can have MDI child windows who need to | |
| 822 // update their appearance. | |
| 823 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL); | |
| 824 } | 814 } |
| 825 | 815 |
| 826 void HWNDMessageHandler::SchedulePaintInRect(const gfx::Rect& rect) { | 816 void HWNDMessageHandler::SchedulePaintInRect(const gfx::Rect& rect) { |
| 827 if (use_layered_buffer_) { | 817 if (use_layered_buffer_) { |
| 828 // We must update the back-buffer immediately, since Windows' handling of | 818 // We must update the back-buffer immediately, since Windows' handling of |
| 829 // invalid rects is somewhat mysterious. | 819 // invalid rects is somewhat mysterious. |
| 830 invalid_rect_.Union(rect); | 820 invalid_rect_.Union(rect); |
| 831 | 821 |
| 832 // In some situations, such as drag and drop, when Windows itself runs a | 822 // In some situations, such as drag and drop, when Windows itself runs a |
| 833 // nested message loop our message loop appears to be starved and we don't | 823 // nested message loop our message loop appears to be starved and we don't |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 868 if (!app_icon.isNull()) { | 858 if (!app_icon.isNull()) { |
| 869 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); | 859 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); |
| 870 HICON old_icon = reinterpret_cast<HICON>( | 860 HICON old_icon = reinterpret_cast<HICON>( |
| 871 SendMessage(hwnd(), WM_SETICON, ICON_BIG, | 861 SendMessage(hwnd(), WM_SETICON, ICON_BIG, |
| 872 reinterpret_cast<LPARAM>(windows_icon))); | 862 reinterpret_cast<LPARAM>(windows_icon))); |
| 873 if (old_icon) | 863 if (old_icon) |
| 874 DestroyIcon(old_icon); | 864 DestroyIcon(old_icon); |
| 875 } | 865 } |
| 876 } | 866 } |
| 877 | 867 |
| 868 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { | |
| 869 fullscreen_handler()->SetFullscreen(fullscreen); | |
| 870 // If we are out of fullscreen and there was a pending DWM transition for the | |
| 871 // window, then go ahead and do it now. | |
| 872 if (!fullscreen && dwm_transition_desired_) | |
| 873 PerformDwmTransition(); | |
| 874 } | |
| 875 | |
| 878 //////////////////////////////////////////////////////////////////////////////// | 876 //////////////////////////////////////////////////////////////////////////////// |
| 879 // HWNDMessageHandler, InputMethodDelegate implementation: | 877 // HWNDMessageHandler, InputMethodDelegate implementation: |
| 880 | 878 |
| 881 void HWNDMessageHandler::DispatchKeyEventPostIME(const ui::KeyEvent& key) { | 879 void HWNDMessageHandler::DispatchKeyEventPostIME(const ui::KeyEvent& key) { |
| 882 SetMsgHandled(delegate_->HandleKeyEvent(key)); | 880 SetMsgHandled(delegate_->HandleKeyEvent(key)); |
| 883 } | 881 } |
| 884 | 882 |
| 885 //////////////////////////////////////////////////////////////////////////////// | 883 //////////////////////////////////////////////////////////////////////////////// |
| 886 // HWNDMessageHandler, gfx::WindowImpl overrides: | 884 // HWNDMessageHandler, gfx::WindowImpl overrides: |
| 887 | 885 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1146 DeleteObject(new_region); | 1144 DeleteObject(new_region); |
| 1147 } | 1145 } |
| 1148 | 1146 |
| 1149 DeleteObject(current_rgn); | 1147 DeleteObject(current_rgn); |
| 1150 } | 1148 } |
| 1151 | 1149 |
| 1152 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() { | 1150 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() { |
| 1153 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 1151 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
| 1154 return; | 1152 return; |
| 1155 | 1153 |
| 1154 if (fullscreen_handler_->fullscreen()) | |
| 1155 return; | |
| 1156 | |
| 1156 DWMNCRENDERINGPOLICY policy = | 1157 DWMNCRENDERINGPOLICY policy = |
| 1157 custom_window_region_ || delegate_->IsUsingCustomFrame() ? | 1158 custom_window_region_ || delegate_->IsUsingCustomFrame() ? |
| 1158 DWMNCRP_DISABLED : DWMNCRP_ENABLED; | 1159 DWMNCRP_DISABLED : DWMNCRP_ENABLED; |
| 1159 | 1160 |
| 1160 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, | 1161 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, |
| 1161 &policy, sizeof(DWMNCRENDERINGPOLICY)); | 1162 &policy, sizeof(DWMNCRENDERINGPOLICY)); |
| 1162 } | 1163 } |
| 1163 | 1164 |
| 1164 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, | 1165 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, |
| 1165 WPARAM w_param, | 1166 WPARAM w_param, |
| (...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2436 ::ClientToScreen(hwnd(), &mouse_location); | 2437 ::ClientToScreen(hwnd(), &mouse_location); |
| 2437 POINT cursor_pos = {0}; | 2438 POINT cursor_pos = {0}; |
| 2438 ::GetCursorPos(&cursor_pos); | 2439 ::GetCursorPos(&cursor_pos); |
| 2439 if (memcmp(&cursor_pos, &mouse_location, sizeof(POINT))) | 2440 if (memcmp(&cursor_pos, &mouse_location, sizeof(POINT))) |
| 2440 return false; | 2441 return false; |
| 2441 return true; | 2442 return true; |
| 2442 } | 2443 } |
| 2443 return false; | 2444 return false; |
| 2444 } | 2445 } |
| 2445 | 2446 |
| 2447 void HWNDMessageHandler::PerformDwmTransition() { | |
| 2448 DCHECK(!fullscreen_handler_->fullscreen()); | |
| 2449 DCHECK(dwm_transition_desired_); | |
| 2450 | |
| 2451 dwm_transition_desired_ = false; | |
| 2452 | |
| 2453 UpdateDwmNcRenderingPolicy(); | |
| 2454 // Don't redraw the window here, because we need to hide and show the window | |
| 2455 // which will also trigger a redraw. | |
| 2456 ResetWindowRegion(true, false); | |
| 2457 // The non-client view needs to update too. | |
| 2458 delegate_->HandleFrameChanged(); | |
| 2459 | |
| 2460 if (IsVisible() && !delegate_->IsUsingCustomFrame()) { | |
| 2461 // For some reason, we need to hide the window after we change from a custom | |
| 2462 // frame to a native frame. If we don't, the client area will be filled | |
| 2463 // with black. This seems to be related to an interaction between DWM and | |
| 2464 // SetWindowRgn, but the details aren't clear. Additionally, we need to | |
| 2465 // specify SWP_NOZORDER here, otherwise if you have multiple chrome windows | |
| 2466 // open they will re-appear with a non-deterministic Z-order. | |
| 2467 UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER; | |
| 2468 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW); | |
| 2469 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW); | |
| 2470 } | |
| 2471 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want | |
| 2472 // to notify our children too, since we can have MDI child windows who need to | |
| 2473 // update their appearance. | |
| 2474 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL); | |
| 2475 } | |
| 2476 | |
| 2446 } // namespace views | 2477 } // namespace views |
| OLD | NEW |