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

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: Rebase Created 5 years 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
« 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 <tchar.h> 10 #include <tchar.h>
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 } 551 }
552 552
553 void HWNDMessageHandler::CenterWindow(const gfx::Size& size) { 553 void HWNDMessageHandler::CenterWindow(const gfx::Size& size) {
554 HWND parent = GetParent(hwnd()); 554 HWND parent = GetParent(hwnd());
555 if (!IsWindow(hwnd())) 555 if (!IsWindow(hwnd()))
556 parent = ::GetWindow(hwnd(), GW_OWNER); 556 parent = ::GetWindow(hwnd(), GW_OWNER);
557 gfx::CenterAndSizeWindow(parent, hwnd(), size); 557 gfx::CenterAndSizeWindow(parent, hwnd(), size);
558 } 558 }
559 559
560 void HWNDMessageHandler::SetRegion(HRGN region) { 560 void HWNDMessageHandler::SetRegion(HRGN region) {
561 custom_window_region_.Set(region); 561 custom_window_region_.reset(region);
562 ResetWindowRegion(true, true); 562 ResetWindowRegion(true, true);
563 } 563 }
564 564
565 void HWNDMessageHandler::StackAbove(HWND other_hwnd) { 565 void HWNDMessageHandler::StackAbove(HWND other_hwnd) {
566 // Windows API allows to stack behind another windows only. 566 // Windows API allows to stack behind another windows only.
567 DCHECK(other_hwnd); 567 DCHECK(other_hwnd);
568 HWND next_window = GetNextWindow(other_hwnd, GW_HWNDPREV); 568 HWND next_window = GetNextWindow(other_hwnd, GW_HWNDPREV);
569 SetWindowPos(hwnd(), next_window ? next_window : HWND_TOP, 0, 0, 0, 0, 569 SetWindowPos(hwnd(), next_window ? next_window : HWND_TOP, 0, 0, 0, 0,
570 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 570 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
571 } 571 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | 743 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS |
744 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION | 744 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION |
745 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER); 745 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER);
746 } 746 }
747 747
748 void HWNDMessageHandler::FlashFrame(bool flash) { 748 void HWNDMessageHandler::FlashFrame(bool flash) {
749 FLASHWINFO fwi; 749 FLASHWINFO fwi;
750 fwi.cbSize = sizeof(fwi); 750 fwi.cbSize = sizeof(fwi);
751 fwi.hwnd = hwnd(); 751 fwi.hwnd = hwnd();
752 if (flash) { 752 if (flash) {
753 fwi.dwFlags = custom_window_region_ ? FLASHW_TRAY : FLASHW_ALL; 753 fwi.dwFlags = custom_window_region_.is_valid() ? FLASHW_TRAY : FLASHW_ALL;
754 fwi.uCount = 4; 754 fwi.uCount = 4;
755 fwi.dwTimeout = 0; 755 fwi.dwTimeout = 0;
756 } else { 756 } else {
757 fwi.dwFlags = FLASHW_STOP; 757 fwi.dwFlags = FLASHW_STOP;
758 } 758 }
759 FlashWindowEx(&fwi); 759 FlashWindowEx(&fwi);
760 } 760 }
761 761
762 void HWNDMessageHandler::ClearNativeFocus() { 762 void HWNDMessageHandler::ClearNativeFocus() {
763 ::SetFocus(hwnd()); 763 ::SetFocus(hwnd());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 } 811 }
812 812
813 void HWNDMessageHandler::FrameTypeChanged() { 813 void HWNDMessageHandler::FrameTypeChanged() {
814 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 814 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
815 // Don't redraw the window here, because we invalidate the window later. 815 // Don't redraw the window here, because we invalidate the window later.
816 ResetWindowRegion(true, false); 816 ResetWindowRegion(true, false);
817 // The non-client view needs to update too. 817 // The non-client view needs to update too.
818 delegate_->HandleFrameChanged(); 818 delegate_->HandleFrameChanged();
819 InvalidateRect(hwnd(), NULL, FALSE); 819 InvalidateRect(hwnd(), NULL, FALSE);
820 } else { 820 } else {
821 if (!custom_window_region_ && !delegate_->IsUsingCustomFrame()) 821 if (!custom_window_region_.is_valid() && !delegate_->IsUsingCustomFrame())
822 dwm_transition_desired_ = true; 822 dwm_transition_desired_ = true;
823 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen()) 823 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen())
824 PerformDwmTransition(); 824 PerformDwmTransition();
825 } 825 }
826 } 826 }
827 827
828 void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, 828 void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon,
829 const gfx::ImageSkia& app_icon) { 829 const gfx::ImageSkia& app_icon) {
830 if (!window_icon.isNull()) { 830 if (!window_icon.isNull()) {
831 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap( 831 base::win::ScopedHICON previous_icon = window_icon_.Pass();
832 *window_icon.bitmap()); 832 window_icon_ =
833 // We need to make sure to destroy the previous icon, otherwise we'll leak 833 IconUtil::CreateHICONFromSkBitmap(*window_icon.bitmap()).Pass();
834 // these GDI objects until we crash! 834 SendMessage(hwnd(), WM_SETICON, ICON_SMALL,
835 HICON old_icon = reinterpret_cast<HICON>( 835 reinterpret_cast<LPARAM>(window_icon_.get()));
836 SendMessage(hwnd(), WM_SETICON, ICON_SMALL,
837 reinterpret_cast<LPARAM>(windows_icon)));
838 if (old_icon)
839 DestroyIcon(old_icon);
840 } 836 }
841 if (!app_icon.isNull()) { 837 if (!app_icon.isNull()) {
842 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); 838 base::win::ScopedHICON previous_icon = app_icon_.Pass();
843 HICON old_icon = reinterpret_cast<HICON>( 839 app_icon_ = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()).Pass();
844 SendMessage(hwnd(), WM_SETICON, ICON_BIG, 840 SendMessage(hwnd(), WM_SETICON, ICON_BIG,
845 reinterpret_cast<LPARAM>(windows_icon))); 841 reinterpret_cast<LPARAM>(app_icon_.get()));
846 if (old_icon)
847 DestroyIcon(old_icon);
848 } 842 }
849 } 843 }
850 844
851 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { 845 void HWNDMessageHandler::SetFullscreen(bool fullscreen) {
852 fullscreen_handler()->SetFullscreen(fullscreen); 846 fullscreen_handler()->SetFullscreen(fullscreen);
853 // If we are out of fullscreen and there was a pending DWM transition for the 847 // If we are out of fullscreen and there was a pending DWM transition for the
854 // window, then go ahead and do it now. 848 // window, then go ahead and do it now.
855 if (!fullscreen && dwm_transition_desired_) 849 if (!fullscreen && dwm_transition_desired_)
856 PerformDwmTransition(); 850 PerformDwmTransition();
857 } 851 }
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 return true; 1108 return true;
1115 } 1109 }
1116 1110
1117 void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) { 1111 void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
1118 // A native frame uses the native window region, and we don't want to mess 1112 // A native frame uses the native window region, and we don't want to mess
1119 // with it. 1113 // with it.
1120 // WS_EX_COMPOSITED is used instead of WS_EX_LAYERED under aura. WS_EX_LAYERED 1114 // WS_EX_COMPOSITED is used instead of WS_EX_LAYERED under aura. WS_EX_LAYERED
1121 // automatically makes clicks on transparent pixels fall through, that isn't 1115 // automatically makes clicks on transparent pixels fall through, that isn't
1122 // the case with WS_EX_COMPOSITED. So, we route WS_EX_COMPOSITED through to 1116 // the case with WS_EX_COMPOSITED. So, we route WS_EX_COMPOSITED through to
1123 // the delegate to allow for a custom hit mask. 1117 // the delegate to allow for a custom hit mask.
1124 if ((window_ex_style() & WS_EX_COMPOSITED) == 0 && !custom_window_region_ && 1118 if ((window_ex_style() & WS_EX_COMPOSITED) == 0 &&
1119 !custom_window_region_.is_valid() &&
1125 (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow())) { 1120 (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow())) {
1126 if (force) 1121 if (force)
1127 SetWindowRgn(hwnd(), NULL, redraw); 1122 SetWindowRgn(hwnd(), NULL, redraw);
1128 return; 1123 return;
1129 } 1124 }
1130 1125
1131 // Changing the window region is going to force a paint. Only change the 1126 // Changing the window region is going to force a paint. Only change the
1132 // window region if the region really differs. 1127 // window region if the region really differs.
1133 base::win::ScopedRegion current_rgn(CreateRectRgn(0, 0, 0, 0)); 1128 base::win::ScopedRegion current_rgn(CreateRectRgn(0, 0, 0, 0));
1134 GetWindowRgn(hwnd(), current_rgn); 1129 GetWindowRgn(hwnd(), current_rgn.get());
1135 1130
1136 RECT window_rect; 1131 RECT window_rect;
1137 GetWindowRect(hwnd(), &window_rect); 1132 GetWindowRect(hwnd(), &window_rect);
1138 base::win::ScopedRegion new_region; 1133 base::win::ScopedRegion new_region;
1139 if (custom_window_region_) { 1134 if (custom_window_region_.is_valid()) {
1140 new_region.Set(::CreateRectRgn(0, 0, 0, 0)); 1135 new_region.reset(CreateRectRgn(0, 0, 0, 0));
1141 ::CombineRgn(new_region, custom_window_region_.Get(), NULL, RGN_COPY); 1136 CombineRgn(new_region.get(), custom_window_region_.get(), NULL, RGN_COPY);
1142 } else if (IsMaximized()) { 1137 } else if (IsMaximized()) {
1143 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST); 1138 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST);
1144 MONITORINFO mi; 1139 MONITORINFO mi;
1145 mi.cbSize = sizeof mi; 1140 mi.cbSize = sizeof mi;
1146 GetMonitorInfo(monitor, &mi); 1141 GetMonitorInfo(monitor, &mi);
1147 RECT work_rect = mi.rcWork; 1142 RECT work_rect = mi.rcWork;
1148 OffsetRect(&work_rect, -window_rect.left, -window_rect.top); 1143 OffsetRect(&work_rect, -window_rect.left, -window_rect.top);
1149 new_region.Set(CreateRectRgnIndirect(&work_rect)); 1144 new_region.reset(CreateRectRgnIndirect(&work_rect));
1150 } else { 1145 } else {
1151 gfx::Path window_mask; 1146 gfx::Path window_mask;
1152 delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left, 1147 delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left,
1153 window_rect.bottom - window_rect.top), 1148 window_rect.bottom - window_rect.top),
1154 &window_mask); 1149 &window_mask);
1155 if (!window_mask.isEmpty()) 1150 if (!window_mask.isEmpty())
1156 new_region.Set(gfx::CreateHRGNFromSkPath(window_mask)); 1151 new_region.reset(gfx::CreateHRGNFromSkPath(window_mask));
1157 } 1152 }
1158 1153
1159 const bool has_current_region = current_rgn != 0; 1154 const bool has_current_region = current_rgn != 0;
1160 const bool has_new_region = new_region != 0; 1155 const bool has_new_region = new_region != 0;
1161 if (has_current_region != has_new_region || 1156 if (has_current_region != has_new_region ||
1162 (has_current_region && !EqualRgn(current_rgn, new_region))) { 1157 (has_current_region && !EqualRgn(current_rgn.get(), new_region.get()))) {
1163 // SetWindowRgn takes ownership of the HRGN. 1158 // SetWindowRgn takes ownership of the HRGN.
1164 SetWindowRgn(hwnd(), new_region.release(), redraw); 1159 SetWindowRgn(hwnd(), new_region.release(), redraw);
1165 } 1160 }
1166 } 1161 }
1167 1162
1168 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() { 1163 void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() {
1169 if (base::win::GetVersion() < base::win::VERSION_VISTA) 1164 if (base::win::GetVersion() < base::win::VERSION_VISTA)
1170 return; 1165 return;
1171 1166
1172 if (fullscreen_handler_->fullscreen()) 1167 if (fullscreen_handler_->fullscreen())
1173 return; 1168 return;
1174 1169
1175 DWMNCRENDERINGPOLICY policy = 1170 DWMNCRENDERINGPOLICY policy =
1176 custom_window_region_ || delegate_->IsUsingCustomFrame() ? 1171 custom_window_region_.is_valid() || delegate_->IsUsingCustomFrame()
1177 DWMNCRP_DISABLED : DWMNCRP_ENABLED; 1172 ? DWMNCRP_DISABLED
1173 : DWMNCRP_ENABLED;
1178 1174
1179 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, 1175 DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY,
1180 &policy, sizeof(DWMNCRENDERINGPOLICY)); 1176 &policy, sizeof(DWMNCRENDERINGPOLICY));
1181 } 1177 }
1182 1178
1183 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, 1179 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
1184 WPARAM w_param, 1180 WPARAM w_param,
1185 LPARAM l_param) { 1181 LPARAM l_param) {
1186 ScopedRedrawLock lock(this); 1182 ScopedRedrawLock lock(this);
1187 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use 1183 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use
(...skipping 1382 matching lines...) Expand 10 before | Expand all | Expand 10 after
2570 2566
2571 default: 2567 default:
2572 left_button_down_on_caption_ = false; 2568 left_button_down_on_caption_ = false;
2573 break; 2569 break;
2574 } 2570 }
2575 return handled; 2571 return handled;
2576 } 2572 }
2577 2573
2578 2574
2579 } // namespace views 2575 } // 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