Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
  • abdsaber000/vlc
  • falbrechtskirchinger/vlc
405 results
Show changes
Commits on Source (7)
Showing
with 1487 additions and 124 deletions
......@@ -3971,6 +3971,7 @@ AS_IF([test "${enable_qt}" != "no"], [
QT_PATH="$(eval $PKG_CONFIG --variable=exec_prefix Qt5Core)"
QT_HOST_PATH="$(eval $PKG_CONFIG --variable=host_bins Qt5Core)"
QT_INCLUDE_DIRECTORY="$(eval $PKG_CONFIG --variable=includedir Qt5Core)"
QT_VERSION="$(eval $PKG_CONFIG --modversion Qt5Gui)"
AC_PATH_PROGS(MOC, [moc-qt5 moc], moc, ["${QT_HOST_PATH}" "${QT_PATH}/bin"])
AC_PATH_PROGS(RCC, [rcc-qt5 rcc], rcc, ["${QT_HOST_PATH}" "${QT_PATH}/bin"])
......@@ -3980,6 +3981,28 @@ AS_IF([test "${enable_qt}" != "no"], [
AC_MSG_WARN([qmlcachegen not found])
])
dnl Check private headers avaibility
VLC_SAVE_FLAGS
CPPFLAGS="${CPPFLAGS} ${QT_CFLAGS}"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtCore/${QT_VERSION}"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtCore/${QT_VERSION}/QtCore"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtGui/${QT_VERSION}"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtGui/${QT_VERSION}/QtGui"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtQml/${QT_VERSION}"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtQml/${QT_VERSION}/QtQml"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtQuick/${QT_VERSION}"
CPPFLAGS="${CPPFLAGS} -I${QT_INCLUDE_DIRECTORY}/QtQuick/${QT_VERSION}/QtQuick"
AS_IF([test "${SYS}" != "mingw32"], [
CPPFLAGS="${CPPFLAGS} -fPIC"
])
AC_LANG_PUSH([C++])
AC_CHECK_HEADERS([private/qquickitem_p.h private/qquickwindow_p.h],
[have_declarative_private="yes"], [])
AC_LANG_POP([C++])
VLC_RESTORE_FLAGS
VLC_SAVE_FLAGS
CPPFLAGS="${CPPFLAGS} ${QT_CFLAGS}"
AC_COMPILE_IFELSE(
......@@ -4044,10 +4067,12 @@ AS_IF([test "${enable_qt}" != "no"], [
ALIASES="${ALIASES} qvlc"
])
AC_SUBST([QT_VERSION])
AC_SUBST([QT_INCLUDE_DIRECTORY])
AM_CONDITIONAL([ENABLE_QT], [test "$enable_qt" != "no"])
AM_CONDITIONAL([HAVE_QT5_X11], [test "${have_qt5_x11}" = "yes"])
AM_CONDITIONAL([HAVE_QT5_WAYLAND], [test "${have_qt5_wayland}" = "yes"])
AM_CONDITIONAL([HAVE_QT5_GTK], [test "${have_qt5_gtk}" = "yes"])
AM_CONDITIONAL([HAVE_QT5_DECLARATIVE_PRIVATE], [test "${have_declarative_private}" = "yes"])
dnl
dnl detect kde4-config patch (used for kde solids).
......
From 3bb63935369d7e1baf53aa401563cc75b87397fb Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
Date: Sat, 29 Jan 2022 21:59:33 +0200
Subject: [PATCH 1/2] Make sure QQuickWidget and its offscreen window's screens
are always in sync
By default, the offscreen window is placed on the primary screen.
However, if the parent widget argument is passed to the QQuickWidget's
constructor, then QQuickWidget's and the offscreen window's screens can
be different and that can create rendering issues, e.g. blurry text if
the primary screen and QQuickWidget's screen have different scale
factors.
Change-Id: I10c62b5635664f943b11828773f14017f198a770
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
(cherry picked from commit a2a2734bffa1459639b31fb3f4f83873ba44ab5c)
---
src/quickwidgets/qquickwidget.cpp | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 39780f8de3..223d91f579 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -106,6 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
renderControl = new QQuickWidgetRenderControl(q);
offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
+ offscreenWindow->setScreen(q->screen());
offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
// Do not call create() on offscreenWindow.
@@ -901,9 +902,7 @@ void QQuickWidgetPrivate::createContext()
context = new QOpenGLContext;
context->setFormat(offscreenWindow->requestedFormat());
- const QWindow *win = q->window()->windowHandle();
- if (win && win->screen())
- context->setScreen(win->screen());
+ context->setScreen(q->screen());
QOpenGLContext *shareContext = qt_gl_global_share_context();
if (!shareContext)
shareContext = QWidgetPrivate::get(q->window())->shareContext();
@@ -1520,19 +1519,16 @@ bool QQuickWidget::event(QEvent *e)
d->handleWindowChange();
break;
- case QEvent::ScreenChangeInternal:
- if (QWindow *window = this->window()->windowHandle()) {
- QScreen *newScreen = window->screen();
-
- if (d->offscreenWindow)
- d->offscreenWindow->setScreen(newScreen);
- if (d->offscreenSurface)
- d->offscreenSurface->setScreen(newScreen);
+ case QEvent::ScreenChangeInternal: {
+ QScreen *newScreen = screen();
+ if (d->offscreenWindow)
+ d->offscreenWindow->setScreen(newScreen);
+ if (d->offscreenSurface)
+ d->offscreenSurface->setScreen(newScreen);
#if QT_CONFIG(opengl)
- if (d->context)
- d->context->setScreen(newScreen);
+ if (d->context)
+ d->context->setScreen(newScreen);
#endif
- }
if (d->useSoftwareRenderer
#if QT_CONFIG(opengl)
@@ -1545,7 +1541,7 @@ bool QQuickWidget::event(QEvent *e)
d->render(true);
}
break;
-
+ }
case QEvent::Show:
case QEvent::Move:
d->updatePosition();
--
2.34.1
From f2afdde302aeb895989a4fef58c6fa75fc93364f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@qt.io>
Date: Fri, 7 May 2021 10:07:50 +0200
Subject: [PATCH 2/2] Implement accessibility for QQuickWidget
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The accessibility tree for the Qt Quick content should
be rooted at the QQuickWidget, and not at the offscreen
QQuickWindow.
For this to be the case, several things must happen:
- QQuickWindow must not report the child interfaces
- QQuickWidget must report the child interfaces
- The child interfaces must report the QQuickWidget as the parent
Create accessibility interfaces for QQuickWidget and
and QQuickWigetOffscreenWindow (which now gets a proper
subclass), where the QQuickWidget interface reports
the child interfaces and the QQuickWigetOffscreenWindow
reports no children
Change the code in QAccessibleQuickItem to use the
true (visible) window, where needed.
Fixes: QTBUG-67290
Change-Id: I387d0ef711138d248a8dd16eefc9839499b35eeb
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 41926e08d73ea6c4bbfc87a1dd52d2cdbc435c27)
---
src/quick/accessible/qaccessiblequickitem.cpp | 29 +++--
src/quick/accessible/qaccessiblequickview_p.h | 2 +-
src/quickwidgets/qaccessiblequickwidget.cpp | 110 ++++++++++++++++++
src/quickwidgets/qaccessiblequickwidget.h | 84 +++++++++++++
.../qaccessiblequickwidgetfactory.cpp | 60 ++++++++++
.../qaccessiblequickwidgetfactory_p.h | 66 +++++++++++
src/quickwidgets/qquickwidget.cpp | 18 ++-
src/quickwidgets/qquickwidget_p.h | 8 ++
src/quickwidgets/quickwidgets.pro | 8 +-
9 files changed, 368 insertions(+), 17 deletions(-)
create mode 100644 src/quickwidgets/qaccessiblequickwidget.cpp
create mode 100644 src/quickwidgets/qaccessiblequickwidget.h
create mode 100644 src/quickwidgets/qaccessiblequickwidgetfactory.cpp
create mode 100644 src/quickwidgets/qaccessiblequickwidgetfactory_p.h
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index 85719fdc80..eb3df4d4cd 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -46,6 +46,7 @@
#include "QtQuick/private/qquicktextinput_p.h"
#include "QtQuick/private/qquickaccessibleattached_p.h"
#include "QtQuick/qquicktextdocument.h"
+#include "QtQuick/qquickrendercontrol.h"
QT_BEGIN_NAMESPACE
#if QT_CONFIG(accessibility)
@@ -57,7 +58,19 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
QWindow *QAccessibleQuickItem::window() const
{
- return item()->window();
+ QQuickWindow *window = item()->window();
+
+ // For QQuickWidget the above window will be the offscreen QQuickWindow,
+ // which is not a part of the accessibility tree. Detect this case and
+ // return the window for the QQuickWidget instead.
+ if (window && !window->handle()) {
+ if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) {
+ if (QWindow *renderWindow = renderControl->renderWindow(nullptr))
+ return renderWindow;
+ }
+ }
+
+ return window;
}
int QAccessibleQuickItem::childCount() const
@@ -113,19 +126,15 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
QAccessibleInterface *QAccessibleQuickItem::parent() const
{
QQuickItem *parent = item()->parentItem();
- QQuickWindow *window = item()->window();
- QQuickItem *ci = window ? window->contentItem() : nullptr;
+ QQuickWindow *itemWindow = item()->window();
+ QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr;
while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci)
parent = parent->parentItem();
if (parent) {
if (parent == ci) {
- // Jump out to the scene widget if the parent is the root item.
- // There are two root items, QQuickWindow::rootItem and
- // QQuickView::declarativeRoot. The former is the true root item,
- // but is not a part of the accessibility tree. Check if we hit
- // it here and return an interface for the scene instead.
- return QAccessible::queryAccessibleInterface(window);
+ // Jump out to the window if the parent is the root item
+ return QAccessible::queryAccessibleInterface(window());
} else {
while (parent && !parent->d_func()->isAccessible)
parent = parent->parentItem();
@@ -188,7 +197,7 @@ QAccessible::State QAccessibleQuickItem::state() const
QRect viewRect_ = viewRect();
QRect itemRect = rect();
- if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
+ if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
state.invisible = true;
if (!viewRect_.intersects(itemRect))
state.offscreen = true;
diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h
index 39ffcaf39c..8baa01330c 100644
--- a/src/quick/accessible/qaccessiblequickview_p.h
+++ b/src/quick/accessible/qaccessiblequickview_p.h
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(accessibility)
-class QAccessibleQuickWindow : public QAccessibleObject
+class Q_QUICK_EXPORT QAccessibleQuickWindow : public QAccessibleObject
{
public:
QAccessibleQuickWindow(QQuickWindow *object);
diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp
new file mode 100644
index 0000000000..6f04d6693f
--- /dev/null
+++ b/src/quickwidgets/qaccessiblequickwidget.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblequickwidget.h"
+
+#include "qquickwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+QAccessibleQuickWidget::QAccessibleQuickWidget(QQuickWidget* widget)
+: QAccessibleWidget(widget)
+, m_accessibleWindow(QQuickWidgetPrivate::get(widget)->offscreenWindow)
+{
+ // NOTE: m_accessibleWindow is a QAccessibleQuickWindow, and not a
+ // QAccessibleQuickWidgetOffscreenWindow (defined below). This means
+ // it will return the Quick item child interfaces, which is what's needed here
+ // (unlike QAccessibleQuickWidgetOffscreenWindow, which will report 0 children).
+}
+
+QAccessibleInterface *QAccessibleQuickWidget::child(int index) const
+{
+ return m_accessibleWindow.child(index);
+}
+
+int QAccessibleQuickWidget::childCount() const
+{
+ return m_accessibleWindow.childCount();
+}
+
+int QAccessibleQuickWidget::indexOfChild(const QAccessibleInterface *iface) const
+{
+ return m_accessibleWindow.indexOfChild(iface);
+}
+
+QAccessibleInterface *QAccessibleQuickWidget::childAt(int x, int y) const
+{
+ return m_accessibleWindow.childAt(x, y);
+}
+
+QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window)
+:QAccessibleQuickWindow(window)
+{
+
+}
+
+QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::child(int index) const
+{
+ Q_UNUSED(index);
+ return nullptr;
+}
+
+int QAccessibleQuickWidgetOffscreenWindow::childCount() const
+{
+ return 0;
+}
+
+int QAccessibleQuickWidgetOffscreenWindow::indexOfChild(const QAccessibleInterface *iface) const
+{
+ Q_UNUSED(iface);
+ return -1;
+}
+
+QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow::childAt(int x, int y) const
+{
+ Q_UNUSED(x);
+ Q_UNUSED(y);
+ return nullptr;
+}
+
+#endif // accessibility
+
+QT_END_NAMESPACE
diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget.h
new file mode 100644
index 0000000000..1f52c78c46
--- /dev/null
+++ b/src/quickwidgets/qaccessiblequickwidget.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEQUICKWIDGET_H
+#define QACCESSIBLEQUICKWIDGET_H
+
+#include "qquickwidget.h"
+#include <QtWidgets/qaccessiblewidget.h>
+
+#include <private/qaccessiblequickview_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+// These classes implement the QQuickWiget accessibility switcharoo,
+// where the child items of the QQuickWidgetOffscreenWindow are reported
+// as child accessible interfaces of the QAccessibleQuickWidget.
+class QAccessibleQuickWidget: public QAccessibleWidget
+{
+public:
+ QAccessibleQuickWidget(QQuickWidget* widget);
+
+ QAccessibleInterface *child(int index) const override;
+ int childCount() const override;
+ int indexOfChild(const QAccessibleInterface *iface) const override;
+ QAccessibleInterface *childAt(int x, int y) const override;
+
+private:
+ QAccessibleQuickWindow m_accessibleWindow;
+ Q_DISABLE_COPY(QAccessibleQuickWidget)
+};
+
+class QAccessibleQuickWidgetOffscreenWindow: public QAccessibleQuickWindow
+{
+public:
+ QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window);
+ QAccessibleInterface *child(int index) const override;
+ int childCount() const override;
+ int indexOfChild(const QAccessibleInterface *iface) const override;
+ QAccessibleInterface *childAt(int x, int y) const override;
+};
+
+#endif // accessibility
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
new file mode 100644
index 0000000000..3756d0c27c
--- /dev/null
+++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblequickwidgetfactory_p.h"
+#include "qaccessiblequickwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object)
+{
+ if (classname == QLatin1String("QQuickWidget")) {
+ return new QAccessibleQuickWidget(qobject_cast<QQuickWidget *>(object));
+ } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) {
+ return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast<QQuickWindow *>(object));
+ }
+ return 0;
+}
+
+#endif // accessibility
+
+QT_END_NAMESPACE
+
diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory_p.h b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
new file mode 100644
index 0000000000..8c63b09f81
--- /dev/null
+++ b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qaccessible.h>
+
+#ifndef QACCESSIBLEQUICKWIDGETFACTORY_H
+#define QACCESSIBLEQUICKWIDGETFACTORY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object);
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 223d91f579..9c97b43518 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -39,6 +39,7 @@
#include "qquickwidget.h"
#include "qquickwidget_p.h"
+#include "qaccessiblequickwidgetfactory_p.h"
#include "private/qquickwindow_p.h"
#include "private/qquickitem_p.h"
@@ -75,9 +76,16 @@
QT_BEGIN_NAMESPACE
+QQuickWidgetOffscreenWindow::QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
+:QQuickWindow(dd, control)
+{
+ setTitle(QString::fromLatin1("Offscreen"));
+ setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
+}
+
// override setVisble to prevent accidental offscreen window being created
// by base class.
-class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate {
+class QQuickWidgetOffscreenWindowPrivate: public QQuickWindowPrivate {
public:
void setVisible(bool visible) override {
Q_Q(QWindow);
@@ -105,10 +113,8 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
Q_Q(QQuickWidget);
renderControl = new QQuickWidgetRenderControl(q);
- offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
+ offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
offscreenWindow->setScreen(q->screen());
- offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
- offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
// Do not call create() on offscreenWindow.
// Check if the Software Adaptation is being used
@@ -139,6 +145,10 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
QWidget::connect(offscreenWindow, &QQuickWindow::focusObjectChanged, q, &QQuickWidget::propagateFocusObjectChanged);
QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate()));
QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
+
+#if QT_CONFIG(accessibility)
+ QAccessible::installFactory(&qAccessibleQuickWidgetFactory);
+#endif
}
void QQuickWidgetPrivate::ensureEngine() const
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index 881f7f9220..1a946bcc71 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -148,6 +148,14 @@ public:
bool forceFullUpdate;
};
+class QQuickWidgetOffscreenWindow: public QQuickWindow
+{
+ Q_OBJECT
+
+public:
+ QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control);
+};
+
QT_END_NAMESPACE
#endif // QQuickWidget_P_H
diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro
index 2438e577ae..f46deb54ac 100644
--- a/src/quickwidgets/quickwidgets.pro
+++ b/src/quickwidgets/quickwidgets.pro
@@ -7,9 +7,13 @@ DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FO
HEADERS += \
qquickwidget.h \
qquickwidget_p.h \
- qtquickwidgetsglobal.h
+ qtquickwidgetsglobal.h \
+ qaccessiblequickwidget.h \
+ qaccessiblequickwidgetfactory_p.h
SOURCES += \
- qquickwidget.cpp
+ qquickwidget.cpp \
+ qaccessiblequickwidget.cpp \
+ qaccessiblequickwidgetfactory.cpp
load(qt_module)
--
2.34.1
......@@ -21,6 +21,8 @@ $(TARBALLS)/qtdeclarative-everywhere-src-$(QTDECLARATIVE_VERSION).tar.xz:
qtdeclarative: qtdeclarative-everywhere-src-$(QTDECLARATIVE_VERSION).tar.xz .sum-qtdeclarative
$(UNPACK)
$(APPLY) $(SRC)/qtdeclarative/0001-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch
$(APPLY) $(SRC)/qtdeclarative/0002-Implement-accessibility-for-QQuickWidget.patch
# do not build qml.exe and other useless tools
sed -i.orig 's,!wasm:!rtems ,!wasm:!rtems:!static ,' "$(UNPACK_DIR)/tools/tools.pro"
$(MOVE)
......
......@@ -81,6 +81,18 @@ endif
if HAVE_QT5_GTK
libqt_plugin_la_CPPFLAGS += -DQT5_HAS_GTK
endif
if HAVE_QT5_DECLARATIVE_PRIVATE
libqt_plugin_la_CPPFLAGS += -DQT5_DECLARATIVE_PRIVATE \
-I$(QT_INCLUDE_DIRECTORY)/QtCore/$(QT_VERSION) \
-I$(QT_INCLUDE_DIRECTORY)/QtCore/$(QT_VERSION)/QtCore \
-I$(QT_INCLUDE_DIRECTORY)/QtGui/$(QT_VERSION) \
-I$(QT_INCLUDE_DIRECTORY)/QtGui/$(QT_VERSION)/QtGui \
-I$(QT_INCLUDE_DIRECTORY)/QtQml/$(QT_VERSION) \
-I$(QT_INCLUDE_DIRECTORY)/QtQml/$(QT_VERSION)/QtQml \
-I$(QT_INCLUDE_DIRECTORY)/QtQuick/$(QT_VERSION) \
-I$(QT_INCLUDE_DIRECTORY)/QtQuick/$(QT_VERSION)/QtQuick
endif
libqt_plugin_la_SOURCES = \
gui/qt/qt.cpp gui/qt/qt.hpp gui/qt/plugins.hpp \
......@@ -152,6 +164,10 @@ libqt_plugin_la_SOURCES = \
gui/qt/dialogs/playlists/playlists.cpp gui/qt/dialogs/playlists/playlists.hpp \
gui/qt/maininterface/compositor.hpp \
gui/qt/maininterface/compositor.cpp \
gui/qt/maininterface/compositor_common.hpp \
gui/qt/maininterface/compositor_common.cpp \
gui/qt/maininterface/compositor_accessibility.cpp \
gui/qt/maininterface/compositor_accessibility.hpp \
gui/qt/maininterface/compositor_dummy.hpp \
gui/qt/maininterface/compositor_dummy.cpp \
gui/qt/maininterface/interface_window_handler.cpp \
......@@ -428,6 +444,7 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/dialogs/toolbar/controlbar_profile_model.moc.cpp \
gui/qt/dialogs/playlists/playlists.moc.cpp \
gui/qt/maininterface/compositor.moc.cpp \
gui/qt/maininterface/compositor_common.moc.cpp \
gui/qt/maininterface/compositor_dummy.moc.cpp \
gui/qt/maininterface/interface_window_handler.moc.cpp \
gui/qt/maininterface/mainctx.moc.cpp \
......
......@@ -43,6 +43,7 @@ class QQmlComponent;
class QWindow;
class QQuickItem;
class QQuickView;
class QQuickWindow;
namespace vlc {
......@@ -100,6 +101,7 @@ public:
virtual QQuickItem * activeFocusItem() const = 0;
};
public:
explicit CompositorVideo(qt_intf_t* p_intf, QObject* parent = nullptr);
virtual ~CompositorVideo();
......
/*****************************************************************************
* Copyright (C) 2023 the VideoLAN team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <QWindow>
#include <QGuiApplication>
#include <QQuickItem>
#if !defined(QT_NO_ACCESSIBILITY) && defined(QT5_DECLARATIVE_PRIVATE)
#include <QAccessibleObject>
#include <private/qquickitem_p.h>
#include "compositor_accessibility.hpp"
#include "compositor.hpp"
#ifdef QT5_HAS_X11_COMPOSITOR
# include "compositor_x11_renderwindow.hpp"
#endif
#ifdef HAVE_DCOMP_H
# include "compositor_dcomp_uisurface.hpp"
#endif
namespace vlc {
/*
* we could have use QAccessibleQuickWindow like in QAccessibleQuickWidget
* but QAccessibleQuickWindow is not publicly exposed in the library, so we
* mimic the behavior of QAccessibleQuickWindow directly
*/
static void unignoredChildren(QQuickItem *item, QList<QQuickItem *> *items)
{
const QList<QQuickItem*> childItems = item->childItems();
for (QQuickItem *child : childItems)
{
if (QQuickItemPrivate::get(child)->isAccessible)
items->append(child);
else
unignoredChildren(child, items);
}
}
static QList<QQuickItem *> accessibleUnignoredChildren(QQuickItem *item)
{
QList<QQuickItem *> items;
unignoredChildren(item, &items);
return items;
}
class QAccessibleRenderWindow: public QAccessibleObject
{
public:
QAccessibleRenderWindow(QWindow* window, AccessibleRenderWindow* renderWindow)
: QAccessibleObject(window)
, m_window(renderWindow->getOffscreenWindow())
{
}
QAccessibleInterface* parent() const override
{
// we assume to be a top level window...
return QAccessible::queryAccessibleInterface(qApp);
}
QList<QQuickItem *> rootItems() const
{
if (QQuickItem *ci = m_window->contentItem())
return accessibleUnignoredChildren(ci);
return QList<QQuickItem *>();
}
QAccessibleInterface* child(int index) const override
{
const QList<QQuickItem*> &kids = rootItems();
if (index >= 0 && index < kids.count())
return QAccessible::queryAccessibleInterface(kids.at(index));
return nullptr;
}
int childCount() const override
{
return rootItems().count();
}
int indexOfChild(const QAccessibleInterface *iface) const override
{
int i = -1;
if (iface)
{
const QList<QQuickItem *> &roots = rootItems();
i = roots.count() - 1;
while (i >= 0)
{
if (iface->object() == roots.at(i))
break;
--i;
}
}
return i;
}
QAccessibleInterface *childAt(int x, int y) const override
{
for (int i = childCount() - 1; i >= 0; --i)
{
QAccessibleInterface *childIface = child(i);
if (childIface && !childIface->state().invisible)
{
if (QAccessibleInterface *iface = childIface->childAt(x, y))
return iface;
if (childIface->rect().contains(x, y))
return childIface;
}
}
return nullptr;
}
QString text(QAccessible::Text) const override
{
return window()->title();
}
QRect rect() const override
{
return QRect(window()->x(), window()->y(), window()->width(), window()->height());
}
QAccessible::Role role() const override
{
return QAccessible::Window;
}
QAccessible::State state() const override
{
QAccessible::State st;
if (window() == QGuiApplication::focusWindow())
st.active = true;
if (!window()->isVisible())
st.invisible = true;
return st;
}
QWindow* window() const override
{
return static_cast<QWindow*>(object());
}
private:
QQuickWindow* m_window;
};
/*
* DCompOffscreenWindow is a top window, mark it as unacessible so it won't
* be introspected by a11y, the QML scene is actually accessible though QAccessibleRenderWindow
*/
class QAccessibleOffscreenWindow: public QAccessibleObject
{
public:
QAccessibleOffscreenWindow(QQuickWindow *window)
: QAccessibleObject(window)
{
}
QAccessibleInterface* parent() const override
{
// we assume to be a top level window...
return QAccessible::queryAccessibleInterface(qApp);
}
QAccessibleInterface* child(int) const override
{
return nullptr;
}
int childCount() const override
{
return 0;
}
int indexOfChild(const QAccessibleInterface *) const override
{
return -1;
}
QAccessibleInterface *childAt(int, int) const override
{
return nullptr;
}
QAccessibleInterface *focusChild() const override
{
return nullptr;
}
QString text(QAccessible::Text) const override
{
return window()->title();
}
QRect rect() const override
{
return QRect(window()->x(), window()->y(), window()->width(), window()->height());
}
QAccessible::Role role() const override
{
return QAccessible::Window;
}
QAccessible::State state() const override
{
QAccessible::State st;
if (window() == QGuiApplication::focusWindow())
st.active = true;
if (!window()->isVisible())
st.invisible = true;
return st;
}
private:
QWindow* window() const override
{
return static_cast<QWindow*>(object());
}
};
QAccessibleInterface* compositionAccessibleFactory(const QString &classname, QObject *object)
{
#ifdef QT5_HAS_X11_COMPOSITOR
if (classname == QLatin1String("vlc::CompositorX11RenderWindow"))
{
CompositorX11RenderWindow* renderWindow = qobject_cast<CompositorX11RenderWindow *>(object);
assert(renderWindow);
return new QAccessibleRenderWindow(renderWindow, renderWindow);
}
#endif
#ifdef HAVE_DCOMP_H
if (classname == QLatin1String("vlc::DCompRenderWindow"))
{
DCompRenderWindow* renderWindow = qobject_cast<DCompRenderWindow *>(object);
assert(renderWindow);
return new QAccessibleRenderWindow(renderWindow, renderWindow);
}
#endif
if (classname == QLatin1String("vlc::CompositorOffscreenWindow")
|| (classname == QLatin1String("vlc::DCompOffscreenWindow")) )
{
return new QAccessibleOffscreenWindow(qobject_cast<QQuickWindow *>(object));
}
return nullptr;
}
}
#endif
/*****************************************************************************
* Copyright (C) 2023 the VideoLAN team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef COMPOSITOR_ACCESSIBLITY_H
#define COMPOSITOR_ACCESSIBLITY_H
#include <QString>
class QObject;
class QAccessibleInterface;
class QQuickWindow;
namespace vlc {
class AccessibleRenderWindow
{
public:
virtual ~AccessibleRenderWindow() = default;
virtual QQuickWindow* getOffscreenWindow() const = 0;
};
#if !defined(QT_NO_ACCESSIBILITY) && defined(QT5_DECLARATIVE_PRIVATE)
QAccessibleInterface* compositionAccessibleFactory(const QString &classname, QObject *object);
#endif
}
#endif /* COMPOSITOR_ACCESSIBLITY_H */
/*****************************************************************************
* Copyright (C) 2023 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "compositor_common.hpp"
#include <QBackingStore>
#ifndef QT_NO_ACCESSIBILITY
#include <QAccessible>
#endif
#ifdef QT5_DECLARATIVE_PRIVATE
#include <private/qquickwindow_p.h>
#endif
using namespace vlc;
DummyRenderWindow::DummyRenderWindow(QWindow* parent)
: QWindow(parent)
{
setSurfaceType(RasterSurface);
QSurfaceFormat fmt = format();
fmt.setAlphaBufferSize(8);
setFormat(fmt);
}
QAccessibleInterface* DummyRenderWindow::accessibleRoot() const
{
#ifndef QT_NO_ACCESSIBILITY
QAccessibleInterface* iface = QAccessible::queryAccessibleInterface(
const_cast<DummyRenderWindow*>(this));
return iface;
#else
return nullptr;
#endif
}
bool DummyRenderWindow::event(QEvent* event)
{
switch (event->type() )
{
case QEvent::UpdateRequest:
render();
return true;
case QEvent::Expose:
if (isExposed())
requestUpdate();
return true;
default:
break;
}
return QWindow::event(event);
}
void DummyRenderWindow::resizeEvent(QResizeEvent* resizeEvent)
{
if (!m_backingStore)
return;
if (!m_initialized)
init();
m_backingStore->resize(resizeEvent->size());
}
void DummyRenderWindow::init()
{
if (m_initialized)
return;
m_initialized = true;
m_backingStore = new QBackingStore(this);
}
void DummyRenderWindow::render()
{
if (!m_initialized)
init();
if (!isExposed())
return;
QRect rect(0, 0, width(), height());
if (m_backingStore->size() != size())
{
m_backingStore->resize(size());
}
//note that we don't need to actually use our backing store
//drawing anything would just lead to flickering
m_backingStore->flush(QRect(0, 0, 1, 1));
return;
}
#ifdef QT5_DECLARATIVE_PRIVATE
class OffscreenWindowPrivate: public QQuickWindowPrivate
{
public:
void setVisible(bool newVisible) override {
Q_Q(QWindow);
if (visible != newVisible)
{
visible = newVisible;
q->visibleChanged(newVisible);
// this stays always invisible
visibility = newVisible ? QWindow::Windowed : QWindow::Hidden;
q->visibilityChanged(visibility); // workaround for QTBUG-49054
}
}
};
CompositorOffscreenWindow::CompositorOffscreenWindow(QQuickRenderControl* renderControl)
: QQuickWindow(* (new OffscreenWindowPrivate()), renderControl)
{
}
static Qt::WindowState resolveWindowState(Qt::WindowStates states)
{
// No more than one of these 3 can be set
if (states & Qt::WindowMinimized)
return Qt::WindowMinimized;
if (states & Qt::WindowMaximized)
return Qt::WindowMaximized;
if (states & Qt::WindowFullScreen)
return Qt::WindowFullScreen;
// No state means "windowed" - we ignore Qt::WindowActive
return Qt::WindowNoState;
}
void CompositorOffscreenWindow::setWindowStateExt(Qt::WindowState state)
{
QWindow::setWindowState(resolveWindowState(state));
}
void CompositorOffscreenWindow::setPseudoVisible(bool visible)
{
setVisible(visible);
}
#else
CompositorOffscreenWindow::CompositorOffscreenWindow(QQuickRenderControl* renderControl)
: QQuickWindow(renderControl)
{
}
void CompositorOffscreenWindow::setWindowStateExt(Qt::WindowState state)
{
QWindow::setWindowState(state);
}
//don't set the window visible, this would create the window, and show make it actually visible
void CompositorOffscreenWindow::setPseudoVisible(bool)
{
}
#endif
/*****************************************************************************
* Copyright (C) 2023 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef COMPOSITOR_COMMON_HPP
#define COMPOSITOR_COMMON_HPP
#include <QWindow>
#include <QQuickWindow>
namespace vlc {
/**
* a minimal window with no content
* this may be useful on linux platform to provide a
* window which can be drawn into, using a bare QWindow
* usually freeze on resize
*/
class DummyRenderWindow : public QWindow
{
Q_OBJECT
public:
explicit DummyRenderWindow(QWindow* parent = nullptr);
virtual QAccessibleInterface *accessibleRoot() const override;
protected:
bool event(QEvent *event) override;
void resizeEvent(QResizeEvent *resizeEvent) override;
private:
void init();
void render();
QBackingStore* m_backingStore = nullptr;
bool m_initialized = false;;
};
/**
* @brief The CompositorOffscreenWindow class allows to fake the visiblilty
* of the the QQuickWindow, note that this feature will only work if QT5_DECLARATIVE_PRIVATE
* are available
*/
class CompositorOffscreenWindow : public QQuickWindow
{
Q_OBJECT
public:
explicit CompositorOffscreenWindow(QQuickRenderControl* renderControl);
void setWindowStateExt(Qt::WindowState);
void setPseudoVisible(bool visible);
};
}
#endif /* COMPOSITOR_COMMON_HPP */
......@@ -252,7 +252,7 @@ bool CompositorDirectComposition::makeMainInterface(MainCtx* mainCtx)
bool ret;
m_mainCtx = mainCtx;
m_rootWindow = new QWindow();
m_rootWindow = new DCompRenderWindow();
m_videoWindowHandler = std::make_unique<VideoWindowHandler>(m_intf);
m_videoWindowHandler->setWindow( m_rootWindow );
......
......@@ -70,7 +70,7 @@ protected:
void windowDestroy() override;
private:
QWindow* m_rootWindow = nullptr;
DCompRenderWindow* m_rootWindow = nullptr;
std::unique_ptr<WinTaskbarWidget> m_taskbarWidget;
......
......@@ -33,6 +33,9 @@
#include <d3dcompiler.h>
#include <comdef.h>
#include "compositor_common.hpp""
#include "compositor_accessibility.hpp"
namespace vlc {
using namespace Microsoft::WRL;
......@@ -138,17 +141,35 @@ private:
HINSTANCE m_compiler_dll = nullptr;
};
QAccessibleInterface* DCompRenderWindow::accessibleRoot() const
{
QAccessibleInterface* iface = QAccessible::queryAccessibleInterface(
const_cast<DCompRenderWindow*>(this));
return iface;
}
void DCompRenderWindow::setOffscreenWindow(CompositorOffscreenWindow* window)
{
m_offscreenWindow = window;
}
QQuickWindow* DCompRenderWindow::getOffscreenWindow() const
{
return m_offscreenWindow;
}
CompositorDCompositionUISurface::CompositorDCompositionUISurface(qt_intf_t* p_intf,
QWindow* window,
DCompRenderWindow* window,
Microsoft::WRL::ComPtr<IDCompositionVisual> dcVisual,
QObject* parent)
: QObject(parent)
, m_intf(p_intf)
, m_dcUiVisual(dcVisual)
, m_rootWindow(window)
, m_renderWindow(window)
{
}
bool CompositorDCompositionUISurface::init()
{
EGLBoolean eglRet;
......@@ -161,7 +182,7 @@ bool CompositorDCompositionUISurface::init()
format.setAlphaBufferSize(8);
m_context = new QOpenGLContext(this);
m_context->setScreen(m_rootWindow->screen());
m_context->setScreen(m_renderWindow->screen());
m_context->setFormat(format);
ret = m_context->create();
if (!ret || !m_context->isValid())
......@@ -198,13 +219,16 @@ bool CompositorDCompositionUISurface::init()
m_uiOffscreenSurface->setFormat(format);;
m_uiOffscreenSurface->create();
m_uiRenderControl = new CompositorDCompositionRenderControl(m_rootWindow);
m_uiRenderControl = new CompositorDCompositionRenderControl(m_renderWindow);
m_uiWindow = new CompositorOffscreenWindow(m_uiRenderControl);
m_uiWindow = new QQuickWindow(m_uiRenderControl);
m_uiWindow->setDefaultAlphaBuffer(true);
m_uiWindow->setFormat(format);
m_uiWindow->setClearBeforeRendering(false);
m_renderWindow->setOffscreenWindow(m_uiWindow);
m_d3dCompiler = std::make_shared<OurD3DCompiler>();
ret = m_d3dCompiler->init(VLC_OBJECT(m_intf));
if (!ret) {
......@@ -212,8 +236,8 @@ bool CompositorDCompositionUISurface::init()
return false;
}
qreal dpr = m_rootWindow->devicePixelRatio();
ret = initialiseD3DSwapchain(dpr * m_rootWindow->width(), dpr * m_rootWindow->height());
qreal dpr = m_renderWindow->devicePixelRatio();
ret = initialiseD3DSwapchain(dpr * m_renderWindow->width(), dpr * m_renderWindow->height());
if (!ret)
return false;
......@@ -225,10 +249,15 @@ bool CompositorDCompositionUISurface::init()
connect(m_uiWindow, &QQuickWindow::sceneGraphInitialized, this, &CompositorDCompositionUISurface::createFbo);
connect(m_uiWindow, &QQuickWindow::sceneGraphInvalidated, this, &CompositorDCompositionUISurface::destroyFbo);
connect(m_uiWindow, &QQuickWindow::focusObjectChanged, this, &CompositorDCompositionUISurface::forwardFocusObjectChanged);
connect(m_uiRenderControl, &QQuickRenderControl::renderRequested, this, &CompositorDCompositionUISurface::requestUpdate);
connect(m_uiRenderControl, &QQuickRenderControl::sceneChanged, this, &CompositorDCompositionUISurface::requestUpdate);
m_rootWindow->installEventFilter(this);
QAccessible::installFactory(&compositionAccessibleFactory);
m_renderWindow->installEventFilter(this);
return true;
}
......@@ -525,7 +554,7 @@ void CompositorDCompositionUISurface::render()
{
EGLBoolean eglRet;
QSize realSize = m_rootWindow->size() * m_rootWindow->devicePixelRatio();
QSize realSize = m_renderWindow->size() * m_renderWindow->devicePixelRatio();
if (realSize != m_surfaceSize)
{
m_surfaceSize = realSize;
......@@ -609,22 +638,36 @@ static void remapInputMethodQueryEvent(QObject *object, QInputMethodQueryEvent *
}
}
bool CompositorDCompositionUISurface::eventFilter(QObject* object, QEvent* event)
{
if (object != m_rootWindow)
if (object != m_renderWindow)
return false;
switch (event->type()) {
case QEvent::Move:
case QEvent::Show:
//offscreen window won't be really visible
m_uiWindow->setPseudoVisible(true);
updatePosition();
break;
case QEvent::Hide:
m_uiWindow->setPseudoVisible(false);
break;
case QEvent::Resize:
updateSizes();
forceRender();
break;
case QEvent::FocusAboutToChange:
return QCoreApplication::sendEvent(m_uiWindow, event);
case QEvent::WindowStateChange:
m_uiWindow->setWindowStateExt(m_renderWindow->windowState());
break;
case QEvent::WindowActivate:
case QEvent::WindowDeactivate:
case QEvent::Leave:
......@@ -639,6 +682,10 @@ bool CompositorDCompositionUISurface::eventFilter(QObject* object, QEvent* event
return ret;
}
case QEvent::FocusIn:
case QEvent::FocusOut:
return QCoreApplication::sendEvent(m_uiWindow, event);
case QEvent::InputMethod:
return QCoreApplication::sendEvent(m_uiWindow->focusObject(), event);
case QEvent::InputMethodQuery:
......@@ -665,6 +712,9 @@ bool CompositorDCompositionUISurface::eventFilter(QObject* object, QEvent* event
QCoreApplication::sendEvent(m_uiWindow, &mappedEvent);
return true;
}
case QEvent::ShortcutOverride:
case QEvent::Wheel:
case QEvent::HoverEnter:
case QEvent::HoverLeave:
......@@ -689,8 +739,9 @@ bool CompositorDCompositionUISurface::eventFilter(QObject* object, QEvent* event
return QCoreApplication::sendEvent(m_uiWindow, event);
case QEvent::ScreenChangeInternal:
m_uiWindow->setScreen(m_rootWindow->screen());
m_uiWindow->setScreen(m_renderWindow->screen());
break;
default:
break;
}
......@@ -700,7 +751,7 @@ bool CompositorDCompositionUISurface::eventFilter(QObject* object, QEvent* event
void CompositorDCompositionUISurface::createFbo()
{
//write to the immediate context
m_uiWindow->setRenderTarget(0, m_rootWindow->size());
m_uiWindow->setRenderTarget(0, m_renderWindow->size());
}
void CompositorDCompositionUISurface::destroyFbo()
......@@ -709,8 +760,8 @@ void CompositorDCompositionUISurface::destroyFbo()
void CompositorDCompositionUISurface::updateSizes()
{
qreal dpr = m_rootWindow->devicePixelRatio();
QSize windowSize = m_rootWindow->size();
qreal dpr = m_renderWindow->devicePixelRatio();
QSize windowSize = m_renderWindow->size();
resizeSwapchain(windowSize.width() * dpr, windowSize.height() * dpr);
updateSharedTexture(windowSize.width() * dpr, windowSize.height() * dpr);
......@@ -722,7 +773,7 @@ void CompositorDCompositionUISurface::updateSizes()
void CompositorDCompositionUISurface::updatePosition()
{
QPoint windowPosition = m_rootWindow->mapToGlobal(QPoint(0,0));
QPoint windowPosition = m_renderWindow->mapToGlobal(QPoint(0,0));
if (m_uiWindow->position() != windowPosition)
m_uiWindow->setPosition(windowPosition);
}
......@@ -736,11 +787,19 @@ void CompositorDCompositionUISurface::requestUpdate()
}
}
QQuickWindow* CompositorDCompositionUISurface::getOffscreenWindow() const {
return m_uiWindow;
}
void CompositorDCompositionUISurface::handleScreenChange()
{
msg_Info(m_intf, "handle screen change");
m_uiWindow->setGeometry(0, 0, m_rootWindow->width(), m_rootWindow->height());;
m_uiWindow->setGeometry(0, 0, m_renderWindow->width(), m_renderWindow->height());;
requestUpdate();
}
void CompositorDCompositionUISurface::forwardFocusObjectChanged(QObject* object)
{
m_renderWindow->focusObjectChanged(object);
}
}
......@@ -59,9 +59,29 @@
#include "qt.hpp"
#include "compositor.hpp"
#include "compositor_accessibility.hpp"
namespace vlc {
class CompositorOffscreenWindow;
//on screen window
class DCompRenderWindow : public QWindow, public AccessibleRenderWindow
{
Q_OBJECT
public:
#ifndef QT_NO_ACCESSIBILITY
QAccessibleInterface* accessibleRoot() const override;
#endif
void setOffscreenWindow(CompositorOffscreenWindow* window);
QQuickWindow* getOffscreenWindow() const override;
private:
CompositorOffscreenWindow* m_offscreenWindow = nullptr;
};
class CompositorDCompositionRenderControl : public QQuickRenderControl
{
Q_OBJECT
......@@ -85,7 +105,7 @@ class CompositorDCompositionUISurface : public QObject, public CompositorVideo::
Q_OBJECT
public:
explicit CompositorDCompositionUISurface(qt_intf_t* p_intf,
QWindow* window,
DCompRenderWindow* window,
Microsoft::WRL::ComPtr<IDCompositionVisual> dcVisual,
QObject *parent = nullptr);
......@@ -94,6 +114,7 @@ public:
bool init();
QQmlEngine* engine() const override { return m_qmlEngine; }
QQuickWindow* getOffscreenWindow() const;
void setContent(QQmlComponent* component, QQuickItem* rootItem) override;
......@@ -113,6 +134,7 @@ private:
void forceRender();
void handleScreenChange();
void forwardFocusObjectChanged(QObject* object);
void createFbo();
void destroyFbo();
......@@ -121,6 +143,8 @@ private:
void updatePosition();
private:
friend class DCompRenderWindow;
qt_intf_t* m_intf = nullptr;
class OurD3DCompiler;
......@@ -171,9 +195,10 @@ private:
CompositorDCompositionRenderControl* m_uiRenderControl = nullptr;
//the actual window where we render
QWindow* m_rootWindow = nullptr;
DCompRenderWindow* m_renderWindow = nullptr;
QQuickWindow* m_uiWindow = nullptr;
//offscreen window for QML content
CompositorOffscreenWindow* m_uiWindow = nullptr;
QQmlEngine* m_qmlEngine = nullptr;
QQmlComponent* m_qmlComponent = nullptr;
QQuickItem* m_rootItem = nullptr;
......
......@@ -25,6 +25,7 @@
#include "interface_window_handler.hpp"
#include "video_window_handler.hpp"
#include "mainui.hpp"
#include "compositor_accessibility.hpp"
using namespace vlc;
......@@ -145,6 +146,10 @@ bool CompositorX11::init()
}
}
#if !defined(QT_NO_ACCESSIBILITY) && defined(QT5_DECLARATIVE_PRIVATE)
QAccessible::installFactory(&compositionAccessibleFactory);
#endif
return true;
}
......@@ -158,13 +163,14 @@ bool CompositorX11::makeMainInterface(MainCtx* mainCtx)
if (!m_renderWindow->init())
return false;
m_videoWidget = std::make_unique<DummyNativeWidget>(m_renderWindow.get());
m_videoWidget = std::make_unique<DummyNativeWidget>();
// widget would normally require WindowTransparentForInput, without this
// we end up with an invisible area within our window that grabs our mouse events.
// But using this this causes rendering issues with some VoutDisplay
// (xcb_render for instance) instead, we manually, set a null input region afterwards
// see setTransparentForMouseEvent
m_videoWidget->winId();
m_videoWidget->windowHandle()->setParent(m_renderWindow.get());
//update manually EventMask as we don't use WindowTransparentForInput
const uint32_t mask = XCB_CW_EVENT_MASK;
......@@ -174,18 +180,16 @@ bool CompositorX11::makeMainInterface(MainCtx* mainCtx)
setTransparentForMouseEvent(QX11Info::connection(), m_videoWidget->winId());
m_videoWidget->show();
m_interfaceWindow = m_renderWindow->getWindow();
m_qmlView = std::make_unique<CompositorX11UISurface>(m_interfaceWindow);
m_qmlView = std::make_unique<CompositorX11UISurface>(m_renderWindow.get());
m_qmlView->setFlag(Qt::WindowType::WindowTransparentForInput);
m_qmlView->setParent(m_interfaceWindow);
m_qmlView->setParent(m_renderWindow.get());
m_qmlView->winId();
m_qmlView->show();
CompositorVideo::Flags flags = CompositorVideo::CAN_SHOW_PIP;
if (m_renderWindow->hasAcrylic())
flags |= CompositorVideo::HAS_ACRYLIC;
commonGUICreate(m_interfaceWindow, m_renderWindow.get(), m_qmlView.get(), flags);
commonGUICreate(m_renderWindow.get(), nullptr, m_qmlView.get(), flags);
m_renderWindow->setInterfaceWindow(m_qmlView.get());
m_renderWindow->setVideoWindow(m_videoWidget->windowHandle());
......@@ -227,6 +231,8 @@ bool CompositorX11::setupVoutWindow(vlc_window_t* p_wnd, VoutDestroyCb destroyCb
return true;
}
QWindow* CompositorX11::interfaceMainWindow() const { return m_renderWindow.get(); }
QQuickItem * CompositorX11::activeFocusItem() const /* override */
{
return m_qmlView->activeFocusItem();
......
......@@ -49,7 +49,7 @@ public:
inline Type type() const override { return X11Compositor; };
inline QWindow* interfaceMainWindow() const override { return m_interfaceWindow; };
QWindow* interfaceMainWindow() const override;
QQuickItem * activeFocusItem() const override;
......@@ -62,7 +62,6 @@ private slots:
void onSurfaceSizeChanged(const QSizeF& size) override;
private:
QWindow* m_interfaceWindow = nullptr;
xcb_connection_t* m_conn = nullptr;
std::unique_ptr<QWidget> m_videoWidget;
......
......@@ -23,6 +23,9 @@
#include <QMainWindow>
#include <QThread>
#include <QSocketNotifier>
#ifndef QT_NO_ACCESSIBILITY
#include <QAccessible>
#endif
#include <xcb/composite.h>
......@@ -80,7 +83,6 @@ void RenderTask::render(unsigned int requestId)
clear, 1, &rect);
}
{
QMutexLocker lock(&m_pictureLock);
if (m_videoEmbed)
......@@ -318,40 +320,23 @@ void X11DamageObserver::onEvent()
//// CompositorX11RenderWindow
CompositorX11RenderWindow::CompositorX11RenderWindow(qt_intf_t* p_intf, xcb_connection_t* conn, bool useCSD, QWidget* parent)
: QMainWindow(parent)
CompositorX11RenderWindow::CompositorX11RenderWindow(qt_intf_t* p_intf, xcb_connection_t* conn, bool useCSD, QWindow* parent)
: DummyRenderWindow(parent)
, m_intf(p_intf)
, m_conn(conn)
{
setAcceptDrops(true);
setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_MouseTracking);
if (useCSD)
setWindowFlag(Qt::FramelessWindowHint);
m_stable = new DummyNativeWidget(this);
m_stable->winId();
setTransparentForMouseEvent(QX11Info::connection(), m_stable->winId());
setCentralWidget(m_stable);
setFlag(Qt::FramelessWindowHint);
winId();
show();
m_window = window()->windowHandle();
m_wid = winId();
}
CompositorX11RenderWindow::~CompositorX11RenderWindow()
{
stopRendering();
removeEventFilter(this);
m_window->removeEventFilter(this);
}
bool CompositorX11RenderWindow::init()
......@@ -377,11 +362,6 @@ bool CompositorX11RenderWindow::init()
blurBehindAtom, XCB_ATOM_CARDINAL, 32, 1, &val);
m_hasAcrylic = true;
}
//install event filters
installEventFilter(this);
m_window->installEventFilter(this);
return true;
}
......@@ -390,7 +370,7 @@ bool CompositorX11RenderWindow::startRendering()
assert(m_interfaceWindow);
//Rendering thread
m_renderTask = new RenderTask(m_intf, m_conn, m_stable->effectiveWinId(), m_pictureLock);
m_renderTask = new RenderTask(m_intf, m_conn, m_wid, m_pictureLock);
m_renderThread = new QThread(this);
m_renderTask->moveToThread(m_renderThread);
......@@ -409,7 +389,7 @@ bool CompositorX11RenderWindow::startRendering()
//pass initial values
m_renderTask->onInterfaceSurfaceChanged(m_interfaceClient.get());
m_renderTask->onVideoSurfaceChanged(m_videoClient.get());
m_renderTask->onWindowSizeChanged(size() * devicePixelRatioF());
m_renderTask->onWindowSizeChanged(size() * devicePixelRatio());
m_renderTask->onAcrylicChanged(m_hasAcrylic);
//use the same thread as the rendering thread, neither tasks are blocking.
......@@ -457,61 +437,33 @@ void CompositorX11RenderWindow::resetClientPixmaps()
}
}
bool CompositorX11RenderWindow::eventFilter(QObject* obj, QEvent* event)
void CompositorX11RenderWindow::exposeEvent(QExposeEvent* event)
{
bool ret = false;
bool needRefresh = false;
//event on the window
if (obj == m_window)
{
//window may get resized without the widget knowing about it
if (event->type() == QEvent::Resize)
{
auto resizeEvent = static_cast<QResizeEvent*>(event);
if (m_interfaceWindow)
m_interfaceWindow->handleWindowEvent(event);
resetClientPixmaps();
emit windowSizeChanged(resizeEvent->size() * devicePixelRatioF());
needRefresh = true;
}
}
else
{
assert(obj == this);
if (event->type() == QEvent::Resize)
return false;
if (m_interfaceWindow)
ret = m_interfaceWindow->handleWindowEvent(event);
DummyRenderWindow::exposeEvent(event);
resetClientPixmaps();
emit requestUIRefresh();
}
switch (event->type())
{
case QEvent::Expose:
{
resetClientPixmaps();
needRefresh = true;
break;
}
case QEvent::Show:
{
resetClientPixmaps();
needRefresh = true;
emit visiblityChanged(true);
break;
}
case QEvent::Hide:
emit visiblityChanged(false);
break;
default:
break;
}
}
void CompositorX11RenderWindow::resizeEvent(QResizeEvent* event)
{
DummyRenderWindow::resizeEvent(event);
resetClientPixmaps();
emit windowSizeChanged(event->size() * devicePixelRatio());
emit requestUIRefresh();
}
if (needRefresh)
emit requestUIRefresh();
void CompositorX11RenderWindow::showEvent(QShowEvent* event)
{
DummyRenderWindow::showEvent(event);
resetClientPixmaps();
emit visiblityChanged(true);
emit requestUIRefresh();
}
return ret;
void CompositorX11RenderWindow::hideEvent(QHideEvent* event)
{
DummyRenderWindow::hideEvent(event);
emit visiblityChanged(false);
}
void CompositorX11RenderWindow::setVideoPosition(const QPoint& position)
......@@ -535,7 +487,7 @@ void CompositorX11RenderWindow::setVideoSize(const QSize& size)
m_videoClient->resetPixmap();
m_videoClient->getPicture();
}
m_videoPosition.setSize(size * devicePixelRatioF());
m_videoPosition.setSize(size * devicePixelRatio());
emit videoPositionChanged(m_videoPosition);
}
}
......@@ -560,6 +512,11 @@ void CompositorX11RenderWindow::disableVideoWindow()
emit registerVideoWindow(0);
}
QQuickWindow* CompositorX11RenderWindow::getOffscreenWindow() const
{
return m_interfaceWindow->getOffscreenWindow();
}
void CompositorX11RenderWindow::setInterfaceWindow(CompositorX11UISurface* window)
{
//ensure Qt x11 pending operation have been forwarded to the server
......
......@@ -26,7 +26,7 @@
#include <QObject>
#include <QMutex>
#include <QMainWindow>
#include <QWindow>
#include <xcb/xcb.h>
#include <xcb/render.h>
......@@ -38,9 +38,12 @@
#include "qt.hpp"
#include "compositor_x11_utils.hpp"
#include "compositor_common.hpp"
#include "compositor_accessibility.hpp"
class QWidget;
class QSocketNotifier;
class QAccessibleInterface;
namespace vlc {
......@@ -144,11 +147,11 @@ public:
QSocketNotifier* m_socketNotifier = nullptr;
};
class CompositorX11RenderWindow : public QMainWindow
class CompositorX11RenderWindow : public DummyRenderWindow, public AccessibleRenderWindow
{
Q_OBJECT
public:
explicit CompositorX11RenderWindow(qt_intf_t* p_intf, xcb_connection_t* conn, bool useCSD, QWidget* parent = nullptr);
explicit CompositorX11RenderWindow(qt_intf_t* p_intf, xcb_connection_t* conn, bool useCSD, QWindow* parent = nullptr);
~CompositorX11RenderWindow();
bool init();
......@@ -156,13 +159,9 @@ public:
bool startRendering();
void stopRendering();
bool eventFilter(QObject *, QEvent *event) override;
void setVideoPosition(const QPoint& position);
void setVideoSize(const QSize& size);
inline QWindow* getWindow() const { return m_window; }
inline bool hasAcrylic() const { return m_hasAcrylic; }
void setVideoWindow(QWindow* window);
......@@ -171,6 +170,8 @@ public:
void enableVideoWindow();
void disableVideoWindow();
QQuickWindow* getOffscreenWindow() const override;
signals:
void windowSizeChanged(const QSize& newSize);
void requestUIRefresh();
......@@ -179,20 +180,25 @@ signals:
void visiblityChanged(bool visible);
void registerVideoWindow(unsigned int xid);
protected:
//override from QWindow
void exposeEvent(QExposeEvent *) override;
void resizeEvent(QResizeEvent *) override;
void showEvent(QShowEvent *) override;
void hideEvent(QHideEvent *) override;
private:
void resetClientPixmaps();
qt_intf_t* m_intf = nullptr;
xcb_connection_t* m_conn = nullptr;
QWidget* m_stable = nullptr;
QThread* m_renderThread = nullptr;
RenderTask* m_renderTask = nullptr;
X11DamageObserver* m_damageObserver = nullptr;
QMutex m_pictureLock;
QWindow* m_window = nullptr;
xcb_window_t m_wid = 0;
bool m_hasAcrylic = false;
......
......@@ -21,16 +21,23 @@
#include <QQuickWindow>
#include <QQuickItem>
#include <QOffscreenSurface>
#include <QGuiApplication>
#include "compositor_x11_uisurface.hpp"
#include "compositor_common.hpp"
using namespace vlc;
CompositorX11UISurface::CompositorX11UISurface(QWindow* window, QScreen* screen)
: QWindow(screen)
, m_renderWindow(window)
{
setSurfaceType(QWindow::OpenGLSurface);
m_renderWindow->installEventFilter(this);
QSurfaceFormat format;
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
format.setDepthBufferSize(8);
......@@ -50,7 +57,7 @@ CompositorX11UISurface::CompositorX11UISurface(QWindow* window, QScreen* screen)
m_uiRenderControl = new CompositorX11RenderControl(window);
m_uiWindow = new QQuickWindow(m_uiRenderControl);
m_uiWindow = new CompositorOffscreenWindow(m_uiRenderControl);
m_uiWindow->setDefaultAlphaBuffer(true);
m_uiWindow->setFormat(format);
m_uiWindow->setColor(Qt::transparent);
......@@ -65,12 +72,16 @@ CompositorX11UISurface::CompositorX11UISurface(QWindow* window, QScreen* screen)
connect(m_uiWindow, &QQuickWindow::beforeRendering, this, &CompositorX11UISurface::beforeRendering);
connect(m_uiWindow, &QQuickWindow::afterRendering, this, &CompositorX11UISurface::afterRendering);
connect(m_uiWindow, &QQuickWindow::focusObjectChanged, this, &CompositorX11UISurface::forwardFocusObjectChanged);
connect(m_uiRenderControl, &QQuickRenderControl::renderRequested, this, &CompositorX11UISurface::requestUpdate);
connect(m_uiRenderControl, &QQuickRenderControl::sceneChanged, this, &CompositorX11UISurface::requestUpdate);
}
CompositorX11UISurface::~CompositorX11UISurface()
{
m_renderWindow->removeEventFilter(this);
auto surface = new QOffscreenSurface();
surface->setFormat(m_context->format());
surface->create();
......@@ -109,6 +120,11 @@ QQuickItem * CompositorX11UISurface::activeFocusItem() const /* override */
return m_uiWindow->activeFocusItem();
}
QQuickWindow* CompositorX11UISurface::getOffscreenWindow() const
{
return m_uiWindow;
}
void CompositorX11UISurface::createFbo()
{
//write to the immediate context
......@@ -191,7 +207,7 @@ static void remapInputMethodQueryEvent(QObject *object, QInputMethodQueryEvent *
}
}
bool CompositorX11UISurface::handleWindowEvent(QEvent *event)
bool CompositorX11UISurface::eventFilter(QObject*, QEvent *event)
{
switch (event->type())
{
......@@ -230,6 +246,17 @@ bool CompositorX11UISurface::handleWindowEvent(QEvent *event)
return ret;
}
case QEvent::FocusAboutToChange:
case QEvent::FocusIn:
case QEvent::FocusOut:
return QCoreApplication::sendEvent(m_uiWindow, event);
case QEvent::Show:
m_uiWindow->setPseudoVisible(true);
break;
case QEvent::Hide:
m_uiWindow->setPseudoVisible(false);
break;
case QEvent::InputMethod:
return QCoreApplication::sendEvent(m_uiWindow->focusObject(), event);
......@@ -321,6 +348,11 @@ void CompositorX11UISurface::handleScreenChange()
requestUpdate();
}
void CompositorX11UISurface::forwardFocusObjectChanged(QObject* object)
{
m_renderWindow->focusObjectChanged(object);
}
QWindow* CompositorX11RenderControl::renderWindow(QPoint* offset)
{
if (offset)
......
......@@ -19,6 +19,7 @@
#define COMPOSITOR_X11_UISURFACE_HPP
#include <QWindow>
#include <QQuickWindow>
#include <QQuickRenderControl>
#include "compositor.hpp"
......@@ -26,9 +27,12 @@ class QQuickWindow;
class QQmlEngine;
class QQmlComponent;
class QQuickItem;
class QQuickRenderControl;
namespace vlc {
class CompositorOffscreenWindow;
class CompositorX11RenderControl : public QQuickRenderControl {
Q_OBJECT
public:
......@@ -37,6 +41,7 @@ public:
, m_window(window)
{}
QWindow *renderWindow(QPoint * offset) override;
private:
......@@ -60,6 +65,8 @@ public:
QQuickItem * activeFocusItem() const override;
QQuickWindow* getOffscreenWindow() const;
signals:
void beforeRendering();
void afterRendering();
......@@ -67,12 +74,14 @@ signals:
void updated();
protected:
bool eventFilter(QObject* object, QEvent *event) override;
bool event(QEvent *event) override;
void resizeEvent(QResizeEvent *) override;
void exposeEvent(QExposeEvent *) override;
void handleScreenChange();
void forwardFocusObjectChanged(QObject* focusObject);
void updateSizes();
......@@ -83,8 +92,9 @@ protected:
private:
QQuickItem* m_rootItem = nullptr;
QOpenGLContext *m_context = nullptr;
QQuickWindow* m_uiWindow = nullptr;
CompositorOffscreenWindow* m_uiWindow = nullptr;
QQmlEngine* m_qmlEngine = nullptr;
QWindow* m_renderWindow = nullptr;
CompositorX11RenderControl* m_uiRenderControl = nullptr;
QSize m_onscreenSize;
......