Окна FLTK в Mac OS X используют одно и то же системное меню

Когда какое-то приложение в OS X имеет несколько окон (много открытых документов, каждое в собственном окне), кажется, что все они используют одно и то же системное меню, по крайней мере, в FLTK. Есть ли способ найти последнее выбранное окно, чтобы отправить ему событие из меню?

Вот моя установка (Mac OS X 10.6.2, FLTK 1.3.3): есть класс Shell с системным меню. Каждый раз, когда открывается новый документ, создается новый Shell:

#ifdef __APPLE__
void Shell::macOpen(const char *fileName)
{
    // If there are empty shell, open the model in it
    if (s_empty != 0)
    {
        ...
        s_empty = 0;
    }
    // Otherwise, create new shell with the model
    else
    {
        char *args[1];
        args[0] = (char *) fileName;
        new Shell(1, args, s_conf, s_dct, fileName, 1);
    }
}
#endif

Затем я отслеживаю последний выбранный Shell, сохраняя его в static Shell *Shell::s_current:

int Shell::handle(int event)
{
    ...
    case FL_FOCUS:
#ifdef __APPLE__
        // We just selected some shell, it is current.
        s_current = this;
        cout << "Select shell with address: [" << s_current << "]" << endl;
#endif
        return 1;
    ...
}

Кажется, эта часть работает, так как я вижу следы каждый раз, когда выбираю несколько Shell:

Select shell with address: [0x8206db0]
Select shell with address: [0x82375f0]
Select shell with address: [0x5d20650]
Select shell with address: [0x82375f0]

Теперь, учитывая:

Shell *Shell::currentShell(Fl_Widget *w)
{
    cout << "Widget address: [" << w << "]" << endl;
    Shell *result = 0;
    if (w != 0)
    {
        result = (Shell *) w->window();
        cout << "Widget wingow address: [" << result << "]" << endl;
    }
#ifdef __APPLE__
    else
    {
        result = s_current;
        cout << "Last selected shell address: [" << result << "]" << endl;
    }
#endif
    return result;
}

У меня есть обратный звонок:

void Shell::shortcutCB(Fl_Widget *w, void *data)
{
    cout << "Shortcut" << endl;
    Shell *ref = currentShell(w);
    if (ref != 0)
    {
         ...
    }
}

Когда этот обратный вызов выполняется из меню и открыты другие Shell, я получаю следующую ошибку:

Bus error

Без следа ни от Shell::shortcutCB, ни от Shell::currentShell. Когда открыт единственный Shell, все работает отлично. Когда открыто больше Shell, и я закрываю все, кроме одного, ошибка возникает снова. Нет проблем, когда тот же обратный вызов вызывается из некоторого виджета в Shell или доставляется с помощью сочетания клавиш.


person Alexandru Popa    schedule 01.05.2016    source источник


Ответы (1)


Решил проблему с помощью следующих 3 шагов:

  1. Объявление manu bar в OS X также статичным (здесь произошел сбой):

    #ifdef __APPLE__
        static Fl_Sys_Menu_Bar *s_menubar;
    #else
        Fl_Sys_Menu_Bar *m_menubar;
    #endif
    
  2. Сохранять текущий Shell::s_current не только для FL_FOCUS события, но и для любого события, обрабатываемого Shell, то есть каждый раз, когда он возвращает 1:

    int Shell::handle(int event)
    {
        int result = 0;
        switch (event)
        {
            // Set result = 1 when handling the event
            ...
        }
    #ifdef __APPLE__
        if (result == 1)
        {
            // We just selected some shell, it is current.
            s_current = this;
            cout << "Select shell with address: [" << s_current << "]" << endl;
        }
    #endif
        return result;
    }
    
  3. Используйте Shell::s_current для обратных вызовов меню в OS X независимо от создания виджета вызова:

    Shell *Shell::currentShell(Fl_Widget *w)
    {
        Shell *result = 0;
    #ifdef __APPLE__
        result = s_current;
        cout << "Last selected shell address: [" << result << "]" << endl;
    #else
        cout << "Widget address: [" << w << "]" << endl;
        if (w != 0)
        {
            result = (Shell *) w->window();
            cout << "Widget wingow address: [" << result << "]" << endl;
        }
    #endif
        return result;
    }
    
person Alexandru Popa    schedule 02.05.2016