summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt2
-rw-r--r--FL/Fl_Menu_Bar.H17
-rw-r--r--FL/Fl_Sys_Menu_Bar.H1
-rw-r--r--src/Fl_MacOS_Sys_Menu_Bar.mm32
-rw-r--r--src/Fl_Menu_Bar.cxx9
-rw-r--r--src/Fl_Sys_Menu_Bar.cxx5
-rw-r--r--src/Fl_Sys_Menu_Bar_Driver.H1
-rw-r--r--src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H1
8 files changed, 56 insertions, 12 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c2ee9e889..282830c8d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -105,6 +105,8 @@ Changes in FLTK 1.4.0 Released: Feb ?? 2024
hardware support is present (a backup mechanism is available in absence
of this support). Thus, all text drawable in Fl_Window's can be drawn
in Fl_Gl_Window's (STR#3450).
+ - New member function Fl_Menu_Bar::play_menu(const char *title) to
+ programmatically open a menu of a menubar.
- New member functions Fl::program_should_quit(void),
and Fl::program_should_quit(int) to support detection by the library
of a request to terminate cleanly the program.
diff --git a/FL/Fl_Menu_Bar.H b/FL/Fl_Menu_Bar.H
index 450708895..df7097996 100644
--- a/FL/Fl_Menu_Bar.H
+++ b/FL/Fl_Menu_Bar.H
@@ -61,18 +61,7 @@
Typing the shortcut() of any of the menu items will cause
callbacks exactly the same as when you pick the item with the mouse.
-
- This code can be used to programmatically open a menu ("Edit" in the example) of a menubar :
- \code
- Fl_Menu_Bar *bar = ……;
- const Fl_Menu_Item *v = bar->find_item("Edit");
- if (v) {
- v = bar->menu()->pulldown(bar->x(), bar->y(), bar->w(), bar->h(), v, bar, 0, 1);
- bar->picked(v);
- }
- \endcode
- This code currently should be avoided with an Fl_Sys_Menu_Bar object on the macOS platform.
-*/
+ */
class FL_EXPORT Fl_Menu_Bar : public Fl_Menu_ {
friend class Fl_Sys_Menu_Bar_Driver;
protected:
@@ -102,6 +91,10 @@ public:
This is useful when the menu bar can be an Fl_Sys_Menu_Bar object.
*/
virtual void update() {}
+ /**
+ Opens the menu named \c title of the menubar.
+ */
+ virtual void play_menu(const char *title);
};
#endif
diff --git a/FL/Fl_Sys_Menu_Bar.H b/FL/Fl_Sys_Menu_Bar.H
index 7045757a6..27bf6a94b 100644
--- a/FL/Fl_Sys_Menu_Bar.H
+++ b/FL/Fl_Sys_Menu_Bar.H
@@ -111,6 +111,7 @@ public:
const Fl_Menu_Item *menu() const {return Fl_Menu_::menu();}
void menu(const Fl_Menu_Item *m);
void update() FL_OVERRIDE;
+ void play_menu(const char *title) FL_OVERRIDE;
int add(const char* label, int shortcut, Fl_Callback*, void *user_data=0, int flags=0);
/** Adds a new menu item.
\see Fl_Menu_::add(const char* label, int shortcut, Fl_Callback*, void *user_data=0, int flags=0)
diff --git a/src/Fl_MacOS_Sys_Menu_Bar.mm b/src/Fl_MacOS_Sys_Menu_Bar.mm
index d51734729..aa8560966 100644
--- a/src/Fl_MacOS_Sys_Menu_Bar.mm
+++ b/src/Fl_MacOS_Sys_Menu_Bar.mm
@@ -726,4 +726,36 @@ void fl_mac_set_about(Fl_Callback *cb, void *user_data, int shortcut) {
Fl_Sys_Menu_Bar::about(cb, user_data);
}
+
+void Fl_MacOS_Sys_Menu_Bar_Driver::play_menu(const char *menu_name) {
+ // Use the accessibility interface to programmatically open a menu of the system menubar
+ char *ts = remove_ampersand(menu_name);
+ NSString *mac_name = [NSString stringWithUTF8String:ts];
+ free(ts);
+ AXUIElementRef appElement = AXUIElementCreateApplication(getpid());
+ AXUIElementRef menuBar;
+ AXError error = AXUIElementCopyAttributeValue(appElement, kAXMenuBarAttribute, (CFTypeRef *)&menuBar);
+ if (error) return;
+ CFIndex count = -1;
+ error = AXUIElementGetAttributeValueCount(menuBar, kAXChildrenAttribute, &count);
+ if (error) { CFRelease(menuBar); return; }
+ NSArray *children = nil;
+ error = AXUIElementCopyAttributeValues(menuBar, kAXChildrenAttribute, 0, count, (CFArrayRef *)&children);
+ if (error) { CFRelease(menuBar); return; }
+ for (id child in children) {
+ AXUIElementRef element = (AXUIElementRef)child;
+ id title;
+ AXError error = AXUIElementCopyAttributeValue(element, kAXTitleAttribute, (CFTypeRef *)&title);
+ if (!error && [title isEqualToString:mac_name]) {
+ AXUIElementPerformAction(element, kAXPressAction);
+ CFRelease(title);
+ break;
+ }
+ CFRelease(title);
+ }
+ CFRelease(menuBar);
+ [children release];
+ CFRelease(appElement);
+}
+
#endif /* __APPLE__ */
diff --git a/src/Fl_Menu_Bar.cxx b/src/Fl_Menu_Bar.cxx
index ebb97b7ca..d605efb1e 100644
--- a/src/Fl_Menu_Bar.cxx
+++ b/src/Fl_Menu_Bar.cxx
@@ -67,3 +67,12 @@ Fl_Menu_Bar::Fl_Menu_Bar(int X, int Y, int W, int H,const char *l)
: Fl_Menu_(X,Y,W,H,l)
{
}
+
+
+void Fl_Menu_Bar::play_menu(const char *title) {
+ const Fl_Menu_Item *v = find_item(title);
+ if (v) {
+ v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
+ picked(v);
+ }
+}
diff --git a/src/Fl_Sys_Menu_Bar.cxx b/src/Fl_Sys_Menu_Bar.cxx
index c0ae88b25..477470cd3 100644
--- a/src/Fl_Sys_Menu_Bar.cxx
+++ b/src/Fl_Sys_Menu_Bar.cxx
@@ -242,6 +242,11 @@ void Fl_Sys_Menu_Bar::create_window_menu() {
}
}
+void Fl_Sys_Menu_Bar::play_menu(const char *title) {
+ if (driver()) fl_sys_menu_bar->driver()->play_menu(title);
+ else Fl_Menu_Bar::play_menu(title);
+}
+
#if !defined(FL_DOXYGEN)
Fl_Sys_Menu_Bar_Driver *Fl_Sys_Menu_Bar::driver() {
return Fl::system_driver()->sys_menu_bar_driver();
diff --git a/src/Fl_Sys_Menu_Bar_Driver.H b/src/Fl_Sys_Menu_Bar_Driver.H
index b8e4b4373..38862ce01 100644
--- a/src/Fl_Sys_Menu_Bar_Driver.H
+++ b/src/Fl_Sys_Menu_Bar_Driver.H
@@ -48,6 +48,7 @@ public:
virtual void replace(int index, const char *name) { bar->Fl_Menu_Bar::replace(index, name); }
virtual void mode(int i, int fl) { bar->Fl_Menu_Bar::mode(i, fl); }
virtual void create_window_menu() {}
+ virtual void play_menu(const char *title) {}
static Fl_Sys_Menu_Bar::window_menu_style_enum window_menu_style() { return window_menu_style_; }
static void window_menu_style(Fl_Sys_Menu_Bar::window_menu_style_enum style) { window_menu_style_ = style; }
};
diff --git a/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H b/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H
index 684ae91f6..28f113a8e 100644
--- a/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H
+++ b/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H
@@ -44,6 +44,7 @@ public:
void remove_window(Fl_Window *win);
void rename_window(Fl_Window *win);
static Fl_MacOS_Sys_Menu_Bar_Driver* driver();
+ void play_menu(const char *menu_name) FL_OVERRIDE;
};