Commit b5a1864e authored by oshima@google.com's avatar oshima@google.com

Send fake event when event_type is set to exit menu so that

nested loop can exit.

BUG=104684
TEST=BrowserTest.CloseWithAppMenuOpen passes on aura build

Review URL: http://codereview.chromium.org/8597010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110774 0039d316-1c4b-4281-b951-d872f2087c98
parent 3b73f527
...@@ -413,6 +413,10 @@ bool Desktop::IsMouseButtonDown() const { ...@@ -413,6 +413,10 @@ bool Desktop::IsMouseButtonDown() const {
return mouse_button_flags_ != 0; return mouse_button_flags_ != 0;
} }
void Desktop::PostNativeEvent(const base::NativeEvent& native_event) {
host_->PostNativeEvent(native_event);
}
void Desktop::SetCapture(Window* window) { void Desktop::SetCapture(Window* window) {
if (capture_window_ == window) if (capture_window_ == window)
return; return;
......
...@@ -125,6 +125,9 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate, ...@@ -125,6 +125,9 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate,
// Are any mouse buttons currently down? // Are any mouse buttons currently down?
bool IsMouseButtonDown() const; bool IsMouseButtonDown() const;
// Posts |native_event| to the platform's event queue.
void PostNativeEvent(const base::NativeEvent& native_event);
// Capture ------------------------------------------------------------------- // Capture -------------------------------------------------------------------
// Sets capture to the specified window. // Sets capture to the specified window.
......
...@@ -58,6 +58,9 @@ class DesktopHost : public MessageLoop::Dispatcher { ...@@ -58,6 +58,9 @@ class DesktopHost : public MessageLoop::Dispatcher {
// You should probably call Desktop::last_mouse_location() instead; this // You should probably call Desktop::last_mouse_location() instead; this
// method can be expensive. // method can be expensive.
virtual gfx::Point QueryMouseLocation() = 0; virtual gfx::Point QueryMouseLocation() = 0;
// Posts |native_event| to the platform's event queue.
virtual void PostNativeEvent(const base::NativeEvent& native_event) = 0;
}; };
} // namespace aura } // namespace aura
......
...@@ -240,6 +240,7 @@ class DesktopHostLinux : public DesktopHost { ...@@ -240,6 +240,7 @@ class DesktopHostLinux : public DesktopHost {
virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual void SetSize(const gfx::Size& size) OVERRIDE;
virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
virtual gfx::Point QueryMouseLocation() OVERRIDE; virtual gfx::Point QueryMouseLocation() OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
// Returns true if there's an X window manager present... in most cases. Some // Returns true if there's an X window manager present... in most cases. Some
// window managers (notably, ion3) don't implement enough of ICCCM for us to // window managers (notably, ion3) don't implement enough of ICCCM for us to
...@@ -481,6 +482,15 @@ gfx::Point DesktopHostLinux::QueryMouseLocation() { ...@@ -481,6 +482,15 @@ gfx::Point DesktopHostLinux::QueryMouseLocation() {
max(0, min(size_.height(), win_y_return))); max(0, min(size_.height(), win_y_return)));
} }
void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) {
DCHECK(xwindow_);
DCHECK(xdisplay_);
XEvent xevent = *native_event;
xevent.xany.display = xdisplay_;
xevent.xany.window = xwindow_;
::XPutBackEvent(xdisplay_, &xevent);
}
bool DesktopHostLinux::IsWindowManagerPresent() { bool DesktopHostLinux::IsWindowManagerPresent() {
// Per ICCCM 2.8, "Manager Selections", window managers should take ownership // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
// of WM_Sn selections (where n is a screen number). // of WM_Sn selections (where n is a screen number).
......
...@@ -225,6 +225,11 @@ gfx::Point DesktopHostWin::QueryMouseLocation() { ...@@ -225,6 +225,11 @@ gfx::Point DesktopHostWin::QueryMouseLocation() {
max(0, min(size.height(), static_cast<int>(pt.y)))); max(0, min(size.height(), static_cast<int>(pt.y))));
} }
void DesktopHostWin::PostNativeEvent(const base::NativeEvent& native_event) {
::PostMessage(
hwnd(), native_event.message, native_event.wParam, native_event.lParam);
}
void DesktopHostWin::OnClose() { void DesktopHostWin::OnClose() {
// TODO: this obviously shouldn't be here. // TODO: this obviously shouldn't be here.
MessageLoopForUI::current()->Quit(); MessageLoopForUI::current()->Quit();
......
...@@ -29,6 +29,7 @@ class DesktopHostWin : public DesktopHost, public ui::WindowImpl { ...@@ -29,6 +29,7 @@ class DesktopHostWin : public DesktopHost, public ui::WindowImpl {
virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual void SetSize(const gfx::Size& size) OVERRIDE;
virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE; virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
virtual gfx::Point QueryMouseLocation() OVERRIDE; virtual gfx::Point QueryMouseLocation() OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
private: private:
BEGIN_MSG_MAP_EX(DesktopHostWin) BEGIN_MSG_MAP_EX(DesktopHostWin)
......
...@@ -103,6 +103,9 @@ UI_EXPORT float GetTouchAngle(const base::NativeEvent& native_event); ...@@ -103,6 +103,9 @@ UI_EXPORT float GetTouchAngle(const base::NativeEvent& native_event);
// Gets the force from a native_event. Normalized to be [0, 1]. Default is 0.0. // Gets the force from a native_event. Normalized to be [0, 1]. Default is 0.0.
UI_EXPORT float GetTouchForce(const base::NativeEvent& native_event); UI_EXPORT float GetTouchForce(const base::NativeEvent& native_event);
// Creates and returns no-op event.
UI_EXPORT base::NativeEvent CreateNoopEvent();
} // namespace ui } // namespace ui
#endif // UI_BASE_EVENTS_H_ #endif // UI_BASE_EVENTS_H_
...@@ -253,4 +253,12 @@ float GetTouchForce(const base::NativeEvent& native_event) { ...@@ -253,4 +253,12 @@ float GetTouchForce(const base::NativeEvent& native_event) {
return 0.0; return 0.0;
} }
base::NativeEvent CreateNoopEvent() {
MSG event;
event.message = WM_USER;
event.wParam = 0;
event.lParam = 0;
return event;
}
} // namespace ui } // namespace ui
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ui/base/events.h" #include "ui/base/events.h"
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
#include "base/logging.h" #include "base/logging.h"
...@@ -354,4 +355,14 @@ float GetTouchForce(const base::NativeEvent& native_event) { ...@@ -354,4 +355,14 @@ float GetTouchForce(const base::NativeEvent& native_event) {
return force; return force;
} }
base::NativeEvent CreateNoopEvent() {
static XEvent* noop = new XEvent();
noop->xclient.type = ClientMessage;
noop->xclient.display = NULL;
noop->xclient.window = None;
noop->xclient.message_type = 0;
noop->xclient.format = 0;
return noop;
}
} // namespace ui } // namespace ui
...@@ -24,11 +24,11 @@ ...@@ -24,11 +24,11 @@
#include "views/widget/root_view.h" #include "views/widget/root_view.h"
#include "views/widget/widget.h" #include "views/widget/widget.h"
#if defined(USE_AURA) && !defined(OS_WIN) #if defined(USE_AURA)
#include "ui/aura/desktop.h" #include "ui/aura/desktop.h"
#endif #endif
#if defined(OS_LINUX) #if defined(TOOLKIT_USES_GTK)
#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
#endif #endif
...@@ -348,7 +348,7 @@ MenuItemView* MenuController::Run(Widget* parent, ...@@ -348,7 +348,7 @@ MenuItemView* MenuController::Run(Widget* parent,
*result_mouse_event_flags = result_mouse_event_flags_; *result_mouse_event_flags = result_mouse_event_flags_;
if (exit_type_ == EXIT_OUTERMOST) { if (exit_type_ == EXIT_OUTERMOST) {
exit_type_ = EXIT_NONE; SetExitType(EXIT_NONE);
} else { } else {
if (nested_menu && result) { if (nested_menu && result) {
// We're nested and about to return a value. The caller might enter // We're nested and about to return a value. The caller might enter
...@@ -359,7 +359,7 @@ MenuItemView* MenuController::Run(Widget* parent, ...@@ -359,7 +359,7 @@ MenuItemView* MenuController::Run(Widget* parent,
// Set exit_all_, which makes sure all nested loops exit immediately. // Set exit_all_, which makes sure all nested loops exit immediately.
if (exit_type_ != EXIT_DESTROYED) if (exit_type_ != EXIT_DESTROYED)
exit_type_ = EXIT_ALL; SetExitType(EXIT_ALL);
} }
} }
...@@ -387,7 +387,7 @@ void MenuController::Cancel(ExitType type) { ...@@ -387,7 +387,7 @@ void MenuController::Cancel(ExitType type) {
} }
MenuItemView* selected = state_.item; MenuItemView* selected = state_.item;
exit_type_ = type; SetExitType(type);
SendMouseCaptureLostToActiveView(); SendMouseCaptureLostToActiveView();
...@@ -426,7 +426,7 @@ void MenuController::OnMousePressed(SubmenuView* source, ...@@ -426,7 +426,7 @@ void MenuController::OnMousePressed(SubmenuView* source,
// We're going to close and we own the mouse capture. We need to repost the // We're going to close and we own the mouse capture. We need to repost the
// mouse down, otherwise the window the user clicked on won't get the // mouse down, otherwise the window the user clicked on won't get the
// event. // event.
#if defined(OS_WIN) #if defined(OS_WIN) && !defined(USE_AURA)
RepostEvent(source, event); RepostEvent(source, event);
// NOTE: not reposting on linux seems fine. // NOTE: not reposting on linux seems fine.
#endif #endif
...@@ -720,7 +720,7 @@ int MenuController::OnPerformDrop(SubmenuView* source, ...@@ -720,7 +720,7 @@ int MenuController::OnPerformDrop(SubmenuView* source,
// Set state such that we exit. // Set state such that we exit.
showing_ = false; showing_ = false;
exit_type_ = EXIT_ALL; SetExitType(EXIT_ALL);
// If over an empty menu item, drop occurs on the parent. // If over an empty menu item, drop occurs on the parent.
if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID) if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID)
...@@ -1101,9 +1101,9 @@ void MenuController::Accept(MenuItemView* item, int mouse_event_flags) { ...@@ -1101,9 +1101,9 @@ void MenuController::Accept(MenuItemView* item, int mouse_event_flags) {
result_ = item; result_ = item;
if (item && !menu_stack_.empty() && if (item && !menu_stack_.empty() &&
!item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) { !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) {
exit_type_ = EXIT_OUTERMOST; SetExitType(EXIT_OUTERMOST);
} else { } else {
exit_type_ = EXIT_ALL; SetExitType(EXIT_ALL);
} }
result_mouse_event_flags_ = mouse_event_flags; result_mouse_event_flags_ = mouse_event_flags;
} }
...@@ -1782,12 +1782,7 @@ bool MenuController::SelectByChar(char16 character) { ...@@ -1782,12 +1782,7 @@ bool MenuController::SelectByChar(char16 character) {
return false; return false;
} }
#if defined(OS_WIN) #if defined(OS_WIN) && !defined(USE_AURA)
#if defined(USE_AURA)
void MenuController::RepostEvent(SubmenuView* source,
const MouseEvent& event) {
}
#else
void MenuController::RepostEvent(SubmenuView* source, void MenuController::RepostEvent(SubmenuView* source,
const MouseEvent& event) { const MouseEvent& event) {
if (!state_.item) { if (!state_.item) {
...@@ -1854,7 +1849,6 @@ void MenuController::RepostEvent(SubmenuView* source, ...@@ -1854,7 +1849,6 @@ void MenuController::RepostEvent(SubmenuView* source,
} }
} }
} }
#endif // !defined(USE_AURA)
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
void MenuController::SetDropMenuItem( void MenuController::SetDropMenuItem(
...@@ -1961,4 +1955,17 @@ void MenuController::SendMouseCaptureLostToActiveView() { ...@@ -1961,4 +1955,17 @@ void MenuController::SendMouseCaptureLostToActiveView() {
active_view->OnMouseCaptureLost(); active_view->OnMouseCaptureLost();
} }
void MenuController::SetExitType(ExitType type) {
exit_type_ = type;
#if defined(USE_AURA)
// On aura, closing menu may not trigger next native event, which
// is necessary to exit from nested loop (See Dispatch methods).
// Send non-op event so that Dispatch method will always be called.
// crbug.com/104684.
if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED)
aura::Desktop::GetInstance()->PostNativeEvent(ui::CreateNoopEvent());
#endif
}
} // namespace views } // namespace views
...@@ -413,6 +413,9 @@ class VIEWS_EXPORT MenuController : public MessageLoop::Dispatcher { ...@@ -413,6 +413,9 @@ class VIEWS_EXPORT MenuController : public MessageLoop::Dispatcher {
// sets it to null. // sets it to null.
void SendMouseCaptureLostToActiveView(); void SendMouseCaptureLostToActiveView();
// Set exit type.
void SetExitType(ExitType type);
// The active instance. // The active instance.
static MenuController* active_instance_; static MenuController* active_instance_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment