Merge pull request #870 from joaomoreno/popup

Allow positioning the context menu
This commit is contained in:
Cheng Zhao 2014-11-28 12:42:49 +08:00
commit 8a736abac7
8 changed files with 47 additions and 7 deletions

View file

@ -246,7 +246,8 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
.SetMethod("isEnabledAt", &Menu::IsEnabledAt) .SetMethod("isEnabledAt", &Menu::IsEnabledAt)
.SetMethod("isVisibleAt", &Menu::IsVisibleAt) .SetMethod("isVisibleAt", &Menu::IsVisibleAt)
.SetMethod("attachToWindow", &Menu::AttachToWindow) .SetMethod("attachToWindow", &Menu::AttachToWindow)
.SetMethod("_popup", &Menu::Popup); .SetMethod("_popup", &Menu::Popup)
.SetMethod("_popupAt", &Menu::PopupAt);
} }
} // namespace api } // namespace api

View file

@ -55,6 +55,7 @@ class Menu : public mate::Wrappable,
virtual void AttachToWindow(Window* window); virtual void AttachToWindow(Window* window);
virtual void Popup(Window* window) = 0; virtual void Popup(Window* window) = 0;
virtual void PopupAt(Window* window, int x, int y) = 0;
scoped_ptr<ui::SimpleMenuModel> model_; scoped_ptr<ui::SimpleMenuModel> model_;
Menu* parent_; Menu* parent_;

View file

@ -20,6 +20,7 @@ class MenuMac : public Menu {
MenuMac(); MenuMac();
virtual void Popup(Window* window) OVERRIDE; virtual void Popup(Window* window) OVERRIDE;
virtual void PopupAt(Window* window, int x, int y) OVERRIDE;
base::scoped_nsobject<AtomMenuController> menu_controller_; base::scoped_nsobject<AtomMenuController> menu_controller_;

View file

@ -46,6 +46,21 @@ void MenuMac::Popup(Window* window) {
forView:web_contents->GetContentNativeView()]; forView:web_contents->GetContentNativeView()];
} }
void MenuMac::PopupAt(Window* window, int x, int y) {
base::scoped_nsobject<AtomMenuController> menu_controller(
[[AtomMenuController alloc] initWithModel:model_.get()]);
NativeWindow* native_window = window->window();
content::WebContents* web_contents = native_window->GetWebContents();
NSView* view = web_contents->GetContentNativeView();
NSMenu* menu = [menu_controller menu];
// Show the menu.
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
atLocation:NSMakePoint(x, [view frame].size.height - y)
inView:view];
}
// static // static
void Menu::SetApplicationMenu(Menu* base_menu) { void Menu::SetApplicationMenu(Menu* base_menu) {
MenuMac* menu = static_cast<MenuMac*>(base_menu); MenuMac* menu = static_cast<MenuMac*>(base_menu);

View file

@ -5,6 +5,7 @@
#include "atom/browser/api/atom_api_menu_views.h" #include "atom/browser/api/atom_api_menu_views.h"
#include "atom/browser/native_window_views.h" #include "atom/browser/native_window_views.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ui/gfx/screen.h" #include "ui/gfx/screen.h"
#include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/menu/menu_runner.h"
@ -16,14 +17,25 @@ MenuViews::MenuViews() {
} }
void MenuViews::Popup(Window* window) { void MenuViews::Popup(Window* window) {
gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(); PopupAtPoint(window, gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
}
void MenuViews::PopupAt(Window* window, int x, int y) {
NativeWindow* nativeWindowViews =
static_cast<NativeWindow*>(window->window());
gfx::Point viewOrigin = nativeWindowViews->GetWebContents()
->GetRenderWidgetHostView()->GetViewBounds().origin();
PopupAtPoint(window, gfx::Point(viewOrigin.x() + x, viewOrigin.y() + y));
}
void MenuViews::PopupAtPoint(Window* window, gfx::Point point) {
views::MenuRunner menu_runner( views::MenuRunner menu_runner(
model(), model(),
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS); views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
ignore_result(menu_runner.RunMenuAt( ignore_result(menu_runner.RunMenuAt(
static_cast<NativeWindowViews*>(window->window())->widget(), static_cast<NativeWindowViews*>(window->window())->widget(),
NULL, NULL,
gfx::Rect(cursor, gfx::Size()), gfx::Rect(point, gfx::Size()),
views::MENU_ANCHOR_TOPLEFT, views::MENU_ANCHOR_TOPLEFT,
ui::MENU_SOURCE_MOUSE)); ui::MENU_SOURCE_MOUSE));
} }

View file

@ -6,6 +6,7 @@
#define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_ #define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
#include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_menu.h"
#include "ui/gfx/screen.h"
namespace atom { namespace atom {
@ -17,8 +18,10 @@ class MenuViews : public Menu {
protected: protected:
virtual void Popup(Window* window) OVERRIDE; virtual void Popup(Window* window) OVERRIDE;
virtual void PopupAt(Window* window, int x, int y) OVERRIDE;
private: private:
void PopupAtPoint(Window* window, gfx::Point point);
DISALLOW_COPY_AND_ASSIGN(MenuViews); DISALLOW_COPY_AND_ASSIGN(MenuViews);
}; };

View file

@ -45,8 +45,11 @@ Menu::_init = ->
break break
v8Util.setHiddenValue group[0], 'checked', true unless checked v8Util.setHiddenValue group[0], 'checked', true unless checked
Menu::popup = (window) -> Menu::popup = (window, x, y) ->
throw new TypeError('Invalid window') unless window?.constructor is BrowserWindow throw new TypeError('Invalid window') unless window?.constructor is BrowserWindow
if x? and y?
@_popupAt(window, x, y)
else
@_popup window @_popup window
Menu::append = (item) -> Menu::append = (item) ->

View file

@ -191,11 +191,15 @@ Generally, the `template` is just an array of `options` for constructing
You can also attach other fields to element of the `template`, and they will You can also attach other fields to element of the `template`, and they will
become properties of the constructed menu items. become properties of the constructed menu items.
### Menu.popup(browserWindow) ### Menu.popup(browserWindow, [x, y])
* `browserWindow` BrowserWindow * `browserWindow` BrowserWindow
* `x` Number
* `y` Number
Popups the this as context menu in the `browserWindow`. Popups this menu as a context menu in the `browserWindow`. You can optionally
provide a `(x,y)` coordinate to place the menu at, otherwise it will be placed
at the current mouse cursor position.
### Menu.append(menuItem) ### Menu.append(menuItem)