From 46e6b5ec3eae6067ebab6fb41625699234cbff7d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 25 Nov 2014 16:47:41 +0100 Subject: [PATCH 1/3] Allow positioning the context menu --- atom/browser/api/atom_api_menu.cc | 3 ++- atom/browser/api/atom_api_menu.h | 1 + atom/browser/api/atom_api_menu_mac.h | 1 + atom/browser/api/atom_api_menu_mac.mm | 15 +++++++++++++++ atom/browser/api/atom_api_menu_views.cc | 15 +++++++++++++-- atom/browser/api/atom_api_menu_views.h | 3 +++ atom/browser/api/lib/menu.coffee | 7 +++++-- 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_menu.cc b/atom/browser/api/atom_api_menu.cc index 7841ea4d7..6c3bd89c2 100644 --- a/atom/browser/api/atom_api_menu.cc +++ b/atom/browser/api/atom_api_menu.cc @@ -246,7 +246,8 @@ void Menu::BuildPrototype(v8::Isolate* isolate, .SetMethod("isEnabledAt", &Menu::IsEnabledAt) .SetMethod("isVisibleAt", &Menu::IsVisibleAt) .SetMethod("attachToWindow", &Menu::AttachToWindow) - .SetMethod("_popup", &Menu::Popup); + .SetMethod("_popup", &Menu::Popup) + .SetMethod("_popupAt", &Menu::PopupAt); } } // namespace api diff --git a/atom/browser/api/atom_api_menu.h b/atom/browser/api/atom_api_menu.h index 10777ba68..7b8e68d01 100644 --- a/atom/browser/api/atom_api_menu.h +++ b/atom/browser/api/atom_api_menu.h @@ -55,6 +55,7 @@ class Menu : public mate::Wrappable, virtual void AttachToWindow(Window* window); virtual void Popup(Window* window) = 0; + virtual void PopupAt(Window* window, int x, int y) = 0; scoped_ptr model_; Menu* parent_; diff --git a/atom/browser/api/atom_api_menu_mac.h b/atom/browser/api/atom_api_menu_mac.h index 7ccacdc32..f055d92cd 100644 --- a/atom/browser/api/atom_api_menu_mac.h +++ b/atom/browser/api/atom_api_menu_mac.h @@ -20,6 +20,7 @@ class MenuMac : public Menu { MenuMac(); virtual void Popup(Window* window) OVERRIDE; + virtual void PopupAt(Window* window, int x, int y) OVERRIDE; base::scoped_nsobject menu_controller_; diff --git a/atom/browser/api/atom_api_menu_mac.mm b/atom/browser/api/atom_api_menu_mac.mm index 748049828..9b1652939 100644 --- a/atom/browser/api/atom_api_menu_mac.mm +++ b/atom/browser/api/atom_api_menu_mac.mm @@ -46,6 +46,21 @@ void MenuMac::Popup(Window* window) { forView:web_contents->GetContentNativeView()]; } +void MenuMac::PopupAt(Window* window, int x, int y) { + base::scoped_nsobject 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 void Menu::SetApplicationMenu(Menu* base_menu) { MenuMac* menu = static_cast(base_menu); diff --git a/atom/browser/api/atom_api_menu_views.cc b/atom/browser/api/atom_api_menu_views.cc index e94830b30..ed751e8dc 100644 --- a/atom/browser/api/atom_api_menu_views.cc +++ b/atom/browser/api/atom_api_menu_views.cc @@ -5,6 +5,7 @@ #include "atom/browser/api/atom_api_menu_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/views/controls/menu/menu_runner.h" @@ -16,14 +17,24 @@ MenuViews::MenuViews() { } 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(window->window()); + content::RenderWidgetHostView* view = nativeWindowViews->GetWebContents()->GetRenderWidgetHostView(); + gfx::Point viewOrigin = view->GetViewBounds().origin(); + PopupAtPoint(window, gfx::Point(viewOrigin.x() + x, viewOrigin.y() + y)); +} + +void MenuViews::PopupAtPoint(Window* window, gfx::Point point) { views::MenuRunner menu_runner( model(), views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS); ignore_result(menu_runner.RunMenuAt( static_cast(window->window())->widget(), NULL, - gfx::Rect(cursor, gfx::Size()), + gfx::Rect(point, gfx::Size()), views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE)); } diff --git a/atom/browser/api/atom_api_menu_views.h b/atom/browser/api/atom_api_menu_views.h index 2256e71c5..fa375fcba 100644 --- a/atom/browser/api/atom_api_menu_views.h +++ b/atom/browser/api/atom_api_menu_views.h @@ -6,6 +6,7 @@ #define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_ #include "atom/browser/api/atom_api_menu.h" +#include "ui/gfx/screen.h" namespace atom { @@ -17,8 +18,10 @@ class MenuViews : public Menu { protected: virtual void Popup(Window* window) OVERRIDE; + virtual void PopupAt(Window* window, int x, int y) OVERRIDE; private: + void PopupAtPoint(Window* window, gfx::Point point); DISALLOW_COPY_AND_ASSIGN(MenuViews); }; diff --git a/atom/browser/api/lib/menu.coffee b/atom/browser/api/lib/menu.coffee index 722c56eb6..bde4e9152 100644 --- a/atom/browser/api/lib/menu.coffee +++ b/atom/browser/api/lib/menu.coffee @@ -45,9 +45,12 @@ Menu::_init = -> break 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 - @_popup window + if x? and y? + @_popupAt(window, x, y) + else + @_popup window Menu::append = (item) -> @insert @getItemCount(), item From c6a16161d91ffd77e65ff4764e685f7f06dcf7dd Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 26 Nov 2014 15:15:55 +0100 Subject: [PATCH 2/3] Update documentation for Menu.popup() --- docs/api/menu.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/api/menu.md b/docs/api/menu.md index ceb00a3ed..464b98f52 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -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 become properties of the constructed menu items. -### Menu.popup(browserWindow) +### Menu.popup(browserWindow, [x, y]) * `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) From c06e844ef4efaac3049f3ba5382c1dc6dc4f1365 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 26 Nov 2014 15:28:03 +0100 Subject: [PATCH 3/3] fix build --- atom/browser/api/atom_api_menu_views.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_menu_views.cc b/atom/browser/api/atom_api_menu_views.cc index ed751e8dc..c8c7ceb50 100644 --- a/atom/browser/api/atom_api_menu_views.cc +++ b/atom/browser/api/atom_api_menu_views.cc @@ -21,9 +21,10 @@ void MenuViews::Popup(Window* window) { } void MenuViews::PopupAt(Window* window, int x, int y) { - NativeWindow* nativeWindowViews = static_cast(window->window()); - content::RenderWidgetHostView* view = nativeWindowViews->GetWebContents()->GetRenderWidgetHostView(); - gfx::Point viewOrigin = view->GetViewBounds().origin(); + NativeWindow* nativeWindowViews = + static_cast(window->window()); + gfx::Point viewOrigin = nativeWindowViews->GetWebContents() + ->GetRenderWidgetHostView()->GetViewBounds().origin(); PopupAtPoint(window, gfx::Point(viewOrigin.x() + x, viewOrigin.y() + y)); }