| 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> |
| 11 | 11 |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/debug/alias.h" | 16 #include "base/debug/alias.h" |
| 17 #include "base/location.h" | 17 #include "base/location.h" |
| 18 #include "base/macros.h" | 18 #include "base/macros.h" |
| 19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
| 22 #include "base/win/scoped_gdi_object.h" | 22 #include "base/win/scoped_gdi_object.h" |
| 23 #include "base/win/windows_version.h" | 23 #include "base/win/windows_version.h" |
| 24 #include "ui/base/touch/touch_enabled.h" | |
| 25 #include "ui/base/view_prop.h" | 24 #include "ui/base/view_prop.h" |
| 26 #include "ui/base/win/internal_constants.h" | 25 #include "ui/base/win/internal_constants.h" |
| 27 #include "ui/base/win/lock_state.h" | 26 #include "ui/base/win/lock_state.h" |
| 28 #include "ui/base/win/mouse_wheel_util.h" | 27 #include "ui/base/win/mouse_wheel_util.h" |
| 29 #include "ui/base/win/shell.h" | 28 #include "ui/base/win/shell.h" |
| 30 #include "ui/base/win/touch_input.h" | 29 #include "ui/base/win/touch_input.h" |
| 31 #include "ui/display/win/dpi.h" | 30 #include "ui/display/win/dpi.h" |
| 32 #include "ui/display/win/screen_win.h" | 31 #include "ui/display/win/screen_win.h" |
| 33 #include "ui/events/event.h" | 32 #include "ui/events/event.h" |
| 34 #include "ui/events/event_utils.h" | 33 #include "ui/events/event_utils.h" |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // The solution is to handle these messages and call DefWindowProc ourselves, | 249 // 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 | 250 // 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 | 251 // 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. | 252 // associated Window's lock and unlock functions as it is created and destroyed. |
| 254 // See documentation in those methods for the technique used. | 253 // See documentation in those methods for the technique used. |
| 255 // | 254 // |
| 256 // The lock only has an effect if the window was visible upon lock creation, as | 255 // 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 | 256 // it doesn't guard against direct visiblility changes, and multiple locks may |
| 258 // exist simultaneously to handle certain nested Windows messages. | 257 // exist simultaneously to handle certain nested Windows messages. |
| 259 // | 258 // |
| 259 // This lock is disabled when DirectComposition is used and there's a child |
| 260 // rendering window, as the WS_CLIPCHILDREN on the parent window should |
| 261 // prevent the glitched rendering and making the window contents non-visible |
| 262 // can cause a them to disappear for a frame. |
| 263 // |
| 264 // We normally skip locked updates when Aero is on for two reasons: |
| 265 // 1. Because it isn't necessary. However, for windows without WS_CAPTION a |
| 266 // close button may still be drawn, so the resize lock remains enabled for |
| 267 // them. See http://crrev.com/130323 |
| 268 // 2. Because toggling the WS_VISIBLE flag may occur while the GPU process is |
| 269 // attempting to present a child window's backbuffer onscreen. When these |
| 270 // two actions race with one another, the child window will either flicker |
| 271 // or will simply stop updating entirely. |
| 272 // |
| 260 // IMPORTANT: Do not use this scoping object for large scopes or periods of | 273 // IMPORTANT: Do not use this scoping object for large scopes or periods of |
| 261 // time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh). | 274 // time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh). |
| 262 // | 275 // |
| 263 // I would love to hear Raymond Chen's explanation for all this. And maybe a | 276 // I would love to hear Raymond Chen's explanation for all this. And maybe a |
| 264 // list of other messages that this applies to ;-) | 277 // list of other messages that this applies to ;-) |
| 265 class HWNDMessageHandler::ScopedRedrawLock { | 278 class HWNDMessageHandler::ScopedRedrawLock { |
| 266 public: | 279 public: |
| 267 explicit ScopedRedrawLock(HWNDMessageHandler* owner) | 280 explicit ScopedRedrawLock(HWNDMessageHandler* owner) |
| 268 : owner_(owner), | 281 : owner_(owner), |
| 269 hwnd_(owner_->hwnd()), | 282 hwnd_(owner_->hwnd()), |
| 270 was_visible_(owner_->IsVisible()), | 283 cancel_unlock_(false), |
| 271 cancel_unlock_(false), | 284 should_lock_(owner_->IsVisible() && !owner->HasChildRenderingWindow() && |
| 272 force_(!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION)) { | 285 ::IsWindow(hwnd_) && |
| 273 if (was_visible_ && ::IsWindow(hwnd_)) | 286 (!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION) || |
| 274 owner_->LockUpdates(force_); | 287 !ui::win::IsAeroGlassEnabled())) { |
| 288 if (should_lock_) |
| 289 owner_->LockUpdates(); |
| 275 } | 290 } |
| 276 | 291 |
| 277 ~ScopedRedrawLock() { | 292 ~ScopedRedrawLock() { |
| 278 if (!cancel_unlock_ && was_visible_ && ::IsWindow(hwnd_)) | 293 if (!cancel_unlock_ && should_lock_ && ::IsWindow(hwnd_)) |
| 279 owner_->UnlockUpdates(force_); | 294 owner_->UnlockUpdates(); |
| 280 } | 295 } |
| 281 | 296 |
| 282 // Cancel the unlock operation, call this if the Widget is being destroyed. | 297 // Cancel the unlock operation, call this if the Widget is being destroyed. |
| 283 void CancelUnlockOperation() { cancel_unlock_ = true; } | 298 void CancelUnlockOperation() { cancel_unlock_ = true; } |
| 284 | 299 |
| 285 private: | 300 private: |
| 286 // The owner having its style changed. | 301 // The owner having its style changed. |
| 287 HWNDMessageHandler* owner_; | 302 HWNDMessageHandler* owner_; |
| 288 // The owner's HWND, cached to avoid action after window destruction. | 303 // The owner's HWND, cached to avoid action after window destruction. |
| 289 HWND hwnd_; | 304 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. | 305 // A flag indicating that the unlock operation was canceled. |
| 293 bool cancel_unlock_; | 306 bool cancel_unlock_; |
| 294 // If true, perform the redraw lock regardless of Aero state. | 307 // If false, don't use redraw lock. |
| 295 bool force_; | 308 const bool should_lock_; |
| 296 | 309 |
| 297 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock); | 310 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock); |
| 298 }; | 311 }; |
| 299 | 312 |
| 300 // static HWNDMessageHandler member initialization. | 313 // static HWNDMessageHandler member initialization. |
| 301 base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap> | 314 base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap> |
| 302 HWNDMessageHandler::fullscreen_monitor_map_ = LAZY_INSTANCE_INITIALIZER; | 315 HWNDMessageHandler::fullscreen_monitor_map_ = LAZY_INSTANCE_INITIALIZER; |
| 303 | 316 |
| 304 //////////////////////////////////////////////////////////////////////////////// | 317 //////////////////////////////////////////////////////////////////////////////// |
| 305 // HWNDMessageHandler, public: | 318 // HWNDMessageHandler, public: |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 ScopedRedrawLock lock(this); | 1231 ScopedRedrawLock lock(this); |
| 1219 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use | 1232 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use |
| 1220 // the WeakPtrFactory to avoid unlocking (and crashing) after destruction. | 1233 // the WeakPtrFactory to avoid unlocking (and crashing) after destruction. |
| 1221 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); | 1234 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); |
| 1222 LRESULT result = DefWindowProc(hwnd(), message, w_param, l_param); | 1235 LRESULT result = DefWindowProc(hwnd(), message, w_param, l_param); |
| 1223 if (!ref) | 1236 if (!ref) |
| 1224 lock.CancelUnlockOperation(); | 1237 lock.CancelUnlockOperation(); |
| 1225 return result; | 1238 return result; |
| 1226 } | 1239 } |
| 1227 | 1240 |
| 1228 void HWNDMessageHandler::LockUpdates(bool force) { | 1241 void HWNDMessageHandler::LockUpdates() { |
| 1229 // We skip locked updates when Aero is on for two reasons: | 1242 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, | 1243 SetWindowLong(hwnd(), GWL_STYLE, |
| 1237 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_VISIBLE); | 1244 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_VISIBLE); |
| 1238 } | 1245 } |
| 1239 } | 1246 } |
| 1240 | 1247 |
| 1241 void HWNDMessageHandler::UnlockUpdates(bool force) { | 1248 void HWNDMessageHandler::UnlockUpdates() { |
| 1242 if ((force || !ui::win::IsAeroGlassEnabled()) && --lock_updates_count_ <= 0) { | 1249 if (--lock_updates_count_ <= 0) { |
| 1243 SetWindowLong(hwnd(), GWL_STYLE, | 1250 SetWindowLong(hwnd(), GWL_STYLE, |
| 1244 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE); | 1251 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE); |
| 1245 lock_updates_count_ = 0; | 1252 lock_updates_count_ = 0; |
| 1246 } | 1253 } |
| 1247 } | 1254 } |
| 1248 | 1255 |
| 1249 void HWNDMessageHandler::ForceRedrawWindow(int attempts) { | 1256 void HWNDMessageHandler::ForceRedrawWindow(int attempts) { |
| 1250 if (ui::IsWorkstationLocked()) { | 1257 if (ui::IsWorkstationLocked()) { |
| 1251 // Presents will continue to fail as long as the input desktop is | 1258 // Presents will continue to fail as long as the input desktop is |
| 1252 // unavailable. | 1259 // unavailable. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 | 1344 |
| 1338 if (!delegate_->HasFrame()) { | 1345 if (!delegate_->HasFrame()) { |
| 1339 SetWindowLong(hwnd(), GWL_STYLE, | 1346 SetWindowLong(hwnd(), GWL_STYLE, |
| 1340 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION); | 1347 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION); |
| 1341 SendFrameChanged(); | 1348 SendFrameChanged(); |
| 1342 } | 1349 } |
| 1343 | 1350 |
| 1344 // Get access to a modifiable copy of the system menu. | 1351 // Get access to a modifiable copy of the system menu. |
| 1345 GetSystemMenu(hwnd(), false); | 1352 GetSystemMenu(hwnd(), false); |
| 1346 | 1353 |
| 1347 if (ui::AreTouchEventsEnabled()) | 1354 RegisterTouchWindow(hwnd(), TWF_WANTPALM); |
| 1348 RegisterTouchWindow(hwnd(), TWF_WANTPALM); | |
| 1349 | 1355 |
| 1350 // We need to allow the delegate to size its contents since the window may not | 1356 // We need to allow the delegate to size its contents since the window may not |
| 1351 // receive a size notification when its initial bounds are specified at window | 1357 // receive a size notification when its initial bounds are specified at window |
| 1352 // creation time. | 1358 // creation time. |
| 1353 ClientAreaSizeChanged(); | 1359 ClientAreaSizeChanged(); |
| 1354 | 1360 |
| 1355 delegate_->HandleCreate(); | 1361 delegate_->HandleCreate(); |
| 1356 | 1362 |
| 1357 windows_session_change_observer_.reset(new WindowsSessionChangeObserver( | 1363 windows_session_change_observer_.reset(new WindowsSessionChangeObserver( |
| 1358 base::Bind(&HWNDMessageHandler::OnSessionChange, | 1364 base::Bind(&HWNDMessageHandler::OnSessionChange, |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2749 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 2755 MONITORINFO monitor_info = {sizeof(monitor_info)}; |
| 2750 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 2756 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
| 2751 &monitor_info); | 2757 &monitor_info); |
| 2752 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | 2758 gfx::Rect shrunk_rect(monitor_info.rcMonitor); |
| 2753 shrunk_rect.set_height(shrunk_rect.height() - 1); | 2759 shrunk_rect.set_height(shrunk_rect.height() - 1); |
| 2754 background_fullscreen_hack_ = true; | 2760 background_fullscreen_hack_ = true; |
| 2755 SetBoundsInternal(shrunk_rect, false); | 2761 SetBoundsInternal(shrunk_rect, false); |
| 2756 } | 2762 } |
| 2757 | 2763 |
| 2758 } // namespace views | 2764 } // namespace views |
| OLD | NEW |