New member function Fl_Menu_Bar::play_menu(const char *title)

This commit is contained in:
ManoloFLTK 2024-05-14 17:46:25 +02:00
parent ea96237525
commit 79c3db48cf
8 changed files with 56 additions and 12 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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__ */

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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; }
};

View File

@ -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;
};