Skip to content

Commit cd0f8c1

Browse files
authored
Merge pull request #27 from DDRBoxman/js-bindings
Visibility JS Bindings
2 parents 531ffcb + 09401cb commit cd0f8c1

14 files changed

+166
-8
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# obs-browser
2+
3+
CEF Based obs-studio browser plugin
4+
5+
## JS Bindings
6+
7+
obs-browser provides a global object that allows access to some obs specific functionality from javascript.
8+
9+
### Get OBS Studio Browser Plugin Version
10+
```
11+
window.obsstudio.pluginVersion
12+
// => 1.24.0
13+
```
14+
15+
### Register for visibility callbacks
16+
```
17+
/**
18+
* onVisibilityChange gets callbacks when the visibility of the browser source changes in OBS
19+
*
20+
* @param {bool} visiblity - True -> visible, False -> hidden
21+
*/
22+
window.obsstudio.onVisibilityChange(visiblity) {
23+
24+
};
25+
```

cef-isolation/cef-isolated-client.mm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,20 @@ - (void)sendKeyClick:(const int)browserIdentifier
287287
}];
288288
}
289289

290+
- (void)executeVisiblityJSCallback:(const int)browserIdentifier visible:(BOOL)visible
291+
{
292+
[self sendEvent:browserIdentifier
293+
event:^(SharedBrowserHandle browserHandle)
294+
{
295+
CefRefPtr<CefBrowser> browser = browserHandle->GetBrowser();
296+
297+
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("Visibility");
298+
CefRefPtr<CefListValue> args = msg->GetArgumentList();
299+
args->SetBool(0, visible);
300+
browser->SendProcessMessage(PID_RENDERER, msg);
301+
}];
302+
}
303+
290304
- (void)destroyBrowser:(const int)browserIdentifier {
291305
if (map.count(browserIdentifier) == 1) {
292306
std::shared_ptr<BrowserHandle> browserHandle =

obs-browser/apple/browser-manager-mac.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class BrowserManager::Impl {
4949
void SendFocus(int browserIdentifier, bool focus);
5050
void SendKeyClick(const int browserIdentifier,
5151
const struct obs_key_event *event, bool keyUp);
52+
53+
void ExecuteVisiblityJSCallback(int browserIdentifier, bool visible);
5254

5355
private:
5456
std::unique_ptr<CEFIsolationServiceManager> cefIsolationServiceManager;

obs-browser/apple/browser-manager-mac.mm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@
8181
pimpl->SendKeyClick(browserIdentifier, event, keyUp);
8282
}
8383

84+
void BrowserManager::ExecuteVisiblityJSCallback(int browserIdentifier, bool visible)
85+
{
86+
pimpl->ExecuteVisiblityJSCallback(browserIdentifier, visible);
87+
}
88+
8489
int BrowserManager::CreateBrowser(const BrowserSettings &browserSettings,
8590
const std::shared_ptr<BrowserListener> &browserListener)
8691
{
@@ -161,6 +166,11 @@
161166
keyUp);
162167
}
163168

169+
void BrowserManager::Impl::ExecuteVisiblityJSCallback(int browserIdentifier, bool visible)
170+
{
171+
cefIsolationServiceManager->ExecuteVisiblityJSCallback(browserIdentifier, visible);
172+
}
173+
164174
static BrowserManager *instance;
165175

166176
BrowserManager *BrowserManager::Instance()

obs-browser/apple/cef-isolation-service-manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class CEFIsolationServiceManager {
5656
void SendKeyClick(int browserIdentifier,
5757
const struct obs_key_event *event, bool key_up);
5858

59+
void ExecuteVisiblityJSCallback(int browserIdentifier, bool visible);
60+
5961
public:
6062
NSString *GetUniqueClientName() { return _uniqueClientName; }
6163

obs-browser/apple/cef-isolation-service-manager.mm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,13 @@
235235
}
236236
@catch (NSException *exception) {}
237237
}
238+
239+
void CEFIsolationServiceManager::ExecuteVisiblityJSCallback(int browserIdentifier, bool visible)
240+
{
241+
id<CEFIsolatedClient> cefIsolatedClient =
242+
[_cefIsolationService client];
243+
@try {
244+
[cefIsolatedClient executeVisiblityJSCallback:browserIdentifier visible:visible];
245+
}
246+
@catch (NSException *exception) {}
247+
}

obs-browser/browser-manager-base.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ void BrowserManager::SendKeyClick(int browserIdentifier,
7575
pimpl->SendKeyClick(browserIdentifier, event, keyUp);
7676
}
7777

