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

Side by Side Diff: ui/views/corewm/tooltip_controller.cc

Issue 274753002: Ignores mouse motion events when mouse is pressed or drag and drop is in progress (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « ui/views/corewm/tooltip_controller.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/corewm/tooltip_controller.h" 5 #include "ui/views/corewm/tooltip_controller.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 10 matching lines...) Expand all
21 #include "ui/views/widget/tooltip_manager.h" 21 #include "ui/views/widget/tooltip_manager.h"
22 #include "ui/wm/public/drag_drop_client.h" 22 #include "ui/wm/public/drag_drop_client.h"
23 23
24 namespace views { 24 namespace views {
25 namespace corewm { 25 namespace corewm {
26 namespace { 26 namespace {
27 27
28 const int kTooltipTimeoutMs = 500; 28 const int kTooltipTimeoutMs = 500;
29 const int kDefaultTooltipShownTimeoutMs = 10000; 29 const int kDefaultTooltipShownTimeoutMs = 10000;
30 30
31 // Delay mouse events so that they are dispatched if there are no mouse location
32 // events pending. Even a short delay delays them until the mouse is steady.
33 const int kMouseMoveDelay = 10;
34
31 // Returns true if |target| is a valid window to get the tooltip from. 35 // Returns true if |target| is a valid window to get the tooltip from.
32 // |event_target| is the original target from the event and |target| the window 36 // |event_target| is the original target from the event and |target| the window
33 // at the same location. 37 // at the same location.
34 bool IsValidTarget(aura::Window* event_target, aura::Window* target) { 38 bool IsValidTarget(aura::Window* event_target, aura::Window* target) {
35 if (!target || (event_target == target)) 39 if (!target || (event_target == target))
36 return true; 40 return true;
37 41
38 void* event_target_grouping_id = event_target->GetNativeWindowProperty( 42 void* event_target_grouping_id = event_target->GetNativeWindowProperty(
39 TooltipManager::kGroupingPropertyKey); 43 TooltipManager::kGroupingPropertyKey);
40 void* target_grouping_id = target->GetNativeWindowProperty( 44 void* target_grouping_id = target->GetNativeWindowProperty(
41 TooltipManager::kGroupingPropertyKey); 45 TooltipManager::kGroupingPropertyKey);
42 return event_target_grouping_id && 46 return event_target_grouping_id &&
43 event_target_grouping_id == target_grouping_id; 47 event_target_grouping_id == target_grouping_id;
44 } 48 }
45 49
46 // Returns the target (the Window tooltip text comes from) based on the event. 50 // Returns the target (the Window tooltip text comes from) based on the event.
47 // If a Window other than event.target() is returned, |location| is adjusted 51 // If a Window other than event.target() is returned, |location| is adjusted
48 // to be in the coordinates of the returned Window. 52 // to be in the coordinates of the returned Window.
49 aura::Window* GetTooltipTarget(const ui::MouseEvent& event, 53 aura::Window* GetTooltipTarget(ui::EventType event_type,
54 aura::Window* target,
50 gfx::Point* location) { 55 gfx::Point* location) {
51 switch (event.type()) { 56 switch (event_type) {
52 case ui::ET_MOUSE_CAPTURE_CHANGED: 57 case ui::ET_MOUSE_CAPTURE_CHANGED:
53 // On windows we can get a capture changed without an exit. We need to 58 // On windows we can get a capture changed without an exit. We need to
54 // reset state when this happens else the tooltip may incorrectly show. 59 // reset state when this happens else the tooltip may incorrectly show.
55 return NULL; 60 return NULL;
56 case ui::ET_MOUSE_EXITED: 61 case ui::ET_MOUSE_EXITED:
57 return NULL; 62 return NULL;
58 case ui::ET_MOUSE_MOVED: 63 case ui::ET_MOUSE_MOVED:
59 case ui::ET_MOUSE_DRAGGED: { 64 case ui::ET_MOUSE_DRAGGED: {
60 aura::Window* event_target = static_cast<aura::Window*>(event.target()); 65 aura::Window* event_target = target;
61 if (!event_target) 66 if (!event_target)
62 return NULL; 67 return NULL;
63 68
64 // If a window other than |event_target| has capture, ignore the event. 69 // If a window other than |event_target| has capture, ignore the event.
65 // This can happen when RootWindow creates events when showing/hiding, or 70 // This can happen when RootWindow creates events when showing/hiding, or
66 // the system generates an extra event. We have to check 71 // the system generates an extra event. We have to check
67 // GetGlobalCaptureWindow() as Windows does not use a singleton 72 // GetGlobalCaptureWindow() as Windows does not use a singleton
68 // CaptureClient. 73 // CaptureClient.
69 if (!event_target->HasCapture()) { 74 if (!event_target->HasCapture()) {
70 aura::Window* root = event_target->GetRootWindow(); 75 aura::Window* root = event_target->GetRootWindow();
71 if (root) { 76 if (root) {
72 aura::client::CaptureClient* capture_client = 77 aura::client::CaptureClient* capture_client =
73 aura::client::GetCaptureClient(root); 78 aura::client::GetCaptureClient(root);
74 if (capture_client) { 79 if (capture_client) {
75 aura::Window* capture_window = 80 aura::Window* capture_window =
76 capture_client->GetGlobalCaptureWindow(); 81 capture_client->GetGlobalCaptureWindow();
77 if (capture_window && event_target != capture_window) 82 if (capture_window && event_target != capture_window)
78 return NULL; 83 return NULL;
79 } 84 }
80 } 85 }
81 return event_target; 86 return event_target;
82 } 87 }
83 88
84 // If |target| has capture all events go to it, even if the mouse is 89 // If |target| has capture all events go to it, even if the mouse is
85 // really over another window. Find the real window the mouse is over. 90 // really over another window. Find the real window the mouse is over.
86 gfx::Point screen_loc(event.location()); 91 gfx::Point screen_loc(*location);
87 aura::client::GetScreenPositionClient(event_target->GetRootWindow())-> 92 aura::client::GetScreenPositionClient(event_target->GetRootWindow())->
88 ConvertPointToScreen(event_target, &screen_loc); 93 ConvertPointToScreen(event_target, &screen_loc);
89 gfx::Screen* screen = gfx::Screen::GetScreenFor(event_target); 94 gfx::Screen* screen = gfx::Screen::GetScreenFor(event_target);
90 aura::Window* target = screen->GetWindowAtScreenPoint(screen_loc); 95 aura::Window* target = screen->GetWindowAtScreenPoint(screen_loc);
91 if (!target) 96 if (!target)
92 return NULL; 97 return NULL;
93 gfx::Point target_loc(screen_loc); 98 gfx::Point target_loc(screen_loc);
94 aura::client::GetScreenPositionClient(target->GetRootWindow())-> 99 aura::client::GetScreenPositionClient(target->GetRootWindow())->
95 ConvertPointFromScreen(target, &target_loc); 100 ConvertPointFromScreen(target, &target_loc);
96 aura::Window* screen_target = target->GetEventHandlerForPoint(target_loc); 101 aura::Window* screen_target = target->GetEventHandlerForPoint(target_loc);
97 if (!IsValidTarget(event_target, screen_target)) 102 if (!IsValidTarget(event_target, screen_target))
pkotwicz 2014/05/07 22:45:08 Idea: It might be useful to check whether there ar
varkha 2014/05/07 23:08:18 This may speed this method but with the throttling
98 return NULL; 103 return NULL;
99 104
100 aura::Window::ConvertPointToTarget(screen_target, target, &target_loc); 105 aura::Window::ConvertPointToTarget(screen_target, target, &target_loc);
101 *location = target_loc; 106 *location = target_loc;
102 return screen_target; 107 return screen_target;
103 } 108 }
104 default: 109 default:
105 NOTREACHED(); 110 NOTREACHED();
106 break; 111 break;
107 } 112 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 TooltipShownTimerFired(); 183 TooltipShownTimerFired();
179 } 184 }
180 } 185 }
181 186
182 void TooltipController::OnMouseEvent(ui::MouseEvent* event) { 187 void TooltipController::OnMouseEvent(ui::MouseEvent* event) {
183 switch (event->type()) { 188 switch (event->type()) {
184 case ui::ET_MOUSE_CAPTURE_CHANGED: 189 case ui::ET_MOUSE_CAPTURE_CHANGED:
185 case ui::ET_MOUSE_EXITED: 190 case ui::ET_MOUSE_EXITED:
186 case ui::ET_MOUSE_MOVED: 191 case ui::ET_MOUSE_MOVED:
187 case ui::ET_MOUSE_DRAGGED: { 192 case ui::ET_MOUSE_DRAGGED: {
188 curr_mouse_loc_ = event->location(); 193 last_mouse_location_ = event->location();
189 aura::Window* target = GetTooltipTarget(*event, &curr_mouse_loc_); 194 mouse_event_timer_.Start(
190 SetTooltipWindow(target); 195 FROM_HERE,
191 if (tooltip_timer_.IsRunning()) 196 base::TimeDelta::FromMilliseconds(kMouseMoveDelay),
192 tooltip_timer_.Reset(); 197 base::Bind(&TooltipController::DispatchMouseEvent,
sky 2014/05/08 19:05:55 What happens if we enter some sort of nested messa
varkha 2014/05/13 19:30:55 We would need to synchronously process any pending
193 198 base::Unretained(this),
194 if (tooltip_->IsVisible()) 199 event->type(),
195 UpdateIfRequired(); 200 static_cast<aura::Window*>(event->target())));
sky 2014/05/08 19:05:55 What if window is destroyed between now and when t
varkha 2014/05/13 19:30:55 We could maintain a set of windows for which we ha
196 break; 201 break;
197 } 202 }
198 case ui::ET_MOUSE_PRESSED: 203 case ui::ET_MOUSE_PRESSED:
199 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) { 204 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) {
sky 2014/05/08 19:05:55 If you process the above async and this (and whell
varkha 2014/05/13 19:30:55 It could. It should be easy to just call a sync di
200 aura::Window* target = static_cast<aura::Window*>(event->target()); 205 aura::Window* target = static_cast<aura::Window*>(event->target());
201 // We don't get a release for non-client areas. 206 // We don't get a release for non-client areas.
202 tooltip_window_at_mouse_press_ = target; 207 tooltip_window_at_mouse_press_ = target;
203 if (target) 208 if (target)
204 tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target); 209 tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target);
205 } 210 }
206 tooltip_->Hide(); 211 tooltip_->Hide();
207 break; 212 break;
208 case ui::ET_MOUSEWHEEL: 213 case ui::ET_MOUSEWHEEL:
209 // Hide the tooltip for click, release, drag, wheel events. 214 // Hide the tooltip for click, release, drag, wheel events.
(...skipping 22 matching lines...) Expand all
232 if (tooltip_window_ == window) { 237 if (tooltip_window_ == window) {
233 tooltip_->Hide(); 238 tooltip_->Hide();
234 tooltip_shown_timeout_map_.erase(tooltip_window_); 239 tooltip_shown_timeout_map_.erase(tooltip_window_);
235 tooltip_window_ = NULL; 240 tooltip_window_ = NULL;
236 } 241 }
237 } 242 }
238 243
239 //////////////////////////////////////////////////////////////////////////////// 244 ////////////////////////////////////////////////////////////////////////////////
240 // TooltipController private: 245 // TooltipController private:
241 246
247 void TooltipController::DispatchMouseEvent(ui::EventType event_type,
248 aura::Window* target) {
249 curr_mouse_loc_ = last_mouse_location_;
250 target = GetTooltipTarget(event_type, target, &curr_mouse_loc_);
251 SetTooltipWindow(target);
252 if (tooltip_timer_.IsRunning())
253 tooltip_timer_.Reset();
254
255 if (tooltip_->IsVisible())
256 UpdateIfRequired();
257 }
258
242 void TooltipController::TooltipTimerFired() { 259 void TooltipController::TooltipTimerFired() {
243 UpdateIfRequired(); 260 UpdateIfRequired();
244 } 261 }
245 262
246 void TooltipController::TooltipShownTimerFired() { 263 void TooltipController::TooltipShownTimerFired() {
247 tooltip_->Hide(); 264 tooltip_->Hide();
248 265
249 // Since the user presumably no longer needs the tooltip, we also stop the 266 // Since the user presumably no longer needs the tooltip, we also stop the
250 // tooltip timer so that tooltip does not pop back up. We will restart this 267 // tooltip timer so that tooltip does not pop back up. We will restart this
251 // timer if the tooltip changes (see UpdateTooltip()). 268 // timer if the tooltip changes (see UpdateTooltip()).
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 return; 361 return;
345 if (tooltip_window_) 362 if (tooltip_window_)
346 tooltip_window_->RemoveObserver(this); 363 tooltip_window_->RemoveObserver(this);
347 tooltip_window_ = target; 364 tooltip_window_ = target;
348 if (tooltip_window_) 365 if (tooltip_window_)
349 tooltip_window_->AddObserver(this); 366 tooltip_window_->AddObserver(this);
350 } 367 }
351 368
352 } // namespace corewm 369 } // namespace corewm
353 } // namespace views 370 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/corewm/tooltip_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698