Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: ui/views/win/hwnd_message_handler.cc

Issue 484963002: Fix a long standing painting problem seen in the tabstrip on Windows Desktop Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added code to delay DWM until the window comes out of fullscreen Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698