SDL заставляет CEF3 создавать дополнительные окна

Я пытаюсь установить CEF3 (Chromium Embedded Framework: https://bitbucket.org/chromiumembedded/cef ) для работы вместе с SDL (простой уровень DirectMedia: https://www.libsdl.org/).

Мое предполагаемое использование этих двух библиотек - использовать SDL для открытия окна, получения от него событий и визуализации графики OpenGL (вместе с другими библиотеками, такими как GLEW). Я хочу использовать CEF3 для визуализации графических элементов пользовательского интерфейса за пределами экрана, а затем отображать их на экране с помощью текстур OpenGL. Все это работает, я могу открывать окна SDL, обрабатывать события, я могу рисовать текстуры OpenGL и получать данные, совместимые с OpenGL, из внеэкранного рендеринга в CEF3.

Проблема в том, что если я запускаю SDL и CEF3 вместе в тестовой среде, CEF3 порождает несколько дополнительных окон.

Это код, который я использую для CEF3.

void Example::webTest()
{
    //Args
    CefMainArgs cefArgs;

    //Settings
    CefSettings cefSettings;
    cefSettings.pack_loading_disabled = true;
    cefSettings.windowless_rendering_enabled = true;

    //Initialize
    CefInitialize(cefArgs, cefSettings, nullptr, nullptr);

    //Render Handler
    renderHandler = new InterfaceRenderHandler();

    //Window Info
    CefWindowInfo cefWindowInfo;
    //cefWindowInfo.SetAsWindowless(0, true);
    cefWindowInfo.windowless_rendering_enabled = true;
    cefWindowInfo.transparent_painting_enabled = true;

    //Interface Browser
    CefRefPtr<InterfaceBrowserClient> cefClient;
    cefClient = new InterfaceBrowserClient(renderHandler);

    //Browser
    CefBrowserSettings cefBrowserSettings;
    cefBrowserSettings.windowless_frame_rate = 60;

    CefBrowserHost::CreateBrowser(cefWindowInfo, cefClient.get(), "http://www.stackoverflow.com", cefBrowserSettings, nullptr);

    //Threaded Loops
    thread renderThread(renderLoop);
    thread sdlThread(sdlLoop);

    //Main Loop
    CefRunMessageLoop();

    //Unthread
    renderThread.join();
    sdlThread.join();

    //Shutdown
    CefShutdown();
}

Несколько примечаний по этому коду:

  • Функция renderLoop предназначена для сбора готовых текстур, но в настоящее время ничего не делает.
  • Функция sdlLoop просто опрашивает окно SDL на предмет событий, а затем отбрасывает их.
  • CefRunMessageLoop блокирует программу. (Я предполагаю, что где-то внутри есть петля).
  • Для отрисовки страницы необходимо запустить CefRunMessageLoop, и, похоже, он не ведет себя правильно, если не выполняется в основном потоке.
  • InterfaceBrowserClient - это класс, который я реализовал на основе CefClient, который просто возвращает renderHandler при вызове, с которым он был создан, и больше ничего не делает.
  • InterfaceRenderHandler - это класс, который я реализовал на основе CefRenderHandler. Он предоставляет размеры предполагаемой области рендеринга в CEF3 и получает данные готового изображения из CEF3.
  • Я поместил здесь код классов http://pastebin.com/sBm9AAQZ на тот случай, если кому-то понадобится их.

Если я инициализирую окно SDL перед запуском этого кода, появляются два дополнительных окна, одно появляется в new InterfaceBrowserClient(renderHandler);, а другое появляется при достижении CefRunMessageLoop();. Эти окна имеют те же размеры, что и окно SDL, и имеют тот же заголовок и такое же содержимое (чистый белый цвет). Затем даже сядьте в точно такое же положение на экране, чтобы был виден только верхний. Однако, хотя исходное окно является отзывчивым, Windows считает эти окна невосприимчивыми, как будто в них нет запущенных циклов обработки событий. Я попытался изменить размер рендеринга, чтобы он отличался от размера окна (это делается внутри InterfaceRenderHandler), и я уверен, что они копируют размер окна SDL, а не размер области рендеринга.

Если я не инициализирую окно SDL, никакие окна не появляются вообще (за исключением, конечно, командной строки), и рендеринг выполняется как обычно (это можно определить по консоли, выводящей предупреждения при загрузке страницы).

Кто-нибудь, кто знает больше об оконной системе, понимает, почему это происходит, и, что более важно, как мне избавиться от этих дополнительных окон? Я не тестировал это ни на каких других ОС, потому что я мало знаю о компиляции Linux C ++, но я попробую, если проблема не исчезнет.

Спасибо.


person user573949    schedule 14.07.2015    source источник
comment
Я не вижу вызова CefExecuteProcess (). Вам нужно проверить его код выхода и вернуться, поскольку CEF запускает несколько процессов. См. Примеры cefclient и cefsimple: relfucker.com"> / chromiumembedded / cef / src /   -  person Czarek Tomczak    schedule 14.07.2015
comment
Я вставил CefExecuteProcess(cefArgs, nullptr, nullptr); перед вызовом CefInitialize, никаких изменений в поведении, рендеринг по-прежнему завершается нормально (как и раньше, мне удалось извлечь файл изображения, и рендеринг действительно работает, как задумано), и окна все еще появляются.   -  person user573949    schedule 14.07.2015


Ответы (1)


Несколько окон, вероятно, CEF порождают свои подпроцессы, GPU, Render и т. Д.

В случае подпроцессов вам просто нужно вызвать CefExecuteProcess и вернуть его код выхода. Это должно произойти до того, как будет выполнен другой ваш код. Вы можете увидеть рабочий пример как часть приложения cefsimple.

https://bitbucket.org/chromiumembedded/cef/src/aefb5ccce879f308f0bcc3ac719c86defe2f9715/tests/cefsimple/cefsimple_win.cc?at=master#cl-51

// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
if (exit_code >= 0) {
  // The sub-process has completed so return here.
  return exit_code;
}
person amaitland    schedule 14.07.2015
comment
Я в замешательстве, конечно, если я вернусь, я не смогу запустить остальной код? Я пробовал запустить CefExecuteProcess(cefArgs, nullptr, nullptr); (без возврата) перед CefInitialize, и ничего не изменилось. - person user573949; 15.07.2015
comment
Я просмотрел эти страницы и добавил CefExecuteProcess с возвратом (возврата не происходит). Я все еще получаю несколько окон, я попытался реализовать свое собственное CefApp на основе SimpleApp из того примера, который вы опубликовали, код которого находится здесь: pastebin.com/suK3JPPm. Есть ли у вас другие предложения? - person user573949; 15.07.2015
comment
Когда вы запускаете приложение и смотрите Task Manager, видите ли вы, что работает несколько экземпляров вашего приложения? Если вы посмотрите на аргументы командной строки, увидите ли вы параметр --type? Если это так, то у вас все еще есть проблемы с подпроцессами. - person amaitland; 16.07.2015
comment
Хорошо, я исправил это, оказалось, что мне нужно было вызвать CefExecuteProcess перед материалом SDL, и я вызывал его только перед выполнением другого кода CEF. Спасибо за вашу помощь! - person user573949; 16.07.2015