Improve implementation of the macOS Window menu
The macOS Window menu is connected to the item array of the macOS menubar via FL_SUBMENU_POINTER. This facilitates memorization of pointers to items of the macOS menubar because the item array no longer changes each time a window opens of gets closed.
This commit is contained in:
parent
4649188cf6
commit
ba5ed296e9
@ -446,6 +446,7 @@ static int process_sys_menu_shortcuts(int event)
|
||||
|
||||
Fl_MacOS_Sys_Menu_Bar_Driver::Fl_MacOS_Sys_Menu_Bar_Driver() : Fl_Sys_Menu_Bar_Driver()
|
||||
{
|
||||
window_menu_items = NULL;
|
||||
Fl::add_handler(process_sys_menu_shortcuts);
|
||||
}
|
||||
|
||||
@ -599,6 +600,7 @@ static void merge_all_windows_cb(Fl_Widget *, void *)
|
||||
|
||||
|
||||
static bool window_menu_installed = false;
|
||||
static int window_menu_items_count = 0;
|
||||
|
||||
void Fl_MacOS_Sys_Menu_Bar_Driver::create_window_menu(void)
|
||||
{
|
||||
@ -621,27 +623,49 @@ void Fl_MacOS_Sys_Menu_Bar_Driver::create_window_menu(void)
|
||||
fl_open_display();
|
||||
new Fl_Sys_Menu_Bar(0,0,0,0);
|
||||
}
|
||||
rank = fl_sys_menu_bar->Fl_Menu_::insert(rank, "Window", 0, NULL, 0, FL_SUBMENU);
|
||||
if (!window_menu_items_count) {
|
||||
window_menu_items_count = 6;
|
||||
window_menu_items = (Fl_Menu_Item*)malloc(window_menu_items_count * sizeof(Fl_Menu_Item));
|
||||
}
|
||||
rank = fl_sys_menu_bar->Fl_Menu_::insert(rank, "Window", 0, NULL, window_menu_items, FL_SUBMENU_POINTER);
|
||||
localized_Window = NSLocalizedString(@"Window", nil);
|
||||
|
||||
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Minimize", FL_COMMAND+'m', minimize_win_cb, 0, FL_MENU_DIVIDER);
|
||||
memset(window_menu_items, 0, sizeof(Fl_Menu_Item));
|
||||
window_menu_items[0].label("Minimize");
|
||||
window_menu_items[0].callback(minimize_win_cb);
|
||||
window_menu_items[0].shortcut(FL_COMMAND+'m');
|
||||
window_menu_items[0].flags = FL_MENU_DIVIDER;
|
||||
rank = 1;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
|
||||
if (fl_mac_os_version >= 101200 && window_menu_style() != Fl_Sys_Menu_Bar::tabbing_mode_none) {
|
||||
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Show Previous Tab", FL_SHIFT+FL_CTRL+0x9, previous_tab_cb, 0, 0);
|
||||
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Show Next Tab", FL_CTRL+0x9, next_tab_cb, 0, 0);
|
||||
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Move Tab To New Window", 0, move_tab_cb, 0, 0);
|
||||
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Merge All Windows", 0, merge_all_windows_cb, 0, FL_MENU_DIVIDER);
|
||||
memset(window_menu_items + 1, 0, sizeof(Fl_Menu_Item));
|
||||
window_menu_items[1].label("Show Previous Tab");
|
||||
window_menu_items[1].callback(previous_tab_cb);
|
||||
window_menu_items[1].shortcut(FL_SHIFT+FL_CTRL+0x9);
|
||||
memset(window_menu_items+2, 0, sizeof(Fl_Menu_Item));
|
||||
window_menu_items[2].label("Show Next Tab");
|
||||
window_menu_items[2].callback(next_tab_cb);
|
||||
window_menu_items[2].shortcut(FL_CTRL+0x9);
|
||||
memset(window_menu_items+3, 0, sizeof(Fl_Menu_Item));
|
||||
window_menu_items[3].label("Move Tab To New Window");
|
||||
window_menu_items[3].callback(move_tab_cb);
|
||||
memset(window_menu_items+4, 0, sizeof(Fl_Menu_Item));
|
||||
window_menu_items[4].label("Merge All Windows");
|
||||
window_menu_items[4].callback(merge_all_windows_cb);
|
||||
window_menu_items[4].flags = FL_MENU_DIVIDER;
|
||||
rank = 5;
|
||||
}
|
||||
#endif
|
||||
((Fl_Menu_Item*)fl_sys_menu_bar->menu()+rank)->user_data(&window_menu_style_);
|
||||
memset(window_menu_items+rank, 0, sizeof(Fl_Menu_Item));
|
||||
window_menu_items[rank-1].user_data(&window_menu_style_);
|
||||
fl_sys_menu_bar->menu_end();
|
||||
fl_sys_menu_bar->update();
|
||||
}
|
||||
|
||||
int Fl_MacOS_Sys_Menu_Bar_Driver::find_first_window()
|
||||
{
|
||||
int count = bar->size(), i;
|
||||
int count = window_menu_items->size(), i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (bar->menu()[i].user_data() == &window_menu_style_) break;
|
||||
if (window_menu_items[i].user_data() == &window_menu_style_) break;
|
||||
}
|
||||
return i < count ? i : -1;
|
||||
}
|
||||
@ -649,12 +673,22 @@ int Fl_MacOS_Sys_Menu_Bar_Driver::find_first_window()
|
||||
void Fl_MacOS_Sys_Menu_Bar_Driver::new_window(Fl_Window *win)
|
||||
{
|
||||
if (!window_menu_style() || !win->label()) return;
|
||||
int index = find_first_window();
|
||||
if (index < 0) return;
|
||||
while ((bar->menu()+index+1)->label()) index++;
|
||||
int index = window_menu_items->size() - 1;
|
||||
if (index >= window_menu_items_count - 1) {
|
||||
window_menu_items_count += 5;
|
||||
window_menu_items = (Fl_Menu_Item*)realloc(window_menu_items,
|
||||
window_menu_items_count * sizeof(Fl_Menu_Item));
|
||||
Fl_Menu_Item *item = (Fl_Menu_Item*)fl_sys_menu_bar->find_item("Window");
|
||||
item->user_data(window_menu_items);
|
||||
}
|
||||
const char *p = win->iconlabel() ? win->iconlabel() : win->label();
|
||||
int index2 = bar->Fl_Menu_::insert(index+1, p, 0, window_menu_cb, win, FL_MENU_RADIO);
|
||||
setonly((Fl_Menu_Item*)bar->menu()+index2);
|
||||
window_menu_items[index].label(p);
|
||||
window_menu_items[index].callback(window_menu_cb);
|
||||
window_menu_items[index].user_data(win);
|
||||
window_menu_items[index].flags = FL_MENU_RADIO;
|
||||
window_menu_items[index+1].label(NULL);
|
||||
window_menu_items[index].setonly();
|
||||
fl_sys_menu_bar->update();
|
||||
}
|
||||
|
||||
void Fl_MacOS_Sys_Menu_Bar_Driver::remove_window(Fl_Window *win)
|
||||
@ -663,19 +697,22 @@ void Fl_MacOS_Sys_Menu_Bar_Driver::remove_window(Fl_Window *win)
|
||||
int index = find_first_window() + 1;
|
||||
if (index < 1) return;
|
||||
while (true) {
|
||||
Fl_Menu_Item *item = (Fl_Menu_Item*)bar->menu() + index;
|
||||
Fl_Menu_Item *item = window_menu_items + index;
|
||||
if (!item->label()) return;
|
||||
if (item->user_data() == win) {
|
||||
bool doit = item->value();
|
||||
remove(index);
|
||||
int count = window_menu_items->size();
|
||||
if (count - index - 1 > 0) memmove(item, item + 1, (count - index - 1)*sizeof(Fl_Menu_Item));
|
||||
memset(window_menu_items + count - 2, 0, sizeof(Fl_Menu_Item));
|
||||
if (doit) { // select Fl::first_window() in Window menu
|
||||
item = (Fl_Menu_Item*)bar->menu() + find_first_window() + 1;
|
||||
item = window_menu_items + find_first_window() + 1;
|
||||
while (item->label() && item->user_data() != Fl::first_window()) item++;
|
||||
if (item->label()) {
|
||||
((Fl_Window*)item->user_data())->show();
|
||||
setonly(item);
|
||||
item->setonly();
|
||||
}
|
||||
}
|
||||
bar->update();
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
@ -688,10 +725,11 @@ void Fl_MacOS_Sys_Menu_Bar_Driver::rename_window(Fl_Window *win)
|
||||
int index = find_first_window() + 1;
|
||||
if (index < 1) return;
|
||||
while (true) {
|
||||
Fl_Menu_Item *item = (Fl_Menu_Item*)bar->menu() + index;
|
||||
Fl_Menu_Item *item = window_menu_items + index;
|
||||
if (!item->label()) return;
|
||||
if (item->user_data() == win) {
|
||||
replace(index, win->iconlabel() ? win->iconlabel() : win->label());
|
||||
item->label(win->iconlabel() ? win->iconlabel() : win->label());
|
||||
bar->update();
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
|
@ -1395,10 +1395,10 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
|
||||
// select the corresponding Window menu item
|
||||
int index = Fl_MacOS_Sys_Menu_Bar_Driver::driver()->find_first_window() + 1;
|
||||
while (index > 0) {
|
||||
Fl_Menu_Item *item = (Fl_Menu_Item*)fl_sys_menu_bar->menu() + index;
|
||||
Fl_Menu_Item *item = Fl_MacOS_Sys_Menu_Bar_Driver::driver()->window_menu_items + index;
|
||||
if (!item->label()) break;
|
||||
if (item->user_data() == window) {
|
||||
if (!item->value()) fl_sys_menu_bar->setonly(item);
|
||||
if (!item->value()) item->setonly();
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
class Fl_MacOS_Sys_Menu_Bar_Driver : public Fl_Sys_Menu_Bar_Driver {
|
||||
public:
|
||||
Fl_Menu_Item *window_menu_items;
|
||||
Fl_MacOS_Sys_Menu_Bar_Driver();
|
||||
virtual ~Fl_MacOS_Sys_Menu_Bar_Driver();
|
||||
void update() FL_OVERRIDE;
|
||||
|
@ -202,8 +202,7 @@ void menu_location_cb(Fl_Widget* w, void* data)
|
||||
smenubar->callback(test_cb);
|
||||
}
|
||||
else { // switch to window menu bar
|
||||
menubar->menu(smenubar->menu());
|
||||
smenubar->clear();
|
||||
menubar->copy(smenubar->menu());
|
||||
delete smenubar;
|
||||
menubar->show();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user