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 if (!custom_window_region_ && !delegate_->IsUsingCustomFrame()) |
805 // The non-client view needs to update too. | 806 dwm_transition_desired_ = true; |
806 delegate_->HandleFrameChanged(); | 807 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen()) |
807 | 808 PerformDwmTransition(); |
808 if (IsVisible() && !delegate_->IsUsingCustomFrame()) { | |
809 // For some reason, we need to hide the window after we change from a custom | |
810 // frame to a native frame. If we don't, the client area will be filled | |
811 // with black. This seems to be related to an interaction between DWM and | |
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 } | 809 } |
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 } | 810 } |
825 | 811 |
826 void HWNDMessageHandler::SchedulePaintInRect(const gfx::Rect& rect) { | 812 void HWNDMessageHandler::SchedulePaintInRect(const gfx::Rect& rect) { |
827 if (use_layered_buffer_) { | 813 if (use_layered_buffer_) { |
828 // We must update the back-buffer immediately, since Windows' handling of | 814 // We must update the back-buffer immediately, since Windows' handling of |
829 // invalid rects is somewhat mysterious. | 815 // invalid rects is somewhat mysterious. |
830 invalid_rect_.Union(rect); | 816 invalid_rect_.Union(rect); |
831 | 817 |
832 // In some situations, such as drag and drop, when Windows itself runs a | 818 // 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 | 819 // 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()) { | 854 if (!app_icon.isNull()) { |
869 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); | 855 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); |
870 HICON old_icon = reinterpret_cast<HICON>( | 856 HICON old_icon = reinterpret_cast<HICON>( |
871 SendMessage(hwnd(), WM_SETICON, ICON_BIG, | 857 SendMessage(hwnd(), WM_SETICON, ICON_BIG, |
872 reinterpret_cast<LPARAM>(windows_icon))); | 858 reinterpret_cast<LPARAM>(windows_icon))); |
873 if (old_icon) | 859 if (old_icon) |
874 DestroyIcon(old_icon); | 860 DestroyIcon(old_icon); |
875 } | 861 } |
876 } | 862 } |
877 | 863 |
| 864 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { |
| 865 fullscreen_handler()->SetFullscreen(fullscreen); |
| 866 // If we are out of fullscreen and there was a pending DWM transition for the |
| 867 // window, then go ahead and do it now. |
| 868 if (!fullscreen && dwm_transition_desired_) |
| 869 PerformDwmTransition(); |
| 870 } |
| 871 |
878 //////////////////////////////////////////////////////////////////////////////// | 872 //////////////////////////////////////////////////////////////////////////////// |
879 // HWNDMessageHandler, InputMethodDelegate implementation: | 873 // HWNDMessageHandler, InputMethodDelegate implementation: |
880 | 874 |
881 void HWNDMessageHandler::DispatchKeyEventPostIME(const ui::KeyEvent& key) { | 875 void HWNDMessageHandler::DispatchKeyEventPostIME(const ui::KeyEvent& key) { |
882 SetMsgHandled(delegate_->HandleKeyEvent(key)); | 876 SetMsgHandled(delegate_->HandleKeyEvent(key)); |
883 } | 877 } |
884 | 878 |
885 //////////////////////////////////////////////////////////////////////////////// | 879 //////////////////////////////////////////////////////////////////////////////// |
886 // HWNDMessageHandler, gfx::WindowImpl overrides: | 880 // HWNDMessageHandler, gfx::WindowImpl overrides: |
887 | 881 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 DeleteObject(new_region); | 1140 DeleteObject(new_region); |
1147 } | 1141 } |
1148 | 1142 |
1149 DeleteObject(current_rgn); | 1143 DeleteObject(current_rgn); |
1150 } | 1144 } |
1151 | 1145 |
1152 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() { | 1146 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() { |
1153 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 1147 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
1154 return; | 1148 return; |
1155 | 1149 |
| 1150 if (fullscreen_handler_->fullscreen()) |
| 1151 return; |
| 1152 |
1156 DWMNCRENDERINGPOLICY policy = | 1153 DWMNCRENDERINGPOLICY policy = |
1157 custom_window_region_ || delegate_->IsUsingCustomFrame() ? | 1154 custom_window_region_ || delegate_->IsUsingCustomFrame() ? |
1158 DWMNCRP_DISABLED : DWMNCRP_ENABLED; | 1155 DWMNCRP_DISABLED : DWMNCRP_ENABLED; |
1159 | 1156 |
1160 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, | 1157 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, |
1161 &policy, sizeof(DWMNCRENDERINGPOLICY)); | 1158 &policy, sizeof(DWMNCRENDERINGPOLICY)); |
1162 } | 1159 } |
1163 | 1160 |
1164 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, | 1161 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, |
1165 WPARAM w_param, | 1162 WPARAM w_param, |
(...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2436 ::ClientToScreen(hwnd(), &mouse_location); | 2433 ::ClientToScreen(hwnd(), &mouse_location); |
2437 POINT cursor_pos = {0}; | 2434 POINT cursor_pos = {0}; |
2438 ::GetCursorPos(&cursor_pos); | 2435 ::GetCursorPos(&cursor_pos); |
2439 if (memcmp(&cursor_pos, &mouse_location, sizeof(POINT))) | 2436 if (memcmp(&cursor_pos, &mouse_location, sizeof(POINT))) |
2440 return false; | 2437 return false; |
2441 return true; | 2438 return true; |
2442 } | 2439 } |
2443 return false; | 2440 return false; |
2444 } | 2441 } |
2445 | 2442 |
| 2443 void HWNDMessageHandler::PerformDwmTransition() { |
| 2444 dwm_transition_desired_ = false; |
| 2445 |
| 2446 UpdateDwmNcRenderingPolicy(); |
| 2447 // Don't redraw the window here, because we need to hide and show the window |
| 2448 // which will also trigger a redraw. |
| 2449 ResetWindowRegion(true, false); |
| 2450 // The non-client view needs to update too. |
| 2451 delegate_->HandleFrameChanged(); |
| 2452 |
| 2453 if (IsVisible() && !delegate_->IsUsingCustomFrame()) { |
| 2454 // For some reason, we need to hide the window after we change from a custom |
| 2455 // frame to a native frame. If we don't, the client area will be filled |
| 2456 // with black. This seems to be related to an interaction between DWM and |
| 2457 // SetWindowRgn, but the details aren't clear. Additionally, we need to |
| 2458 // specify SWP_NOZORDER here, otherwise if you have multiple chrome windows |
| 2459 // open they will re-appear with a non-deterministic Z-order. |
| 2460 UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER; |
| 2461 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW); |
| 2462 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW); |
| 2463 } |
| 2464 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want |
| 2465 // to notify our children too, since we can have MDI child windows who need to |
| 2466 // update their appearance. |
| 2467 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL); |
| 2468 } |
| 2469 |
2446 } // namespace views | 2470 } // namespace views |
OLD | NEW |