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

Side by Side Diff: ui/views/controls/menu/menu_controller.cc

Issue 9466028: aura: Repost click events that cause a menu to hide itself. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 10 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/controls/menu/menu_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/controls/menu/menu_controller.h" 5 #include "ui/views/controls/menu/menu_controller.h"
6 6
7 #include "base/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/i18n/rtl.h" 8 #include "base/i18n/rtl.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "ui/base/dragdrop/os_exchange_data.h" 11 #include "ui/base/dragdrop/os_exchange_data.h"
12 #include "ui/base/events.h" 12 #include "ui/base/events.h"
13 #include "ui/base/keycodes/keyboard_codes.h" 13 #include "ui/base/keycodes/keyboard_codes.h"
14 #include "ui/base/l10n/l10n_util.h" 14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/gfx/canvas_skia.h" 15 #include "ui/gfx/canvas_skia.h"
16 #include "ui/gfx/screen.h" 16 #include "ui/gfx/screen.h"
17 #include "ui/views/controls/button/menu_button.h" 17 #include "ui/views/controls/button/menu_button.h"
18 #include "ui/views/controls/menu/menu_controller_delegate.h" 18 #include "ui/views/controls/menu/menu_controller_delegate.h"
19 #include "ui/views/controls/menu/menu_scroll_view_container.h" 19 #include "ui/views/controls/menu/menu_scroll_view_container.h"
20 #include "ui/views/controls/menu/submenu_view.h" 20 #include "ui/views/controls/menu/submenu_view.h"
21 #include "ui/views/drag_utils.h" 21 #include "ui/views/drag_utils.h"
22 #include "ui/views/view_constants.h" 22 #include "ui/views/view_constants.h"
23 #include "ui/views/views_delegate.h" 23 #include "ui/views/views_delegate.h"
24 #include "ui/views/widget/root_view.h" 24 #include "ui/views/widget/root_view.h"
25 #include "ui/views/widget/widget.h" 25 #include "ui/views/widget/widget.h"
26 26
27 #if defined(USE_AURA) 27 #if defined(USE_AURA)
28 #include "ui/aura/client/dispatcher_client.h" 28 #include "ui/aura/client/dispatcher_client.h"
29 #include "ui/aura/env.h" 29 #include "ui/aura/env.h"
30 #include "ui/aura/event.h"
30 #include "ui/aura/root_window.h" 31 #include "ui/aura/root_window.h"
31 #elif defined(TOOLKIT_USES_GTK) 32 #elif defined(TOOLKIT_USES_GTK)
32 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h" 33 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
33 #endif 34 #endif
34 35
35 using base::Time; 36 #if defined(USE_AURA) && defined(USE_X11)
37 #include <X11/Xlib.h>
38 #endif
39
36 using base::TimeDelta; 40 using base::TimeDelta;
37 using ui::OSExchangeData; 41 using ui::OSExchangeData;
38 42
39 // Period of the scroll timer (in milliseconds). 43 // Period of the scroll timer (in milliseconds).
40 static const int kScrollTimerMS = 30; 44 static const int kScrollTimerMS = 30;
41 45
42 // Delay, in ms, between when menus are selected are moused over and the menu 46 // Delay, in ms, between when menus are selected are moused over and the menu
43 // appears. 47 // appears.
44 static const int kShowDelay = 400; 48 static const int kShowDelay = 400;
45 49
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 if (!part.is_scroll()) { 160 if (!part.is_scroll()) {
157 StopScrolling(); 161 StopScrolling();
158 return; 162 return;
159 } 163 }
160 DCHECK(part.submenu); 164 DCHECK(part.submenu);
161 SubmenuView* new_menu = part.submenu; 165 SubmenuView* new_menu = part.submenu;
162 bool new_is_up = (part.type == MenuController::MenuPart::SCROLL_UP); 166 bool new_is_up = (part.type == MenuController::MenuPart::SCROLL_UP);
163 if (new_menu == submenu_ && is_scrolling_up_ == new_is_up) 167 if (new_menu == submenu_ && is_scrolling_up_ == new_is_up)
164 return; 168 return;
165 169
166 start_scroll_time_ = Time::Now(); 170 start_scroll_time_ = base::Time::Now();
167 start_y_ = part.submenu->GetVisibleBounds().y(); 171 start_y_ = part.submenu->GetVisibleBounds().y();
168 submenu_ = new_menu; 172 submenu_ = new_menu;
169 is_scrolling_up_ = new_is_up; 173 is_scrolling_up_ = new_is_up;
170 174
171 if (!scrolling_timer_.IsRunning()) { 175 if (!scrolling_timer_.IsRunning()) {
172 scrolling_timer_.Start(FROM_HERE, 176 scrolling_timer_.Start(FROM_HERE,
173 TimeDelta::FromMilliseconds(kScrollTimerMS), 177 TimeDelta::FromMilliseconds(kScrollTimerMS),
174 this, &MenuScrollTask::Run); 178 this, &MenuScrollTask::Run);
175 } 179 }
176 } 180 }
177 181
178 void StopScrolling() { 182 void StopScrolling() {
179 if (scrolling_timer_.IsRunning()) { 183 if (scrolling_timer_.IsRunning()) {
180 scrolling_timer_.Stop(); 184 scrolling_timer_.Stop();
181 submenu_ = NULL; 185 submenu_ = NULL;
182 } 186 }
183 } 187 }
184 188
185 // The menu being scrolled. Returns null if not scrolling. 189 // The menu being scrolled. Returns null if not scrolling.
186 SubmenuView* submenu() const { return submenu_; } 190 SubmenuView* submenu() const { return submenu_; }
187 191
188 private: 192 private:
189 void Run() { 193 void Run() {
190 DCHECK(submenu_); 194 DCHECK(submenu_);
191 gfx::Rect vis_rect = submenu_->GetVisibleBounds(); 195 gfx::Rect vis_rect = submenu_->GetVisibleBounds();
192 const int delta_y = static_cast<int>( 196 const int delta_y = static_cast<int>(
193 (Time::Now() - start_scroll_time_).InMilliseconds() * 197 (base::Time::Now() - start_scroll_time_).InMilliseconds() *
194 pixels_per_second_ / 1000); 198 pixels_per_second_ / 1000);
195 vis_rect.set_y(is_scrolling_up_ ? 199 vis_rect.set_y(is_scrolling_up_ ?
196 std::max(0, start_y_ - delta_y) : 200 std::max(0, start_y_ - delta_y) :
197 std::min(submenu_->height() - vis_rect.height(), start_y_ + delta_y)); 201 std::min(submenu_->height() - vis_rect.height(), start_y_ + delta_y));
198 submenu_->ScrollRectToVisible(vis_rect); 202 submenu_->ScrollRectToVisible(vis_rect);
199 } 203 }
200 204
201 // SubmenuView being scrolled. 205 // SubmenuView being scrolled.
202 SubmenuView* submenu_; 206 SubmenuView* submenu_;
203 207
204 // Direction scrolling. 208 // Direction scrolling.
205 bool is_scrolling_up_; 209 bool is_scrolling_up_;
206 210
207 // Timer to periodically scroll. 211 // Timer to periodically scroll.
208 base::RepeatingTimer<MenuScrollTask> scrolling_timer_; 212 base::RepeatingTimer<MenuScrollTask> scrolling_timer_;
209 213
210 // Time we started scrolling at. 214 // Time we started scrolling at.
211 Time start_scroll_time_; 215 base::Time start_scroll_time_;
212 216
213 // How many pixels to scroll per second. 217 // How many pixels to scroll per second.
214 int pixels_per_second_; 218 int pixels_per_second_;
215 219
216 // Y-coordinate of submenu_view_ when scrolling started. 220 // Y-coordinate of submenu_view_ when scrolling started.
217 int start_y_; 221 int start_y_;
218 222
219 DISALLOW_COPY_AND_ASSIGN(MenuScrollTask); 223 DISALLOW_COPY_AND_ASSIGN(MenuScrollTask);
220 }; 224 };
221 225
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 return; // Ignore presses on scroll buttons. 782 return; // Ignore presses on scroll buttons.
779 783
780 if (part.type == MenuPart::NONE || 784 if (part.type == MenuPart::NONE ||
781 (part.type == MenuPart::MENU_ITEM && part.menu && 785 (part.type == MenuPart::MENU_ITEM && part.menu &&
782 part.menu->GetRootMenuItem() != state_.item->GetRootMenuItem())) { 786 part.menu->GetRootMenuItem() != state_.item->GetRootMenuItem())) {
783 // Mouse wasn't pressed over any menu, or the active menu, cancel. 787 // Mouse wasn't pressed over any menu, or the active menu, cancel.
784 788
785 // We're going to close and we own the mouse capture. We need to repost the 789 // We're going to close and we own the mouse capture. We need to repost the
786 // mouse down, otherwise the window the user clicked on won't get the 790 // mouse down, otherwise the window the user clicked on won't get the
787 // event. 791 // event.
788 #if defined(OS_WIN) && !defined(USE_AURA) 792 #if defined(OS_WIN) || defined(USE_AURA)
789 RepostEvent(source, event); 793 RepostEvent(source, event);
790 // NOTE: not reposting on linux seems fine. 794 // NOTE: not reposting on linux seems fine.
791 #endif 795 #endif
792 796
793 // And close. 797 // And close.
794 ExitType exit_type = EXIT_ALL; 798 ExitType exit_type = EXIT_ALL;
795 if (!menu_stack_.empty()) { 799 if (!menu_stack_.empty()) {
796 // We're running nested menus. Only exit all if the mouse wasn't over one 800 // We're running nested menus. Only exit all if the mouse wasn't over one
797 // of the menus from the last run. 801 // of the menus from the last run.
798 gfx::Point screen_loc(event.location()); 802 gfx::Point screen_loc(event.location());
(...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 } 1833 }
1830 1834
1831 // If no mnemonics found, look at first character of titles. 1835 // If no mnemonics found, look at first character of titles.
1832 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic); 1836 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
1833 if (details.first_match != -1) 1837 if (details.first_match != -1)
1834 return AcceptOrSelect(item, details); 1838 return AcceptOrSelect(item, details);
1835 1839
1836 return false; 1840 return false;
1837 } 1841 }
1838 1842
1839 #if defined(OS_WIN) && !defined(USE_AURA) 1843 #if defined(OS_WIN)
1840 void MenuController::RepostEvent(SubmenuView* source, 1844 void MenuController::RepostEvent(SubmenuView* source,
1841 const LocatedEvent& event) { 1845 const LocatedEvent& event) {
1842 if (!state_.item) { 1846 if (!state_.item) {
1843 // We some times get an event after closing all the menus. Ignore it. 1847 // We some times get an event after closing all the menus. Ignore it.
1844 // Make sure the menu is in fact not visible. If the menu is visible, then 1848 // Make sure the menu is in fact not visible. If the menu is visible, then
1845 // we're in a bad state where we think the menu isn't visibile but it is. 1849 // we're in a bad state where we think the menu isn't visibile but it is.
1846 DCHECK(!source->GetWidget()->IsVisible()); 1850 DCHECK(!source->GetWidget()->IsVisible());
1847 return; 1851 return;
1848 } 1852 }
1849 1853
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1897 if (in_client_area) { 1901 if (in_client_area) {
1898 PostMessage(window, event_type, event.native_event().wParam, 1902 PostMessage(window, event_type, event.native_event().wParam,
1899 MAKELPARAM(window_x, window_y)); 1903 MAKELPARAM(window_x, window_y));
1900 } else { 1904 } else {
1901 PostMessage(window, event_type, nc_hit_result, 1905 PostMessage(window, event_type, nc_hit_result,
1902 MAKELPARAM(screen_loc.x(), screen_loc.y())); 1906 MAKELPARAM(screen_loc.x(), screen_loc.y()));
1903 } 1907 }
1904 } 1908 }
1905 } 1909 }
1906 } 1910 }
1907 #endif // defined(OS_WIN) 1911 #elif defined(USE_AURA)
1912 void MenuController::RepostEvent(SubmenuView* source,
1913 const LocatedEvent& event) {
1914 if (!state_.item) {
1915 // We some times get an event after closing all the menus. Ignore it.
1916 // Make sure the menu is in fact not visible. If the menu is visible, then
1917 // we're in a bad state where we think the menu isn't visibile but it is.
1918 DCHECK(!source->GetWidget()->IsVisible());
1919 return;
1920 }
1921
1922 // Release the capture.
1923 SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu();
1924 submenu->ReleaseCapture();
1925
1926 gfx::Point screen_loc(event.location());
1927 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
1928
1929 XEvent xevent;
1930 xevent.type = ButtonPress;
1931 xevent.xbutton.x = screen_loc.x();
1932 xevent.xbutton.y = screen_loc.y();
1933 xevent.xbutton.state = 0;
1934 xevent.xbutton.same_screen = True;
1935 int flags = event.flags();
1936 if (flags & ui::EF_LEFT_MOUSE_BUTTON)
1937 xevent.xbutton.button = 1;
1938 else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
1939 xevent.xbutton.button = 2;
1940 else if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
1941 xevent.xbutton.button = 3;
1942 else
1943 return;
1944
1945 aura::RootWindow::GetInstance()->PostNativeEvent(&xevent);
1946 }
1947 #endif // defined(USE_AURA)
1908 1948
1909 void MenuController::SetDropMenuItem( 1949 void MenuController::SetDropMenuItem(
1910 MenuItemView* new_target, 1950 MenuItemView* new_target,
1911 MenuDelegate::DropPosition new_position) { 1951 MenuDelegate::DropPosition new_position) {
1912 if (new_target == drop_target_ && new_position == drop_position_) 1952 if (new_target == drop_target_ && new_position == drop_position_)
1913 return; 1953 return;
1914 1954
1915 if (drop_target_) { 1955 if (drop_target_) {
1916 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem( 1956 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem(
1917 NULL, MenuDelegate::DROP_NONE); 1957 NULL, MenuDelegate::DROP_NONE);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 (!pending_state_.item->HasSubmenu() || 2084 (!pending_state_.item->HasSubmenu() ||
2045 !pending_state_.item->GetSubmenu()->IsShowing())) { 2085 !pending_state_.item->GetSubmenu()->IsShowing())) {
2046 // On exit if the user hasn't selected an item with a submenu, move the 2086 // On exit if the user hasn't selected an item with a submenu, move the
2047 // selection back to the parent menu item. 2087 // selection back to the parent menu item.
2048 SetSelection(pending_state_.item->GetParentMenuItem(), 2088 SetSelection(pending_state_.item->GetParentMenuItem(),
2049 SELECTION_OPEN_SUBMENU); 2089 SELECTION_OPEN_SUBMENU);
2050 } 2090 }
2051 } 2091 }
2052 2092
2053 } // namespace views 2093 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698