Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Linux browser panel support [CEF 4280 / Chromium 87] #254

Merged
merged 2 commits into from
Jan 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,7 @@ if (APPLE)
)
endif()

# only allow browser panels on win32 for now -- other operating systems
# need more testing
if((WIN32 OR APPLE) AND BROWSER_PANEL_SUPPORT_ENABLED)
if(BROWSER_PANEL_SUPPORT_ENABLED)
list(APPEND obs-browser_SOURCES
panel/browser-panel.cpp
panel/browser-panel-client.cpp
Expand Down
2 changes: 2 additions & 0 deletions panel/browser-panel-internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class QCefWidgetInternal : public QCefWidget {
std::string script;
CefRefPtr<CefRequestContext> rqc;
QTimer timer;
QPointer<QWindow> window;
QPointer<QWidget> container;
bool allowAllPopups_ = false;

virtual void resizeEvent(QResizeEvent *event) override;
Expand Down
84 changes: 61 additions & 23 deletions panel/browser-panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include <util/base.h>
#include <thread>

#if !defined(_WIN32) && !defined(__APPLE__)
#include <X11/Xlib.h>
#endif

extern bool QueueCEFTask(std::function<void()> task);
extern "C" void obs_browser_initialize(void);
extern os_event_t *cef_started_event;
Expand Down Expand Up @@ -86,6 +90,7 @@ struct QCefCookieManagerInternal : QCefCookieManager {
BPtr<char> rpath = obs_module_config_path(storage_path.c_str());
if (os_mkdirs(rpath.Get()) == MKDIR_ERROR)
throw "Failed to create cookie directory";

BPtr<char> path = os_get_abs_path_ptr(rpath.Get());

#if CHROME_VERSION_BUILD < 3770
Expand Down Expand Up @@ -171,6 +176,9 @@ QCefWidgetInternal::QCefWidgetInternal(QWidget *parent, const std::string &url_,
setAttribute(Qt::WA_NativeWindow);

setFocusPolicy(Qt::ClickFocus);

window = new QWindow();
window->setFlags(Qt::FramelessWindowHint);
}

QCefWidgetInternal::~QCefWidgetInternal()
Expand Down Expand Up @@ -231,28 +239,28 @@ void QCefWidgetInternal::closeBrowser()

void QCefWidgetInternal::Init()
{
WId id = winId();
WId handle = window->winId();

bool success = QueueCEFTask([this, id]() {
QSize size = this->size();
#ifdef SUPPORTS_FRACTIONAL_SCALING
size *= devicePixelRatioF();
#else
size *= devicePixelRatio();
#endif

bool success = QueueCEFTask([this, handle, size]() {
CefWindowInfo windowInfo;

/* Make sure Init isn't called more than once. */
if (cefBrowser)
return;

QSize size = this->size();
#ifdef _WIN32
#ifdef SUPPORTS_FRACTIONAL_SCALING
size *= devicePixelRatioF();
#elif
size *= devicePixelRatio();
#endif
RECT rc = {0, 0, size.width(), size.height()};
windowInfo.SetAsChild((HWND)id, rc);
#elif __APPLE__
windowInfo.SetAsChild((CefWindowHandle)id, 0, 0, size.width(),
size.height());
#else
CefRect rc = {0, 0, size.width(), size.height()};
cg2121 marked this conversation as resolved.
Show resolved Hide resolved
#endif
windowInfo.SetAsChild((CefWindowHandle)handle, rc);

CefRefPtr<QCefBrowserClient> browserClient =
new QCefBrowserClient(this, script, allowAllPopups_);
Expand All @@ -264,13 +272,19 @@ void QCefWidgetInternal::Init()
CefRefPtr<CefDictionaryValue>(),
#endif
rqc);
#ifdef _WIN32
Resize();
#endif
});

if (success)
if (success) {
timer.stop();

if (!container) {
container =
QWidget::createWindowContainer(window, this);
container->show();
}

Resize();
}
}

void QCefWidgetInternal::resizeEvent(QResizeEvent *event)
Expand All @@ -281,23 +295,47 @@ void QCefWidgetInternal::resizeEvent(QResizeEvent *event)

void QCefWidgetInternal::Resize()
{
#ifdef _WIN32
cg2121 marked this conversation as resolved.
Show resolved Hide resolved
#ifdef SUPPORTS_FRACTIONAL_SCALING
QSize size = this->size() * devicePixelRatioF();
#elif
#else
QSize size = this->size() * devicePixelRatio();
#endif

QueueCEFTask([this, size]() {
bool success = QueueCEFTask([this, size]() {
if (!cefBrowser)
return;
HWND hwnd = cefBrowser->GetHost()->GetWindowHandle();
SetWindowPos(hwnd, nullptr, 0, 0, size.width(), size.height(),

CefWindowHandle handle =
cefBrowser->GetHost()->GetWindowHandle();

if (!handle)
return;

#ifdef _WIN32
SetWindowPos((HWND)handle, nullptr, 0, 0, size.width(),
size.height(),
SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
SendMessage(hwnd, WM_SIZE, 0,
SendMessage((HWND)handle, WM_SIZE, 0,
MAKELPARAM(size.width(), size.height()));
});
#elif __APPLE__
#else
Display *xDisplay = cef_get_xdisplay();

if (!xDisplay)
return;

XWindowChanges changes = {0};
changes.x = 0;
changes.y = 0;
changes.width = size.width();
changes.height = size.height();
XConfigureWindow(xDisplay, (Window)handle,
CWX | CWY | CWHeight | CWWidth, &changes);
#endif
});

if (success && container)
container->resize(size.width(), size.height());
}

void QCefWidgetInternal::showEvent(QShowEvent *event)
Expand Down
41 changes: 26 additions & 15 deletions panel/browser-panel.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <obs-module.h>
#include <util/platform.h>
#include <util/util.hpp>
#include <QWidget>
Expand Down Expand Up @@ -72,36 +73,46 @@ struct QCef {
QObject *obj) = 0;
};

static inline void *obs_browser_dlsym(const char *name)
static inline void *get_browser_lib()
{
#if defined(_WIN32)
void *lib = os_dlopen("obs-browser");
#elif defined(__APPLE__)
void *lib = RTLD_DEFAULT;
#else
void *lib = os_dlopen("../obs-plugins/obs-browser");
#endif
if (!lib) {
obs_module_t *browserModule = obs_get_module("obs-browser");

if (!browserModule)
return nullptr;
}

return os_dlsym(lib, name);
return obs_get_module_lib(browserModule);
}

static inline QCef *obs_browser_init_panel(void)
{
QCef *(*create_qcef)(void) = (decltype(create_qcef))obs_browser_dlsym(
"obs_browser_create_qcef");
void *lib = get_browser_lib();
QCef *(*create_qcef)(void) = nullptr;

if (!lib)
return nullptr;

create_qcef =
(decltype(create_qcef))os_dlsym(lib, "obs_browser_create_qcef");

if (!create_qcef)
return nullptr;

return create_qcef();
}

static inline int obs_browser_qcef_version(void)
{
int (*qcef_version)(void) = (decltype(qcef_version))obs_browser_dlsym(
"obs_browser_qcef_version_export");
void *lib = get_browser_lib();
int (*qcef_version)(void) = nullptr;

if (!lib)
return 0;

qcef_version = (decltype(qcef_version))os_dlsym(
lib, "obs_browser_qcef_version_export");

if (!qcef_version)
return 0;

return qcef_version();
}