Какао-плагин Firefox

Я создал простой плагин, похожий на hello world, который рисует красную рамку.

После встраивания в приложение xulrunner плагин работает почти нормально. Приложение Xulrunner успешно перерисовывает поле при изменении размера окна приложения.

Но после любого события мыши, например - щелчка левой кнопкой мыши, мое приложение вылетает с "Переполнением стека". Отладчик говорит, что причина в бесконечном цикле из двух вызовов forwardMethod, за которыми следует один вызов JSD_GetValueForObject.

После сбоя содержимое стека выглядит следующим образом:

  • -[NSApplication _indexOfWindow:]
  • -[NSEvent window]
  • JSD_GetValueForObject
  • JSD_GetValueForObject
  • JSD_GetValueForObject
  • forwardMethod
  • forwardMethod
  • JSD_GetValueForObject
  • forwardMethod
  • forwardMethod
  • JSD_GetValueForObject
  • forwardMethod
  • forwardMethod
  • JSD_GetValueForObject
  • forwardMethod
  • forwardMethod
  • JSD_GetValueForObject
  • forwardMethod
  • forwardMethod
  • JSD_GetValueForObject
  • forwardMethod
  • forwardMethod
  • .....и т.д

Мой код:

int16_t NPP_HandleEvent(NPP instance, void* event)
{
    EventRecord* carbonEvent = (EventRecord*)event;

    if (carbonEvent && (carbonEvent->what == updateEvt))
    {       
        PluginInstance* currentInstance = (PluginInstance*)(instance->pdata);
        CGContextRef cgContext = ((NP_CGContext*)(currentInstance->window.window))->context;
        float windowWidth = currentInstance->window.width;
        float windowHeight = currentInstance->window.height;

        static int x = 0;

        if (x++)
            return;

        NPRect clipRect = currentInstance->window.clipRect;

        NP_CGContext* npContext = currentInstance->window.window;

        NSWindow* browserWindow = [[[NSWindow alloc] initWithWindowRef:npContext->window] autorelease];

        int y = [browserWindow frame].size.height - (clipRect.bottom - clipRect.top) -  currentInstance->window.y;

        //[plugin attachToWindow:browserWindow at:NSMakePoint(window->x, y)];
        NSPoint point = NSMakePoint(currentInstance->window.x, y);

        // find the NSView at the point
        NSView* hitView = [[browserWindow contentView] hitTest:NSMakePoint(point.x+1, point.y+1)];
        if (hitView == nil || ![[hitView className] isEqualToString:@"ChildView"]) 
        {
            x = 0;
            return;
        }

        NSView* parentView = hitView;       

        NSBox *box = [[NSBox alloc] initWithFrame:NSMakeRect(0.0, 0.0, 100, 100)];
        [box setBoxType:NSBoxCustom];
        [box setBorderType:NSLineBorder];
        [box setTitlePosition:NSNoTitle];
        [box setFillColor:[NSColor redColor]];

        [parentView addSubview:box];

        //DrawPlugin(cgContext, windowWidth, windowHeight);
    }

    return 0;
}

person Mischa    schedule 20.11.2009    source источник
comment
EventRecord не является записью о событии Carbon — это запись о событии *pre-*Carbon. То есть это тип из диспетчера событий Toolbox. Хотя этот Event Manager все еще существует в Carbon (в 32-разрядной версии), настоящий «Carbon Event Manager» — это отдельный API со своим собственным непрозрачным типом EventRef.   -  person Peter Hosey    schedule 20.11.2009
comment
Спасибо, Петр за ваш комментарий. Возможно проблема решится после перехода на настоящую модель Carbon Event... Если это возможно....   -  person Mischa    schedule 21.11.2009
comment
Я попробовал следующий код в отладчике: NPError NPP_New(...) { NPBool supportsCoreGraphics; if (browser-›getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR) supportsCoreGraphics = FALSE; NPBool поддерживает углерод; if (browser-›getvalue(instance, NPNVsupportsCarbonBool, &supportsCarbon) != NPERR_NO_ERROR) supportsCarbon = FALSE; вернуть 0; } После того, как отладчик остановился, он возвращает supportsCarbon = false !!! Я пробовал последнюю стабильную версию xulrunner и даже последнюю бета-версию, и результат всегда остается прежним.   -  person Mischa    schedule 21.11.2009
comment
Таким образом, плагины не могут даже поддерживать настоящую модель углеродных событий. Странно, очень странно.... Может я что-то не так делаю?   -  person Mischa    schedule 21.11.2009


Ответы (3)


Я не думаю, что Cocoa и старая система EventRecord очень хорошо сочетаются друг с другом.

Модель событий какао теперь доступна в последней сборке Mozilla.

