Chromium Code Reviews| 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/controls/button/menu_button.h" | 5 #include "ui/views/controls/button/menu_button.h" |
| 6 | 6 |
| 7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "ui/accessibility/ax_view_state.h" | 8 #include "ui/accessibility/ax_view_state.h" |
| 9 #include "ui/base/dragdrop/drag_drop_types.h" | 9 #include "ui/base/dragdrop/drag_drop_types.h" |
| 10 #include "ui/base/l10n/l10n_util.h" | 10 #include "ui/base/l10n/l10n_util.h" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 } | 164 } |
| 165 return prefsize; | 165 return prefsize; |
| 166 } | 166 } |
| 167 | 167 |
| 168 const char* MenuButton::GetClassName() const { | 168 const char* MenuButton::GetClassName() const { |
| 169 return kViewClassName; | 169 return kViewClassName; |
| 170 } | 170 } |
| 171 | 171 |
| 172 bool MenuButton::OnMousePressed(const ui::MouseEvent& event) { | 172 bool MenuButton::OnMousePressed(const ui::MouseEvent& event) { |
| 173 RequestFocus(); | 173 RequestFocus(); |
| 174 if (state() != STATE_DISABLED) { | 174 if (ShouldEnterPushedState(event) && HitTestPoint(event.location())) { |
| 175 // If we're draggable (GetDragOperations returns a non-zero value), then | 175 TimeDelta delta = TimeTicks::Now() - menu_closed_time_; |
| 176 // don't pop on press, instead wait for release. | 176 if (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks) |
| 177 if (event.IsOnlyLeftMouseButton() && | 177 return Activate(); |
| 178 HitTestPoint(event.location()) && | |
| 179 GetDragOperations(event.location()) == ui::DragDropTypes::DRAG_NONE) { | |
| 180 TimeDelta delta = TimeTicks::Now() - menu_closed_time_; | |
| 181 if (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks) | |
| 182 return Activate(); | |
| 183 } | |
| 184 } | 178 } |
| 185 return true; | 179 return true; |
| 186 } | 180 } |
| 187 | 181 |
| 188 void MenuButton::OnMouseReleased(const ui::MouseEvent& event) { | 182 void MenuButton::OnMouseReleased(const ui::MouseEvent& event) { |
| 189 // Explicitly test for left mouse button to show the menu. If we tested for | 183 if (ShouldEnterPushedState(event) && HitTestPoint(event.location())) |
| 190 // !IsTriggerableEvent it could lead to a situation where we end up showing | |
| 191 // the menu and context menu (this would happen if the right button is not | |
| 192 // triggerable and there's a context menu). | |
| 193 if (GetDragOperations(event.location()) != ui::DragDropTypes::DRAG_NONE && | |
| 194 state() != STATE_DISABLED && !InDrag() && event.IsOnlyLeftMouseButton() && | |
| 195 HitTestPoint(event.location())) { | |
| 196 Activate(); | 184 Activate(); |
| 197 } else { | 185 else |
| 198 LabelButton::OnMouseReleased(event); | 186 LabelButton::OnMouseReleased(event); |
| 199 } | |
| 200 } | 187 } |
| 201 | 188 |
| 202 void MenuButton::OnMouseEntered(const ui::MouseEvent& event) { | 189 void MenuButton::OnMouseEntered(const ui::MouseEvent& event) { |
| 203 if (pressed_lock_count_ == 0) // Ignore mouse movement if state is locked. | 190 if (pressed_lock_count_ == 0) // Ignore mouse movement if state is locked. |
| 204 CustomButton::OnMouseEntered(event); | 191 LabelButton::OnMouseEntered(event); |
| 205 } | 192 } |
| 206 | 193 |
| 207 void MenuButton::OnMouseExited(const ui::MouseEvent& event) { | 194 void MenuButton::OnMouseExited(const ui::MouseEvent& event) { |
| 208 if (pressed_lock_count_ == 0) // Ignore mouse movement if state is locked. | 195 if (pressed_lock_count_ == 0) // Ignore mouse movement if state is locked. |
| 209 CustomButton::OnMouseExited(event); | 196 LabelButton::OnMouseExited(event); |
| 210 } | 197 } |
| 211 | 198 |
| 212 void MenuButton::OnMouseMoved(const ui::MouseEvent& event) { | 199 void MenuButton::OnMouseMoved(const ui::MouseEvent& event) { |
| 213 if (pressed_lock_count_ == 0) // Ignore mouse movement if state is locked. | 200 if (pressed_lock_count_ == 0) // Ignore mouse movement if state is locked. |
| 214 CustomButton::OnMouseMoved(event); | 201 LabelButton::OnMouseMoved(event); |
| 215 } | 202 } |
| 216 | 203 |
| 217 void MenuButton::OnGestureEvent(ui::GestureEvent* event) { | 204 void MenuButton::OnGestureEvent(ui::GestureEvent* event) { |
| 218 if (state() != STATE_DISABLED && event->type() == ui::ET_GESTURE_TAP && | 205 if (ShouldEnterPushedState(*event) && !Activate()) { |
| 219 !Activate()) { | |
| 220 // When |Activate()| returns |false|, it means that a menu is shown and | 206 // When |Activate()| returns |false|, it means that a menu is shown and |
| 221 // has handled the gesture event. So, there is no need to further process | 207 // has handled the gesture event. So, there is no need to further process |
| 222 // the gesture event here. | 208 // the gesture event here. |
| 223 return; | 209 return; |
| 224 } | 210 } |
| 225 LabelButton::OnGestureEvent(event); | 211 LabelButton::OnGestureEvent(event); |
| 226 } | 212 } |
| 227 | 213 |
| 228 bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) { | 214 bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) { |
| 229 switch (event.key_code()) { | 215 switch (event.key_code()) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 gfx::Size s = size(); | 266 gfx::Size s = size(); |
| 281 | 267 |
| 282 if (show_menu_marker_) { | 268 if (show_menu_marker_) { |
| 283 s.set_width(s.width() - menu_marker_->width() - kMenuMarkerPaddingLeft - | 269 s.set_width(s.width() - menu_marker_->width() - kMenuMarkerPaddingLeft - |
| 284 kMenuMarkerPaddingRight); | 270 kMenuMarkerPaddingRight); |
| 285 } | 271 } |
| 286 | 272 |
| 287 return gfx::Rect(s); | 273 return gfx::Rect(s); |
| 288 } | 274 } |
| 289 | 275 |
| 276 bool MenuButton::ShouldEnterPushedState(const ui::Event& event) { | |
| 277 if (state() == STATE_DISABLED) | |
|
sky
2014/10/14 20:05:06
This function shouldn't have to check disabled (ju
jonross
2014/10/14 21:42:17
Done.
| |
| 278 return false; | |
| 279 | |
| 280 if (event.IsMouseEvent()) { | |
| 281 const ui::MouseEvent& mouseev = static_cast<const ui::MouseEvent&>(event); | |
| 282 // Active on left mouse button only, to prevent a menu from being activated | |
| 283 // when a right-click would also activate a context menu. | |
| 284 if (!mouseev.IsOnlyLeftMouseButton()) | |
| 285 return false; | |
| 286 // If dragging is supported activate on release, otherwise activate on | |
| 287 // pressed. | |
| 288 ui::EventType active_on = | |
| 289 GetDragOperations(mouseev.location()) == ui::DragDropTypes::DRAG_NONE ? | |
| 290 ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED; | |
| 291 if (event.type() == active_on && !InDrag()) | |
|
sky
2014/10/14 20:05:06
I also think InDrag should be checked in the call
jonross
2014/10/14 21:42:17
Done.
| |
| 292 return true; | |
| 293 } | |
| 294 | |
| 295 if (event.type() == ui::ET_GESTURE_TAP) | |
|
sky
2014/10/14 20:05:06
nit: return event.type() == ET_GESTURE_TAP.
jonross
2014/10/14 21:42:17
Done.
| |
| 296 return true; | |
| 297 | |
| 298 return false; | |
| 299 } | |
| 300 | |
| 290 void MenuButton::IncrementPressedLocked() { | 301 void MenuButton::IncrementPressedLocked() { |
| 291 ++pressed_lock_count_; | 302 ++pressed_lock_count_; |
| 292 SetState(STATE_PRESSED); | 303 SetState(STATE_PRESSED); |
| 293 } | 304 } |
| 294 | 305 |
| 295 void MenuButton::DecrementPressedLocked() { | 306 void MenuButton::DecrementPressedLocked() { |
| 296 --pressed_lock_count_; | 307 --pressed_lock_count_; |
| 297 DCHECK_GE(pressed_lock_count_, 0); | 308 DCHECK_GE(pressed_lock_count_, 0); |
| 298 | 309 |
| 299 // If this was the last lock, manually reset state to "normal". We set | 310 // If this was the last lock, manually reset state to "normal". We set |
| 300 // "normal" and not "hot" because the likelihood is that the mouse is now | 311 // "normal" and not "hot" because the likelihood is that the mouse is now |
| 301 // somewhere else (user clicked elsewhere on screen to close the menu or | 312 // somewhere else (user clicked elsewhere on screen to close the menu or |
| 302 // selected an item) and we will inevitably refresh the hot state in the event | 313 // selected an item) and we will inevitably refresh the hot state in the event |
| 303 // the mouse _is_ over the view. | 314 // the mouse _is_ over the view. |
| 304 if (pressed_lock_count_ == 0) | 315 if (pressed_lock_count_ == 0) |
| 305 SetState(STATE_NORMAL); | 316 SetState(STATE_NORMAL); |
| 306 } | 317 } |
| 307 | 318 |
| 308 int MenuButton::GetMaximumScreenXCoordinate() { | 319 int MenuButton::GetMaximumScreenXCoordinate() { |
| 309 if (!GetWidget()) { | 320 if (!GetWidget()) { |
| 310 NOTREACHED(); | 321 NOTREACHED(); |
| 311 return 0; | 322 return 0; |
| 312 } | 323 } |
| 313 | 324 |
| 314 gfx::Rect monitor_bounds = GetWidget()->GetWorkAreaBoundsInScreen(); | 325 gfx::Rect monitor_bounds = GetWidget()->GetWorkAreaBoundsInScreen(); |
| 315 return monitor_bounds.right() - 1; | 326 return monitor_bounds.right() - 1; |
| 316 } | 327 } |
| 317 | 328 |
| 318 } // namespace views | 329 } // namespace views |
| OLD | NEW |