1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 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)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/ui/views/toolbar/toolbar_button.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/menu_model.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/base/theme_provider.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/gfx/display.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/gfx/screen.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/strings/grit/ui_strings.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/controls/button/label_button_border.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_model_adapter.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_runner.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ToolbarButton::ToolbarButton(views::ButtonListener* listener,
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             ui::MenuModel* model)
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : views::LabelButton(listener, base::string16()),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      model_(model),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      menu_showing_(false),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y_position_on_lbuttondown_(0),
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      show_menu_factory_(this) {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  set_context_menu_controller(this);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ToolbarButton::~ToolbarButton() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::Init() {
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetFocusable(false);
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetAccessibilityFocusable(true);
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  image()->EnableCanvasFlippingForRTLUI(true);
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::ClearPendingMenu() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_menu_factory_.InvalidateWeakPtrs();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ToolbarButton::IsMenuShowing() const {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return menu_showing_;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ToolbarButton::GetPreferredSize() const {
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Size size(image()->GetPreferredSize());
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Size label_size = label()->GetPreferredSize();
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (label_size.width() > 0)
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size.Enlarge(label_size.width() + LocationBarView::kItemPadding, 0);
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return size;
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ToolbarButton::OnMousePressed(const ui::MouseEvent& event) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enabled() && ShouldShowMenu() &&
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IsTriggerableEvent(event) && HitTestPoint(event.location())) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Store the y pos of the mouse coordinates so we can use them later to
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // determine if the user dragged the mouse down (which should pop up the
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // drag down menu immediately, instead of waiting for the timer)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_position_on_lbuttondown_ = event.y();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Schedule a task that will show the menu.
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const int kMenuTimerDelay = 500;
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&ToolbarButton::ShowDropDownMenu,
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   show_menu_factory_.GetWeakPtr(),
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   ui::GetMenuSourceTypeForEvent(event)),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kMenuTimerDelay));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return LabelButton::OnMousePressed(event);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ToolbarButton::OnMouseDragged(const ui::MouseEvent& event) {
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool result = LabelButton::OnMouseDragged(event);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (show_menu_factory_.HasWeakPtrs()) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the mouse is dragged to a y position lower than where it was when
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // clicked then we should not wait for the menu to appear but show
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it immediately.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event.y() > y_position_on_lbuttondown_ + GetHorizontalDragThreshold()) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      show_menu_factory_.InvalidateWeakPtrs();
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ShowDropDownMenu(ui::GetMenuSourceTypeForEvent(event));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::OnMouseReleased(const ui::MouseEvent& event) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsTriggerableEvent(event) ||
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (event.IsRightMouseButton() && !HitTestPoint(event.location()))) {
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LabelButton::OnMouseReleased(event);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsTriggerableEvent(event))
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    show_menu_factory_.InvalidateWeakPtrs();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::OnMouseCaptureLost() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::OnMouseExited(const ui::MouseEvent& event) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starting a drag results in a MouseExited, we need to ignore it.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A right click release triggers an exit event. We want to
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // remain in a PUSHED state until the drop down menu closes.
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (state_ != STATE_DISABLED && !InDrag() && state_ != STATE_PRESSED)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetState(STATE_NORMAL);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::OnGestureEvent(ui::GestureEvent* event) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (menu_showing_) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // While dropdown menu is showing the button should not handle gestures.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->StopPropagation();
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LabelButton::OnGestureEvent(event);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ToolbarButton::GetAccessibleState(ui::AXViewState* state) {
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CustomButton::GetAccessibleState(state);
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->role = ui::AX_ROLE_BUTTON_DROP_DOWN;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->default_action = l10n_util::GetStringUTF16(IDS_APP_ACCACTION_PRESS);
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  state->AddStateFlag(ui::AX_STATE_HASPOPUP);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<views::LabelButtonBorder>
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ToolbarButton::CreateDefaultBorder() const {
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<views::LabelButtonBorder> border =
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LabelButton::CreateDefaultBorder();
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ui::ThemeProvider* provider = GetThemeProvider();
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (provider && provider->UsingSystemTheme()) {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // We set smaller insets here to accommodate the slightly larger GTK+
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // icons.
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    border->set_insets(gfx::Insets(2, 2, 2, 2));
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return border.Pass();
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::ShowContextMenuForView(View* source,
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                           const gfx::Point& point,
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                           ui::MenuSourceType source_type) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!enabled())
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_menu_factory_.InvalidateWeakPtrs();
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ShowDropDownMenu(source_type);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ToolbarButton::ShouldEnterPushedState(const ui::Event& event) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enter PUSHED state on press with Left or Right mouse button or on taps.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remain in this state while the context menu is open.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return event.type() == ui::ET_GESTURE_TAP ||
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         event.type() == ui::ET_GESTURE_TAP_DOWN ||
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (event.IsMouseEvent() && ((ui::EF_LEFT_MOUSE_BUTTON |
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ui::EF_RIGHT_MOUSE_BUTTON) & event.flags()) != 0);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ToolbarButton::ShouldShowMenu() {
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return model_ != NULL;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ToolbarButton::ShowDropDownMenu(ui::MenuSourceType source_type) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldShowMenu())
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect lb = GetLocalBounds();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both the menu position and the menu anchor type change if the UI layout
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is right-to-left.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point menu_position(lb.origin());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu_position.Offset(0, lb.height() - 1);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::i18n::IsRTL())
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_position.Offset(lb.width() - 1, 0);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View::ConvertPointToScreen(this, &menu_position);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int left_bound = GetSystemMetrics(SM_XVIRTUALSCREEN);
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#elif defined(OS_CHROMEOS)
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // A window won't overlap between displays on ChromeOS.
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Use the left bound of the display on which
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the menu button exists.
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  gfx::NativeView view = GetWidget()->GetNativeView();
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  gfx::Display display = gfx::Screen::GetScreenFor(
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      view)->GetDisplayNearestWindow(view);
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int left_bound = display.bounds().x();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The window might be positioned over the edge between two screens. We'll
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // want to position the dropdown on the screen the mouse cursor is on.
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::NativeView view = GetWidget()->GetNativeView();
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Screen* screen = gfx::Screen::GetScreenFor(view);
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Display display = screen->GetDisplayNearestPoint(
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      screen->GetCursorScreenPoint());
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int left_bound = display.bounds().x();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (menu_position.x() < left_bound)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_position.set_x(left_bound);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the button look depressed while the menu is open.
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetState(STATE_PRESSED);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu_showing_ = true;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create and run menu.  Display an empty menu if model is NULL.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_.get()) {
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    views::MenuModelAdapter menu_delegate(model_.get());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_delegate.set_triggerable_event_flags(triggerable_event_flags());
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    menu_runner_.reset(new views::MenuRunner(menu_delegate.CreateMenu(),
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             views::MenuRunner::HAS_MNEMONICS));
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    views::MenuRunner::RunResult result =
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        menu_runner_->RunMenuAt(GetWidget(),
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                NULL,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                gfx::Rect(menu_position, gfx::Size(0, 0)),
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                views::MENU_ANCHOR_TOPLEFT,
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                source_type);
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (result == views::MenuRunner::MENU_DELETED)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    views::MenuDelegate menu_delegate;
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    views::MenuItemView* menu = new views::MenuItemView(&menu_delegate);
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    menu_runner_.reset(
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        new views::MenuRunner(menu, views::MenuRunner::HAS_MNEMONICS));
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    views::MenuRunner::RunResult result =
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        menu_runner_->RunMenuAt(GetWidget(),
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                NULL,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                gfx::Rect(menu_position, gfx::Size(0, 0)),
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                views::MENU_ANCHOR_TOPLEFT,
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                source_type);
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (result == views::MenuRunner::MENU_DELETED)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu_showing_ = false;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need to explicitly clear mouse handler so that events get sent
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // properly after the menu finishes running. If we don't do this, then
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the first click to other parts of the UI is eaten.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetMouseHandler(NULL);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the state back to normal after the drop down menu is closed.
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (state_ != STATE_DISABLED)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetState(STATE_NORMAL);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
251