Ознакомьтесь с деревом comm-central с помощью Mercurial и попробуйте:
hg clone http://hg.mozilla.org/mozilla-central/ источник
Путь к проекту Xcode:
src/modules/plugin/sdk/samples/basic/mac/
и подключаемый модуль необходимо скопировать в:
< em>/Библиотека/Интернет-плагины/

Я попробовал это сам с базовым плагином Firefox, и система событий какао работает.
Я просто не знаю, как получить указатель на текущий NSView.

Я думаю, что это нужно было сделать для 64-битной версии Firefox на Mac. Он недоступен в Firefox 3.6, но может быть в Firefox 3.7, а версия NPAPI SDK с моделью событий Cocoa — версия 0.23.

РЕДАКТИРОВАТЬ:
Чтобы попробовать напрямую, без меркурия, загрузите последнюю сборку Mozilla от имени Миши по адресу:
http://ftp.mozilla.org/pub/mozilla.org/xulrunner/nightly/latest-trunk/
Проект Xcode с моделью событий Cocoa по адресу:
http://mxr.mozilla.org/mozilla-central/source/modules/plugin/sdk/samples/basic/mac/

Пример NetscapeCocoaPlugin в исходниках Webkit также использует модель событий какао.

person Winz    schedule 20.11.2009
comment
На самом деле модель событий Cocoa не поддерживается в 32-битной версии. Вот почему все 32-битные плагины какао должны использовать модель событий Carbon и не могут использовать такие замечательные вещи, как CoreAnimation, которые требуют модели событий Cocoa. - person Mischa; 20.11.2009
comment
Миша: Вы имеете в виду плагины Netscape? Он отлично поддерживается в 32-битных приложениях. - person Peter Hosey; 20.11.2009
comment
Это не модель углеродных событий, в которой используется EventRef. EventRecord — это устаревшая модель классической Mac OS. - person Winz; 20.11.2009
comment
›Миша: Вы имеете в виду плагины Netscape? Конечно, да, в плагинах Netscape. Это проблема только 32-битных плагинов Netscape Cocoa. - person Mischa; 21.11.2009
comment
Спасибо, Винз! Не могли бы вы сказать мне, какую именно версию Mozilla вы использовали? И было бы здорово, если бы вы дали пример проекта hello-world, такого как проект Xcode, для скачивания — или просто пришлите его мне по электронной почте ([email protected]). Яve got a feeling that iм делаю что-то не так с настройками Xcode или что-то в этом роде. - person Mischa; 21.11.2009
comment
... потому что я уже пробовал последние версии Xulrunner, включая последнюю бета-версию, и тест NPNVsupportsCocoaBool всегда возвращал false. - person Mischa; 21.11.2009
comment
Gecko 1.9.3 — первая версия, поддерживающая модель событий Cocoa. - person smorgan; 18.05.2010

Спасибо, Винз, большое!

Я только что скачал последнюю сборку Mozilla и SDK с сайта

http://ftp.mozilla.org/pub/mozilla.org/xulrunner/nightly/latest-trunk/

И BasicPlugin.xcodeproj из

http://mxr.mozilla.org/mozilla-central/source/modules/plugin/sdk/samples/basic/mac/

Теперь доступна модель событий Cocoa.

person Mischa    schedule 23.11.2009
comment
Да, я использовал последнюю сборку, а не последнюю бета-версию. Я пытался получить указатель на NSView, прежде чем отправить вам электронное письмо, но пока не преуспел. Более того, в исходном коде firefox есть еще один класс, называемый nsview! Не стесняйтесь редактировать или опубликовать ответ, чтобы рассказать нам, как вы внедрили свое приложение ^_^ - person Winz; 23.11.2009

Я просто не знаю, как получить указатель на текущий NSView

Привет, Винз!

Ответ кажется очевидным — мы можем получить NSView, используя унаследованную модель событий EventRecord, а ПОСЛЕ ЭТОГО переключиться на модель событий Cocoa, добавив строку:

браузер- > setvalue (экземпляр, NPPVpluginEventModel, (void *) NPEventModelCocoa);

После этого мое приложение стало абсолютно стабильным. Больше никаких сбоев!!!

Я только что получил NPCocoaEventDrawRect после активации главного окна моего приложения. Таким образом, модель событий какао, кажется, работает.

person Mischa    schedule 25.11.2009
comment
Я проверю это, спасибо. Я попытался использовать образец NetscapeCocoaPlugin из последних источников Webkit: вызов [NSView focusView] в NPP_SetWindow также возвращает текущий NSView. - person Winz; 25.11.2009
comment
Вы категорически не должны этого делать. Согласно wiki.mozilla.org/NPAPI:Models изменение моделей за пределами NPP_New не допускается. Тот факт, что это работает для вас, является случайностью реализации. Вы не можете получить указатель на собственный NSView в модели событий Cocoa, и это сделано по замыслу. Любой обходной путь, который вам удастся придумать, потерпит неудачу, как только ваш плагин перестанет работать. - person smorgan; 18.05.2010