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 | 10 |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 remove_standard_frame_(false), | 312 remove_standard_frame_(false), |
313 use_system_default_icon_(false), | 313 use_system_default_icon_(false), |
314 restored_enabled_(false), | 314 restored_enabled_(false), |
315 current_cursor_(NULL), | 315 current_cursor_(NULL), |
316 previous_cursor_(NULL), | 316 previous_cursor_(NULL), |
317 active_mouse_tracking_flags_(0), | 317 active_mouse_tracking_flags_(0), |
318 is_right_mouse_pressed_on_caption_(false), | 318 is_right_mouse_pressed_on_caption_(false), |
319 lock_updates_count_(0), | 319 lock_updates_count_(0), |
320 ignore_window_pos_changes_(false), | 320 ignore_window_pos_changes_(false), |
321 last_monitor_(NULL), | 321 last_monitor_(NULL), |
322 use_layered_buffer_(false), | |
323 layered_alpha_(255), | |
324 waiting_for_redraw_layered_window_contents_(false), | |
325 is_first_nccalc_(true), | 322 is_first_nccalc_(true), |
326 menu_depth_(0), | 323 menu_depth_(0), |
327 id_generator_(0), | 324 id_generator_(0), |
328 needs_scroll_styles_(false), | 325 needs_scroll_styles_(false), |
329 in_size_loop_(false), | 326 in_size_loop_(false), |
330 touch_down_contexts_(0), | 327 touch_down_contexts_(0), |
331 last_mouse_hwheel_time_(0), | 328 last_mouse_hwheel_time_(0), |
332 msg_handled_(FALSE), | 329 msg_handled_(FALSE), |
333 dwm_transition_desired_(false), | 330 dwm_transition_desired_(false), |
334 autohide_factory_(this), | 331 autohide_factory_(this), |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 delegate_->HandleFrameChanged(); | 778 delegate_->HandleFrameChanged(); |
782 InvalidateRect(hwnd(), NULL, FALSE); | 779 InvalidateRect(hwnd(), NULL, FALSE); |
783 } else { | 780 } else { |
784 if (!custom_window_region_ && !delegate_->IsUsingCustomFrame()) | 781 if (!custom_window_region_ && !delegate_->IsUsingCustomFrame()) |
785 dwm_transition_desired_ = true; | 782 dwm_transition_desired_ = true; |
786 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen()) | 783 if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen()) |
787 PerformDwmTransition(); | 784 PerformDwmTransition(); |
788 } | 785 } |
789 } | 786 } |
790 | 787 |
791 void HWNDMessageHandler::SchedulePaintInRect(const gfx::Rect& rect) { | |
792 if (use_layered_buffer_) { | |
793 // We must update the back-buffer immediately, since Windows' handling of | |
794 // invalid rects is somewhat mysterious. | |
795 invalid_rect_.Union(rect); | |
796 | |
797 // In some situations, such as drag and drop, when Windows itself runs a | |
798 // nested message loop our message loop appears to be starved and we don't | |
799 // receive calls to DidProcessMessage(). This only seems to affect layered | |
800 // windows, so we schedule a redraw manually using a task, since those never | |
801 // seem to be starved. Also, wtf. | |
802 if (!waiting_for_redraw_layered_window_contents_) { | |
803 waiting_for_redraw_layered_window_contents_ = true; | |
804 base::MessageLoop::current()->PostTask( | |
805 FROM_HERE, | |
806 base::Bind(&HWNDMessageHandler::RedrawLayeredWindowContents, | |
807 weak_factory_.GetWeakPtr())); | |
808 } | |
809 } else { | |
810 // InvalidateRect() expects client coordinates. | |
811 RECT r = rect.ToRECT(); | |
812 InvalidateRect(hwnd(), &r, FALSE); | |
813 } | |
814 } | |
815 | |
816 void HWNDMessageHandler::SetOpacity(BYTE opacity) { | |
817 layered_alpha_ = opacity; | |
818 } | |
819 | |
820 void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, | 788 void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, |
821 const gfx::ImageSkia& app_icon) { | 789 const gfx::ImageSkia& app_icon) { |
822 if (!window_icon.isNull()) { | 790 if (!window_icon.isNull()) { |
823 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap( | 791 HICON windows_icon = IconUtil::CreateHICONFromSkBitmap( |
824 *window_icon.bitmap()); | 792 *window_icon.bitmap()); |
825 // We need to make sure to destroy the previous icon, otherwise we'll leak | 793 // We need to make sure to destroy the previous icon, otherwise we'll leak |
826 // these GDI objects until we crash! | 794 // these GDI objects until we crash! |
827 HICON old_icon = reinterpret_cast<HICON>( | 795 HICON old_icon = reinterpret_cast<HICON>( |
828 SendMessage(hwnd(), WM_SETICON, ICON_SMALL, | 796 SendMessage(hwnd(), WM_SETICON, ICON_SMALL, |
829 reinterpret_cast<LPARAM>(windows_icon))); | 797 reinterpret_cast<LPARAM>(windows_icon))); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 TrackMouseEvent(&tme); | 1069 TrackMouseEvent(&tme); |
1102 } else if (mouse_tracking_flags != active_mouse_tracking_flags_) { | 1070 } else if (mouse_tracking_flags != active_mouse_tracking_flags_) { |
1103 TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL); | 1071 TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL); |
1104 TrackMouseEvents(mouse_tracking_flags); | 1072 TrackMouseEvents(mouse_tracking_flags); |
1105 } | 1073 } |
1106 } | 1074 } |
1107 | 1075 |
1108 void HWNDMessageHandler::ClientAreaSizeChanged() { | 1076 void HWNDMessageHandler::ClientAreaSizeChanged() { |
1109 gfx::Size s = GetClientAreaBounds().size(); | 1077 gfx::Size s = GetClientAreaBounds().size(); |
1110 delegate_->HandleClientSizeChanged(s); | 1078 delegate_->HandleClientSizeChanged(s); |
1111 if (use_layered_buffer_) | |
1112 layered_window_contents_.reset(new gfx::Canvas(s, 1.0f, false)); | |
1113 } | 1079 } |
1114 | 1080 |
1115 bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { | 1081 bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { |
1116 if (delegate_->GetClientAreaInsets(insets)) | 1082 if (delegate_->GetClientAreaInsets(insets)) |
1117 return true; | 1083 return true; |
1118 DCHECK(insets->empty()); | 1084 DCHECK(insets->empty()); |
1119 | 1085 |
1120 // Returning false causes the default handling in OnNCCalcSize() to | 1086 // Returning false causes the default handling in OnNCCalcSize() to |
1121 // be invoked. | 1087 // be invoked. |
1122 if (!delegate_->IsWidgetWindow() || | 1088 if (!delegate_->IsWidgetWindow() || |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1232 } | 1198 } |
1233 | 1199 |
1234 void HWNDMessageHandler::UnlockUpdates(bool force) { | 1200 void HWNDMessageHandler::UnlockUpdates(bool force) { |
1235 if ((force || !ui::win::IsAeroGlassEnabled()) && --lock_updates_count_ <= 0) { | 1201 if ((force || !ui::win::IsAeroGlassEnabled()) && --lock_updates_count_ <= 0) { |
1236 SetWindowLong(hwnd(), GWL_STYLE, | 1202 SetWindowLong(hwnd(), GWL_STYLE, |
1237 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE); | 1203 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE); |
1238 lock_updates_count_ = 0; | 1204 lock_updates_count_ = 0; |
1239 } | 1205 } |
1240 } | 1206 } |
1241 | 1207 |
1242 void HWNDMessageHandler::RedrawLayeredWindowContents() { | |
1243 waiting_for_redraw_layered_window_contents_ = false; | |
1244 if (invalid_rect_.IsEmpty()) | |
1245 return; | |
1246 | |
1247 // We need to clip to the dirty rect ourselves. | |
1248 layered_window_contents_->sk_canvas()->save(); | |
1249 double scale = gfx::GetDPIScale(); | |
1250 layered_window_contents_->sk_canvas()->scale( | |
1251 SkScalar(scale),SkScalar(scale)); | |
1252 layered_window_contents_->ClipRect(invalid_rect_); | |
1253 delegate_->PaintLayeredWindow(layered_window_contents_.get()); | |
1254 layered_window_contents_->sk_canvas()->scale( | |
1255 SkScalar(1.0/scale),SkScalar(1.0/scale)); | |
1256 layered_window_contents_->sk_canvas()->restore(); | |
1257 | |
1258 RECT wr; | |
1259 GetWindowRect(hwnd(), &wr); | |
1260 SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; | |
1261 POINT position = {wr.left, wr.top}; | |
1262 HDC dib_dc = skia::BeginPlatformPaint(layered_window_contents_->sk_canvas()); | |
1263 POINT zero = {0, 0}; | |
1264 BLENDFUNCTION blend = {AC_SRC_OVER, 0, layered_alpha_, AC_SRC_ALPHA}; | |
1265 UpdateLayeredWindow(hwnd(), NULL, &position, &size, dib_dc, &zero, | |
1266 RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); | |
1267 invalid_rect_.SetRect(0, 0, 0, 0); | |
1268 skia::EndPlatformPaint(layered_window_contents_->sk_canvas()); | |
1269 } | |
1270 | |
1271 void HWNDMessageHandler::ForceRedrawWindow(int attempts) { | 1208 void HWNDMessageHandler::ForceRedrawWindow(int attempts) { |
1272 if (ui::IsWorkstationLocked()) { | 1209 if (ui::IsWorkstationLocked()) { |
1273 // Presents will continue to fail as long as the input desktop is | 1210 // Presents will continue to fail as long as the input desktop is |
1274 // unavailable. | 1211 // unavailable. |
1275 if (--attempts <= 0) | 1212 if (--attempts <= 0) |
1276 return; | 1213 return; |
1277 base::MessageLoop::current()->PostDelayedTask( | 1214 base::MessageLoop::current()->PostDelayedTask( |
1278 FROM_HERE, | 1215 FROM_HERE, |
1279 base::Bind(&HWNDMessageHandler::ForceRedrawWindow, | 1216 base::Bind(&HWNDMessageHandler::ForceRedrawWindow, |
1280 weak_factory_.GetWeakPtr(), | 1217 weak_factory_.GetWeakPtr(), |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 // should ignore it. | 1295 // should ignore it. |
1359 if (notification_code > 1 || delegate_->HandleAppCommand(command)) | 1296 if (notification_code > 1 || delegate_->HandleAppCommand(command)) |
1360 SetMsgHandled(FALSE); | 1297 SetMsgHandled(FALSE); |
1361 } | 1298 } |
1362 | 1299 |
1363 LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) { | 1300 LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) { |
1364 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. | 1301 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. |
1365 tracked_objects::ScopedTracker tracking_profile1( | 1302 tracked_objects::ScopedTracker tracking_profile1( |
1366 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate1")); | 1303 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate1")); |
1367 | 1304 |
1368 use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED); | |
1369 | |
1370 if (window_ex_style() & WS_EX_COMPOSITED) { | 1305 if (window_ex_style() & WS_EX_COMPOSITED) { |
1371 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. | 1306 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. |
1372 tracked_objects::ScopedTracker tracking_profile2( | 1307 tracked_objects::ScopedTracker tracking_profile2( |
1373 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 1308 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
1374 "440919 HWNDMessageHandler::OnCreate2")); | 1309 "440919 HWNDMessageHandler::OnCreate2")); |
1375 | 1310 |
1376 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 1311 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
1377 // This is part of the magic to emulate layered windows with Aura | 1312 // This is part of the magic to emulate layered windows with Aura |
1378 // see the explanation elsewere when we set WS_EX_COMPOSITED style. | 1313 // see the explanation elsewere when we set WS_EX_COMPOSITED style. |
1379 MARGINS margins = {-1,-1,-1,-1}; | 1314 MARGINS margins = {-1,-1,-1,-1}; |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2047 } else { | 1982 } else { |
2048 RECT rgn_bounding_box; | 1983 RECT rgn_bounding_box; |
2049 GetRgnBox(rgn, &rgn_bounding_box); | 1984 GetRgnBox(rgn, &rgn_bounding_box); |
2050 if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect)) | 1985 if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect)) |
2051 return; // Dirty region doesn't intersect window bounds, bale. | 1986 return; // Dirty region doesn't intersect window bounds, bale. |
2052 | 1987 |
2053 // rgn_bounding_box is in screen coordinates. Map it to window coordinates. | 1988 // rgn_bounding_box is in screen coordinates. Map it to window coordinates. |
2054 OffsetRect(&dirty_region, -window_rect.left, -window_rect.top); | 1989 OffsetRect(&dirty_region, -window_rect.left, -window_rect.top); |
2055 } | 1990 } |
2056 | 1991 |
2057 gfx::Rect old_paint_region = invalid_rect_; | |
2058 if (!old_paint_region.IsEmpty()) { | |
2059 // The root view has a region that needs to be painted. Include it in the | |
2060 // region we're going to paint. | |
2061 | |
2062 RECT old_paint_region_crect = old_paint_region.ToRECT(); | |
2063 RECT tmp = dirty_region; | |
2064 UnionRect(&dirty_region, &tmp, &old_paint_region_crect); | |
2065 } | |
2066 | |
2067 SchedulePaintInRect(gfx::Rect(dirty_region)); | |
2068 delegate_->HandlePaintAccelerated(gfx::Rect(dirty_region)); | 1992 delegate_->HandlePaintAccelerated(gfx::Rect(dirty_region)); |
2069 | 1993 |
2070 // When using a custom frame, we want to avoid calling DefWindowProc() since | 1994 // When using a custom frame, we want to avoid calling DefWindowProc() since |
2071 // that may render artifacts. | 1995 // that may render artifacts. |
2072 SetMsgHandled(delegate_->IsUsingCustomFrame()); | 1996 SetMsgHandled(delegate_->IsUsingCustomFrame()); |
2073 } | 1997 } |
2074 | 1998 |
2075 LRESULT HWNDMessageHandler::OnNCUAHDrawCaption(UINT message, | 1999 LRESULT HWNDMessageHandler::OnNCUAHDrawCaption(UINT message, |
2076 WPARAM w_param, | 2000 WPARAM w_param, |
2077 LPARAM l_param) { | 2001 LPARAM l_param) { |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2808 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW); | 2732 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW); |
2809 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW); | 2733 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW); |
2810 } | 2734 } |
2811 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want | 2735 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want |
2812 // to notify our children too, since we can have MDI child windows who need to | 2736 // to notify our children too, since we can have MDI child windows who need to |
2813 // update their appearance. | 2737 // update their appearance. |
2814 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL); | 2738 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL); |
2815 } | 2739 } |
2816 | 2740 |
2817 } // namespace views | 2741 } // namespace views |
OLD | NEW |