macOS Browser Panel Support #197
No reviewers
Labels
No labels
area/accessibility
area/dependency
Confirmed
Crash Report
Delayed
Design Issue
Duplicate
Feedback required
Good first issue
kind/bug
kind/cleanup
kind/enhancement
platform/linux
platform/macos
platform/windows
priority/high
Question
Request for Comments
Seeking Other Contributors
Seeking Testers
Won't Fix / By Design
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-obsproject/obs-browser!197
Loading…
Reference in a new issue
No description provided.
Delete branch "macos"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Mac support for browser panels.
Depends on https://github.com/obsproject/obs-studio/pull/2386
Motivation and Context
How Has This Been Tested?
Build and run on 10.14.6, click around, not that many things crash
Types of changes
Checklist:
TODO:
The packaging is incredibly janky, so I'm just going to say it's Somebody Else's Problem
Packaging?
Getting
Chromium Embedded Framework.frameworkinto the right place relative to the executable. Though it's possible this has already been solved by the CI scripts and it's just broken for me because I don't build the same way as CI.Yea I'm confused, we already include it for the browser source. Were you meaning something different?
No, you understood right. I guess that's not actually a problem.
Is there some way to package the app in the same way that CI does but locally?
Short answer is not very easily at the moment. Long answer is we used to be able to do that with the bundle_app.py script but some things changed and now the CI scripts seem to have some added (and probably unnecessary) complexity. I think they should be something that can be simplified in to a single script but it's multiple scripts at the moment on CI. I was going to take a look at it after we release 25 originally.
It's very hard to resize panels with this. Seems like you need to get the mouse onto exactly the pixel between the panels, or the panel will grab the mouse event.
Calling
objc_msgSenddirectly is discouraged and Xcode 11 refuses to compile, this works however:@tbodt Checked this out today, resizing is indeed hard - even if the mouse cursor changed to the vertical/horizontal resize variant, you end up creating a selection box in the canvas.
Also when closed in detached state and then reopened, the reopened window can't be resized, but dragged and re-attached.
Panels stay in their attached and detached places between OBS sessions, so that part seems to work fine.
Did some further checks today, most functionality seems fine (i.e. renaming the title, opening links in a new tab when modifier is pressed), the size is restored correctly for attached panels, but detached panels are reset, maybe the
Resize()method needs to be implemented for macOS as well.Reloading a panel is not possible as the default keystroke CMD+R is already taken by OBS to reset transforms, might be better to move those transform-keystrokes to CMD+Option+R, etc.
As for packaging, CEF expects to be placed in a proper macOS app bundle which CMake doesn't generate, so the framework references need to be patched, which Cmake would do automatically when
-DBROWSER_DEPLOY=OFFis used, but that part needs to be updated and even with it in place OBS crashes right now.I've added a PR to the main project with a cleaned-up build script which just needs to be run with
-s -bto create an app bundle that will run with all necessary libraries.Maybe this is as good a time as any to implement a refresh button in the title bar of the dock itself.
Would adding a couple pixels of margin around the CEF wrapper in the dock do the trick? Likely best to add it on all sides.
From what I could tell this is an issue with all panels on macOS not just with the browser panel.
Aside from the compilation fix above I'd say that the non-resizable window that you end up when
the panel needs to be fixed as well and then this might be good to go. Haven't had time to figure out to test the built-in Twitch panels with oAuth-flow though.
Weird, because that's supposed to be controlled by macOS. I guess time to experiment with these? According to a quick Google, modifying the styling of the widget itself won't help.
Follow-up from my previous comment - after experimenting with docks on Windows, I can (unfortunately) confirm that docks are locked to the
Qt::Toolwindow type, which means we have very little more we can do (as in, we can't use "bigger" native decorations).Technically, Qt supports custom window decorations, but in my testing on Windows the grips around the window turn from 5px to 1px in custom mode, and I expect the behaviour would be similar on other platforms. It's a terrible experience and I wouldn't recommend the switch.
I'm running into the
objc_msgSendissue when I try to build this@Eric if I'm not mistaken this issue will occur when a more recent version of platform libraries or
clangis used, so it's a must fix in my book.Is someone else going to take up the work on this pull request?
To make it easier to make that change:
I prefer something a little more compact
For the curious, I'm pretty sure they changed the objc_msgSend prototype because they knew the varargs ABI wouldn't be compatible with normal parameters on the upcoming ARM macs, and decided to change the prototype a year early to get everyone ready
Went ahead and rebased this as well
Great! Time to discuss potential solutions for the TODOs.
For 1, I think that ideally the correct behaviour is treating the Qt shortcuts as priority, and if the user has a CEF panel focused, allowing OBS to pass things back and forth. The problem is that the OBS Copy/Paste isn't designed for text, it's purely for sources. Showing different copy/paste options while a panel is focused would probably be a very unpleasant hack UX-wise, so I'm not sure what we should do here.
For 2/3, does https://github.com/obsproject/obs-studio/pull/2890 help in achieving them?
Has this been explored? The goal is to resize the window based on the size of the widget.
github.com/obsproject/obs-browser@2e5f316b54/panel/browser-panel.cpp (L272-L275)I'd do it opposite - let's give the new functionality (ie. browser panels) the less common keys, the check itself is pretty simple otherwise
github.com/obsproject/obs-browser@2e5f316b54/panel/browser-panel-client.cpp (L204-L206)Yep, let's cross those off the list (thanks @PatTheMav!)
The difficulty of resizing is much more annoying to me than any of the other problems you mention, but it seems like that's a problem with all the panels and not just browser panels. Is there another issue open for that?
Copy/pasting with keyboard shortcuts seems to work fine in QT text fields, so maybe we can do whatever that's doing in browser panels.
It seems weird to me that OBS has completely custom handling of copy/paste though: shouldn't QT be handling that by passing it to whatever the currently focused thing is? Then the same action can work for sources and everything else.
Based on my own research, as far as I can tell this is a limitation of macOS "tool" windows, and can probably be reproduced with non-Qt apps. We don't currently have an issue open on our side, no.
Qt normally does, yes. The problem is with how CEF handles focus - either due to how we have it implemented, or for some other reason. Switching focus from OBS itself to a browser panel does not provide any event to Qt that focus has changed. Once you then unfocus the entire OBS window (including the dock) without clicking within OBS itself, Qt never receives an unfocus event, because CEF never passes it over to Qt. This can result in a disconnect, where OBS still thinks it's focused (breaking hotkeys, for example). In my testing, the CEF Focus Handler just doesn't do what it should. You can find my attempts here: https://github.com/obsproject/obs-browser/compare/master...WizardCM:fix-focus - but I've basically hit a wall.
AFAIK macOS doesn't have a native concept of "tool" windows, or docks of the type QT supports. That's entirely implemented within QT. I just tried another QT app with docks (https://sqlitebrowser.org/) and resizing was much smoother than in OBS, so it must be a problem with OBS.
@tbodt
Do you know what version of Qt they are using? As I understand it, there have been a lot of changes between Qt 5.10 and 5.15 that may change performance on macOS, some causing performance regressions and some improvements.
They use 5.12 apparently. https://github.com/sqlitebrowser/sqlitebrowser/pull/2287#issuecomment-645774467
In that case, let's try something.
If this solves the issue, this is either caused by specific QSS code on our end, or it's caused by Qt's "reset" when custom QSS is used. If either of those is the case, should be easy to fix with our own QSS.
If this doesn't solve the issue, then SQLiteBrowser is doing something different from us, and we may still be able to solve it by looking at their code.
To clarify, as far as I know, the graphics changes in Qt that I'm referencing were initially released in 5.12.3 and 5.14. Additional changes were done in 5.12.6, 5.12.7, 5.12.8, 5.12.9, 5.14.1, 5.14.2, 5.15, and the upcoming 5.15.1.
I did try the "System" theme in OBS and it behaved badly in the same way.
Hi, I built OBS Studio and Xcode gave an error.
CI + -G Xcode (image)
https://user-images.githubusercontent.com/71022195/95679952-be670580-0bde-11eb-8ef8-94e2f3caee5e.png@H20CH3PO2 what was the precise make call that you used to configure the Xcode project? Also what Xcode version and macOS version do you have there?
@PatTheMav
I used (wiki/inst intructions)
or also, with expanded vars, used CI+-GXcode at another build dir
My macOS ver: 10.15.7 (19H2)
My Xcode ver: 12.0.1 (12A7300)
Maybe stupid question, but did you run the additional fix-ups for CEF (see below)?
@PatTheMav
Thank you. The instructions did say, “Tell the user to move the necessary files,” but I had no idea about the tests that weren't working. I apologize.
All good - the combined build script contains all the "secrets" to successfully build OBS and bundle/package it with all bells and whistles. Feel free to copy from it what you need.
You can also just use the script to build it, make code-changes and re-run the script to compile/bundle (which is necessary for CEF anyway) with just one command. It will take care of dependencies and all.
I've played around with this a bit and IMO this piece should be removed:
github.com/obsproject/obs-browser@39f7ea62b4/CMakeLists.txt (L255)The main reason is that CEF expects to run as part of an application bundle - it will crash otherwise (as it tries to find a bundle path and fails). So creating an app bundle is necessary to run a build with CEF included on macOS to begin with, which the build script will take care of (e.g. to create a proper bundle from an Xcode build works via
BUILD_DIR="xcodebuild" BUILD_CONFIG="Debug" ./CI/full-build-macos.sh -d -s -b).With this change, when OBS is compiled with browser support but not bundled, the app will crash as soon as a browser panel or browser source is active in the current profile.
Small update - I've tried the last 5 days to find the root cause of Qt resizing the browser dock to 80x80 pixels if it has been closed in a detached state and to be brutally honest, I hit a roadblock.
minimumSizeinAddExtraBrowserDockQtDockWidgetwill size itself to fit its content (it cannot be resized itself)QCefWidgetInternal::showEventwith the size used in the docked stateQCefWidgetInternal::resizeEventis called with 80x80QCefWidgetInternal::resizeEventmultiple times until it reaches the final sizeQCefWidgetInternal::resizeEventagain with a size of 80x80When removing the
minimumSizeon the dock widget, Qt will not show the detached dock. Investigating the frame stack and checking the sizes reported byQCefWidgetInternalas well as theCefBrowserHostViewshows that both have a correct size, yet Qt ignores it and sets theminimumSize. The dock itself also becomes non-resizable.Only restarting OBS makes the dock resizable again, re-attaching and detaching will keep the size, until the dock is closed in the detached state again.
This seems to require someone with more Qt/OBS UI knowledge to figure out, as I tried a number of hacks to set/reset/override the sizes at multiple events, but Qt always ignores these values or sets the dock size as well as the contained widget's sizes to 80 by 80 points before the event handlers in
QCefWidgetInternalare called.The most unpleasant bug that I have is a crash when the program is started with browserdock initialization. Before that, I open dockbrowser and close OBS Studio after which is saved in the settings that it should open dock at startup. I am working in Xcode. I did everything for the make according to the instructions. My macOS version 10.15.7. I would like to know if you get a similar bug.
re the issue where the dock widget locks to 80x80 size after undocking-closing-showing again.
here's the fix:
you have to change how BrowserDock::closeEvent behaves
instead of relying on the event propagating to the parent and doing the work, all you have to do is to add those two lines at the end of the method:
with this change, everything begins behaving as it should.
here's the complete working version of the method:
you might want to put the last two lines between an #ifdef APPLE_ & #endif pair -- I haven't tested this change on Windows.
one more thing
with this fix, you can remove the
cefWidget->closeBrowser()call completely and allow browsers to run in the background.my theory is that the close event propagated to CEF, and caused havoc inside. once you set
event->ignore()this no longer happensthe close event starts behaving the same as hiding the dock widget from the menu
@zavitax This is great news - that fixes it indeed. Would you have any insight why this is only an issue on macOS but not on Windows? I'm trying to figure out if this will have unintended consequences on Windows where the docks work as intended right now.
@PatTheMav given my extremely low mileage with macOS (just a bit over a month), I can only speculate that this is due to differences in docks implementation between the platforms, which is kind of inevitable. I would love to know more details myself.
This can really stem from CEF, Qt or macOS internals...
Just rebased
@tbodt @WizardCM with regards to resize grip widths:
First and foremost, it is a function of a stylesheet margin: if you set
dock->setStyleSheet("QDockWidget { margin: 0px 4px 4px 4px; }");you get a large enough margin to grab onto. I'm using 4px since it corresponds to the 4 pixels used by the privateQWidgetResizeHandlerimplementation.Enlarging the margin without replacing
QWidgetResizeHandlerhas no effect except a visual one.I've also tried implementing a rudimentary
QWidgetResizeHandlerwith#define RANGE 24(RANGE = default size grip width) and setmargin: 24px- this had the expected effect of having a much wider resize grip areas.So, this can be easily fixed by modifying the
QDockWidgettheme stylesheet.I'm not convinced there needs to be a margin. Other Qt apps seem to work fine without one. The QSplitterHandle is supposed to overlap the dock widget by a bit, so mouse events near the edge get captured by the splitter handle. I checked the view hierarchy in Xcode and they do overlap, so not sure what's happening with the event handling.
Are we talking about floating or docked widgets? QSplitterHandle seems to apply to docked panels. I was addressing floating state.
Oh, I'm talking about docked panels. Didn't realize you were talking about something different, since they both have some kind of resize grip.
There you have it. I was not aware docked state even has an issue.
Some more info from Qt's docs:
https://doc.qt.io/qt-5/stylesheet-reference.html
QDockWidgetSupports styling of the title bar and the title bar buttons when docked.
The dock widget border can be styled using the border property. The ::title subcontrol can be used to customize the title bar. The close and float buttons are positioned with respect to the ::title subcontrol using the ::close-button and ::float-button respectively.
When the title bar is vertical, the :vertical pseudo class is set. In addition, depending on QDockWidget::DockWidgetFeature, the :closable, :floatable and :movable pseudo states are set.
Note: Use
QMainWindow::separatorto style the resize handle.Warning: The style sheet has no effect when the QDockWidget is undocked as Qt uses native top level windows when undocked.
So far I've figured out that despite the splitter being 5px wide (in OBS default dark theme) its QWidgetWindow has a mask that ignores any input outside a 1px wide region. I'm not sure where this mask comes from. The QSplitter widget sets a mask on itself, but my understanding is that widget masks affect only drawing, not input. On top of this it looks like there might be a bug in Qt handling of mouse events on masked windows, where the mouse down event passes through but not the mouse drag or mouse up event.
Unrelated to the current discussion, I just realised a discrepency of featureset - on Windows, we listen for a Ctrl+R keypress to allow users to reload the panel's contents. A similar condition should be added for macOS (I assume Cmd+R would be best?).
github.com/obsproject/obs-browser@35b26e9dc0/panel/browser-panel-client.cpp (L200-L209)As mentioned in https://github.com/obsproject/obs-browser/pull/197#issuecomment-626829236:
Even better would be non-global keyboard shortcuts (that is shortcuts that change based on window focus) but that's not how Qt works iirc.
At least on Windows, when CEF is focused, Qt doesn't have focus so default shortcuts don't work. I assume this behaviour is different on macOS due to the command bar? I assume you've verified the behaviour yourself by adding in the relevant check?
#ifndef _WIN32
#include <dlfcn.h>
#endif
Because does not compile on Windows
@WizardCM I wouldn't know where to implement those checks, but I can confirm that OBS intercepts all keystrokes, so even copy&paste functionality is intercepted (so no pasting passwords into the oauth panels). Right-clicking in the CEF window and choosing "copy/paste" works however.
This change must be reverted - CEF will make OBS crash if it is found and loaded without OBS being packaged into an application bundle
Adding this would prohibit debugging OBS in Xcode without bundling it manually on every build. Also this is taken care of by
full-build-macoswhen an application bundle is created.This needs to be changed at least for macOS:
github.com/obsproject/obs-browser@1c34fd79e4/panel/browser-panel.cpp (L83)obs_module_config_pathalready returns an absolute path on macOS (possibly all POSIX-based systems?) and for some reasonos_get_abs_path_ptrwill fail (asrealpathwill return an error, probably because the path didn't exist on first run).Possible fix:
With this Twitch oauth and panels worked fine, as did chat addons.
@PatTheMav I can confirm on Ubuntu 20.04 that that line requires changing too. Nice catch!
Done. The Linux PR has a different solution for this, we can revert the changes to this file entirely if that lands.
Done
I've seen @tbodt pushed some requested changes - great! Would you mind applying this change as well? macOS and Linux require it: https://github.com/obsproject/obs-browser/pull/197#issuecomment-738076375
@PatTheMav I can't reproduce the crash. Is there something special I need to do?
You need to delete the
obs_profile_cookiesdirectory underApplication Support/obs-studio/plugin_config/obs-browserif it exists. When you launch OBS without that fix it will crash.I've tested this PR with and without Twitch OAUTH support and also with CEF 3770 and CEF 4183, works fine with both versions. Our patched Qt 5.15.2 fixes the resize bug with detached panels and otherwise I didn't run into unexpected behaviour.
I will try testing this with a debug build tomorrow to catch any low-level CEF issues, but looks fine so far.
I tested this today as well, deleted the obs-browser plugin config directory before and did not get any crash so far. Also tested our Twitch authentication with it, all worked as expected (including the quirks known from the Windows side of things).
Good to merge from my POV.
Confirmed everything works very well with latest OBS master on 10.14. I was unable to reproduce the quirks others have mentioned, so I have to assume they are introduced in 10.15 and above.
🚀