From 1a8ea7e262c71e760c33e0ed6b8505bbd0103c40 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 30 Mar 2022 21:03:27 +0200 Subject: [PATCH 1/3] Add RFC: Switch to Advanced Docking System --- .../0047-switch-to-advanced-docking-system.md | 377 ++++++++++++++++++ .../legacy_dock.png | Bin 0 -> 9367 bytes .../linux_native_floating_dock_titlebar.png | Bin 0 -> 9460 bytes .../linux_qwidget_floating_dock_titlebar.png | Bin 0 -> 9238 bytes 4 files changed, 377 insertions(+) create mode 100644 text/0047-switch-to-advanced-docking-system.md create mode 100644 text/0047-switch-to-advanced-docking-system/legacy_dock.png create mode 100644 text/0047-switch-to-advanced-docking-system/linux_native_floating_dock_titlebar.png create mode 100644 text/0047-switch-to-advanced-docking-system/linux_qwidget_floating_dock_titlebar.png diff --git a/text/0047-switch-to-advanced-docking-system.md b/text/0047-switch-to-advanced-docking-system.md new file mode 100644 index 0000000..dd9897f --- /dev/null +++ b/text/0047-switch-to-advanced-docking-system.md @@ -0,0 +1,377 @@ +# Summary + +- Switch main dock system to [ADS][1] +- Make ADS dock state per profile +- Allow the user to switch between pre-made layouts + - Plugins could register their own + - Users could save their own +- Dock added by plugins with the old method are added as "*Legacy dock*" +- Frontend API methods and events about ADS docks + +Note: The "central widget" design is kept. + +# Motivation + +Provide a better dock system to end-users. + +# Design +**DISCLAIMER**: The "central widget" design is kept, switching to a non-"central widget" one is not part of this RFC. + +## Main window dock separation +To make OBS Studio compatible with ADS, Controls, Transitions, Mixer, Sources, Scenes docks need to be separated from the main window. + +And the central widget of main window should also be separated as well to become the central dock. + +So the docks will be separated as widget class with their own UI class. + +Then those widget are inserted in OBSDock (QDockWidget) and the central widget and put as main window central widget. + +And then we switch to ADS, all those widget will become docks and added to the ADS dock manager. + +The OBSBasic heavily rely on some UI element from those docks, to resolve that the related code will be refactored to remove this dependance going toward a MVC pattern. + +Each widget class will be put as a friend class in OBSBasic to allow access to private slot and avoid moving them as public. + +### Controls widget +*Future ADS Controls dock widget* + +All the buttons of this dock will be connected through signal and slots to OBSBasic. + +Some hotkeys and pause functions rely on UI buttons, so OBS Basic will be refactored to remove this dependance. + +### Transistions widget +*Future ADS Transitions dock widget* + +Transitions will be stored in OBSBasic and selected through the combo box of the widget. + +The transition duration will become an attribute of OBSBasic, and signal and slots will be setup to synchromise it with the dock spinbox. + +Buttons for adding, removing and open settings will be connected through signals and slots to OBSBasic. + +### Mixer widget +*Future ADS Mixer dock widget* + +The base dock is easily separable, but the VolControl class can be refactored (toward MVC) later because this is not a requirement for this RFC. + +### Sources widget +*Future ADS Sources dock widget* + +OBSBasic heavily rely on the SourceTree from the widget, but a refactoring will not be considered as a requirement for this RFC. So the class of the sources widget will have OBSBasic as a friend class. + +### Scenes widget +*Future ADS Scenes dock widget* + +OBSBasic heavily rely on the SceneTree from the widget, but a refactoring will not be considered as a requirement for this RFC. So the class of the scenes widget will have OBSBasic as a friend class. + +### Central widget +*Future ADS Central dock widget* + +Some context bar, preview/program and nudge related code is moved to the central widget class. + +This class will have OBSBasicPreview as a friend class. + +This class will be a friend class of OBSBasic also to have access to some gs_vertbuffer_t type attributes. + +## ADS +The Advanced Docking System, require to add a Dock Manager in the main window and then add the central widget and then add other docks. + +Some work on themes CSS will be required. + +### About obs-deps + +obs-deps already build Qt for macOS and Windows, so adding a ADS script to the Qt tarballs is not a problem. + +### Floating docks titlebar on X11 +On X11, ADS provide two type of titlebar for floating docks: + +- Native + +[![Native titlebar under GNOME](./0047-switch-to-advanced-docking-system/linux_native_floating_dock_titlebar.png)]() + +- QWidget based (WIP CSS) + +[![QWidget titlebar](./0047-switch-to-advanced-docking-system/linux_qwidget_floating_dock_titlebar.png)]() + +The QWidget one is used by default when using KWin based Desktop Environement like Plasma. And this titlebar requires some CSS in the themes to match it. + +So the QWidget based titlebar usage will be enforced thanks to a flag for the Dock Manager to "unify" experience between desktop environement. +Theme makers may ignore to theme this bar. + +### Dock state +*The per profile dock state feature is not taken into account to describe those changes.* + +In the global config (`global.ini`). +- `"dockState"` is kept for for backward compatiblity and no longer overwitten. It will be used if the following state is not present. +- `"windowState"` is the state of the main window, since it does not store only the state of legacy docks. +- `"advDockState"` is the state of the dock manager which contain only the states of any ADS dock. + +Service integrations only save `"advDockProfile"` + +ADS dock state is compressed by default but behind the scene it's XML. + +### OBSAdvDock +OBSAdvDock is a class which inherit `ads::CDockWidget` class. + +This class has a constructor which require a QWidget and setup some things arround the widget and set some connections. + +It adds a warning message when closing a dock from a close dock button. + +It allows to reset a dock position after a UI reset or a layout change with a possibility to reset the size if set beforehand. + +### Custom Browser docks and BrowserAdvDock +The custom browser docks feature is modified to use BrowserAdvDock which inherit OBSAdvDock. + +Those docks are stored in the dock manager and their names is stored in a QStringList for browser docks to be able to get the dock from the manager to modify it like changing the URL. + +Each of those browser dock is named `extraBrowser_$UUID` where `$UUID` is replaced by the dock UUID to have a really unique name. + +### Service integration docks + +Like custom browser docks, those integration are modified to use BrowserAdvDock. But their names is stored in the QStringList for plugins extra docks. + +Those docks are named `obs-$SERVICE_$DOCK_NAME` where `$SERVICE` is the service name in lowercase and `$DOCK_NAME` the name of the dock. + +`"dockState"` will be imported from the integration config if `"windowState"` is not present. + +### Reset UI action +1. Legacy dock are hidden +2. The default state written in XML is applied +3. Each not shown OBSAdvDock/BrowserAdvDock dock have its position and size reseted. + +## Legacy dock + +If switching to ADS is made at the same as switching to Qt 6. This feature will only concern builds that still use Qt 5 (e.g. Ubuntu 20.04). + +The frontend API method `obs_frontend_add_dock()` is put in deprecation. And if dual switch only Qt5 and on Qt 6 the method is removed or does nothing, this is possible because plugin will need to be rebuilt agaisnt Qt6. + +And dock added through this method are added to a sub-menu named `Legacy dock` of the Dock menu. + +[![Legacy dock menu](./0047-switch-to-advanced-docking-system/legacy_dock.png)]() + +When openning a legacy dock, a message will appear explaining that those docks will not meld wery well with "new" docks. + +The state of those are saved through `"windowState"` global config. + +## Per profile dock state +Move the `"advDockState"` from global config to the profile and integration no longer store their own state. `"windowState"` is kept global. + +If a release happen between the switch to ADS and this feature, import the one from the integration service if the profile has one set up. + +## Layouts management +Add the feature, to switch between registered/saved dock layouts: +- Though a sub-menu in the dock menu +- Through a hotkey +- Through the frontend API + +OBS Studio could provide layouts, the default count as one. + +Plugins could also register their own XML layouts through the frontend API. + +Users could be able to save their own layouts. Those layouts will have their name prefixed with`user_` to avoid name conflicts. + +Note: ADS perspective feature is not directly used because it relies heavily on QSettings. +## Frontend API +Like said earlier, the method `obs_frontend_add_dock()` is put in deprecation. + +All add/remove methods related to ADS requiring a name will require the plugin module to be able to prefix the given name with the module name (`mod_name`) to avoid conflicts. + +So the following method will be added to libobs to access modules `mod_name`: +```c++ +EXPORT const char *obs_get_module_mod_name(obs_module_t *module); +``` + +### Add a dock +```c++ +/* takes QWidget */ +#define obs_frontend_add_dock_2(title, unique_name, widget) \ + obs_frontend_add_module_dock(obs_current_module(), title, \ + unique_name, widget) +EXPORT void obs_frontend_add_module_dock(obs_module_t *module, + const char *title, + const char *unique_name, + void *widget); +``` + +This allow to add a OBSAdvDock with the given QWidget. Those docks are stored in the Dock Manager and their names is stored in the QStringList for plugins extra docks. + +Default height and width would based on the widget actual size except if `"defaultWidth"` and `"defaultHeight"` properties are set with the [`setProperty()`][7] method on the widget. + +Minimum sizes used by the dock are based on the widget ones. + +### Remove a dock +```c++ +#define obs_frontend_remove_dock(unique_name) \ + obs_frontend_remove_module_dock(obs_current_module(), unique_name) +EXPORT void obs_frontend_remove_module_dock(obs_module_t *module, + const char *unique_name); +``` + +This allow the plugin to remove a dock added earlier. + +### Add a browser dock +```c++ +EXPORT bool obs_frontend_is_browser_available(void); +``` + +This allow to know if the running OBS Studio has browser feature enabled. So it return false if OBS Studio was built without browser or is running under Wayland. + +```c++ +#define obs_frontend_add_browser_dock(dock_params, browser_params) \ + obs_frontend_add_module_browser_dock(obs_current_module(), \ + dock_params, browser_params) +EXPORT void obs_frontend_add_module_browser_dock(obs_module_t *module, + struct obs_frontend_browser_dock_params *dock_params, + struct obs_frontend_browser_params *browser_params); +``` + +This allow the plugin to add a dock with a QCefWidget as widget. + +If browser docks are added in the module load or post load steps, their parameter will be stored and those will be really added later. + +The QCefWidget will get parameters from this structure: + +```c++ +struct obs_frontend_browser_params { + const char *url; + bool enable_cookie; + struct dstr startup_script; + DARRAY(char *) force_popup_urls; +}; +``` + +- `bool enable_cookie`: if true `panel_cookie` will be used. The plugin maker will have to remove the dock the between profile change because the cookie manager is per profile. +- `struct dstr startup_script` allow to set a startup script for the QCefWidget. +- `DARRAY(char *) force_popup_urls` allow to set a list of url forced to popup. + +And the dock itself will get parameters from this structure: + +```c++ +struct obs_frontend_browser_dock_params { + const char *unique_name; + const char *title; + int default_width; + int default_height; + int min_width; + int min_height; +}; +``` + +`obs_frontend_remove_dock()` can be used to remove the browser dock. + +### Remove browser cookie +Since enabling cookie is posible, allowing to delete those is required. + +```c++ +EXPORT void obs_frontend_delete_browser_cookie(const char *url); +``` + +This will remove cookie related to the given URL. + +### Add a dock layouts +```c++ +#define obs_frontend_add_dock_layout(title, unique_name, xml_layout) \ + obs_frontend_add_module_dock_layout(obs_current_module(), \ + title, unique_name, xml_layout) +EXPORT void obs_frontend_add_module_dock_layout(obs_module_t *module, + const char *title, + const char *unique_name, + const char *xml_layout); +``` + +This allow the plugin to add a dock layouts in XML to the UI. ADS allow to test a layout (state/perspective) without applying it, so the layout will be tested before registering it. + +### Get a list of docks layouts +```c++ +EXPORT char **obs_frontend_get_dock_layouts(void); +``` + +This allow the plugin to get a list of registered dock layouts from the UI. + +### Set a registered dock layout +```c++ +EXPORT void obs_frontend_set_dock_layouts(const char *layout_name); +``` + +This allow the plugin to set a registered dock layouts to the UI, the asked name should come directly from the get list method. + +### Remove a dock layouts +```c++ +#define obs_frontend_remove_dock_layout(unique_name) \ + obs_frontend_remove_module_dock_layout(obs_current_module(), \ + unique_name) +EXPORT void obs_frontend_remove_module_dock_layout(obs_module_t *module, + const char *unique_name); +``` + +This allow the plugin to remove a dock layouts from the UI. + +### Add a entirely custom dock +```c++ +/* takes ads::CDockWidget */ +#define obs_frontend_add_custom_dock(unique_name, dock) \ + obs_frontend_add_module_custom_dock(obs_current_module(), \ + unique_name, dock) +EXPORT void obs_frontend_add_module_custom_dock(obs_module_t *module, + const char *unique_name, + void *dock); +``` + +Some plugin like [Sources Dock][6], do not add their docks to the Dock menu. + +So this method allow to do this but requires the plugin to be link against ADS library. + +And the dock will not have OBSAdvDock features. + +Even if the plugin has the control over the dock, the the name is changed by the frontend API to be prefixed by the module name. + +`obs_frontend_remove_dock()` can be used to remove the reference stored in the Dock Manager. Because their names is stored in the QStringList for plugins custom extra docks. + +### Get the XML behind a registered dock layout +*Method meant to allow a Dock Layout editor tool to exist* + +```c++ +EXPORT char *obs_frontend_get_dock_layout(const char *layout_name); +``` + +This allow the plugin to get a registered dock layouts XML, the asked name should come directly from the get list method. + +### Get the XML of the actual dock state +*Method meant to allow a Dock Layout editor tool to exist* + +```c++ +EXPORT char *obs_frontend_get_current_dock_state(void); +``` + +This allow the plugin to get the dock states XML of the UI. + +### Events addition +- An event before the startup restore dock state and `OBS_FRONTEND_EVENT_FINISHED_LOADING` to allow plugins to load their docks before the restore or redo a restore if the number of extra docks has changed. This event could possibly be emitted when profile is changed before restoring profile dock state and `OBS_FRONTEND_EVENT_PROFILE_CHANGED`. + +- An event when the a dock layout is applied (reset or not) to allow plugins to reset the positions of their customs docks, if they want to. + +## About making dock states future proof +By default generated state are version 0. If one day we make a breaking change like remove the notion of central widget and so change the version. + +We could take the saved `"advDockState"` and uncompress to edit the XML, to make it compatible with the change. + +# Drawbacks +We can't convert old `"dockState"` to the new dock system. + +# Additional Information +About Wayland support, Qt and ADS docking system have very bad support because of Qt Wayland. The Wayland backend is apparently third-class on Qt's priorities. + +My WIP branches: +- [Dock separation][2] +- [Central widget separation][8] +- [Switch to ADS][3] +- [Frontend API to add ADS dock][4] +- [Frontend API to add custom ADS dock][5] + +[1]: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System +[2]: https://github.com/tytan652/obs-studio/tree/dock_separation +[3]: https://github.com/tytan652/obs-studio/tree/advanced_docking +[4]: https://github.com/tytan652/obs-studio/tree/ads_frontend_api +[5]: https://github.com/tytan652/obs-studio/tree/add_custom_dock +[6]: https://obsproject.com/forum/resources/source-dock.1317/ +[7]: https://doc.qt.io/qt-5/qobject.html#setProperty +[8]: https://github.com/tytan652/obs-studio/tree/central_widget_separation \ No newline at end of file diff --git a/text/0047-switch-to-advanced-docking-system/legacy_dock.png b/text/0047-switch-to-advanced-docking-system/legacy_dock.png new file mode 100644 index 0000000000000000000000000000000000000000..41392765ea7ece37146bd7e98ea9fc98228b100c GIT binary patch literal 9367 zcmbVyWmJ`2)a`>HA}!M0B@%*2mvncRaOiHNeJKF}Dd{e0=?3ZU?(UXG;@f`r$NhQ7 zxX&0IIOA~6*?X_G=A3J;Cqz+R0u7lE8G;}*DM?Xf2!e|Te`_E;1CJ8P>Du7eOM6Kz zCkR6C{PzPF_XeE^g2*8$QDIg0l%rHP-HD#39+og_ArW#>p{Tc?8ou-V7A`U>$@&^< zj$^GRl&M|Lcvlo!V>Bg#gJ<*?y>^1*Vx$|B=6D^WtK#dO4F)WP}rpEA8hL z%3r_e85rOoVqRA!TLWEnQ(WZ0=ssA_4eb)` zEO-MA6&06Ro6CBam4i@EM<@CFcSU`DQUU@CTU%z_Fe^(-`4lcCeSLK3^x`6g+c>Yh zyj+O7x4$=3kQf6>;QL%rR>lI6Gcp!7G&GcmMY54jc;_W2B_Rj4H{CaNvWK9dp+SD& zRCu_#-%oxZzI~9?x7EkNm^rLqepnf z+@VsoI1V=U&)S7!c3AKC!^6Y0@+oheWWLXT;@)T=A^g`66finDxw*cstfn?qgIS_a zgef_ak)PjV$U4dV34-1wro_kN;p6|jN^1;BPS&x*$W&Riugl8HTBx-v(rbqxY~-z> zJUDEK7Y+5uNUD95gg$-djzZ4~G__ zk_j}`2A?_@85?VqXy+=urpLB?dVEkWxERg+cp|eJiZyN))tJ?3RPH5UkgIopcjti~ zY;0&~2!rK}Ltb89(J?V<9->Y;d3g~8?0II^E}z7t$T1li8D(Ws5p z@$g(-VPaQU&%Gm!oRNCDapq1yK+qFGa(;RF{{4HKhurUdn*}QQX}oU7Q$-qNM+ku; zse-2L=w>{9o`3q+IDXd$`6X%so=D$|U8Nb+aANL1>AsIj7iO(Le}0wE zcPlY_-@fG-B5Ks*=;U>(YO0#|u|Z8uO`2~QtY)nRU(`ym zqV{3QZN)_kB-7sB9!M8;RVy2t5}4kE@v1#n{np8H^TApaef#uu&5@-N6Yk%;JFscz z^ZqtJIQUqmL{QeMY+qf4vd6GfS>GiN*45S7Uiq$fhBP$r)T?n34-X6!B|o^mCLtja zn{o3v)E<|3g&bIEHX`1Ae!BLNgd`PYZ&B_}APOF1ftrn*!BO&8Oi78Ks+K(>G;ZIR zb?Y*48$oX9H#iq8GD=AFcwQeDbV<)B4&W4#uKw8?P|264!9?00X9)m%<>cV#eK3O5 z)QUH<@SZ90@{yJqXGW(oxGZ^ni-=IqGO}bFGbt`E_Hctzccx2pl6E-(7_qS_*~VEi z(q11t|8fBh4}%Js7em;6CkZ{PN5y9qdQ02zEih2*1U+M>-uI~`i?NOcaSR>6n#Y(& zWPQ#XkulwGZH5$m>*9RSu@v{{&$)e9cxD$PJrT3A^v)Y!KNyc81?125{~ z`=zC&E&jQ%ccMGIfxM~CDwhU$ZAKY5AHwdweJ7?{U074aHeeMs|rvWtvLwg zY;Wn_Z&`D>fe$=>U;@&$^X2H8tIN*x+^23z4OLgRGc|B=*-R9i59YipT5k;S*aT& zA)uq9qljrAVPZhL#%Zly(y`V&@2 z4$8u*F7tKvhb-*pBZ>i(Q^$G=t7!<4J#V5}6J_(xzD}vDt5=#1W$})NAOIBJFz|hF zdAPeA7L=!qIXpUIXMZ=vMa|3GXtPiwm8)E!IuA}nQ!^nUK~qPkNc{B@%zM*A15X3; z(_|_wDv|MyPD)8B<{RA0|0pT>wX(7@KR8mwso=1WRVe2R0fz;Tu6Z; z1cZdl+Ew%%9934NQ%O_|414p{R)C&sYHHx%;FwF97krl=$!>TG106QHn>{Z3mzVXG z;NQF{ij9pOA6KTM%a3T(2B}k~->h7b7t;rOO)I@b-cvuedjD@_Ur{ZvEt=j zLsqyA48!)fAKc^rUf>JB`hz>FQN(HEq{S$sgvc>NL_w$ke8>Tkl+I-g&va9&I-`l{ zTVG%2C^GsI_KZxx-JNrf=}%2@G3sZB``NRSg&Imb8*6J$+r^us+Lf%a-TFr-ety0) zcfPPLX-P@e9Q@%_Uc9ibhPsBF{CrT)Ng|m{x>cideFR}$rZ89v-)F2_vF@&}R9?5? zo}OUo+#edTWP+|%?4$ciW1>H{#_r`OtuC74B zwizBSHzyC7s?f*U#d{qHxnUv)&Xno3I-Dayve7Q z^_LGqXBvH%_$?=YPEM*qe!=-Yg9Pjas+Qi~59z-5iBXAg&~Kyi^X;MYiwkP35Ku}s zVg%vhEC%Jo;UXsswIk!>@961!CnvEpg!JW?TOR&SUJV=z!`>03%8v{WlfHv}&EllT z?jIhOr^n9A$pIS#k%pkA=4Rj9Ej$_pIEavtP*+#Cfq>3Af%G#RG^Y}2m_UYT;6mQZ(qg$CKQ%!j}12Z!zn~|uP zSm1(vEs!&YtoRM^{A>&kq1V`nvNc9s$dF%L98U5OB2=thz3@O>7OF|Oe#-$w0Q zVag#f^!xtyoJFrC)}Be2Qk}EU$Z3}4k3k(s#=JbBa-TD!etV>8$ZBezo8zXWGy-u0 zO#`S8`3QMHmZt9#IS5ORMjCIDyBb8700gNq#`!d#9#mCTftUApcN3D5T>ofHd?4U) z-USS1I+T>#G>2#4rKGESe|Kqxf)W<#;RwoBS}(J6x>zf_G^a^A1+@Vc(La&H0-R9{ z1o`;*5DqCXk^mL5GnknD6L(H?boE%E&kq4IH+1FXvsN*VDJ?CXL120I<+mX#59tLy z5fSewNpy6yDCMij9vNwAM>jV+mz`#(9rWN1pdGm9xIx~1uKx`AnJJ{dLJEjDgH93d zfh3eq<-zgg(ofIvJznI_Ar9*zmElrXQK7;_+Drlux3{;<%*>GAD=Kl_7O%u(p`O>L z04KZzS}Q7|l{$V^Ryq+KBR-~jCM6`yE-XBq?T`T^uc^7(o5-hHlAzoMqRDQh;q5Al zK*LU#H7xqF5Ap-J#eer#>9bb7EbYL^$jD$n@dsNFn2Cw=_FNPoSSh1^zQ=5oWjw#W zJ^_t`wKY=(VTq|~-pQau zBxx$YXU)=+O(9!c&qg)R{N&VB=9oEFNB|RKGU3XJvotjpZt~O}AvEg16M7g12LbMD z1|@j6m+x{gO`%qTmC+0E;5cE-SXo(_iHWJAqC#3m=0zhaCz*L#Obk3E>74>7>2PD? zH9ofc*?Jd%RRRJ+ILOGz=)2D^O>22ud0ri|KvUU|c`mAqmzM`KC0m!5m#S2Zke@8= z%v6owZ3RfPiV8+%X4?m9-=~M`kk@pjn&tluY^4c!H?Z%?{N*ZAFW~{0sI9H-b}u;r z)O;lAlH0S{+K)=hnD0esV@A>ieL?FZ@AGh1O^X~Wo$LE>sUa%b32L(XQwJifOmv}dWMpP$M$l)}tO?7QLsxUSlaso|Y;Uws3Evh3^$_U%}9hxJaiB6WtsRMt--2UbIOVKk|7 zf3B|5wmuAWb^;j!ItvOI{NM=fEYA^;-1cIdGU%H{0nRw}3Bi4jzK?7^_ z#@t+!ku?66mKMob0-n^;>};x-KIsAJF>?+?f3PFaTu20M@^=x{zgntM)ImZpFe+IVDASPd;Um3aIl2!S7LUL!TqmO${|&`xm&AW{B@b*MKVzd z-fi|zy@8-NGH?8VbH+!yqWu#`R8;hEvAz<;C_p^h|G)om-)e6H;99QYw+v`A)YR4< zP8T#d_Ik~2)8u(=3)UUhg@uG*RF3c82AWOEC@%9+ayvUa;9Cr{$N;!F*x#3=R%RJi zh&yqSP2;OS(s74>IqtUS4qre8O5?J{`|l)HTx(vQ>7UI$>C(V!p1i!goso32a!m|U zzB>0aBMXZH=|~-IZQGR=Z{Vw?)<4Cjrt(|Q{wj^A(gACGBaKTHCAqk?1fXQO2D1=9 z=OjzF3$$0I2CV`<_wHM%8>9)A_ccc(pTJE>)yAmw)v~5s4U!7^qBy?CJ{lr zmq=0Vcrg8z25w_}ICa5cMaZ8Kw0qRGeB|UpQ>EnTw9=}@2CY6OCMIP3@l7Ddf4tSf zN9}HKIcRTh=dpG7|6`u-DRqwA6KaS{<| ztH{V!*!|}k-R#`m>$2v1BFQ32c-3vy(gl*f2=QRy;NUHRj~x zJU%{7b%+fM4?prjniCkt5WLU0M?Cui|H8wR8ngl$l%Ien7)p&QgyV0H7ZnvH?dSx0 zCtybshUf8_D2a;)WoK`I!vbetw5Tg0(hfehkxTvUr-2`Dr3GF9@v)Z-5BZ&*+S8ng z^$!dzEiT6Lp=-o`Z;@%l$ptQ2bgUp{)K^LBLc%L54i4-yKc(^R|6`mmx)kYYYH7vA z$G<6*la(i$*rP}J@;jVsxFeMvjOv&qv zMb!Nx3ZXkpY4qYXUDRh^%s+sB6!WVqyxRZcNqSajvjFMrjjT@-nivOvt7g<`bx`;D zp3nzuZo;<3-S=QPXW=vt>LNj_fQsAsE_&p#s!L?#*Jj+OD~n_R^!b7L=3NMOy} zDSIo*(`&{-gQ&+jyFd`<%3??Nd zg@Vh3goeiN@FxIJ*k+KVn1$Aq3@{?h1{22MgJLo9@g>LUj+QE~Uq`WK?A0gey4$5` ztlUV=o)XG%zJGA^Pdmbg{C*bfFKwaSyRrPr@!=@@wNE5CSLXc;GH3Qsbn`9yss^t} zzrQO~xT6dho~gL`@0&Ltv?$GKleoud1DczEb^8n%VHdCg!i(z1{emr$2aYl&?Z#LSx(y2xr976K9_Kx$cW7lN7@Z1XauHZHW z-^WGx^3tX~XyzUHMC~OptEU@=_kZ()1HOT>6YTHESt^0oe0hF;etJ4OGsD8dq97^x zv#?OR)z({B7%mz{ZY`D&RwQF?{!^B=va&jC5wqTTZ+vxib${Q|vw?ppZFtL(MXw>=rP4`*gg8{hY%_}1l^x<1d)4$Dg98Tfhv)Bucbmsi%iZL<4NNe#)Jx$+~lRxzE zU7U*hliavtBu8uDcW=EY9hc{Etw}MTh^jg~q zF3RLWYzo{>t2dbg`<5-44jesBF2|QH?WEld3ngla7k_bca@aPbB z!<{L|+^tOZ*q3*&40bDuPmip_>S=W?=+elf2R92pc-Q)FsGX=O0ppu4$2J{&R(^2>fbv=U^b0?(Xh@`(oEui5dx?y&`8I6FVLGGp7b#;OfG*xn8jeQ`#7keHOjh#Q8JTju8E)?vs7 zL@?mUq(?cI#58>+M`RWISU6aG0R&+!p~!GrFv#I>wyZS|oLqM?Vk3r4H@U%T93d0lNQ(;lHIqd)AqG%5M*YyGkxEan3xCx2l+KMHR0NZ zfkRhiEGa5Fzq-m(E&%GUrbfMVPp8(d+3PlXWM=?Y0jO24-UIkNV!!cn7Ns1X21zVp zQd8ezBj+kx$ji&O`aEc-%e5qZgP}9MVUbZ#C@U$6lg=G^mzJ221=pAJIWoe&7Uz3SIByAdV zQLl>{$>@wUoD9r%6-!>`J-wC@9W0QV`udg#K-kFyranGk9a54S^8r^5b_(L zUu8%B3Ll)sdg2t3Bo}EUz^mgT@a!XbqHM@yHSyTx$kywQK1sed-Cw*hOy8Y33nbjk zleI{sL{K4M&&txqSPKpJ_gh+6loP=|wA*x^?~I@zBjd8@d!4O|c{X?-5Qg^MV;U$h zVP&(K7pOK^Owgw92`psS;^AVaaeWrCbrnGLAG@0$9c6Xb`sEyg4X7wn%;**5Cz3gs z^nPG|o-hNFN}v3FKPsg%(Yklsg~b^b-t`NK-axUcMTt%)SKis^#U;6BiFsVi}EBglgx< zjjv!*d-A{%dA)tx_=c$D2Q`JZO4Y=MH=Tz#C2n?!>L+J3sfgEe^?i#oiLq-wN8$Su zqK8S-wOF*KOPrpZgvqjtbH*vsV*`sZhmM71q;JfkZs8PEx?z(s zJ|SVmy)|`ApLHBxJ@3}g&`^j}$j)%OPM!T)=r0_d?3(_NfT=vcE+Y~ydvY)?v+>^j zGaA$oRH9QGDw-8yAWM97Mlo6=y+@viCM%FmhKE;c+=G6?uv}}mqz;Sf*oMJi-_Gzi z3{Os1*We)`t2+-csPwt<<}&ekLujDXpJSA$dHR^HD&lw}qNp=|asQtz_|tl~#S z)pphk#E)i-`()WxUnvL^{+^WhI)B$md=9OuoA!x%`H8$jtb-B}Bs1tHd-kMW9wcZz zfYNGV_h!IG1}+k(cajh}y}K3!^$rXXy|)CwTj-$^SbXSZdb7E?Nxuh7p817^>@o8w zNmVVakeN1kXm-dNIS_Pl1vhZIG@Y2+bKwN5N<$OQVbB!MCPIU#5!HH4TcpUirkJjlD7IQaskWeH0Ao9Z3eQ; zKx()rk*Kd|w%b@r@)uh1D^HQ`KM8!B9s{azwDXkQGV|A~>oal8A$H?#RMN=!`1F|t zc%?5@RUBe!-eO(uaU&~wx^!!mV>}IaHE9pDJ}b9o+-1tkdfJiM3CVw-5P4F2NuS*! zI1sJjVi7BAXw;gWke1BW+nH=i2C^r&fa$joq^l(I7(Yo@5L&p(FO7tdwFLSlA@X@N zRkr{8M9yr4eog&N&W_SLe+d*j!yU%+Wmx zQ976FT_|{X@yr)e*<;|I09x6E)!p5jvuWvq!omiJ4RJ7l)7I4iBPo7h$sAu#nDBUt z_gNeIG`&K|Qs*f!D#=j%nJW_yf;HdUD+xRv;PT}DJ`VzxVO14t;-FrmD~0X#{&W8} zRaMo5#pzPzvk8hcnoSmIP%N$EzCrSx!*4RG3eY!ta zaCYW!Bsgdduw={=i^n3LmpPyj0E1Z)VE+TN3v|Pxlu?q@pTLPLge7)0)g}uFrd)WTbiByNs;Z1 zFs1rUGJuVUoG`d&gMy`@!05XI!j#vwPOCncRgO#enZ;rvi8g*=MEoLDMFhr;|DR9B ztkH8Q{DTKk63lFEhd0iao4lQNM>8AddBU{=gviqgEfvdia&r9q{35o1@Ox!N8387S pH)qCrdV0Wb#LoeZ;?LBl7y5HXq8Uv|Oh83JQeyI=r6Pv^{SQ(nKpy}A literal 0 HcmV?d00001 diff --git a/text/0047-switch-to-advanced-docking-system/linux_native_floating_dock_titlebar.png b/text/0047-switch-to-advanced-docking-system/linux_native_floating_dock_titlebar.png new file mode 100644 index 0000000000000000000000000000000000000000..54473949fcfa4d6d6ded6383bf259b4e6859b486 GIT binary patch literal 9460 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 xpFoXuK1ZynpCeURp(}6!!k}{{rqQ6Hx#F literal 0 HcmV?d00001 diff --git a/text/0047-switch-to-advanced-docking-system/linux_qwidget_floating_dock_titlebar.png b/text/0047-switch-to-advanced-docking-system/linux_qwidget_floating_dock_titlebar.png new file mode 100644 index 0000000000000000000000000000000000000000..ca31c879dbf02ff4ddf398db1c629d053c0479e0 GIT binary patch literal 9238 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 Date: Sun, 31 Mar 2024 11:20:39 +0200 Subject: [PATCH 2/3] Remove unneeded pieces --- .../0047-switch-to-advanced-docking-system.md | 101 +++--------------- 1 file changed, 13 insertions(+), 88 deletions(-) diff --git a/text/0047-switch-to-advanced-docking-system.md b/text/0047-switch-to-advanced-docking-system.md index dd9897f..08f88d8 100644 --- a/text/0047-switch-to-advanced-docking-system.md +++ b/text/0047-switch-to-advanced-docking-system.md @@ -5,8 +5,7 @@ - Allow the user to switch between pre-made layouts - Plugins could register their own - Users could save their own -- Dock added by plugins with the old method are added as "*Legacy dock*" -- Frontend API methods and events about ADS docks +- Dock added by plugins with the old methods are added as "*Legacy dock*" Note: The "central widget" design is kept. @@ -140,7 +139,7 @@ Those docks are named `obs-$SERVICE_$DOCK_NAME` where `$SERVICE` is the service ## Legacy dock -If switching to ADS is made at the same as switching to Qt 6. This feature will only concern builds that still use Qt 5 (e.g. Ubuntu 20.04). +**TODO: Talk about `obs_frontend_add_custom_qdock()`** The frontend API method `obs_frontend_add_dock()` is put in deprecation. And if dual switch only Qt5 and on Qt 6 the method is removed or does nothing, this is possible because plugin will need to be rebuilt agaisnt Qt6. @@ -171,103 +170,23 @@ Users could be able to save their own layouts. Those layouts will have their nam Note: ADS perspective feature is not directly used because it relies heavily on QSettings. ## Frontend API -Like said earlier, the method `obs_frontend_add_dock()` is put in deprecation. -All add/remove methods related to ADS requiring a name will require the plugin module to be able to prefix the given name with the module name (`mod_name`) to avoid conflicts. - -So the following method will be added to libobs to access modules `mod_name`: -```c++ -EXPORT const char *obs_get_module_mod_name(obs_module_t *module); -``` - -### Add a dock -```c++ -/* takes QWidget */ -#define obs_frontend_add_dock_2(title, unique_name, widget) \ - obs_frontend_add_module_dock(obs_current_module(), title, \ - unique_name, widget) -EXPORT void obs_frontend_add_module_dock(obs_module_t *module, - const char *title, - const char *unique_name, - void *widget); -``` +**TODO: Talk about obs_frontend_add_dock_by_id() that is now a thing** This allow to add a OBSAdvDock with the given QWidget. Those docks are stored in the Dock Manager and their names is stored in the QStringList for plugins extra docks. -Default height and width would based on the widget actual size except if `"defaultWidth"` and `"defaultHeight"` properties are set with the [`setProperty()`][7] method on the widget. +Default height and width would based on the widget actual size. Minimum sizes used by the dock are based on the widget ones. ### Remove a dock -```c++ -#define obs_frontend_remove_dock(unique_name) \ - obs_frontend_remove_module_dock(obs_current_module(), unique_name) -EXPORT void obs_frontend_remove_module_dock(obs_module_t *module, - const char *unique_name); -``` - -This allow the plugin to remove a dock added earlier. - -### Add a browser dock -```c++ -EXPORT bool obs_frontend_is_browser_available(void); -``` - -This allow to know if the running OBS Studio has browser feature enabled. So it return false if OBS Studio was built without browser or is running under Wayland. - -```c++ -#define obs_frontend_add_browser_dock(dock_params, browser_params) \ - obs_frontend_add_module_browser_dock(obs_current_module(), \ - dock_params, browser_params) -EXPORT void obs_frontend_add_module_browser_dock(obs_module_t *module, - struct obs_frontend_browser_dock_params *dock_params, - struct obs_frontend_browser_params *browser_params); -``` - -This allow the plugin to add a dock with a QCefWidget as widget. -If browser docks are added in the module load or post load steps, their parameter will be stored and those will be really added later. +**TODO: Talk about `obs_frontend_remove_dock()` that is now a thing** -The QCefWidget will get parameters from this structure: - -```c++ -struct obs_frontend_browser_params { - const char *url; - bool enable_cookie; - struct dstr startup_script; - DARRAY(char *) force_popup_urls; -}; -``` - -- `bool enable_cookie`: if true `panel_cookie` will be used. The plugin maker will have to remove the dock the between profile change because the cookie manager is per profile. -- `struct dstr startup_script` allow to set a startup script for the QCefWidget. -- `DARRAY(char *) force_popup_urls` allow to set a list of url forced to popup. - -And the dock itself will get parameters from this structure: - -```c++ -struct obs_frontend_browser_dock_params { - const char *unique_name; - const char *title; - int default_width; - int default_height; - int min_width; - int min_height; -}; -``` - -`obs_frontend_remove_dock()` can be used to remove the browser dock. - -### Remove browser cookie -Since enabling cookie is posible, allowing to delete those is required. - -```c++ -EXPORT void obs_frontend_delete_browser_cookie(const char *url); -``` +### Add a dock layouts -This will remove cookie related to the given URL. +**TODO: Refactor API design** -### Add a dock layouts ```c++ #define obs_frontend_add_dock_layout(title, unique_name, xml_layout) \ obs_frontend_add_module_dock_layout(obs_current_module(), \ @@ -295,6 +214,9 @@ EXPORT void obs_frontend_set_dock_layouts(const char *layout_name); This allow the plugin to set a registered dock layouts to the UI, the asked name should come directly from the get list method. ### Remove a dock layouts + +**TODO: Refactor API design** + ```c++ #define obs_frontend_remove_dock_layout(unique_name) \ obs_frontend_remove_module_dock_layout(obs_current_module(), \ @@ -306,6 +228,9 @@ EXPORT void obs_frontend_remove_module_dock_layout(obs_module_t *module, This allow the plugin to remove a dock layouts from the UI. ### Add a entirely custom dock + +**TODO: Redo as those will be only legacy docks** + ```c++ /* takes ads::CDockWidget */ #define obs_frontend_add_custom_dock(unique_name, dock) \ From c9a21f29a5429e35ea29996fa7d78afb1fd8d00d Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 31 Mar 2024 13:14:58 +0200 Subject: [PATCH 3/3] Update to new API and one more TODO --- .../0047-switch-to-advanced-docking-system.md | 67 +++++++------------ 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/text/0047-switch-to-advanced-docking-system.md b/text/0047-switch-to-advanced-docking-system.md index 08f88d8..3404e10 100644 --- a/text/0047-switch-to-advanced-docking-system.md +++ b/text/0047-switch-to-advanced-docking-system.md @@ -94,17 +94,17 @@ On X11, ADS provide two type of titlebar for floating docks: The QWidget one is used by default when using KWin based Desktop Environement like Plasma. And this titlebar requires some CSS in the themes to match it. So the QWidget based titlebar usage will be enforced thanks to a flag for the Dock Manager to "unify" experience between desktop environement. -Theme makers may ignore to theme this bar. +Theme authors may ignore to theme this bar. ### Dock state *The per profile dock state feature is not taken into account to describe those changes.* In the global config (`global.ini`). -- `"dockState"` is kept for for backward compatiblity and no longer overwitten. It will be used if the following state is not present. -- `"windowState"` is the state of the main window, since it does not store only the state of legacy docks. +- `"dockState"` is kept for for backward compatiblity and no longer overwritten. It will be used if the following state is not present. +- `"windowState"` is the state of the main window which also contains legacy docks state. - `"advDockState"` is the state of the dock manager which contain only the states of any ADS dock. -Service integrations only save `"advDockProfile"` +Service integrations only save `"advDockState"` ADS dock state is compressed by default but behind the scene it's XML. @@ -139,18 +139,20 @@ Those docks are named `obs-$SERVICE_$DOCK_NAME` where `$SERVICE` is the service ## Legacy dock -**TODO: Talk about `obs_frontend_add_custom_qdock()`** - -The frontend API method `obs_frontend_add_dock()` is put in deprecation. And if dual switch only Qt5 and on Qt 6 the method is removed or does nothing, this is possible because plugin will need to be rebuilt agaisnt Qt6. - -And dock added through this method are added to a sub-menu named `Legacy dock` of the Dock menu. +If the deprecated frontend API method `obs_frontend_add_dock()` is used the dock added through this method are added to a sub-menu named `Legacy dock` of the Dock menu. [![Legacy dock menu](./0047-switch-to-advanced-docking-system/legacy_dock.png)]() -When openning a legacy dock, a message will appear explaining that those docks will not meld wery well with "new" docks. +When openning a legacy dock, a message will appear explaining that those docks will not meld wery well with ADS docks. The state of those are saved through `"windowState"` global config. +`obs_frontend` + +### About custom QDockWidget + +Docks added through `obs_frontend_add_custom_qdock()` (or `obs_frontend_add_dock()` with the returned QAction deleted)will have almost the same treatment as legacy docks because by design those don't have a QAction in the dock menu. + ## Per profile dock state Move the `"advDockState"` from global config to the profile and integration no longer store their own state. `"windowState"` is kept global. @@ -159,8 +161,8 @@ If a release happen between the switch to ADS and this feature, import the one f ## Layouts management Add the feature, to switch between registered/saved dock layouts: - Though a sub-menu in the dock menu -- Through a hotkey - Through the frontend API +- Can be extended later to be through a hotkey OBS Studio could provide layouts, the default count as one. @@ -169,19 +171,15 @@ Plugins could also register their own XML layouts through the frontend API. Users could be able to save their own layouts. Those layouts will have their name prefixed with`user_` to avoid name conflicts. Note: ADS perspective feature is not directly used because it relies heavily on QSettings. -## Frontend API - -**TODO: Talk about obs_frontend_add_dock_by_id() that is now a thing** - -This allow to add a OBSAdvDock with the given QWidget. Those docks are stored in the Dock Manager and their names is stored in the QStringList for plugins extra docks. +**TODO: Check if ADS perpective has changed, or maybe upstream improvement to it** -Default height and width would based on the widget actual size. +## Frontend API -Minimum sizes used by the dock are based on the widget ones. +`obs_frontend_add_dock_by_id()` implementation is to be modified to use OBSAdvDock rather than OBSDock. -### Remove a dock +Default height and width would need to be based on the widget size when added as a dock. -**TODO: Talk about `obs_frontend_remove_dock()` that is now a thing** +`obs_frontend_remove_dock()` stay the function to remove the dock. ### Add a dock layouts @@ -227,29 +225,13 @@ EXPORT void obs_frontend_remove_module_dock_layout(obs_module_t *module, This allow the plugin to remove a dock layouts from the UI. -### Add a entirely custom dock - -**TODO: Redo as those will be only legacy docks** - -```c++ -/* takes ads::CDockWidget */ -#define obs_frontend_add_custom_dock(unique_name, dock) \ - obs_frontend_add_module_custom_dock(obs_current_module(), \ - unique_name, dock) -EXPORT void obs_frontend_add_module_custom_dock(obs_module_t *module, - const char *unique_name, - void *dock); -``` - -Some plugin like [Sources Dock][6], do not add their docks to the Dock menu. - -So this method allow to do this but requires the plugin to be link against ADS library. - -And the dock will not have OBSAdvDock features. +### About custom dock -Even if the plugin has the control over the dock, the the name is changed by the frontend API to be prefixed by the module name. +Switching to ADS would force to deprecate this "feature", plugins authors will have to use only `obs_frontend_add_dock_by_id()`. -`obs_frontend_remove_dock()` can be used to remove the reference stored in the Dock Manager. Because their names is stored in the QStringList for plugins custom extra docks. +- ADS will be built as a static library on most of the platforms and so plugins authors will be unable to use it's API. +- `obs_frontend_add_custom_qdock()` was a temporary measure until a change of docking system could allow the behavior to be truly deprecated. +- Custom docks were mainly used to avoid over-filling the docks menu which would create a long list (e.g. [Sources Dock][6]). ### Get the XML behind a registered dock layout *Method meant to allow a Dock Layout editor tool to exist* @@ -290,13 +272,10 @@ My WIP branches: - [Central widget separation][8] - [Switch to ADS][3] - [Frontend API to add ADS dock][4] -- [Frontend API to add custom ADS dock][5] [1]: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System [2]: https://github.com/tytan652/obs-studio/tree/dock_separation [3]: https://github.com/tytan652/obs-studio/tree/advanced_docking [4]: https://github.com/tytan652/obs-studio/tree/ads_frontend_api -[5]: https://github.com/tytan652/obs-studio/tree/add_custom_dock [6]: https://obsproject.com/forum/resources/source-dock.1317/ -[7]: https://doc.qt.io/qt-5/qobject.html#setProperty [8]: https://github.com/tytan652/obs-studio/tree/central_widget_separation \ No newline at end of file