78+
void BrowserManager::ExecuteVisiblityJSCallback(int browserIdentifier, bool visible)
79+
{
80+
pimpl->ExecuteVisiblityJSCallback(browserIdentifier, visible);
81+
}
82+
7883
BrowserManager::Impl::Impl()
7984
{
8085
os_event_init(&dispatchEvent, OS_EVENT_TYPE_AUTO);
@@ -98,7 +103,6 @@ int BrowserManager::Impl::CreateBrowser(
98103
CefPostTask(TID_UI, BrowserTask::newTask(
99104
[&]
100105
{
101-
102106
CefRefPtr<BrowserRenderHandler> renderHandler(
103107
new BrowserRenderHandler(browserSettings.width,
104108
browserSettings.height, browserListener));
@@ -268,6 +272,16 @@ void BrowserManager::Impl::SendKeyClick(int browserIdentifier,
268272
});
269273
}
270274

275+
void BrowserManager::Impl::ExecuteVisiblityJSCallback(int browserIdentifier, bool visible)
276+
{
277+
ExecuteOnBrowser(browserIdentifier, [&](CefRefPtr<CefBrowser> b)
278+
{
279+
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("Visibility");
280+
CefRefPtr<CefListValue> args = msg->GetArgumentList();
281+
args->SetBool(0, visible);
282+
b->SendProcessMessage(PID_RENDERER, msg);
283+
});
284+
}
271285

272286
void
273287
BrowserManager::Impl::Startup()

obs-browser/browser-manager-base.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class BrowserManager::Impl
5454

5555
void PushEvent(std::function<void()> event);
5656

57+
void ExecuteVisiblityJSCallback(int browserIdentifier, bool visible);
58+
5759
private:
5860
void ExecuteOnBrowser(int browserIdentifier,
5961
std::function<void(CefRefPtr<CefBrowser>)> f,

obs-browser/main-source.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,32 @@ static const char *browser_source_get_name(void *)
130130
return obs_module_text("BrowserSource");
131131
}
132132

133+
// Called when the source is visible
133134
static void browser_source_show(void *data)
134135
{
135136
BrowserSource *bs = static_cast<BrowserSource *>(data);
136137

137-
if ( bs->GetShutdown() )
138+
if ( bs->GetShutdown() ) {
138139
bs->UpdateBrowser();
139-
140+
}
141+
else {
142+
bs->ExecuteVisiblityJSCallback(true);
143+
}
140144
}
141145

146+
// Called when the source is no longer visible
142147
static void browser_source_hide(void *data)
143148
{
144149
BrowserSource *bs = static_cast<BrowserSource *>(data);
145150

146-
if (bs->GetShutdown())
151+
if (bs->GetShutdown()) {
147152
BrowserManager::Instance()->DestroyBrowser(bs->GetBrowserIdentifier());
153+
}
154+
else {
155+
bs->ExecuteVisiblityJSCallback(false);
156+
}
148157
}
149158

150-
151159
static void *browser_source_create(obs_data_t *settings, obs_source_t *source)
152160
{
153161
BrowserSource *browserSource = new BrowserSource(settings, source);

shared/browser-app.cpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@
1717

1818
#include "browser-app.hpp"
1919

20+
#include <iostream>
2021
#include <string>
2122

2223
#include "cefsimple/simple_handler.h"
2324
#include "include/cef_browser.h"
2425
#include "include/cef_command_line.h"
2526
#include "include/wrapper/cef_helpers.h"
27+
#include "browser-version.h"
2628

27-
BrowserApp::BrowserApp()
28-
{}
29+
BrowserApp::BrowserApp(){
30+
}
31+
32+
CefRefPtr<CefRenderProcessHandler> BrowserApp::GetRenderProcessHandler()
33+
{
34+
return this;
35+
}
2936

3037
void BrowserApp::OnRegisterCustomSchemes(
3138
CefRefPtr<CefSchemeRegistrar> registrar)
@@ -49,4 +56,48 @@ void BrowserApp::OnBeforeCommandLineProcessing(
4956
command_line->AppendSwitch("enable-begin-frame-scheduling");
5057

5158
command_line->AppendSwitch("enable-system-flash");
59+
}
60+
61+
void BrowserApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
62+
CefRefPtr<CefFrame> frame,
63+
CefRefPtr<CefV8Context> context)
64+
{
65+
CefRefPtr<CefV8Value> globalObj = context->GetGlobal();
66+
67+
CefRefPtr<CefV8Value> obsStudioObj = CefV8Value::CreateObject(0);
68+
globalObj->SetValue("obsstudio", obsStudioObj, V8_PROPERTY_ATTRIBUTE_NONE);
69+
70+
CefRefPtr<CefV8Value> pluginVersion = CefV8Value::CreateString(OBS_BROWSER_VERSION);
71+
obsStudioObj->SetValue("pluginVersion", pluginVersion, V8_PROPERTY_ATTRIBUTE_NONE);
72+
}
73+
74+
bool BrowserApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
75+
CefProcessId source_process,
76+
CefRefPtr<CefProcessMessage> message) {
77+
DCHECK(source_process == PID_BROWSER);
78+
79+
if (message->GetName() == "Visibility") {
80+
CefRefPtr<CefListValue> args = message->GetArgumentList();
81+
82+
CefRefPtr<CefV8Context> context = browser->GetMainFrame()->GetV8Context();
83+
84+
context->Enter();
85+
86+
CefRefPtr<CefV8Value> globalObj = context->GetGlobal();
87+
88+
CefRefPtr<CefV8Value> obsStudioObj = globalObj->GetValue("obsstudio");
89+
90+
CefRefPtr<CefV8Value> visibilityFunction = obsStudioObj->GetValue("onVisibilityChange");
91+
if (visibilityFunction && visibilityFunction->IsFunction()) {
92+
CefV8ValueList arguments;
93+
arguments.push_back(CefV8Value::CreateBool(args->GetBool(0)));
94+
visibilityFunction->ExecuteFunction(NULL, arguments);
95+
}
96+
97+
context->Exit();
98+
99+
return true;
100+
}
101+
102+
return false;
52103
}

0 commit comments

Comments
 (0)