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

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

Issue 1143333002: Revert "Correctly release the touch events on Lenovo Horizon device." (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months 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') | ui/views/win/hwnd_message_handler_unittest.cc » ('j') | 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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/logging.h"
14 #include "base/profiler/scoped_tracker.h" 13 #include "base/profiler/scoped_tracker.h"
15 #include "base/trace_event/trace_event.h" 14 #include "base/trace_event/trace_event.h"
16 #include "base/tracked_objects.h" 15 #include "base/tracked_objects.h"
17 #include "base/win/scoped_gdi_object.h" 16 #include "base/win/scoped_gdi_object.h"
18 #include "base/win/win_util.h" 17 #include "base/win/win_util.h"
19 #include "base/win/windows_version.h" 18 #include "base/win/windows_version.h"
20 #include "ui/base/touch/touch_enabled.h" 19 #include "ui/base/touch/touch_enabled.h"
21 #include "ui/base/view_prop.h" 20 #include "ui/base/view_prop.h"
22 #include "ui/base/win/internal_constants.h" 21 #include "ui/base/win/internal_constants.h"
23 #include "ui/base/win/lock_state.h" 22 #include "ui/base/win/lock_state.h"
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 last_monitor_(NULL), 321 last_monitor_(NULL),
323 is_first_nccalc_(true), 322 is_first_nccalc_(true),
324 menu_depth_(0), 323 menu_depth_(0),
325 id_generator_(0), 324 id_generator_(0),
326 needs_scroll_styles_(false), 325 needs_scroll_styles_(false),
327 in_size_loop_(false), 326 in_size_loop_(false),
328 touch_down_contexts_(0), 327 touch_down_contexts_(0),
329 last_mouse_hwheel_time_(0), 328 last_mouse_hwheel_time_(0),
330 msg_handled_(FALSE), 329 msg_handled_(FALSE),
331 dwm_transition_desired_(false), 330 dwm_transition_desired_(false),
332 active_touch_point_count_(0),
333 autohide_factory_(this), 331 autohide_factory_(this),
334 weak_factory_(this) { 332 weak_factory_(this) {
335 } 333 }
336 334
337 HWNDMessageHandler::~HWNDMessageHandler() { 335 HWNDMessageHandler::~HWNDMessageHandler() {
338 delegate_ = NULL; 336 delegate_ = NULL;
339 // Prevent calls back into this class via WNDPROC now that we've been 337 // Prevent calls back into this class via WNDPROC now that we've been
340 // destroyed. 338 // destroyed.
341 ClearUserData(); 339 ClearUserData();
342 } 340 }
(...skipping 1953 matching lines...) Expand 10 before | Expand all | Expand 10 after
2296 tracked_objects::ScopedTracker tracking_profile( 2294 tracked_objects::ScopedTracker tracking_profile(
2297 FROM_HERE_WITH_EXPLICIT_FUNCTION( 2295 FROM_HERE_WITH_EXPLICIT_FUNCTION(
2298 "440919 HWNDMessageHandler::OnTouchEvent")); 2296 "440919 HWNDMessageHandler::OnTouchEvent"));
2299 2297
2300 // Handle touch events only on Aura for now. 2298 // Handle touch events only on Aura for now.
2301 int num_points = LOWORD(w_param); 2299 int num_points = LOWORD(w_param);
2302 scoped_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]); 2300 scoped_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
2303 if (ui::GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param), 2301 if (ui::GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param),
2304 num_points, input.get(), 2302 num_points, input.get(),
2305 sizeof(TOUCHINPUT))) { 2303 sizeof(TOUCHINPUT))) {
2304 int flags = ui::GetModifiersFromKeyState();
2305 TouchEvents touch_events;
2306 for (int i = 0; i < num_points; ++i) { 2306 for (int i = 0; i < num_points; ++i) {
2307 POINT point; 2307 POINT point;
2308 point.x = TOUCH_COORD_TO_PIXEL(input[i].x); 2308 point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
2309 point.y = TOUCH_COORD_TO_PIXEL(input[i].y); 2309 point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
2310 2310
2311 if (base::win::GetVersion() == base::win::VERSION_WIN7) { 2311 if (base::win::GetVersion() == base::win::VERSION_WIN7) {
2312 // Windows 7 sends touch events for touches in the non-client area, 2312 // Windows 7 sends touch events for touches in the non-client area,
2313 // whereas Windows 8 does not. In order to unify the behaviour, always 2313 // whereas Windows 8 does not. In order to unify the behaviour, always
2314 // ignore touch events in the non-client area. 2314 // ignore touch events in the non-client area.
2315 LPARAM l_param_ht = MAKELPARAM(point.x, point.y); 2315 LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
2316 LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht); 2316 LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht);
2317 2317
2318 if (hittest != HTCLIENT) 2318 if (hittest != HTCLIENT)
2319 return 0; 2319 return 0;
2320 } 2320 }
2321
2322 ScreenToClient(hwnd(), &point);
2323
2324 last_touch_message_time_ = ::GetMessageTime();
2325
2326 ui::EventType touch_event_type = ui::ET_UNKNOWN;
2327
2328 if (input[i].dwFlags & TOUCHEVENTF_DOWN) {
2329 touch_ids_.insert(input[i].dwID);
2330 touch_event_type = ui::ET_TOUCH_PRESSED;
2331 touch_down_contexts_++;
2332 base::MessageLoop::current()->PostDelayedTask(
2333 FROM_HERE,
2334 base::Bind(&HWNDMessageHandler::ResetTouchDownContext,
2335 weak_factory_.GetWeakPtr()),
2336 base::TimeDelta::FromMilliseconds(kTouchDownContextResetTimeout));
2337 } else if (input[i].dwFlags & TOUCHEVENTF_UP) {
2338 touch_ids_.erase(input[i].dwID);
2339 touch_event_type = ui::ET_TOUCH_RELEASED;
2340 } else if (input[i].dwFlags & TOUCHEVENTF_MOVE) {
2341 touch_event_type = ui::ET_TOUCH_MOVED;
2342 }
2343 if (touch_event_type != ui::ET_UNKNOWN) {
2344 // input[i].dwTime doesn't necessarily relate to the system time at all,
2345 // so use base::TimeTicks::Now()
2346 const base::TimeTicks now = base::TimeTicks::Now();
2347 ui::TouchEvent event(touch_event_type,
2348 gfx::Point(point.x, point.y),
2349 id_generator_.GetGeneratedID(input[i].dwID),
2350 now - base::TimeTicks());
2351 event.set_flags(flags);
2352 event.latency()->AddLatencyNumberWithTimestamp(
2353 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
2354 0,
2355 0,
2356 base::TimeTicks::FromInternalValue(
2357 event.time_stamp().ToInternalValue()),
2358 1);
2359
2360 touch_events.push_back(event);
2361 if (touch_event_type == ui::ET_TOUCH_RELEASED)
2362 id_generator_.ReleaseNumber(input[i].dwID);
2363 }
2321 } 2364 }
2322 TouchEvents touch_events;
2323 int old_touch_down_contexts = touch_down_contexts_;
2324 PrepareTouchEventList(input.get(), num_points, &touch_events);
2325 int new_touch_presses = touch_down_contexts_ - old_touch_down_contexts;
2326 if (new_touch_presses > 0) {
2327 base::MessageLoop::current()->PostDelayedTask(
2328 FROM_HERE, base::Bind(&HWNDMessageHandler::DecrementTouchDownContext,
2329 weak_factory_.GetWeakPtr(), new_touch_presses),
2330 base::TimeDelta::FromMilliseconds(kTouchDownContextResetTimeout));
2331 }
2332
2333 // Handle the touch events asynchronously. We need this because touch 2365 // Handle the touch events asynchronously. We need this because touch
2334 // events on windows don't fire if we enter a modal loop in the context of 2366 // events on windows don't fire if we enter a modal loop in the context of
2335 // a touch event. 2367 // a touch event.
2336 base::MessageLoop::current()->PostTask( 2368 base::MessageLoop::current()->PostTask(
2337 FROM_HERE, 2369 FROM_HERE,
2338 base::Bind(&HWNDMessageHandler::HandleTouchEvents, 2370 base::Bind(&HWNDMessageHandler::HandleTouchEvents,
2339 weak_factory_.GetWeakPtr(), touch_events)); 2371 weak_factory_.GetWeakPtr(), touch_events));
2340 } 2372 }
2341 CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(l_param)); 2373 CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(l_param));
2342 SetMsgHandled(FALSE); 2374 SetMsgHandled(FALSE);
2343 return 0; 2375 return 0;
2344 } 2376 }
2345 2377
2346 void HWNDMessageHandler::PrepareTouchEventList(TOUCHINPUT input[],
2347 int num_points,
2348 TouchEvents* touch_events) {
2349 for (int i = 0; i < num_points; ++i) {
2350 POINT point;
2351 point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
2352 point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
2353 gfx::Point point_location(point.x, point.y);
2354
2355 ScreenToClient(hwnd(), &point);
2356
2357 // TOUCHEVENTF_DOWN cannot be combined with TOUCHEVENTF_MOVE or
2358 // TOUCHEVENTF_UP, but TOUCHEVENTF_MOVE and TOUCHEVENTF_UP can be combined
2359 // in one input.
2360 if (input[i].dwFlags & TOUCHEVENTF_DOWN) {
2361 touch_down_contexts_++;
2362 active_touch_point_count_++;
2363 GenerateTouchEvent(input[i].dwID, point_location, ui::ET_TOUCH_PRESSED,
2364 touch_events);
2365 } else {
2366 if (input[i].dwFlags & TOUCHEVENTF_MOVE) {
2367 GenerateTouchEvent(input[i].dwID, point_location, ui::ET_TOUCH_MOVED,
2368 touch_events);
2369 }
2370 if (input[i].dwFlags & TOUCHEVENTF_UP) {
2371 active_touch_point_count_--;
2372 GenerateTouchEvent(input[i].dwID, point_location, ui::ET_TOUCH_RELEASED,
2373 touch_events);
2374 }
2375 }
2376 }
2377 last_touch_message_time_ = ::GetMessageTime();
2378
2379 UpdateTouchPointStates(touch_events);
2380 }
2381
2382 void HWNDMessageHandler::GenerateTouchEvent(DWORD input_dwID,
2383 const gfx::Point& point_location,
2384 ui::EventType touch_event_type,
2385 TouchEvents* touch_events) {
2386 int touch_id = static_cast<int>(id_generator_.GetGeneratedID(input_dwID));
2387 if (touch_id < 0 || touch_id >= static_cast<int>(touch_id_list_.size())) {
2388 return;
2389 }
2390
2391 TouchPoint& touch_point = touch_id_list_[touch_id];
2392 int flags = ui::GetModifiersFromKeyState();
2393
2394 // The dwTime of every input in the WM_TOUCH message doesn't necessarily
2395 // relate to the system time at all, so use base::TimeTicks::Now() for
2396 // touchevent time.
2397 base::TimeDelta now = ui::EventTimeForNow();
2398
2399 // We set a check to assert that we do not have missing touch presses in
2400 // every message.
2401 bool has_missing_touch_press = touch_event_type != ui::ET_TOUCH_PRESSED &&
2402 touch_point.in_touch_list == InTouchList::NotPresent;
2403 CHECK(!has_missing_touch_press) << "There are missing touch presses";
2404
2405 ui::TouchEvent event(touch_event_type, point_location, touch_id, now);
2406 event.set_flags(flags);
2407 event.latency()->AddLatencyNumberWithTimestamp(
2408 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, base::TimeTicks::Now(),
2409 1);
2410 touch_events->push_back(event);
2411
2412 // Mark the active touch pointers in the touch_id_list_ to be
2413 // InCurrentMessage, so we can track the ones which are missed in the
2414 // current message and release them.
2415 if (touch_event_type == ui::ET_TOUCH_RELEASED) {
2416 id_generator_.ReleaseNumber(input_dwID);
2417 touch_point.in_touch_list = InTouchList::NotPresent;
2418 } else {
2419 touch_point.in_touch_list = InTouchList::InCurrentMessage;
2420 touch_point.location = point_location;
2421 }
2422 }
2423
2424 void HWNDMessageHandler::UpdateTouchPointStates(TouchEvents* touch_events) {
2425 for (size_t i = 0; i != touch_id_list_.size(); ++i) {
2426 // Loop through the touch pointers list, if we see any which is only in
2427 // the previous message, we will send a touch release event for this ID.
2428 TouchPoint& touch_point = touch_id_list_[i];
2429 if (touch_point.in_touch_list == InTouchList::InPreviousMessage) {
2430 base::TimeDelta now = base::TimeTicks::Now() - base::TimeTicks();
2431 ui::TouchEvent event(ui::ET_TOUCH_RELEASED, touch_point.location,
2432 static_cast<int>(i), now);
2433 touch_events->push_back(event);
2434 touch_point.in_touch_list = InTouchList::NotPresent;
2435 id_generator_.ReleaseGeneratedID(i);
2436 active_touch_point_count_--;
2437 } else if (touch_point.in_touch_list == InTouchList::InCurrentMessage) {
2438 touch_point.in_touch_list = InTouchList::InPreviousMessage;
2439 }
2440 }
2441 }
2442
2443 void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { 2378 void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
2444 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. 2379 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
2445 tracked_objects::ScopedTracker tracking_profile( 2380 tracked_objects::ScopedTracker tracking_profile(
2446 FROM_HERE_WITH_EXPLICIT_FUNCTION( 2381 FROM_HERE_WITH_EXPLICIT_FUNCTION(
2447 "440919 HWNDMessageHandler::OnWindowPosChanging")); 2382 "440919 HWNDMessageHandler::OnWindowPosChanging"));
2448 2383
2449 if (ignore_window_pos_changes_) { 2384 if (ignore_window_pos_changes_) {
2450 // If somebody's trying to toggle our visibility, change the nonclient area, 2385 // If somebody's trying to toggle our visibility, change the nonclient area,
2451 // change our Z-order, or activate us, we should probably let it go through. 2386 // change our Z-order, or activate us, we should probably let it go through.
2452 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | 2387 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2567 if (status_code == WTS_SESSION_UNLOCK) 2502 if (status_code == WTS_SESSION_UNLOCK)
2568 ForceRedrawWindow(10); 2503 ForceRedrawWindow(10);
2569 } 2504 }
2570 2505
2571 void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) { 2506 void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) {
2572 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); 2507 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
2573 for (size_t i = 0; i < touch_events.size() && ref; ++i) 2508 for (size_t i = 0; i < touch_events.size() && ref; ++i)
2574 delegate_->HandleTouchEvent(touch_events[i]); 2509 delegate_->HandleTouchEvent(touch_events[i]);
2575 } 2510 }
2576 2511
2577 void HWNDMessageHandler::DecrementTouchDownContext(int decrement) { 2512 void HWNDMessageHandler::ResetTouchDownContext() {
2578 touch_down_contexts_ -= decrement; 2513 touch_down_contexts_--;
2579 } 2514 }
2580 2515
2581 LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message, 2516 LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
2582 WPARAM w_param, 2517 WPARAM w_param,
2583 LPARAM l_param, 2518 LPARAM l_param,
2584 bool track_mouse) { 2519 bool track_mouse) {
2585 if (active_touch_point_count_) 2520 if (!touch_ids_.empty())
2586 return 0; 2521 return 0;
2587 2522
2588 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. 2523 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
2589 tracked_objects::ScopedTracker tracking_profile1( 2524 tracked_objects::ScopedTracker tracking_profile1(
2590 FROM_HERE_WITH_EXPLICIT_FUNCTION( 2525 FROM_HERE_WITH_EXPLICIT_FUNCTION(
2591 "440919 HWNDMessageHandler::HandleMouseEventInternal1")); 2526 "440919 HWNDMessageHandler::HandleMouseEventInternal1"));
2592 2527
2593 // We handle touch events on Windows Aura. Windows generates synthesized 2528 // We handle touch events on Windows Aura. Windows generates synthesized
2594 // mouse messages in response to touch which we should ignore. However touch 2529 // mouse messages in response to touch which we should ignore. However touch
2595 // messages are only received for the client area. We need to ignore the 2530 // messages are only received for the client area. We need to ignore the
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW); 2736 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW);
2802 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW); 2737 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW);
2803 } 2738 }
2804 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want 2739 // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want
2805 // to notify our children too, since we can have MDI child windows who need to 2740 // to notify our children too, since we can have MDI child windows who need to
2806 // update their appearance. 2741 // update their appearance.
2807 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL); 2742 EnumChildWindows(hwnd(), &SendDwmCompositionChanged, NULL);
2808 } 2743 }
2809 2744
2810 } // namespace views 2745 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | ui/views/win/hwnd_message_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698