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

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

Issue 1406403007: Eliminate HICON leaks caused by creating icons from bitmap image. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use ScopedGeneric to define ScopedGDIObject. Created 5 years, 1 month 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
« ui/gfx/icon_util.cc ('K') | « 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 10
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 } 531 }
532 532
533 void HWNDMessageHandler::CenterWindow(const gfx::Size& size) { 533 void HWNDMessageHandler::CenterWindow(const gfx::Size& size) {
534 HWND parent = GetParent(hwnd()); 534 HWND parent = GetParent(hwnd());
535 if (!IsWindow(hwnd())) 535 if (!IsWindow(hwnd()))
536 parent = ::GetWindow(hwnd(), GW_OWNER); 536 parent = ::GetWindow(hwnd(), GW_OWNER);
537 gfx::CenterAndSizeWindow(parent, hwnd(), size); 537 gfx::CenterAndSizeWindow(parent, hwnd(), size);
538 } 538 }
539 539
540 void HWNDMessageHandler::SetRegion(HRGN region) { 540 void HWNDMessageHandler::SetRegion(HRGN region) {
541 custom_window_region_.Set(region); 541 custom_window_region_.reset(region);
542 ResetWindowRegion(true, true); 542 ResetWindowRegion(true, true);
543 } 543 }
544 544
545 void HWNDMessageHandler::StackAbove(HWND other_hwnd) { 545 void HWNDMessageHandler::StackAbove(HWND other_hwnd) {
546 // Windows API allows to stack behind another windows only. 546 // Windows API allows to stack behind another windows only.
547 DCHECK(other_hwnd); 547 DCHECK(other_hwnd);
548 HWND next_window = GetNextWindow(other_hwnd, GW_HWNDPREV); 548 HWND next_window = GetNextWindow(other_hwnd, GW_HWNDPREV);
549 SetWindowPos(hwnd(), next_window ? next_window : HWND_TOP, 0, 0, 0, 0, 549 SetWindowPos(hwnd(), next_window ? next_window : HWND_TOP, 0, 0, 0, 0,
550 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 550 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
551 } 551 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | 723 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS |
724 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION | 724 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION |
725 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER); 725 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER);
726 } 726 }
727 727
728 void HWNDMessageHandler::FlashFrame(bool flash) { 728 void HWNDMessageHandler::FlashFrame(bool flash) {
729 FLASHWINFO fwi; 729 FLASHWINFO fwi;
730 fwi.cbSize = sizeof(fwi); 730 fwi.cbSize = sizeof(fwi);
731 fwi.hwnd = hwnd(); 731 fwi.hwnd = hwnd();
732 if (flash) { 732 if (flash) {
733 fwi.dwFlags = custom_window_region_ ? FLASHW_TRAY : FLASHW_ALL; 733 fwi.dwFlags = custom_window_region_.is_valid() ? FLASHW_TRAY : FLASHW_ALL;
734 fwi.uCount = 4; 734 fwi.uCount = 4;
735 fwi.dwTimeout = 0; 735 fwi.dwTimeout = 0;
736 } else { 736 } else {
737 fwi.dwFlags = FLASHW_STOP; 737 fwi.dwFlags = FLASHW_STOP;
738 } 738 }
739 FlashWindowEx(&fwi); 739 FlashWindowEx(&fwi);
740 } 740 }
741 741
742 void HWNDMessageHandler::ClearNativeFocus() { 742 void HWNDMessageHandler::ClearNativeFocus() {
743 ::SetFocus(hwnd()); 743 ::SetFocus(hwnd());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 } 791 }
792 792
793 void HWNDMessageHandler::FrameTypeChanged() { 793 void HWNDMessageHandler::FrameTypeChanged() {
794 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 794 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
795 // Don't redraw the window here, because we invalidate the window later. 795 // Don't redraw the window here, because we invalidate the window later.
796 ResetWindowRegion(true, false); 796 ResetWindowRegion(true, false);
797 // The non-client view needs to update too. 797 // The non-client view needs to update too.
798 delegate_->HandleFrameChanged(); 798 delegate_->HandleFrameChanged();
799 InvalidateRect(hwnd(), NULL, FALSE); 799 InvalidateRect(hwnd(), NULL, FALSE);
800 } else { 800 } else {
801 if (!custom_window_region_ && !delegate_->IsUsingCustomFrame()) 801 if (!custom_window_region_.is_valid() && !delegate_->IsUsingCustomFrame())
802 dwm_transition_desired_ = true; 802 dwm_transition_desired_ = true;
803 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen()) 803 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen())
804 PerformDwmTransition(); 804 PerformDwmTransition();
805 } 805 }
806 } 806 }
807 807
808 void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, 808 void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon,
809 const gfx::ImageSkia& app_icon) { 809 const gfx::ImageSkia& app_icon) {
810 if (!window_icon.isNull()) { 810 if (!window_icon.isNull()) {
811 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap( 811 base::win::ScopedHICON previous_icon = window_icon_.Pass();
812 *window_icon.bitmap()); 812 window_icon_.reset(
813 // We need to make sure to destroy the previous icon, otherwise we'll leak 813 IconUtil::CreateHICONFromSkBitmap(*window_icon.bitmap()));
814 // these GDI objects until we crash! 814 SendMessage(hwnd(), WM_SETICON, ICON_SMALL,
815 HICON old_icon = reinterpret_cast<HICON>( 815 reinterpret_cast<LPARAM>(window_icon_.get()));
816 SendMessage(hwnd(), WM_SETICON, ICON_SMALL,
817 reinterpret_cast<LPARAM>(windows_icon)));
818 if (old_icon)
819 DestroyIcon(old_icon);
820 } 816 }
821 if (!app_icon.isNull()) { 817 if (!app_icon.isNull()) {
822 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); 818 base::win::ScopedHICON previous_icon = app_icon_.Pass();
823 HICON old_icon = reinterpret_cast<HICON>( 819 app_icon_.reset(IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()));
824 SendMessage(hwnd(), WM_SETICON, ICON_BIG, 820 SendMessage(hwnd(), WM_SETICON, ICON_BIG,
825 reinterpret_cast<LPARAM>(windows_icon))); 821 reinterpret_cast<LPARAM>(app_icon_.get()));
826 if (old_icon)
827 DestroyIcon(old_icon);
828 } 822 }
829 } 823 }
830 824
831 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { 825 void HWNDMessageHandler::SetFullscreen(bool fullscreen) {
832 fullscreen_handler()->SetFullscreen(fullscreen); 826 fullscreen_handler()->SetFullscreen(fullscreen);
833 // If we are out of fullscreen and there was a pending DWM transition for the 827 // If we are out of fullscreen and there was a pending DWM transition for the
834 // window, then go ahead and do it now. 828 // window, then go ahead and do it now.
835 if (!fullscreen && dwm_transition_desired_) 829 if (!fullscreen && dwm_transition_desired_)
836 PerformDwmTransition(); 830 PerformDwmTransition();
837 } 831 }
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 return true; 1088 return true;
1095 } 1089 }
1096 1090
1097 void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) { 1091 void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
1098 // A native frame uses the native window region, and we don't want to mess 1092 // A native frame uses the native window region, and we don't want to mess
1099 // with it. 1093 // with it.
1100 // WS_EX_COMPOSITED is used instead of WS_EX_LAYERED under aura. WS_EX_LAYERED 1094 // WS_EX_COMPOSITED is used instead of WS_EX_LAYERED under aura. WS_EX_LAYERED
1101 // automatically makes clicks on transparent pixels fall through, that isn't 1095 // automatically makes clicks on transparent pixels fall through, that isn't
1102 // the case with WS_EX_COMPOSITED. So, we route WS_EX_COMPOSITED through to 1096 // the case with WS_EX_COMPOSITED. So, we route WS_EX_COMPOSITED through to
1103 // the delegate to allow for a custom hit mask. 1097 // the delegate to allow for a custom hit mask.
1104 if ((window_ex_style() & WS_EX_COMPOSITED) == 0 && !custom_window_region_ && 1098 if ((window_ex_style() & WS_EX_COMPOSITED) == 0 &&
1099 !custom_window_region_.is_valid() &&
1105 (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow())) { 1100 (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow())) {
1106 if (force) 1101 if (force)
1107 SetWindowRgn(hwnd(), NULL, redraw); 1102 SetWindowRgn(hwnd(), NULL, redraw);
1108 return; 1103 return;
1109 } 1104 }
1110 1105
1111 // Changing the window region is going to force a paint. Only change the 1106 // Changing the window region is going to force a paint. Only change the
1112 // window region if the region really differs. 1107 // window region if the region really differs.
1113 base::win::ScopedRegion current_rgn(CreateRectRgn(0, 0, 0, 0)); 1108 base::win::ScopedRegion current_rgn(CreateRectRgn(0, 0, 0, 0));
1114 GetWindowRgn(hwnd(), current_rgn); 1109 GetWindowRgn(hwnd(), current_rgn.get());
1115 1110
1116 RECT window_rect; 1111 RECT window_rect;
1117 GetWindowRect(hwnd(), &window_rect); 1112 GetWindowRect(hwnd(), &window_rect);
1118 base::win::ScopedRegion new_region; 1113 base::win::ScopedRegion new_region;
1119 if (custom_window_region_) { 1114 if (custom_window_region_.is_valid()) {
1120 new_region.Set(::CreateRectRgn(0, 0, 0, 0)); 1115 new_region.reset(CreateRectRgn(0, 0, 0, 0));
1121 ::CombineRgn(new_region, custom_window_region_.Get(), NULL, RGN_COPY); 1116 CombineRgn(new_region.get(), custom_window_region_.get(), NULL, RGN_COPY);
1122 } else if (IsMaximized()) { 1117 } else if (IsMaximized()) {
1123 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST); 1118 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST);
1124 MONITORINFO mi; 1119 MONITORINFO mi;
1125 mi.cbSize = sizeof mi; 1120 mi.cbSize = sizeof mi;
1126 GetMonitorInfo(monitor, &mi); 1121 GetMonitorInfo(monitor, &mi);
1127 RECT work_rect = mi.rcWork; 1122 RECT work_rect = mi.rcWork;
1128 OffsetRect(&work_rect, -window_rect.left, -window_rect.top); 1123 OffsetRect(&work_rect, -window_rect.left, -window_rect.top);
1129 new_region.Set(CreateRectRgnIndirect(&work_rect)); 1124 new_region.reset(CreateRectRgnIndirect(&work_rect));
1130 } else { 1125 } else {
1131 gfx::Path window_mask; 1126 gfx::Path window_mask;
1132 delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left, 1127 delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left,
1133 window_rect.bottom - window_rect.top), 1128 window_rect.bottom - window_rect.top),
1134 &window_mask); 1129 &window_mask);
1135 if (!window_mask.isEmpty()) 1130 if (!window_mask.isEmpty())
1136 new_region.Set(gfx::CreateHRGNFromSkPath(window_mask)); 1131 new_region.reset(gfx::CreateHRGNFromSkPath(window_mask));
1137 } 1132 }
1138 1133
1139 const bool has_current_region = current_rgn != 0; 1134 const bool has_current_region = current_rgn != 0;
1140 const bool has_new_region = new_region != 0; 1135 const bool has_new_region = new_region != 0;
1141 if (has_current_region != has_new_region || 1136 if (has_current_region != has_new_region ||
1142 (has_current_region && !EqualRgn(current_rgn, new_region))) { 1137 (has_current_region && !EqualRgn(current_rgn.get(), new_region.get()))) {
1143 // SetWindowRgn takes ownership of the HRGN. 1138 // SetWindowRgn takes ownership of the HRGN.
1144 SetWindowRgn(hwnd(), new_region.release(), redraw); 1139 SetWindowRgn(hwnd(), new_region.release(), redraw);
1145 } 1140 }
1146 } 1141 }
1147 1142
1148 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() { 1143 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() {
1149 if (base::win::GetVersion() < base::win::VERSION_VISTA) 1144 if (base::win::GetVersion() < base::win::VERSION_VISTA)
1150 return; 1145 return;
1151 1146
1152 if (fullscreen_handler_->fullscreen()) 1147 if (fullscreen_handler_->fullscreen())
1153 return; 1148 return;
1154 1149
1155 DWMNCRENDERINGPOLICY policy = 1150 DWMNCRENDERINGPOLICY policy =
1156 custom_window_region_ || delegate_->IsUsingCustomFrame() ? 1151 custom_window_region_.is_valid() || delegate_->IsUsingCustomFrame()
1157 DWMNCRP_DISABLED : DWMNCRP_ENABLED; 1152 ? DWMNCRP_DISABLED
1153 : DWMNCRP_ENABLED;
1158 1154
1159 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, 1155 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY,
1160 &policy, sizeof(DWMNCRENDERINGPOLICY)); 1156 &policy, sizeof(DWMNCRENDERINGPOLICY));
1161 } 1157 }
1162 1158
1163 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, 1159 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
1164 WPARAM w_param, 1160 WPARAM w_param,
1165 LPARAM l_param) { 1161 LPARAM l_param) {
1166 ScopedRedrawLock lock(this); 1162 ScopedRedrawLock lock(this);
1167 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use 1163 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use
(...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after
2460 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 2456 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
2461 0, 2457 0,
2462 0, 2458 0,
2463 event_time, 2459 event_time,
2464 1); 2460 1);
2465 2461
2466 touch_events->push_back(event); 2462 touch_events->push_back(event);
2467 } 2463 }
2468 2464
2469 } // namespace views 2465 } // namespace views
OLDNEW
« ui/gfx/icon_util.cc ('K') | « 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