15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/accessibility/accessible_view_state.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_drop_types.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_constants.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/button.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button_listener.h" 21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ui/views/mouse_constants.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/root_view.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using base::TimeTicks; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default menu offset. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultMenuOffsetX = -2; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultMenuOffsetY = -4; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 35a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst char MenuButton::kViewClassName[] = "MenuButton"; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int MenuButton::kMenuMarkerPaddingLeft = 3; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int MenuButton::kMenuMarkerPaddingRight = -1; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuButton - constructors, destructors, initialization 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuButton::MenuButton(ButtonListener* listener, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& text, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuButtonListener* menu_button_listener, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool show_menu_marker) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : TextButton(listener, text), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_visible_(false), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_offset_(kDefaultMenuOffsetX, kDefaultMenuOffsetY), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_(menu_button_listener), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_marker_(show_menu_marker), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_marker_(ui::ResourceBundle::GetSharedInstance().GetImageNamed( 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_MENU_DROPARROW).ToImageSkia()), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destroyed_flag_(NULL) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_alignment(TextButton::ALIGN_LEFT); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuButton::~MenuButton() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (destroyed_flag_) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *destroyed_flag_ = true; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuButton - Public APIs 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuButton::Activate() { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetState(STATE_PRESSED); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listener_) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect lb = GetLocalBounds(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The position of the menu depends on whether or not the locale is 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right-to-left. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point menu_position(lb.right(), lb.bottom()); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL()) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_position.set_x(lb.x()); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View::ConvertPointToScreen(this, &menu_position); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL()) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_position.Offset(-menu_offset_.x(), menu_offset_.y()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_position.Offset(menu_offset_.x(), menu_offset_.y()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_x_coordinate = GetMaximumScreenXCoordinate(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_x_coordinate && max_x_coordinate <= menu_position.x()) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_position.set_x(max_x_coordinate - 1); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're about to show the menu from a mouse press. By showing from the 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouse press event we block RootView in mouse dispatching. This also 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appears to cause RootView to get a mouse pressed BEFORE the mouse 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release is seen, which means RootView sends us another mouse press no 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // matter where the user pressed. To force RootView to recalculate the 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouse target during the mouse press we explicitly set the mouse handler 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to NULL. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<internal::RootView*>(GetWidget()->GetRootView())-> 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMouseHandler(NULL); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_visible_ = true; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool destroyed = false; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destroyed_flag_ = &destroyed; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_->OnMenuButtonClicked(this, menu_position); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (destroyed) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The menu was deleted while showing. Don't attempt any processing. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destroyed_flag_ = NULL; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_visible_ = false; 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) menu_closed_time_ = TimeTicks::Now(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now that the menu has closed, we need to manually reset state to 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "normal" since the menu modal loop will have prevented normal 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouse move messages from getting to this View. We set "normal" 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and not "hot" because the likelihood is that the mouse is now 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // somewhere else (user clicked elsewhere on screen to close the menu 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or selected an item) and we will inevitably refresh the hot state 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the event the mouse _is_ over the view. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetState(STATE_NORMAL); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We must return false here so that the RootView does not get stuck 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sending all mouse pressed events to us instead of the appropriate 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // target. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TextButton::PaintButton(canvas, mode); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (show_menu_marker_) 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PaintMenuMarker(canvas); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuButton - Events 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size MenuButton::GetPreferredSize() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size prefsize = TextButton::GetPreferredSize(); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_menu_marker_) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefsize.Enlarge(menu_marker_->width() + kMenuMarkerPaddingLeft + 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMenuMarkerPaddingRight, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return prefsize; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* MenuButton::GetClassName() const { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kViewClassName; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuButton::OnMousePressed(const ui::MouseEvent& event) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestFocus(); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state() != STATE_DISABLED) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're draggable (GetDragOperations returns a non-zero value), then 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't pop on press, instead wait for release. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.IsOnlyLeftMouseButton() && 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HitTestPoint(event.location()) && 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDragOperations(event.location()) == ui::DragDropTypes::DRAG_NONE) { 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TimeDelta delta = TimeTicks::Now() - menu_closed_time_; 172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Activate(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuButton::OnMouseReleased(const ui::MouseEvent& event) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Explicitly test for left mouse button to show the menu. If we tested for 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // !IsTriggerableEvent it could lead to a situation where we end up showing 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the menu and context menu (this would happen if the right button is not 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggerable and there's a context menu). 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetDragOperations(event.location()) != ui::DragDropTypes::DRAG_NONE && 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state() != STATE_DISABLED && !InDrag() && event.IsOnlyLeftMouseButton() && 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HitTestPoint(event.location())) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Activate(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TextButton::OnMouseReleased(event); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The reason we override View::OnMouseExited is because we get this event when 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we display the menu. If we don't override this method then 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BaseButton::OnMouseExited will get the event and will set the button's state 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to STATE_NORMAL instead of keeping the state BM_PUSHED. This, in turn, will 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cause the button to appear depressed while the menu is displayed. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuButton::OnMouseExited(const ui::MouseEvent& event) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((state_ != STATE_DISABLED) && (!menu_visible_) && (!InDrag())) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetState(STATE_NORMAL); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MenuButton::OnGestureEvent(ui::GestureEvent* event) { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state() != STATE_DISABLED && event->type() == ui::ET_GESTURE_TAP) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Activate()) 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->StopPropagation(); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TextButton::OnGestureEvent(event); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (event.key_code()) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_SPACE: 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Alt-space on windows should show the window menu. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.IsAltDown()) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_RETURN: 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_UP: 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::VKEY_DOWN: { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WARNING: we may have been deleted by the time Activate returns. 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool ret = Activate(); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is to prevent the keyboard event from being dispatched twice. 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The Activate function returns false in most cases. In AURA if the 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // keyboard event is not handled, we pass it to the default handler 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // which dispatches the event back to us causing the menu to get 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // displayed again. 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = true; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MenuButton::OnKeyReleased(const ui::KeyEvent& event) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Override CustomButton's implementation, which presses the button when 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // you press space and clicks it when you release space. For a MenuButton 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we always activate the menu on key press. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuButton::GetAccessibleState(ui::AccessibleViewState* state) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CustomButton::GetAccessibleState(state); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->role = ui::AccessibilityTypes::ROLE_BUTTONMENU; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->default_action = l10n_util::GetStringUTF16(IDS_APP_ACCACTION_PRESS); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->state = ui::AccessibilityTypes::STATE_HASPOPUP; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MenuButton::PaintMenuMarker(gfx::Canvas* canvas) { 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Insets insets = GetInsets(); 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We can not use the views' mirroring infrastructure for mirroring a 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // MenuButton control (see TextButton::OnPaint() for a detailed explanation 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // regarding why we can not flip the canvas). Therefore, we need to 2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // manually mirror the position of the down arrow. 2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Rect arrow_bounds(width() - insets.right() - 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) menu_marker_->width() - kMenuMarkerPaddingRight, 2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) height() / 2 - menu_marker_->height() / 2, 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) menu_marker_->width(), 2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) menu_marker_->height()); 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) arrow_bounds.set_x(GetMirroredXForRect(arrow_bounds)); 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) canvas->DrawImageInt(*menu_marker_, arrow_bounds.x(), arrow_bounds.y()); 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MenuButton::GetMaximumScreenXCoordinate() { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetWidget()) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect monitor_bounds = GetWidget()->GetWorkAreaBoundsInScreen(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return monitor_bounds.right() - 1; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 281