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

UI: Add API to create Browser Docks #5679

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
26 changes: 26 additions & 0 deletions UI/api-interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,32 @@ struct OBSStudioAPI : obs_frontend_callbacks {
return (void *)main->AddDockWidget((QDockWidget *)dock);
}

void *obs_frontend_add_browser_dock(const char *id, const char *title,
const char *url) override
{
#ifdef BROWSER_AVAILABLE
QString qstrID = QT_UTF8(id);
QString qstrTitle = QT_UTF8(title);
QString qstrURL = QT_UTF8(url);

return main->AddPluginBrowserDock(qstrID, qstrTitle, qstrURL);
#else
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(title);
UNUSED_PARAMETER(url);
return nullptr;
#endif
}

void obs_frontend_remove_browser_dock(void *dock) override
{
#ifdef BROWSER_AVAILABLE
main->RemovePluginBrowserDock((QDockWidget *)dock);
#else
UNUSED_PARAMETER(dock);
#endif
}

void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
void *private_data) override
{
Expand Down
14 changes: 14 additions & 0 deletions UI/obs-frontend-api/obs-frontend-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,20 @@ void *obs_frontend_add_dock(void *dock)
return !!callbacks_valid() ? c->obs_frontend_add_dock(dock) : nullptr;
}

void *obs_frontend_add_browser_dock(const char *id, const char *title,
const char *url)
{
return !!callbacks_valid()
? c->obs_frontend_add_browser_dock(id, title, url)
: nullptr;
}

void obs_frontend_remove_browser_dock(void *dock)
{
if (callbacks_valid())
c->obs_frontend_remove_browser_dock(dock);
}

