| 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 <tchar.h> | 10 #include <tchar.h> |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // The solution is to handle these messages and call DefWindowProc ourselves, | 250 // The solution is to handle these messages and call DefWindowProc ourselves, |
| 251 // but prevent the window from being able to update itself for the duration of | 251 // but prevent the window from being able to update itself for the duration of |
| 252 // the call. We do this with this class, which automatically calls its | 252 // the call. We do this with this class, which automatically calls its |
| 253 // associated Window's lock and unlock functions as it is created and destroyed. | 253 // associated Window's lock and unlock functions as it is created and destroyed. |
| 254 // See documentation in those methods for the technique used. | 254 // See documentation in those methods for the technique used. |
| 255 // | 255 // |
| 256 // The lock only has an effect if the window was visible upon lock creation, as | 256 // The lock only has an effect if the window was visible upon lock creation, as |
| 257 // it doesn't guard against direct visiblility changes, and multiple locks may | 257 // it doesn't guard against direct visiblility changes, and multiple locks may |
| 258 // exist simultaneously to handle certain nested Windows messages. | 258 // exist simultaneously to handle certain nested Windows messages. |
| 259 // | 259 // |
| 260 // This lock is disabled when DirectComposition is used and there's a child |
| 261 // rendering window, as the WS_CLIPCHILDREN on the parent window should |
| 262 // prevent the glitched rendering and making the window contents non-visible |
| 263 // can cause a them to disappear for a frame. |
| 264 // |
| 265 // We normally skip locked updates when Aero is on for two reasons: |
| 266 // 1. Because it isn't necessary. However, for windows without WS_CAPTION a |
| 267 // close button may still be drawn, so the resize lock remains enabled for |
| 268 // them. See http://crrev.com/130323 |
| 269 // 2. Because toggling the WS_VISIBLE flag may occur while the GPU process is |
| 270 // attempting to present a child window's backbuffer onscreen. When these |
| 271 // two actions race with one another, the child window will either flicker |
| 272 // or will simply stop updating entirely. |
| 273 // |
| 260 // IMPORTANT: Do not use this scoping object for large scopes or periods of | 274 // IMPORTANT: Do not use this scoping object for large scopes or periods of |
| 261 // time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh). | 275 // time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh). |
| 262 // | 276 // |
| 263 // I would love to hear Raymond Chen's explanation for all this. And maybe a | 277 // I would love to hear Raymond Chen's explanation for all this. And maybe a |
| 264 // list of other messages that this applies to ;-) | 278 // list of other messages that this applies to ;-) |
| 265 class HWNDMessageHandler::ScopedRedrawLock { | 279 class HWNDMessageHandler::ScopedRedrawLock { |
| 266 public: | 280 public: |
| 267 explicit ScopedRedrawLock(HWNDMessageHandler* owner) | 281 explicit ScopedRedrawLock(HWNDMessageHandler* owner) |
| 268 : owner_(owner), | 282 : owner_(owner), |
| 269 hwnd_(owner_->hwnd()), | 283 hwnd_(owner_->hwnd()), |
| 270 was_visible_(owner_->IsVisible()), | 284 cancel_unlock_(false), |
| 271 cancel_unlock_(false), | 285 should_lock_(owner_->IsVisible() && !owner->HasChildRenderingWindow() && |
| 272 force_(!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION)) { | 286 ::IsWindow(hwnd_) && |
| 273 if (was_visible_ && ::IsWindow(hwnd_)) | 287 (!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION) || |
| 274 owner_->LockUpdates(force_); | 288 !ui::win::IsAeroGlassEnabled())) { |
| 289 if (should_lock_) |
| 290 owner_->LockUpdates(); |
| 275 } | 291 } |
| 276 | 292 |
| 277 ~ScopedRedrawLock() { | 293 ~ScopedRedrawLock() { |
| 278 if (!cancel_unlock_ && was_visible_ && ::IsWindow(hwnd_)) | 294 if (!cancel_unlock_ && should_lock_ && ::IsWindow(hwnd_)) |
| 279 owner_->UnlockUpdates(force_); | 295 owner_->UnlockUpdates(); |
| 280 } | 296 } |
| 281 | 297 |
| 282 // Cancel the unlock operation, call this if the Widget is being destroyed. | 298 // Cancel the unlock operation, call this if the Widget is being destroyed. |
| 283 void CancelUnlockOperation() { cancel_unlock_ = true; } | 299 void CancelUnlockOperation() { cancel_unlock_ = true; } |
| 284 | 300 |
| 285 private: | 301 private: |
| 286 // The owner having its style changed. | 302 // The owner having its style changed. |
| 287 HWNDMessageHandler* owner_; | 303 HWNDMessageHandler* owner_; |
| 288 // The owner's HWND, cached to avoid action after window destruction. | 304 // The owner's HWND, cached to avoid action after window destruction. |
| 289 HWND hwnd_; | 305 HWND hwnd_; |
| 290 // Records the HWND visibility at the time of creation. | |
| 291 bool was_visible_; | |
| 292 // A flag indicating that the unlock operation was canceled. | 306 // A flag indicating that the unlock operation was canceled. |
| 293 bool cancel_unlock_; | 307 bool cancel_unlock_; |
| 294 // If true, perform the redraw lock regardless of Aero state. | 308 // If false, don't use redraw lock. |
| 295 bool force_; | 309 const bool should_lock_; |
| 296 | 310 |
| 297 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock); | 311 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock); |
| 298 }; | 312 }; |
| 299 | 313 |
| 300 // static HWNDMessageHandler member initialization. | 314 // static HWNDMessageHandler member initialization. |
| 301 base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap> | 315 base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap> |
| 302 HWNDMessageHandler::fullscreen_monitor_map_ = LAZY_INSTANCE_INITIALIZER; | 316 HWNDMessageHandler::fullscreen_monitor_map_ = LAZY_INSTANCE_INITIALIZER; |
| 303 | 317 |
| 304 //////////////////////////////////////////////////////////////////////////////// | 318 //////////////////////////////////////////////////////////////////////////////// |
| 305 // HWNDMessageHandler, public: | 319 // HWNDMessageHandler, public: |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 ScopedRedrawLock lock(this); | 1232 ScopedRedrawLock lock(this); |
| 1219 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use | 1233 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use |
| 1220 // the WeakPtrFactory to avoid unlocking (and crashing) after destruction. | 1234 // the WeakPtrFactory to avoid unlocking (and crashing) after destruction. |
| 1221 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); | 1235 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); |
| 1222 LRESULT result = DefWindowProc(hwnd(), message, w_param, l_param); | 1236 LRESULT result = DefWindowProc(hwnd(), message, w_param, l_param); |
| 1223 if (!ref) | 1237 if (!ref) |
| 1224 lock.CancelUnlockOperation(); | 1238 lock.CancelUnlockOperation(); |
| 1225 return result; | 1239 return result; |
| 1226 } | 1240 } |
| 1227 | 1241 |
| 1228 void HWNDMessageHandler::LockUpdates(bool force) { | 1242 void HWNDMessageHandler::LockUpdates() { |
| 1229 // We skip locked updates when Aero is on for two reasons: | 1243 if (++lock_updates_count_ == 1) { |
| 1230 // 1. Because it isn't necessary | |
| 1231 // 2. Because toggling the WS_VISIBLE flag may occur while the GPU process is | |
| 1232 // attempting to present a child window's backbuffer onscreen. When these | |
| 1233 // two actions race with one another, the child window will either flicker | |
| 1234 // or will simply stop updating entirely. | |
| 1235 if ((force || !ui::win::IsAeroGlassEnabled()) && ++lock_updates_count_ == 1) { | |
| 1236 SetWindowLong(hwnd(), GWL_STYLE, | 1244 SetWindowLong(hwnd(), GWL_STYLE, |
| 1237 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_VISIBLE); | 1245 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_VISIBLE); |
| 1238 } | 1246 } |
| 1239 } | 1247 } |
| 1240 | 1248 |
| 1241 void HWNDMessageHandler::UnlockUpdates(bool force) { | 1249 void HWNDMessageHandler::UnlockUpdates() { |
| 1242 if ((force || !ui::win::IsAeroGlassEnabled()) && --lock_updates_count_ <= 0) { | 1250 if (--lock_updates_count_ <= 0) { |
| 1243 SetWindowLong(hwnd(), GWL_STYLE, | 1251 SetWindowLong(hwnd(), GWL_STYLE, |
| 1244 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE); | 1252 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE); |
| 1245 lock_updates_count_ = 0; | 1253 lock_updates_count_ = 0; |
| 1246 } | 1254 } |
| 1247 } | 1255 } |
| 1248 | 1256 |
| 1249 void HWNDMessageHandler::ForceRedrawWindow(int attempts) { | 1257 void HWNDMessageHandler::ForceRedrawWindow(int attempts) { |
| 1250 if (ui::IsWorkstationLocked()) { | 1258 if (ui::IsWorkstationLocked()) { |
| 1251 // Presents will continue to fail as long as the input desktop is | 1259 // Presents will continue to fail as long as the input desktop is |
| 1252 // unavailable. | 1260 // unavailable. |
| (...skipping 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2749 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 2757 MONITORINFO monitor_info = {sizeof(monitor_info)}; |
| 2750 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 2758 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
| 2751 &monitor_info); | 2759 &monitor_info); |
| 2752 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | 2760 gfx::Rect shrunk_rect(monitor_info.rcMonitor); |
| 2753 shrunk_rect.set_height(shrunk_rect.height() - 1); | 2761 shrunk_rect.set_height(shrunk_rect.height() - 1); |
| 2754 background_fullscreen_hack_ = true; | 2762 background_fullscreen_hack_ = true; |
| 2755 SetBoundsInternal(shrunk_rect, false); | 2763 SetBoundsInternal(shrunk_rect, false); |
| 2756 } | 2764 } |
| 2757 | 2765 |
| 2758 } // namespace views | 2766 } // namespace views |
| OLD | NEW |