void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
void *private_data)
{
Expand Down
5 changes: 5 additions & 0 deletions UI/obs-frontend-api/obs-frontend-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ EXPORT void obs_frontend_add_tools_menu_item(const char *name,

/* takes QDockWidget and returns QAction */
EXPORT void *obs_frontend_add_dock(void *dock);
/* returns QDockWidget */
EXPORT void *obs_frontend_add_browser_dock(const char *id, const char *title,
const char *url);
/* takes QDockWidget, calls delete on dock and its corresponding QAction */
EXPORT void obs_frontend_remove_browser_dock(void *dock);

typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event,
void *private_data);
Expand Down
4 changes: 4 additions & 0 deletions UI/obs-frontend-api/obs-frontend-internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ struct obs_frontend_callbacks {
void *private_data) = 0;

virtual void *obs_frontend_add_dock(void *dock) = 0;
virtual void *obs_frontend_add_browser_dock(const char *id,
const char *title,
const char *url) = 0;
virtual void obs_frontend_remove_browser_dock(void *dock) = 0;

virtual void
obs_frontend_add_event_callback(obs_frontend_event_cb callback,
Expand Down
33 changes: 25 additions & 8 deletions UI/window-basic-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1923,6 +1923,8 @@ void OBSBasic::OBSInit()

#ifdef BROWSER_AVAILABLE
if (cef) {
LoadPluginBrowserDocks();

QAction *action = new QAction(QTStr("Basic.MainMenu.Docks."
"CustomBrowserDocks"),
this);
Expand Down Expand Up @@ -9530,8 +9532,30 @@ void OBSBasic::ResizeOutputSizeOfSource()

QAction *OBSBasic::AddDockWidget(QDockWidget *dock)
{
bool hasDock = false;
QString dockUUID = dock->property("uuid").toString();
/* prune deleted docks and prevent adding the same dock again */
for (int i = extraDocks.size() - 1; i >= 0; i--) {
if (!extraDocks[i]) {
extraDocks.removeAt(i);
continue;
}
if (!hasDock &&
extraDocks[i]->property("uuid").toString() == dockUUID) {
hasDock = true;
}
}
if (hasDock) {
/* Return the existing action */
for (const auto action : ui->menuDocks->actions()) {
if (action->property("uuid").toString() == dockUUID) {
return action;
}
}
}

QAction *action = ui->menuDocks->addAction(dock->windowTitle());
action->setProperty("uuid", dock->property("uuid").toString());
action->setProperty("uuid", dockUUID);
action->setCheckable(true);
assignDockToggle(dock, action);
extraDocks.push_back(dock);
Expand All @@ -9545,13 +9569,6 @@ QAction *OBSBasic::AddDockWidget(QDockWidget *dock)

dock->setFeatures(features);

/* prune deleted docks */
for (int i = extraDocks.size() - 1; i >= 0; i--) {
if (!extraDocks[i]) {
extraDocks.removeAt(i);
}
}

return action;
}

Expand Down
9 changes: 9 additions & 0 deletions UI/window-basic-main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,15 @@ class OBSBasic : public OBSMainWindow {
void ManageExtraBrowserDocks();
void AddExtraBrowserDock(const QString &title, const QString &url,
const QString &uuid, bool firstCreate);

QStringList pluginBrowserDockTargets;
QList<QPointer<QDockWidget>> pluginBrowserDocks;

void LoadPluginBrowserDocks();
void *AddPluginBrowserDock(const QString &id, const QString &title,
const QString &url);
void RemovePluginBrowserDock(QDockWidget *dock);

#endif

QIcon imageIcon;
Expand Down
104 changes: 85 additions & 19 deletions UI/window-extra-browsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ void OBSExtraBrowsers::on_apply_clicked()

/* ------------------------------------------------------------------------- */

static QAction *PrepareBrowserDockWindow(OBSBasic *api, BrowserDock *dock,
QString url, bool firstCreate);

void OBSBasic::ClearExtraBrowserDocks()
{
extraBrowserDockTargets.clear();
Expand Down Expand Up @@ -524,11 +527,6 @@ void OBSBasic::ManageExtraBrowserDocks()
void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
const QString &uuid, bool firstCreate)
{
static int panel_version = -1;
if (panel_version == -1) {
panel_version = obs_browser_qcef_version();
}

BrowserDock *dock = new BrowserDock();
QString bId(uuid.isEmpty() ? QUuid::createUuid().toString() : uuid);
bId.replace(QRegularExpression("[{}-]"), "");
Expand All @@ -539,6 +537,84 @@ void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
dock->setWindowTitle(title);
dock->setAllowedAreas(Qt::AllDockWidgetAreas);

QAction *action =
PrepareBrowserDockWindow(this, dock, url, firstCreate);
if (!action) {
return;
}

if (firstCreate) {
dock->setVisible(true);
action->blockSignals(true);
action->setChecked(true);
action->blockSignals(false);
}

extraBrowserDocks.push_back(QSharedPointer<QDockWidget>(dock));
extraBrowserDockActions.push_back(QSharedPointer<QAction>(action));
extraBrowserDockTargets.push_back(url);
}

void OBSBasic::LoadPluginBrowserDocks()
{
/* Deferred loading of plugin browser docks since CEF is initialized
at this point */
for (int i = 0; i < pluginBrowserDocks.size(); ++i) {
auto dock = static_cast<BrowserDock *>(
pluginBrowserDocks[i].data());
(void)PrepareBrowserDockWindow(
this, dock, pluginBrowserDockTargets[i], true);
}
}

void *OBSBasic::AddPluginBrowserDock(const QString &id, const QString &title,
const QString &url)
{

BrowserDock *dock = new BrowserDock();
QString bId(QUuid::createUuid().toString());
bId.replace(QRegularExpression("[{}-]"), "");
dock->setProperty("uuid", bId);
dock->setObjectName(id + "_pluginBrowser");
dock->resize(460, 600);
dock->setMinimumSize(80, 80);
dock->setWindowTitle(title);
dock->setAllowedAreas(Qt::AllDockWidgetAreas);
dock->setVisible(false);

pluginBrowserDocks.push_back(dock);
pluginBrowserDockTargets.push_back(url);

if (cef) {
(void)PrepareBrowserDockWindow(this, dock, url, true);
}

return static_cast<QDockWidget *>(dock);
}

void OBSBasic::RemovePluginBrowserDock(QDockWidget *dock)
{
QString dockUUID = dock->property("uuid").toString();
for (const auto action : ui->menuDocks->actions()) {
if (action && action->property("uuid").toString() == dockUUID) {
delete action;
}
}
delete dock;
}

/* fills a browser dock window with CEF and adds compatibility shims */
static QAction *PrepareBrowserDockWindow(OBSBasic *api, BrowserDock *dock,
QString url, bool firstCreate)
{
if (!dock) {
return nullptr;
}
static int panel_version = -1;
if (panel_version == -1) {
panel_version = obs_browser_qcef_version();
}

QCefWidget *browser =
cef->create_widget(dock, QT_TO_UTF8(url), nullptr);
if (browser && panel_version >= 1)
Expand All @@ -564,30 +640,20 @@ void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
}
}

addDockWidget(Qt::RightDockWidgetArea, dock);
api->addDockWidget(Qt::RightDockWidgetArea, dock);

if (firstCreate) {
dock->setFloating(true);

QPoint curPos = pos();
QSize wSizeD2 = size() / 2;
QPoint curPos = api->pos();
QSize wSizeD2 = api->size() / 2;
QSize dSizeD2 = dock->size() / 2;

curPos.setX(curPos.x() + wSizeD2.width() - dSizeD2.width());
curPos.setY(curPos.y() + wSizeD2.height() - dSizeD2.height());

dock->move(curPos);
dock->setVisible(true);
}

QAction *action = AddDockWidget(dock);
if (firstCreate) {
action->blockSignals(true);
action->setChecked(true);
action->blockSignals(false);
}

extraBrowserDocks.push_back(QSharedPointer<QDockWidget>(dock));
extraBrowserDockActions.push_back(QSharedPointer<QAction>(action));
extraBrowserDockTargets.push_back(url);
return api->AddDockWidget(dock);
}
26 changes: 25 additions & 1 deletion docs/sphinx/reference-frontend-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Structures/Enumerations
- **OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED**

Triggered when the transition duration has been changed by the
user.
user.

- **OBS_FRONTEND_EVENT_TBAR_VALUE_CHANGED**

Expand Down Expand Up @@ -423,6 +423,30 @@ Functions

---------------------------------------

.. function:: void *obs_frontend_add_browser_dock(const char *id, const char *title, const char *url)

Adds a plugin-controlled browser dock to the UI. The dock will automatically
be added to the Docks menu, however in order to retrieve the associated
QAction, you must call :c:func:`obs_frontend_add_dock()` with the returned
pointer.

:param id: A unique ID used to identify this dock
:param title: Name of the dock to create
:param url: URL of page to show in the new dock
:return: A pointer to a new QDockWidget

---------------------------------------

.. function:: void obs_frontend_remove_browser_dock(void *dock)

Deletes a browser dock and any associated QActions. This is an alternative
to calling delete directly on the returned pointer for non-C++ plugins.

:param dock: A pointer to a QDockWidget returned from
:c:func:`obs_frontend_add_browser_dock()`

---------------------------------------

.. function:: void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data)

Adds a callback that will be called when a frontend event occurs.
Expand Down