2017-10-21 13:50:30 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
|
|
|
|
2021-09-28 15:55:43 +02:00
|
|
|
#include <QtFrame.hxx>
|
|
|
|
#include <QtFrame.moc>
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:55:43 +02:00
|
|
|
#include <QtData.hxx>
|
|
|
|
#include <QtDragAndDrop.hxx>
|
2022-05-02 08:50:33 +02:00
|
|
|
#include <QtFontFace.hxx>
|
2021-09-28 15:55:43 +02:00
|
|
|
#include <QtGraphics.hxx>
|
|
|
|
#include <QtInstance.hxx>
|
|
|
|
#include <QtMainWindow.hxx>
|
|
|
|
#include <QtMenu.hxx>
|
|
|
|
#include <QtSvpGraphics.hxx>
|
|
|
|
#include <QtSystem.hxx>
|
|
|
|
#include <QtTools.hxx>
|
|
|
|
#include <QtTransferable.hxx>
|
2022-06-15 23:34:01 +02:00
|
|
|
#if CHECK_ANY_QT_USING_X11
|
|
|
|
#include <QtX11Support.hxx>
|
|
|
|
#endif
|
2017-10-27 13:15:37 +02:00
|
|
|
|
2019-02-27 09:40:50 +01:00
|
|
|
#include <QtCore/QMimeData>
|
2017-10-30 18:33:06 +01:00
|
|
|
#include <QtCore/QPoint>
|
|
|
|
#include <QtCore/QSize>
|
2019-06-02 21:01:33 +00:00
|
|
|
#include <QtCore/QThread>
|
2019-08-08 17:59:20 +00:00
|
|
|
#include <QtGui/QDragMoveEvent>
|
|
|
|
#include <QtGui/QDropEvent>
|
2017-10-30 18:33:06 +01:00
|
|
|
#include <QtGui/QIcon>
|
2017-10-27 13:15:37 +02:00
|
|
|
#include <QtGui/QWindow>
|
2017-10-30 19:44:40 +01:00
|
|
|
#include <QtGui/QScreen>
|
tdf#156894 qt: Prefer dark icon theme in dark mode
When in dark mode, pass the param to prefer a dark
icon theme to
`StyleSettings::SetPreferredIconTheme`.
For Qt >= 6.5 use `QStyleHints::colorScheme`
introduced in Qt 6.5 to get the color scheme.
For older Qt versions, use the same algorithm based
on the gray value of the window background as
xdg-desktop-portal-kde does for evaluating whether
a light or dark color scheme is preferred [1].
On my Debian testing, the Breeze dark icon theme is
now used as expected with kf5 or qt6 when setting
the Global KDE Plasma theme to "Breeze Dark" and
manually setting the Icon theme to "GNOME" afterwards.
Previously, this would not use a dark icon theme and
icons would be hard to see.
Without manually setting the icon theme to "GNOME",
the Breeze Dark icon theme would already be used
before, because selecting "Breeze Dark" as the
global KDE Plasma theme also selects the "Breeze Dark"
icon theme by default, and therefore "breeze-dark"
was already passed as the first param to
`StyleSettings::SetPreferredIconTheme` and since
that icon theme is present, the `bPreferDarkTheme`
wouldn't be evaluated at all; it's only used
when determining the fallback icon theme when
the specified icon theme is not present.
(Likewise, by enabling the "Breeze Dark" global theme
and then manually setting the icon theme to "Breeze"
in Plasma System settings, the Breeze light icon theme
will be used in LibreOffice as well, resulting in hard
to see icons, but I tend to think that that behavior is
correct and works as designed - it's a misconfiguration.)
The color scheme is also specified in xdg-desktop-portal
(s. commit [2]) and can be retrived via dbus.
Example with "Breeze Light" active:
$ dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'
variant variant uint32 2
With "Breeze Dark":
$ dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'
variant variant uint32 1
[1] https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/blob/0a4237549debf9518f8cfbaf531456850c0729bd/src/settings.cpp#L213-227
[2] https://github.com/flatpak/xdg-desktop-portal/commit/d7a304a00697d7d608821253cd013f3b97ac0fb6
Change-Id: I8f347c6e7f775cc55377c5c84481de3051c3cf24
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156465
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-02 10:12:54 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
|
|
|
#include <QtGui/QStyleHints>
|
|
|
|
#endif
|
2018-08-09 14:51:41 +02:00
|
|
|
#include <QtWidgets/QStyle>
|
|
|
|
#include <QtWidgets/QToolTip>
|
2017-10-30 19:55:18 +01:00
|
|
|
#include <QtWidgets/QApplication>
|
2018-08-09 14:51:41 +02:00
|
|
|
#include <QtWidgets/QMenuBar>
|
2018-08-09 17:14:14 +02:00
|
|
|
#include <QtWidgets/QMainWindow>
|
2021-12-01 08:53:25 +01:00
|
|
|
#if CHECK_QT5_USING_X11
|
2019-06-14 02:08:22 +00:00
|
|
|
#include <QtX11Extras/QX11Info>
|
|
|
|
#endif
|
|
|
|
|
2017-11-14 00:10:58 +02:00
|
|
|
#include <window.h>
|
2017-10-30 18:33:06 +01:00
|
|
|
#include <vcl/syswin.hxx>
|
|
|
|
|
2018-10-15 14:44:29 +02:00
|
|
|
#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
|
|
|
|
|
2017-10-24 19:49:45 +02:00
|
|
|
#include <cairo.h>
|
|
|
|
#include <headless/svpgdi.hxx>
|
|
|
|
|
2022-05-02 08:50:33 +02:00
|
|
|
#include <unx/fontmanager.hxx>
|
|
|
|
|
2017-10-24 19:49:45 +02:00
|
|
|
static void SvpDamageHandler(void* handle, sal_Int32 nExtentsX, sal_Int32 nExtentsY,
|
|
|
|
sal_Int32 nExtentsWidth, sal_Int32 nExtentsHeight)
|
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
QtFrame* pThis = static_cast<QtFrame*>(handle);
|
2017-10-24 19:49:45 +02:00
|
|
|
pThis->Damage(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight);
|
|
|
|
}
|
|
|
|
|
2019-05-29 19:01:28 +02:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
sal_Int32 screenNumber(const QScreen* pScreen)
|
|
|
|
{
|
|
|
|
const QList<QScreen*> screens = QApplication::screens();
|
|
|
|
|
|
|
|
sal_Int32 nScreen = 0;
|
|
|
|
bool bFound = false;
|
|
|
|
for (const QScreen* pCurScreen : screens)
|
|
|
|
{
|
|
|
|
if (pScreen == pCurScreen)
|
|
|
|
{
|
|
|
|
bFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nScreen++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bFound ? nScreen : -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
QtFrame::QtFrame(QtFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo)
|
2018-08-09 17:14:14 +02:00
|
|
|
: m_pTopLevel(nullptr)
|
|
|
|
, m_bUseCairo(bUseCairo)
|
2018-09-04 09:17:11 +02:00
|
|
|
, m_bNullRegion(true)
|
2017-10-24 19:49:45 +02:00
|
|
|
, m_bGraphicsInUse(false)
|
2017-10-30 19:32:45 +01:00
|
|
|
, m_ePointerStyle(PointerStyle::Arrow)
|
2018-10-15 14:44:29 +02:00
|
|
|
, m_pDragSource(nullptr)
|
|
|
|
, m_pDropTarget(nullptr)
|
|
|
|
, m_bInDrag(false)
|
2017-10-30 19:44:40 +01:00
|
|
|
, m_bDefaultSize(true)
|
|
|
|
, m_bDefaultPos(true)
|
2018-12-14 12:39:44 +03:00
|
|
|
, m_bFullScreen(false)
|
2019-05-29 19:01:28 +02:00
|
|
|
, m_bFullScreenSpanAll(false)
|
2021-12-01 08:53:25 +01:00
|
|
|
#if CHECK_ANY_QT_USING_X11
|
2021-07-19 15:17:53 +02:00
|
|
|
, m_nKeyModifiers(ModKeyFlags::NONE)
|
|
|
|
#endif
|
Qt5 report input method language
This is in the spirit of tdf#108151, based on the information Qt
provides for the IM setting. I don't know how correct it is,
especially looking at Caolans comment 3 in that bug report
regarding the assumed validity of GtkIMContextInfo. OTOH it seems
to work well enough for my simple tests.
Some BG info: while the QInputMethod object is a global one, it's
"bound" to the focused window. So you'll get change events, when
you change the input window, with the correct IM settings for the
new one, be it a real window or just the menu bar.
To prevent unneeded flushes of buffers and language lookup, this
caches the current IM language of a window.
The language is not affected just by changing keyboard mappings,
which the bug reporter requested! It just works with a configured
input method, like fcitx or ibus (which can have keyboard mappings
too, which work correctly).
Change-Id: Ia9133edf4d1ce77d29adbfe57c180db15db0a560
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106354
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-11-22 14:53:14 +01:00
|
|
|
, m_nInputLanguage(LANGUAGE_DONTKNOW)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2022-01-13 21:04:19 +01:00
|
|
|
QtInstance* pInst = GetQtInstance();
|
2017-10-27 13:15:37 +02:00
|
|
|
pInst->insertFrame(this);
|
|
|
|
|
2017-10-24 19:49:45 +02:00
|
|
|
m_aDamageHandler.handle = this;
|
|
|
|
m_aDamageHandler.damaged = ::SvpDamageHandler;
|
|
|
|
|
2017-10-27 13:15:37 +02:00
|
|
|
if (nStyle & SalFrameStyleFlags::DEFAULT) // ensure default style
|
|
|
|
{
|
|
|
|
nStyle |= SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE
|
|
|
|
| SalFrameStyleFlags::CLOSEABLE;
|
|
|
|
nStyle &= ~SalFrameStyleFlags::FLOAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nStyle = nStyle;
|
|
|
|
m_pParent = pParent;
|
|
|
|
|
2021-10-31 14:08:57 +01:00
|
|
|
Qt::WindowFlags aWinFlags(Qt::Widget);
|
2021-11-10 12:18:39 +01:00
|
|
|
if (!(nStyle & SalFrameStyleFlags::SYSTEMCHILD))
|
2017-10-27 13:15:37 +02:00
|
|
|
{
|
|
|
|
if (nStyle & SalFrameStyleFlags::INTRO)
|
2021-10-31 14:08:57 +01:00
|
|
|
aWinFlags = Qt::SplashScreen;
|
2019-02-13 12:24:38 +01:00
|
|
|
// floating toolbars are frameless tool windows
|
|
|
|
// + they must be able to receive keyboard focus
|
|
|
|
else if ((nStyle & SalFrameStyleFlags::FLOAT)
|
|
|
|
&& (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION))
|
2021-10-31 14:08:57 +01:00
|
|
|
aWinFlags = Qt::Tool | Qt::FramelessWindowHint;
|
2021-07-19 22:13:21 +02:00
|
|
|
else if (nStyle & SalFrameStyleFlags::TOOLTIP)
|
2021-10-31 14:08:57 +01:00
|
|
|
aWinFlags = Qt::ToolTip;
|
tdf#144585 Qt fix Wayland LO fake popups
So Michael Weghorn was somehow reminded of an abandoned
commit from me ("Qt5 rework parent handling") archived in
https://gerrit.libreoffice.org/c/core/+/73463.
The bug introducing the new QWidget parenting, tdf#145363, was
resolved in a better way by explicitly setting parents for the
modal dialogs, so LO doesn't break Qt anymore. The actual problem
is, that an additional modal dialog needs to be stacked to the
previous modal dialog; no "parallel" modal dialogs are allowed,
which my original fix tried to enforce by reparenting.
Then there is the problem with Qt::Popup's focus grabbing on show,
which breaks LO's editable ComboBox. So LO's popup / FLOAT windows
are mapped to Qt::ToolTip, which are automatically advertised as
tooltips via accessibility. For X11 / xcb, Qt:Window with the
Qt::BypassWindowManagerHint works well enough as an alternative,
but WASM and Wayland don't seem to implement it correctly, so this
just handles popups as Qt::ToolTip on all platforms.
This reverts commit b00a68a8e19370e106cd76258a3c1825f43613ee
("tdf#145363 Qt reparent modal dialogs on show").
In addition the popup widgets are switched back to Qt::ToolTip.
Change-Id: If726771b4e9cc3f639f21cf502b3ec5985873643
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132526
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2022-04-04 18:02:28 +02:00
|
|
|
// Can't use Qt::Popup, because it grabs the input focus and generates a focus-out event,
|
|
|
|
// instantly auto-closing the LO's editable ComboBox popup.
|
|
|
|
// On X11, the alternative Qt::Window | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint
|
|
|
|
// seems to work well enough, but at least on Wayland and WASM, this results in problems.
|
|
|
|
// So while using Qt::ToolTip, the popups are wrongly advertised via accessibility, at least
|
|
|
|
// the GUI seems to work on all platforms... what a mess.
|
2021-07-30 05:25:37 +02:00
|
|
|
else if (isPopup())
|
2021-10-29 22:24:12 +02:00
|
|
|
aWinFlags = Qt::ToolTip | Qt::FramelessWindowHint;
|
2017-10-27 13:15:37 +02:00
|
|
|
else if (nStyle & SalFrameStyleFlags::TOOLWINDOW)
|
2021-10-31 14:08:57 +01:00
|
|
|
aWinFlags = Qt::Tool;
|
2019-12-03 08:20:21 +01:00
|
|
|
// top level windows can't be transient in Qt, so make them dialogs, if they have a parent. At least
|
|
|
|
// the plasma shell relies on this setting to skip dialogs in the window list. And Qt Xcb will just
|
|
|
|
// set transient for the types Dialog, Sheet, Tool, SplashScreen, ToolTip, Drawer and Popup.
|
|
|
|
else if (nStyle & SalFrameStyleFlags::DIALOG || m_pParent)
|
2021-10-31 14:08:57 +01:00
|
|
|
aWinFlags = Qt::Dialog;
|
2017-10-27 13:15:37 +02:00
|
|
|
else
|
2021-10-31 14:08:57 +01:00
|
|
|
aWinFlags = Qt::Window;
|
2017-10-27 13:15:37 +02:00
|
|
|
}
|
|
|
|
|
2019-02-21 10:24:39 +03:00
|
|
|
if (aWinFlags == Qt::Window)
|
2018-08-09 17:14:14 +02:00
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
m_pTopLevel = new QtMainWindow(*this, aWinFlags);
|
tdf#144585 Qt fix Wayland LO fake popups
So Michael Weghorn was somehow reminded of an abandoned
commit from me ("Qt5 rework parent handling") archived in
https://gerrit.libreoffice.org/c/core/+/73463.
The bug introducing the new QWidget parenting, tdf#145363, was
resolved in a better way by explicitly setting parents for the
modal dialogs, so LO doesn't break Qt anymore. The actual problem
is, that an additional modal dialog needs to be stacked to the
previous modal dialog; no "parallel" modal dialogs are allowed,
which my original fix tried to enforce by reparenting.
Then there is the problem with Qt::Popup's focus grabbing on show,
which breaks LO's editable ComboBox. So LO's popup / FLOAT windows
are mapped to Qt::ToolTip, which are automatically advertised as
tooltips via accessibility. For X11 / xcb, Qt:Window with the
Qt::BypassWindowManagerHint works well enough as an alternative,
but WASM and Wayland don't seem to implement it correctly, so this
just handles popups as Qt::ToolTip on all platforms.
This reverts commit b00a68a8e19370e106cd76258a3c1825f43613ee
("tdf#145363 Qt reparent modal dialogs on show").
In addition the popup widgets are switched back to Qt::ToolTip.
Change-Id: If726771b4e9cc3f639f21cf502b3ec5985873643
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132526
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2022-04-04 18:02:28 +02:00
|
|
|
m_pQWidget = new QtWidget(*this);
|
2018-08-09 17:14:14 +02:00
|
|
|
m_pTopLevel->setCentralWidget(m_pQWidget);
|
2019-11-25 14:08:44 +00:00
|
|
|
m_pTopLevel->setFocusProxy(m_pQWidget);
|
2018-08-09 17:14:14 +02:00
|
|
|
}
|
2018-07-17 15:57:41 +02:00
|
|
|
else
|
2022-04-12 00:29:56 +02:00
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
m_pQWidget = new QtWidget(*this, aWinFlags);
|
2022-04-12 00:29:56 +02:00
|
|
|
// from Qt's POV the popup window doesn't have the input focus, so we must force tooltips...
|
|
|
|
if (isPopup())
|
|
|
|
m_pQWidget->setAttribute(Qt::WA_AlwaysShowToolTips);
|
|
|
|
}
|
2018-12-11 12:12:52 +01:00
|
|
|
|
2022-05-24 18:14:16 +02:00
|
|
|
FillSystemEnvData(m_aSystemData, reinterpret_cast<sal_IntPtr>(this), m_pQWidget);
|
|
|
|
|
2022-04-07 01:07:43 +02:00
|
|
|
QWindow* pChildWindow = windowHandle();
|
|
|
|
connect(pChildWindow, &QWindow::screenChanged, this, &QtFrame::screenChanged);
|
|
|
|
|
2017-10-27 13:15:37 +02:00
|
|
|
if (pParent && !(pParent->m_nStyle & SalFrameStyleFlags::PLUG))
|
|
|
|
{
|
2022-01-09 00:51:09 +01:00
|
|
|
QWindow* pParentWindow = pParent->windowHandle();
|
2019-02-21 10:24:39 +03:00
|
|
|
if (pParentWindow && pChildWindow && (pParentWindow != pChildWindow))
|
2017-10-27 13:15:37 +02:00
|
|
|
pChildWindow->setTransientParent(pParentWindow);
|
|
|
|
}
|
2017-12-08 11:37:18 +00:00
|
|
|
|
2019-02-27 16:13:48 +01:00
|
|
|
SetIcon(SV_ICON_ID_OFFICE);
|
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
This is the application level equivalent of the Qt5 fix for bug
QTBUG-46626 / commit 0de4b32 ("xcb: fix issue with dialogs hidden
by other windows"), which was broken since Qt 5.4 and is just
fixed since Qt 5.12.
It is needed for some window managers, which don't know about the
WM_CLIENT_LEADER property. Both settings are the same, but just
the latter is set by older Qt5 releases. This probably isn't a
real problem, as GNOME or XFCE would use the gtk VCL plugin, but
since I already wrote the code when debugging tdf#129071, there
is also no reason to drop it (except: more code, more bugs...).
This fix is optional and needs development headers for xcb-icccm,
which can actually be compiled into Qt5. If missing configure will
just print a warning, since it's a runtime requirement and we
explicitly drop the linked Qt version symbol, so the potential
build Qt version won't matter.
Change-Id: Ifc5a8f8a40ee13779a911efb53e8b8b868614d0b
Reviewed-on: https://gerrit.libreoffice.org/84299
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2019-12-03 08:32:58 +01:00
|
|
|
}
|
|
|
|
|
2022-04-07 01:07:43 +02:00
|
|
|
void QtFrame::screenChanged(QScreen*) { m_pQWidget->fakeResize(); }
|
|
|
|
|
2021-11-17 13:03:23 +01:00
|
|
|
void QtFrame::FillSystemEnvData(SystemEnvData& rData, sal_IntPtr pWindow, QWidget* pWidget)
|
|
|
|
{
|
2022-05-24 18:14:16 +02:00
|
|
|
assert(rData.platform == SystemEnvData::Platform::Invalid);
|
|
|
|
assert(rData.toolkit == SystemEnvData::Toolkit::Invalid);
|
2021-11-17 13:03:23 +01:00
|
|
|
if (QGuiApplication::platformName() == "wayland")
|
|
|
|
rData.platform = SystemEnvData::Platform::Wayland;
|
|
|
|
else if (QGuiApplication::platformName() == "xcb")
|
|
|
|
rData.platform = SystemEnvData::Platform::Xcb;
|
2021-10-29 22:24:12 +02:00
|
|
|
else if (QGuiApplication::platformName() == "wasm")
|
|
|
|
rData.platform = SystemEnvData::Platform::WASM;
|
2021-11-17 13:03:23 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// maybe add a SystemEnvData::Platform::Unsupported to avoid special cases and not abort?
|
|
|
|
SAL_WARN("vcl.qt",
|
|
|
|
"Unsupported qt VCL platform: " << toOUString(QGuiApplication::platformName()));
|
|
|
|
std::abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
rData.toolkit = SystemEnvData::Toolkit::Qt;
|
|
|
|
rData.aShellWindow = pWindow;
|
|
|
|
rData.pWidget = pWidget;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
QtFrame::~QtFrame()
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2022-01-13 21:04:19 +01:00
|
|
|
QtInstance* pInst = GetQtInstance();
|
2017-10-27 13:15:37 +02:00
|
|
|
pInst->eraseFrame(this);
|
2019-06-02 15:38:25 +00:00
|
|
|
delete asChild();
|
2018-10-05 11:39:49 +02:00
|
|
|
m_aSystemData.aShellWindow = 0;
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth,
|
|
|
|
sal_Int32 nExtentsHeight) const
|
2017-10-24 19:49:45 +02:00
|
|
|
{
|
2023-03-24 08:06:56 +01:00
|
|
|
m_pQWidget->update(scaledQRect(QRect(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight),
|
|
|
|
1 / devicePixelRatioF()));
|
2017-10-24 19:49:45 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
SalGraphics* QtFrame::AcquireGraphics()
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-10-31 01:07:06 +01:00
|
|
|
if (m_bGraphicsInUse)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
m_bGraphicsInUse = true;
|
|
|
|
|
2017-10-24 19:49:45 +02:00
|
|
|
if (m_bUseCairo)
|
|
|
|
{
|
2021-07-19 23:28:47 +02:00
|
|
|
if (!m_pSvpGraphics)
|
2017-10-24 19:49:45 +02:00
|
|
|
{
|
2023-03-24 08:06:56 +01:00
|
|
|
QSize aSize = m_pQWidget->size() * devicePixelRatioF();
|
2021-09-28 15:02:47 +02:00
|
|
|
m_pSvpGraphics.reset(new QtSvpGraphics(this));
|
2021-04-11 17:40:26 +02:00
|
|
|
m_pSurface.reset(
|
|
|
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.width(), aSize.height()));
|
|
|
|
m_pSvpGraphics->setSurface(m_pSurface.get(),
|
|
|
|
basegfx::B2IVector(aSize.width(), aSize.height()));
|
2021-09-28 15:02:47 +02:00
|
|
|
cairo_surface_set_user_data(m_pSurface.get(), QtSvpGraphics::getDamageKey(),
|
2021-04-11 17:40:26 +02:00
|
|
|
&m_aDamageHandler, nullptr);
|
2017-10-24 19:49:45 +02:00
|
|
|
}
|
2021-04-11 17:40:26 +02:00
|
|
|
return m_pSvpGraphics.get();
|
2017-10-24 19:49:45 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
if (!m_pQtGraphics)
|
2017-10-24 19:49:45 +02:00
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
m_pQtGraphics.reset(new QtGraphics(this));
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
m_pQImage.reset(
|
2023-03-24 08:06:56 +01:00
|
|
|
new QImage(m_pQWidget->size() * devicePixelRatioF(), Qt_DefaultFormat32));
|
2018-11-07 17:48:06 +03:00
|
|
|
m_pQImage->fill(Qt::transparent);
|
2021-09-28 15:02:47 +02:00
|
|
|
m_pQtGraphics->ChangeQImage(m_pQImage.get());
|
2017-10-24 19:49:45 +02:00
|
|
|
}
|
2021-09-28 15:02:47 +02:00
|
|
|
return m_pQtGraphics.get();
|
2017-10-24 19:49:45 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::ReleaseGraphics(SalGraphics* pSalGraph)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-10-31 01:07:06 +01:00
|
|
|
(void)pSalGraph;
|
2017-10-24 19:49:45 +02:00
|
|
|
if (m_bUseCairo)
|
2021-04-11 17:40:26 +02:00
|
|
|
assert(pSalGraph == m_pSvpGraphics.get());
|
2017-10-24 19:49:45 +02:00
|
|
|
else
|
2021-09-28 15:02:47 +02:00
|
|
|
assert(pSalGraph == m_pQtGraphics.get());
|
2017-10-31 01:07:06 +01:00
|
|
|
m_bGraphicsInUse = false;
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2022-01-13 21:04:19 +01:00
|
|
|
QtInstance* pInst = GetQtInstance();
|
2018-10-30 10:48:22 +02:00
|
|
|
pInst->PostEvent(this, pData.release(), SalEvent::UserEvent);
|
2017-10-31 01:07:06 +01:00
|
|
|
return true;
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2022-04-07 01:07:43 +02:00
|
|
|
QWidget* QtFrame::asChild() const
|
|
|
|
{
|
|
|
|
if (m_pTopLevel)
|
|
|
|
return m_pTopLevel;
|
|
|
|
return m_pQWidget;
|
|
|
|
}
|
2019-06-02 15:38:25 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
qreal QtFrame::devicePixelRatioF() const { return asChild()->devicePixelRatioF(); }
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::isWindow() const { return asChild()->isWindow(); }
|
2018-08-09 17:14:14 +02:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
QWindow* QtFrame::windowHandle() const
|
2018-08-09 17:14:14 +02:00
|
|
|
{
|
tdf#122293 qt5: Use "alien widgets" by default on Wayland
As described in QWidget doc [1], calling 'QWidget::winId()',
implicitly enforces a native window, i.e. one that has a
native window associated with it.
For this reason, avoid calling 'QWidget::winId()' for the Wayland
case. Quoting QWidget doc:
> Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
> system. They do not have a native window handle associated with them.
> This feature significantly speeds up widget painting, resizing, and
> removes flicker.
This in particular avoids tdf#122293/QTBUG-75766, which led to
'mousePressEvent's not being emitted unless a mouse button was pressed,
causing non-existent reaction to hovering over objects.
As a consequence to widgets being non-native by default on Wayland,
'Qt5Frame::windowHandle' needs to be adapted to make sure that the
widgets handled in there are native ones, otherwise no window handle
is associated with them.
Probably more needs to be done here to make video playback via GStreamer
work under Wayland, s.a. commit c0d4f3ad3307c ("implement wayland handle
passing for gstreamer") for how it was done for gtk3.
With and without this change, slideshows with videos are currently not
handled properly with kde5 on Wayland (s. tdf#125219).
[1] https://doc.qt.io/qt-5/qwidget.html#native-widgets-vs-alien-widgets
Change-Id: Id46678e0ea594220a1765c3e59d39c41cb8bfe25
Reviewed-on: https://gerrit.libreoffice.org/72164
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2019-05-11 21:31:33 +02:00
|
|
|
// set attribute 'Qt::WA_NativeWindow' first to make sure a window handle actually exists
|
2019-06-02 15:38:25 +00:00
|
|
|
QWidget* pChild = asChild();
|
2022-01-09 00:51:09 +01:00
|
|
|
assert(pChild->window() == pChild);
|
2022-05-24 18:14:16 +02:00
|
|
|
switch (m_aSystemData.platform)
|
|
|
|
{
|
|
|
|
case SystemEnvData::Platform::Wayland:
|
|
|
|
case SystemEnvData::Platform::Xcb:
|
|
|
|
pChild->setAttribute(Qt::WA_NativeWindow);
|
|
|
|
break;
|
|
|
|
case SystemEnvData::Platform::WASM:
|
|
|
|
// no idea, why Qt::WA_NativeWindow breaks the menubar for EMSCRIPTEN
|
|
|
|
break;
|
|
|
|
case SystemEnvData::Platform::Invalid:
|
|
|
|
std::abort();
|
|
|
|
break;
|
|
|
|
}
|
2019-06-02 15:38:25 +00:00
|
|
|
return pChild->windowHandle();
|
2018-08-09 17:14:14 +02:00
|
|
|
}
|
|
|
|
|
2023-08-03 21:30:22 +02:00
|
|
|
QScreen* QtFrame::screen() const { return asChild()->screen(); }
|
2018-08-29 14:04:56 +02:00
|
|
|
|
2023-09-02 10:37:47 +02:00
|
|
|
bool QtFrame::GetUseDarkMode() const
|
tdf#156894 qt: Prefer dark icon theme in dark mode
When in dark mode, pass the param to prefer a dark
icon theme to
`StyleSettings::SetPreferredIconTheme`.
For Qt >= 6.5 use `QStyleHints::colorScheme`
introduced in Qt 6.5 to get the color scheme.
For older Qt versions, use the same algorithm based
on the gray value of the window background as
xdg-desktop-portal-kde does for evaluating whether
a light or dark color scheme is preferred [1].
On my Debian testing, the Breeze dark icon theme is
now used as expected with kf5 or qt6 when setting
the Global KDE Plasma theme to "Breeze Dark" and
manually setting the Icon theme to "GNOME" afterwards.
Previously, this would not use a dark icon theme and
icons would be hard to see.
Without manually setting the icon theme to "GNOME",
the Breeze Dark icon theme would already be used
before, because selecting "Breeze Dark" as the
global KDE Plasma theme also selects the "Breeze Dark"
icon theme by default, and therefore "breeze-dark"
was already passed as the first param to
`StyleSettings::SetPreferredIconTheme` and since
that icon theme is present, the `bPreferDarkTheme`
wouldn't be evaluated at all; it's only used
when determining the fallback icon theme when
the specified icon theme is not present.
(Likewise, by enabling the "Breeze Dark" global theme
and then manually setting the icon theme to "Breeze"
in Plasma System settings, the Breeze light icon theme
will be used in LibreOffice as well, resulting in hard
to see icons, but I tend to think that that behavior is
correct and works as designed - it's a misconfiguration.)
The color scheme is also specified in xdg-desktop-portal
(s. commit [2]) and can be retrived via dbus.
Example with "Breeze Light" active:
$ dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'
variant variant uint32 2
With "Breeze Dark":
$ dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'
variant variant uint32 1
[1] https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/blob/0a4237549debf9518f8cfbaf531456850c0729bd/src/settings.cpp#L213-227
[2] https://github.com/flatpak/xdg-desktop-portal/commit/d7a304a00697d7d608821253cd013f3b97ac0fb6
Change-Id: I8f347c6e7f775cc55377c5c84481de3051c3cf24
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156465
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-02 10:12:54 +02:00
|
|
|
{
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
|
|
|
const QStyleHints* pStyleHints = QApplication::styleHints();
|
|
|
|
return pStyleHints->colorScheme() == Qt::ColorScheme::Dark;
|
|
|
|
#else
|
|
|
|
// use same mechanism for determining dark mode preference as xdg-desktop-portal-kde, s.
|
|
|
|
// https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/blob/0a4237549debf9518f8cfbaf531456850c0729bd/src/settings.cpp#L213-227
|
|
|
|
const QPalette aPalette = QApplication::palette();
|
|
|
|
const int nWindowBackGroundGray = qGray(aPalette.window().color().rgb());
|
|
|
|
return nWindowBackGroundGray < 192;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::isMinimized() const { return asChild()->isMinimized(); }
|
2018-08-29 14:04:56 +02:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::isMaximized() const { return asChild()->isMaximized(); }
|
2018-08-09 17:14:14 +02:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetWindowStateImpl(Qt::WindowStates eState)
|
2019-02-11 11:22:30 +01:00
|
|
|
{
|
2019-06-02 15:38:25 +00:00
|
|
|
return asChild()->setWindowState(eState);
|
2019-02-11 11:22:30 +01:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetTitle(const OUString& rTitle)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
qt: Set window title etc. in main thread
These QWidget methods need to be called
in the main thread.
Otherwise, opening the Update dialog
("Help" -> "Check for Updates", enabled
by `--enable-online-update` autogen switch)
triggers asserts like the one below with
a self-compiled Qt 6 development build
(qtbase dev branch as of
c802a9e987c9e38c01580f467eab92a651b3e033).
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp, line 537
Thread 40 "InitUpdateCheck" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff7ffff6c0 (LWP 1516868)]
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007ffff78a815f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 0x00007ffff785a472 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007ffff78444b2 in __GI_abort () at ./stdlib/abort.c:79
#4 0x00007fffe32eb45a in qAbort() () at /home/michi/development/git/qt5/qtbase/src/corelib/global/qglobal.cpp:161
#5 0x00007fffe32f9ee5 in qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&) (context=..., message=...) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:2057
#6 0x00007fffe32f620c in QMessageLogger::fatal(char const*, ...) const (this=0x7fff7fffb980, msg=0x7fffe37fd9a0 "ASSERT failure in %s: \"%s\", file %s, line %d")
at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:938
#7 0x00007fffe32e9d54 in qt_assert_x(char const*, char const*, char const*, int)
(where=0x7fffe38131e9 "QCoreApplication::sendEvent", what=0x7fff78180110 "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file=0x7fffe3812e18 "/home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp", line=537) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qassert.cpp:77
#8 0x00007fffe33a4d74 in QCoreApplicationPrivate::checkReceiverThread(QObject*) (receiver=0x55555d27d5d0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:537
#9 0x00007fffe19a3a81 in QApplication::notify(QObject*, QEvent*) (this=0x5555555fcb80, receiver=0x55555d27d5d0, e=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2584
#10 0x00007fffe33a5ed0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1125
#11 0x00007fffe33a6991 in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1559
#12 0x00007fffe1a279b4 in QWidget::setWindowTitle(QString const&) (this=0x55555d27d5d0, title=...) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidget.cpp:6119
#13 0x00007fffe3c9d4c4 in QtFrame::SetTitle(rtl::OUString const&) (this=0x555555619d20, rTitle="Check for Updates") at /home/michi/development/git/libreoffice/vcl/qt6/../qt5/QtFrame.cxx:365
#14 0x00007fffedd98d44 in vcl::Window::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/window.cxx:3042
#15 0x00007fffedd311c9 in SystemWindow::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/syswin.cxx:1048
#16 0x00007ffff048bd6b in VCLXWindow::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindow.cxx:1515
#17 0x00007ffff03e486d in VCLXContainer::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxcontainer.cxx:260
#18 0x00007ffff04dfa2c in VCLXDialog::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindows.cxx:2364
#19 0x00007ffff06a89b7 in UnoControl::ImplSetPeerProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7803b4f0, rPropName="Title", rVal=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:288
#20 0x00007ffff06aa701 in UnoControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:649
#21 0x00007ffff0531ae9 in ControlContainerBase::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/controlmodelcontainerbase.cxx:1600
#22 0x00007ffff0575a25 in UnoDialogControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:651
#23 0x00007ffff06a95f3 in UnoControl::propertiesChange(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:431
#24 0x00007ffff66bc4ee in cppu::OPropertySetHelper::firePropertiesChangeEvent(com::sun::star::uno::Sequence<rtl::OUString> const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertiesChangeListener> const&)
(this=0x7fff78006170, rPropertyNames=uno::Sequence of length 51 = {...}, rListener=uno::Reference to (UnoDialogControl *) 0x7fff7803b540) at /home/michi/development/git/libreoffice/cppuhelper/source/propshlp.cxx:961
#25 0x00007ffff06a8c6b in UnoControl::updateFromModel() (this=0x7fff7803b4f0) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:320
#26 0x00007ffff06aefc9 in UnoControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:1325
#27 0x00007ffff06c9905 in UnoControlContainer::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParent=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrolcontainer.cxx:727
#28 0x00007ffff057336d in UnoDialogControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:358
#29 0x00007fffb7264e62 in UpdateHandler::createDialog() (this=0x7fff78003aa0) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:1232
#30 0x00007fffb725b0e1 in UpdateHandler::setVisible(bool) (this=0x7fff78003aa0, bVisible=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:188
#31 0x00007fffb7235887 in UpdateCheck::showDialog(bool) (this=0x7fff78000b90, forceCheck=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheck.cxx:1171
#32 0x00007fffb7255c5e in (anonymous namespace)::InitUpdateCheckJobThread::run() (this=0x55555d192690) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheckjob.cxx:148
#33 0x00007fffb723a74a in osl::threadFunc(void*) (param=0x55555d192690) at /home/michi/development/git/libreoffice/include/osl/thread.hxx:189
#34 0x00007ffff7f3f693 in osl_thread_start_Impl(void*) (pData=0x55555d1a68b0) at /home/michi/development/git/libreoffice/sal/osl/unx/thread.cxx:237
#35 0x00007ffff78a63ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#36 0x00007ffff7926a1c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Change-Id: I6ccdee00fe26619f201459ebbe6c4d8cf8b57b45
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156426
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-01 17:50:19 +02:00
|
|
|
QtInstance* pSalInst(GetQtInstance());
|
|
|
|
assert(pSalInst);
|
|
|
|
pSalInst->RunInMainThread(
|
|
|
|
[this, rTitle]() { m_pQWidget->window()->setWindowTitle(toQString(rTitle)); });
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetIcon(sal_uInt16 nIcon)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-11-13 09:08:30 +01:00
|
|
|
if (m_nStyle
|
|
|
|
& (SalFrameStyleFlags::PLUG | SalFrameStyleFlags::SYSTEMCHILD
|
|
|
|
| SalFrameStyleFlags::FLOAT | SalFrameStyleFlags::INTRO
|
|
|
|
| SalFrameStyleFlags::OWNERDRAWDECORATION)
|
2018-08-09 17:14:14 +02:00
|
|
|
|| !isWindow())
|
2017-10-30 18:33:06 +01:00
|
|
|
return;
|
|
|
|
|
2019-05-10 10:09:21 +02:00
|
|
|
QString appicon;
|
2017-10-30 18:33:06 +01:00
|
|
|
|
|
|
|
if (nIcon == SV_ICON_ID_TEXT)
|
|
|
|
appicon = "libreoffice-writer";
|
|
|
|
else if (nIcon == SV_ICON_ID_SPREADSHEET)
|
|
|
|
appicon = "libreoffice-calc";
|
|
|
|
else if (nIcon == SV_ICON_ID_DRAWING)
|
|
|
|
appicon = "libreoffice-draw";
|
|
|
|
else if (nIcon == SV_ICON_ID_PRESENTATION)
|
|
|
|
appicon = "libreoffice-impress";
|
|
|
|
else if (nIcon == SV_ICON_ID_DATABASE)
|
|
|
|
appicon = "libreoffice-base";
|
|
|
|
else if (nIcon == SV_ICON_ID_FORMULA)
|
|
|
|
appicon = "libreoffice-math";
|
|
|
|
else
|
|
|
|
appicon = "libreoffice-startcenter";
|
|
|
|
|
|
|
|
QIcon aIcon = QIcon::fromTheme(appicon);
|
|
|
|
m_pQWidget->window()->setWindowIcon(aIcon);
|
2024-02-12 14:09:45 +01:00
|
|
|
|
|
|
|
if (QGuiApplication::platformName() == "wayland" && m_pQWidget->window()->isVisible())
|
|
|
|
{
|
|
|
|
// Qt currently doesn't provide API to directly set the app_id for a single
|
|
|
|
// window/toplevel on Wayland, but the one set for the application is picked up
|
|
|
|
// on hide/show, so do that.
|
|
|
|
// An alternative would be to use private Qt API and low-level wayland API to set the
|
|
|
|
// app_id directly, s. discussion in QTBUG-77182.
|
|
|
|
const QString sOrigDesktopFileName = QGuiApplication::desktopFileName();
|
|
|
|
QGuiApplication::setDesktopFileName(appicon);
|
|
|
|
m_pQWidget->window()->hide();
|
|
|
|
m_pQWidget->window()->show();
|
|
|
|
QGuiApplication::setDesktopFileName(sOrigDesktopFileName);
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetMenu(SalMenu*) {}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetExtendedFrameStyle(SalExtStyle /*nExtStyle*/) { /* not needed */}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::Show(bool bVisible, bool bNoActivate)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2018-08-09 17:14:14 +02:00
|
|
|
assert(m_pQWidget);
|
2021-04-15 00:37:55 +02:00
|
|
|
if (bVisible == asChild()->isVisible())
|
|
|
|
return;
|
2018-08-29 14:04:56 +02:00
|
|
|
|
2022-01-13 21:04:19 +01:00
|
|
|
auto* pSalInst(GetQtInstance());
|
2021-10-31 02:33:46 +02:00
|
|
|
assert(pSalInst);
|
|
|
|
|
|
|
|
if (!bVisible) // hide
|
|
|
|
{
|
tdf#144585 Qt fix Wayland LO fake popups
So Michael Weghorn was somehow reminded of an abandoned
commit from me ("Qt5 rework parent handling") archived in
https://gerrit.libreoffice.org/c/core/+/73463.
The bug introducing the new QWidget parenting, tdf#145363, was
resolved in a better way by explicitly setting parents for the
modal dialogs, so LO doesn't break Qt anymore. The actual problem
is, that an additional modal dialog needs to be stacked to the
previous modal dialog; no "parallel" modal dialogs are allowed,
which my original fix tried to enforce by reparenting.
Then there is the problem with Qt::Popup's focus grabbing on show,
which breaks LO's editable ComboBox. So LO's popup / FLOAT windows
are mapped to Qt::ToolTip, which are automatically advertised as
tooltips via accessibility. For X11 / xcb, Qt:Window with the
Qt::BypassWindowManagerHint works well enough as an alternative,
but WASM and Wayland don't seem to implement it correctly, so this
just handles popups as Qt::ToolTip on all platforms.
This reverts commit b00a68a8e19370e106cd76258a3c1825f43613ee
("tdf#145363 Qt reparent modal dialogs on show").
In addition the popup widgets are switched back to Qt::ToolTip.
Change-Id: If726771b4e9cc3f639f21cf502b3ec5985873643
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132526
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2022-04-04 18:02:28 +02:00
|
|
|
pSalInst->RunInMainThread([this]() { asChild()->setVisible(false); });
|
2021-10-31 02:33:46 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// show
|
2019-06-21 04:09:02 +00:00
|
|
|
SetDefaultSize();
|
2018-08-29 14:04:56 +02:00
|
|
|
|
2021-10-31 02:33:46 +02:00
|
|
|
pSalInst->RunInMainThread([this, bNoActivate]() {
|
|
|
|
QWidget* const pChild = asChild();
|
2022-01-09 01:01:49 +01:00
|
|
|
pChild->setVisible(true);
|
2021-10-31 02:33:46 +02:00
|
|
|
pChild->raise();
|
2021-10-29 22:24:12 +02:00
|
|
|
if (!bNoActivate)
|
2021-04-15 00:37:55 +02:00
|
|
|
{
|
2021-10-31 02:33:46 +02:00
|
|
|
pChild->activateWindow();
|
|
|
|
pChild->setFocus();
|
2021-04-15 00:37:55 +02:00
|
|
|
}
|
|
|
|
});
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetMinClientSize(tools::Long nWidth, tools::Long nHeight)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-10-31 01:07:06 +01:00
|
|
|
if (!isChild())
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
{
|
|
|
|
const qreal fRatio = devicePixelRatioF();
|
|
|
|
asChild()->setMinimumSize(round(nWidth / fRatio), round(nHeight / fRatio));
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetMaxClientSize(tools::Long nWidth, tools::Long nHeight)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-10-31 01:07:06 +01:00
|
|
|
if (!isChild())
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
{
|
|
|
|
const qreal fRatio = devicePixelRatioF();
|
|
|
|
asChild()->setMaximumSize(round(nWidth / fRatio), round(nHeight / fRatio));
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2023-03-24 08:06:56 +01:00
|
|
|
int QtFrame::menuBarOffset() const
|
|
|
|
{
|
|
|
|
QtMainWindow* pTopLevel = m_pParent->GetTopLevelWindow();
|
|
|
|
if (pTopLevel && pTopLevel->menuBar() && pTopLevel->menuBar()->isVisible())
|
|
|
|
return round(pTopLevel->menuBar()->geometry().height() * devicePixelRatioF());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetDefaultPos()
|
2017-10-30 19:44:40 +01:00
|
|
|
{
|
2019-06-24 06:37:45 +02:00
|
|
|
if (!m_bDefaultPos)
|
|
|
|
return;
|
|
|
|
|
2023-03-24 08:06:56 +01:00
|
|
|
// center on parent
|
2017-10-30 19:44:40 +01:00
|
|
|
if (m_pParent)
|
|
|
|
{
|
2023-03-24 08:06:56 +01:00
|
|
|
const qreal fRatio = devicePixelRatioF();
|
2021-12-20 13:02:33 +01:00
|
|
|
QWidget* const pParentWin = m_pParent->asChild()->window();
|
2023-03-24 08:06:56 +01:00
|
|
|
QWidget* const pChildWin = asChild()->window();
|
|
|
|
QPoint aPos = (pParentWin->rect().center() - pChildWin->rect().center()) * fRatio;
|
|
|
|
aPos.ry() -= menuBarOffset();
|
|
|
|
SetPosSize(aPos.x(), aPos.y(), 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y);
|
|
|
|
assert(!m_bDefaultPos);
|
2017-10-30 19:44:40 +01:00
|
|
|
}
|
2019-06-24 06:37:45 +02:00
|
|
|
else
|
2023-03-24 08:06:56 +01:00
|
|
|
m_bDefaultPos = false;
|
2017-10-30 19:44:40 +01:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
Size QtFrame::CalcDefaultSize()
|
2017-10-30 19:44:40 +01:00
|
|
|
{
|
2018-08-09 17:14:14 +02:00
|
|
|
assert(isWindow());
|
2018-08-29 14:04:56 +02:00
|
|
|
|
2019-05-29 19:01:28 +02:00
|
|
|
Size aSize;
|
2018-12-14 12:39:44 +03:00
|
|
|
if (!m_bFullScreen)
|
2019-05-29 19:01:28 +02:00
|
|
|
{
|
|
|
|
const QScreen* pScreen = screen();
|
2021-09-24 06:39:09 +02:00
|
|
|
if (!pScreen)
|
|
|
|
pScreen = QGuiApplication::screens().at(0);
|
|
|
|
aSize = bestmaxFrameSizeForScreenSize(toSize(pScreen->size()));
|
2019-05-29 19:01:28 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!m_bFullScreenSpanAll)
|
2020-01-13 09:55:12 +01:00
|
|
|
{
|
2022-06-02 22:42:20 +02:00
|
|
|
aSize = toSize(QGuiApplication::screens().at(maGeometry.screen())->size());
|
2020-01-13 09:55:12 +01:00
|
|
|
}
|
2019-05-29 19:01:28 +02:00
|
|
|
else
|
|
|
|
{
|
2021-09-24 06:39:09 +02:00
|
|
|
QScreen* pScreen = QGuiApplication::screenAt(QPoint(0, 0));
|
|
|
|
aSize = toSize(pScreen->availableVirtualGeometry().size());
|
2019-05-29 19:01:28 +02:00
|
|
|
}
|
|
|
|
}
|
2018-12-14 12:39:44 +03:00
|
|
|
|
|
|
|
return aSize;
|
2017-10-30 19:44:40 +01:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetDefaultSize()
|
2017-10-30 19:44:40 +01:00
|
|
|
{
|
2019-06-21 04:09:02 +00:00
|
|
|
if (!m_bDefaultSize)
|
|
|
|
return;
|
|
|
|
|
2017-10-30 19:44:40 +01:00
|
|
|
Size aDefSize = CalcDefaultSize();
|
|
|
|
SetPosSize(0, 0, aDefSize.Width(), aDefSize.Height(),
|
|
|
|
SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT);
|
2019-06-21 04:09:02 +00:00
|
|
|
assert(!m_bDefaultSize);
|
2017-10-30 19:44:40 +01:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetPosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
|
|
|
|
sal_uInt16 nFlags)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2018-08-09 17:14:14 +02:00
|
|
|
if (!isWindow() || isChild(true, false))
|
2017-10-30 19:44:40 +01:00
|
|
|
return;
|
|
|
|
|
2019-06-21 04:09:02 +00:00
|
|
|
if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
|
2017-10-30 19:44:40 +01:00
|
|
|
{
|
|
|
|
if (isChild(false) || !m_pQWidget->isMaximized())
|
|
|
|
{
|
2019-06-21 04:09:02 +00:00
|
|
|
if (!(nFlags & SAL_FRAME_POSSIZE_WIDTH))
|
2022-06-02 22:42:20 +02:00
|
|
|
nWidth = maGeometry.width();
|
2019-06-21 04:09:02 +00:00
|
|
|
else if (!(nFlags & SAL_FRAME_POSSIZE_HEIGHT))
|
2022-06-02 22:42:20 +02:00
|
|
|
nHeight = maGeometry.height();
|
2019-06-21 04:09:02 +00:00
|
|
|
|
|
|
|
if (nWidth > 0 && nHeight > 0)
|
|
|
|
{
|
2019-06-24 06:37:45 +02:00
|
|
|
m_bDefaultSize = false;
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
const int nNewWidth = round(nWidth / devicePixelRatioF());
|
|
|
|
const int nNewHeight = round(nHeight / devicePixelRatioF());
|
2019-06-21 04:09:02 +00:00
|
|
|
if (m_nStyle & SalFrameStyleFlags::SIZEABLE)
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
asChild()->resize(nNewWidth, nNewHeight);
|
2019-06-21 04:09:02 +00:00
|
|
|
else
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
asChild()->setFixedSize(nNewWidth, nNewHeight);
|
2019-06-24 06:37:45 +02:00
|
|
|
}
|
2019-06-21 04:09:02 +00:00
|
|
|
|
2019-06-24 06:37:45 +02:00
|
|
|
// assume the resize happened
|
|
|
|
// needed for calculations and will eventually be corrected by events
|
|
|
|
if (nWidth > 0)
|
2022-06-02 22:42:20 +02:00
|
|
|
maGeometry.setWidth(nWidth);
|
2019-06-24 06:37:45 +02:00
|
|
|
if (nHeight > 0)
|
2022-06-02 22:42:20 +02:00
|
|
|
maGeometry.setHeight(nHeight);
|
2017-10-30 19:44:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
if (!(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)))
|
2021-12-20 13:32:52 +01:00
|
|
|
{
|
|
|
|
if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
|
|
|
|
SetDefaultPos();
|
2020-08-04 09:22:10 +02:00
|
|
|
return;
|
2021-12-20 13:32:52 +01:00
|
|
|
}
|
2020-08-04 09:22:10 +02:00
|
|
|
|
|
|
|
if (m_pParent)
|
2017-10-30 19:44:40 +01:00
|
|
|
{
|
2020-08-04 09:22:10 +02:00
|
|
|
const SalFrameGeometry& aParentGeometry = m_pParent->maGeometry;
|
|
|
|
if (QGuiApplication::isRightToLeft())
|
2023-03-24 08:06:56 +01:00
|
|
|
nX = aParentGeometry.x() + aParentGeometry.width() - nX - maGeometry.width() - 1;
|
2020-08-04 09:22:10 +02:00
|
|
|
else
|
2023-03-24 08:06:56 +01:00
|
|
|
nX += aParentGeometry.x();
|
|
|
|
nY += aParentGeometry.y() + menuBarOffset();
|
2020-08-04 09:22:10 +02:00
|
|
|
}
|
2019-06-21 04:09:02 +00:00
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
if (!(nFlags & SAL_FRAME_POSSIZE_X))
|
2022-06-02 22:42:20 +02:00
|
|
|
nX = maGeometry.x();
|
2020-08-04 09:22:10 +02:00
|
|
|
else if (!(nFlags & SAL_FRAME_POSSIZE_Y))
|
2022-06-02 22:42:20 +02:00
|
|
|
nY = maGeometry.y();
|
2017-12-08 11:37:18 +00:00
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
// assume the reposition happened
|
|
|
|
// needed for calculations and will eventually be corrected by events later
|
2022-06-02 22:42:20 +02:00
|
|
|
maGeometry.setPos({ nX, nY });
|
2020-08-04 09:22:10 +02:00
|
|
|
|
|
|
|
m_bDefaultPos = false;
|
|
|
|
asChild()->move(round(nX / devicePixelRatioF()), round(nY / devicePixelRatioF()));
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::GetClientSize(tools::Long& rWidth, tools::Long& rHeight)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2023-03-24 08:06:56 +01:00
|
|
|
rWidth = round(m_pQWidget->width() * devicePixelRatioF());
|
|
|
|
rHeight = round(m_pQWidget->height() * devicePixelRatioF());
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2023-07-20 08:19:52 +02:00
|
|
|
void QtFrame::GetWorkArea(AbsoluteScreenPixelRectangle& rRect)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2018-08-09 17:14:14 +02:00
|
|
|
if (!isWindow())
|
2017-10-30 19:44:40 +01:00
|
|
|
return;
|
2018-08-09 17:14:14 +02:00
|
|
|
QScreen* pScreen = screen();
|
2017-10-30 19:44:40 +01:00
|
|
|
if (!pScreen)
|
|
|
|
return;
|
|
|
|
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
QSize aSize = pScreen->availableVirtualSize() * devicePixelRatioF();
|
2023-07-20 08:19:52 +02:00
|
|
|
rRect = AbsoluteScreenPixelRectangle(0, 0, aSize.width(), aSize.height());
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
SalFrame* QtFrame::GetParent() const { return m_pParent; }
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetModal(bool bModal)
|
2018-06-27 10:41:03 +02:00
|
|
|
{
|
2021-10-31 02:33:46 +02:00
|
|
|
if (!isWindow() || asChild()->isModal() == bModal)
|
2020-08-04 09:22:10 +02:00
|
|
|
return;
|
2019-06-02 21:01:33 +00:00
|
|
|
|
2022-01-13 21:04:19 +01:00
|
|
|
auto* pSalInst(GetQtInstance());
|
2020-08-04 09:22:10 +02:00
|
|
|
assert(pSalInst);
|
|
|
|
pSalInst->RunInMainThread([this, bModal]() {
|
tdf#119856 vcl: fix Qt warning Qt5Frame::SetModal()
This prints a warning "Cannot create children for a parent that is in a
different thread"; let's fix it before it causes another hard to debug
crash.
0 check_parent_thread(QObject*, QThreadData*, QThreadData*) (parent=parent@entry=0xe88ca0, parentThreadData=<optimized out>, currentThreadData=<optimized out>) at kernel/qobject.cpp:781
1 check_parent_thread (currentThreadData=<optimized out>, parentThreadData=<optimized out>, parent=0xe88ca0) at kernel/qobject.cpp:822
2 QObject::QObject(QObject*) (this=0x9ed2e80, parent=0xe88ca0) at kernel/qobject.cpp:810
3 Adwaita::GenericData::GenericData(QObject*, QWidget*, int) () at /usr/lib64/qt5/plugins/styles/adwaita.so
4 Adwaita::WidgetStateEngine::registerWidget(QWidget*, QFlags<Adwaita::AnimationMode>) () at /usr/lib64/qt5/plugins/styles/adwaita.so
5 Adwaita::Animations::registerWidget(QWidget*) const () at /usr/lib64/qt5/plugins/styles/adwaita.so
6 Adwaita::Style::polish(QWidget*) () at /usr/lib64/qt5/plugins/styles/adwaita.so
7 QWidget::event(QEvent*) () at /lib64/libQt5Widgets.so.5
8 Qt5Widget::event(QEvent*) (this=0x7321790, pEvent=0x7f90c27d3750) at vcl/qt5/Qt5Widget.cxx:416
9 QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
10 QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
11 QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x7321790, event=0x7f90c27d3750) at kernel/qcoreapplication.cpp:1047
12 QWidget::ensurePolished() const () at /lib64/libQt5Widgets.so.5
13 QWidget::setVisible(bool) () at /lib64/libQt5Widgets.so.5
14 Qt5Frame::SetModal(bool) (this=0x9f411b0, bModal=true) at vcl/qt5/Qt5Frame.cxx:482
Change-Id: Ib6b4d1ee859dfce650422a6c7860abf2eb2686f1
Reviewed-on: https://gerrit.libreoffice.org/68356
Tested-by: Jenkins
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
2019-02-25 16:56:59 +01:00
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
QWidget* const pChild = asChild();
|
|
|
|
const bool bWasVisible = pChild->isVisible();
|
tdf#119856 vcl: fix Qt warning Qt5Frame::SetModal()
This prints a warning "Cannot create children for a parent that is in a
different thread"; let's fix it before it causes another hard to debug
crash.
0 check_parent_thread(QObject*, QThreadData*, QThreadData*) (parent=parent@entry=0xe88ca0, parentThreadData=<optimized out>, currentThreadData=<optimized out>) at kernel/qobject.cpp:781
1 check_parent_thread (currentThreadData=<optimized out>, parentThreadData=<optimized out>, parent=0xe88ca0) at kernel/qobject.cpp:822
2 QObject::QObject(QObject*) (this=0x9ed2e80, parent=0xe88ca0) at kernel/qobject.cpp:810
3 Adwaita::GenericData::GenericData(QObject*, QWidget*, int) () at /usr/lib64/qt5/plugins/styles/adwaita.so
4 Adwaita::WidgetStateEngine::registerWidget(QWidget*, QFlags<Adwaita::AnimationMode>) () at /usr/lib64/qt5/plugins/styles/adwaita.so
5 Adwaita::Animations::registerWidget(QWidget*) const () at /usr/lib64/qt5/plugins/styles/adwaita.so
6 Adwaita::Style::polish(QWidget*) () at /usr/lib64/qt5/plugins/styles/adwaita.so
7 QWidget::event(QEvent*) () at /lib64/libQt5Widgets.so.5
8 Qt5Widget::event(QEvent*) (this=0x7321790, pEvent=0x7f90c27d3750) at vcl/qt5/Qt5Widget.cxx:416
9 QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
10 QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
11 QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x7321790, event=0x7f90c27d3750) at kernel/qcoreapplication.cpp:1047
12 QWidget::ensurePolished() const () at /lib64/libQt5Widgets.so.5
13 QWidget::setVisible(bool) () at /lib64/libQt5Widgets.so.5
14 Qt5Frame::SetModal(bool) (this=0x9f411b0, bModal=true) at vcl/qt5/Qt5Frame.cxx:482
Change-Id: Ib6b4d1ee859dfce650422a6c7860abf2eb2686f1
Reviewed-on: https://gerrit.libreoffice.org/68356
Tested-by: Jenkins
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
2019-02-25 16:56:59 +01:00
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
// modality change is only effective if the window is hidden
|
|
|
|
if (bWasVisible)
|
2023-04-01 20:08:13 +03:00
|
|
|
{
|
2020-08-04 09:22:10 +02:00
|
|
|
pChild->hide();
|
2023-04-01 20:08:13 +03:00
|
|
|
if (QGuiApplication::platformName() == "xcb")
|
|
|
|
{
|
|
|
|
SAL_WARN("vcl.qt", "SetModal called after Show - apply delay");
|
|
|
|
// tdf#152979 give QXcbConnection some time to avoid
|
|
|
|
// "qt.qpa.xcb: internal error: void QXcbWindow::setNetWmStateOnUnmappedWindow() called on mapped window"
|
|
|
|
QThread::msleep(100);
|
|
|
|
}
|
|
|
|
}
|
tdf#119856 vcl: fix Qt warning Qt5Frame::SetModal()
This prints a warning "Cannot create children for a parent that is in a
different thread"; let's fix it before it causes another hard to debug
crash.
0 check_parent_thread(QObject*, QThreadData*, QThreadData*) (parent=parent@entry=0xe88ca0, parentThreadData=<optimized out>, currentThreadData=<optimized out>) at kernel/qobject.cpp:781
1 check_parent_thread (currentThreadData=<optimized out>, parentThreadData=<optimized out>, parent=0xe88ca0) at kernel/qobject.cpp:822
2 QObject::QObject(QObject*) (this=0x9ed2e80, parent=0xe88ca0) at kernel/qobject.cpp:810
3 Adwaita::GenericData::GenericData(QObject*, QWidget*, int) () at /usr/lib64/qt5/plugins/styles/adwaita.so
4 Adwaita::WidgetStateEngine::registerWidget(QWidget*, QFlags<Adwaita::AnimationMode>) () at /usr/lib64/qt5/plugins/styles/adwaita.so
5 Adwaita::Animations::registerWidget(QWidget*) const () at /usr/lib64/qt5/plugins/styles/adwaita.so
6 Adwaita::Style::polish(QWidget*) () at /usr/lib64/qt5/plugins/styles/adwaita.so
7 QWidget::event(QEvent*) () at /lib64/libQt5Widgets.so.5
8 Qt5Widget::event(QEvent*) (this=0x7321790, pEvent=0x7f90c27d3750) at vcl/qt5/Qt5Widget.cxx:416
9 QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
10 QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
11 QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x7321790, event=0x7f90c27d3750) at kernel/qcoreapplication.cpp:1047
12 QWidget::ensurePolished() const () at /lib64/libQt5Widgets.so.5
13 QWidget::setVisible(bool) () at /lib64/libQt5Widgets.so.5
14 Qt5Frame::SetModal(bool) (this=0x9f411b0, bModal=true) at vcl/qt5/Qt5Frame.cxx:482
Change-Id: Ib6b4d1ee859dfce650422a6c7860abf2eb2686f1
Reviewed-on: https://gerrit.libreoffice.org/68356
Tested-by: Jenkins
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
2019-02-25 16:56:59 +01:00
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
pChild->setWindowModality(bModal ? Qt::WindowModal : Qt::NonModal);
|
|
|
|
|
|
|
|
if (bWasVisible)
|
|
|
|
pChild->show();
|
|
|
|
});
|
2018-06-27 10:41:03 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::GetModal() const { return isWindow() && windowHandle()->isModal(); }
|
2018-11-02 18:21:20 +00:00
|
|
|
|
2022-06-02 22:42:20 +02:00
|
|
|
void QtFrame::SetWindowState(const vcl::WindowData* pState)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2018-08-09 17:14:14 +02:00
|
|
|
if (!isWindow() || !pState || isChild(true, false))
|
2017-10-30 18:33:06 +01:00
|
|
|
return;
|
|
|
|
|
2022-06-02 22:42:20 +02:00
|
|
|
const vcl::WindowDataMask nMaxGeometryMask
|
|
|
|
= vcl::WindowDataMask::PosSize | vcl::WindowDataMask::MaximizedX
|
|
|
|
| vcl::WindowDataMask::MaximizedY | vcl::WindowDataMask::MaximizedWidth
|
|
|
|
| vcl::WindowDataMask::MaximizedHeight;
|
2017-10-30 18:33:06 +01:00
|
|
|
|
2022-06-02 22:42:20 +02:00
|
|
|
if ((pState->mask() & vcl::WindowDataMask::State)
|
|
|
|
&& (pState->state() & vcl::WindowState::Maximized) && !isMaximized()
|
|
|
|
&& (pState->mask() & nMaxGeometryMask) == nMaxGeometryMask)
|
2019-02-11 11:22:30 +01:00
|
|
|
{
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
const qreal fRatio = devicePixelRatioF();
|
2019-06-02 15:38:25 +00:00
|
|
|
QWidget* const pChild = asChild();
|
2022-06-02 22:42:20 +02:00
|
|
|
pChild->resize(ceil(pState->width() / fRatio), ceil(pState->height() / fRatio));
|
|
|
|
pChild->move(ceil(pState->x() / fRatio), ceil(pState->y() / fRatio));
|
2019-02-11 11:22:30 +01:00
|
|
|
SetWindowStateImpl(Qt::WindowMaximized);
|
|
|
|
}
|
2022-06-02 22:42:20 +02:00
|
|
|
else if (pState->mask() & vcl::WindowDataMask::PosSize)
|
2017-10-30 18:33:06 +01:00
|
|
|
{
|
2017-10-30 19:44:40 +01:00
|
|
|
sal_uInt16 nPosSizeFlags = 0;
|
2022-06-02 22:42:20 +02:00
|
|
|
if (pState->mask() & vcl::WindowDataMask::X)
|
2017-10-30 19:44:40 +01:00
|
|
|
nPosSizeFlags |= SAL_FRAME_POSSIZE_X;
|
2022-06-02 22:42:20 +02:00
|
|
|
if (pState->mask() & vcl::WindowDataMask::Y)
|
2017-10-30 19:44:40 +01:00
|
|
|
nPosSizeFlags |= SAL_FRAME_POSSIZE_Y;
|
2022-06-02 22:42:20 +02:00
|
|
|
if (pState->mask() & vcl::WindowDataMask::Width)
|
2017-10-30 19:44:40 +01:00
|
|
|
nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH;
|
2022-06-02 22:42:20 +02:00
|
|
|
if (pState->mask() & vcl::WindowDataMask::Height)
|
2017-10-30 19:44:40 +01:00
|
|
|
nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT;
|
2022-06-02 22:42:20 +02:00
|
|
|
SetPosSize(pState->x(), pState->y(), pState->width(), pState->height(), nPosSizeFlags);
|
2017-10-30 18:33:06 +01:00
|
|
|
}
|
2022-06-02 22:42:20 +02:00
|
|
|
else if (pState->mask() & vcl::WindowDataMask::State && !isChild())
|
2017-10-30 18:33:06 +01:00
|
|
|
{
|
2022-06-02 22:42:20 +02:00
|
|
|
if (pState->state() & vcl::WindowState::Maximized)
|
2019-02-11 11:22:30 +01:00
|
|
|
SetWindowStateImpl(Qt::WindowMaximized);
|
2022-06-02 22:42:20 +02:00
|
|
|
else if (pState->state() & vcl::WindowState::Minimized)
|
2019-02-11 11:22:30 +01:00
|
|
|
SetWindowStateImpl(Qt::WindowMinimized);
|
2017-10-30 18:33:06 +01:00
|
|
|
else
|
2019-02-11 11:22:30 +01:00
|
|
|
SetWindowStateImpl(Qt::WindowNoState);
|
2017-10-30 18:33:06 +01:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2022-06-02 22:42:20 +02:00
|
|
|
bool QtFrame::GetWindowState(vcl::WindowData* pState)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2022-06-02 22:42:20 +02:00
|
|
|
pState->setState(vcl::WindowState::Normal);
|
|
|
|
pState->setMask(vcl::WindowDataMask::State);
|
|
|
|
if (isMinimized())
|
|
|
|
pState->rState() |= vcl::WindowState::Minimized;
|
2018-10-25 11:45:13 +02:00
|
|
|
else if (isMaximized())
|
2022-06-02 22:42:20 +02:00
|
|
|
pState->rState() |= vcl::WindowState::Maximized;
|
2017-10-30 18:33:06 +01:00
|
|
|
else
|
|
|
|
{
|
2022-06-05 08:55:43 +02:00
|
|
|
// we want the frame position and the client area size
|
|
|
|
QRect rect = scaledQRect({ asChild()->pos(), asChild()->size() }, devicePixelRatioF());
|
2022-06-02 22:42:20 +02:00
|
|
|
pState->setPosSize(toRectangle(rect));
|
|
|
|
pState->rMask() |= vcl::WindowDataMask::PosSize;
|
2017-10-30 18:33:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::ShowFullScreen(bool bFullScreen, sal_Int32 nScreen)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2018-10-25 12:29:34 +02:00
|
|
|
// only top-level windows can go fullscreen
|
2018-09-04 09:17:11 +02:00
|
|
|
assert(m_pTopLevel);
|
|
|
|
|
2019-05-29 19:01:28 +02:00
|
|
|
if (m_bFullScreen == bFullScreen)
|
|
|
|
return;
|
|
|
|
|
2018-12-14 12:39:44 +03:00
|
|
|
m_bFullScreen = bFullScreen;
|
2019-05-29 19:01:28 +02:00
|
|
|
m_bFullScreenSpanAll = m_bFullScreen && (nScreen < 0);
|
2018-12-14 12:39:44 +03:00
|
|
|
|
2018-10-25 12:29:34 +02:00
|
|
|
// show it if it isn't shown yet
|
|
|
|
if (!isWindow())
|
|
|
|
m_pTopLevel->show();
|
2018-09-04 09:17:11 +02:00
|
|
|
|
2019-02-26 15:07:51 +01:00
|
|
|
if (m_bFullScreen)
|
|
|
|
{
|
|
|
|
m_aRestoreGeometry = m_pTopLevel->geometry();
|
2022-06-02 22:42:20 +02:00
|
|
|
m_nRestoreScreen = maGeometry.screen();
|
2019-05-29 19:01:28 +02:00
|
|
|
SetScreenNumber(m_bFullScreenSpanAll ? m_nRestoreScreen : nScreen);
|
|
|
|
if (!m_bFullScreenSpanAll)
|
|
|
|
windowHandle()->showFullScreen();
|
|
|
|
else
|
|
|
|
windowHandle()->showNormal();
|
2019-02-26 15:07:51 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-05-29 19:01:28 +02:00
|
|
|
SetScreenNumber(m_nRestoreScreen);
|
2019-02-26 15:07:51 +01:00
|
|
|
windowHandle()->showNormal();
|
|
|
|
m_pTopLevel->setGeometry(m_aRestoreGeometry);
|
|
|
|
}
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::StartPresentation(bool bStart)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2022-06-18 21:11:28 +02:00
|
|
|
#if CHECK_ANY_QT_USING_X11
|
2022-06-15 23:34:01 +02:00
|
|
|
// meh - so there's no Qt platform independent solution
|
|
|
|
// https://forum.qt.io/topic/38504/solved-qdialog-in-fullscreen-disable-os-screensaver
|
|
|
|
assert(m_aSystemData.platform != SystemEnvData::Platform::Invalid);
|
2023-05-08 11:17:00 +01:00
|
|
|
unsigned int nRootWindow(0);
|
2020-02-21 07:26:06 +01:00
|
|
|
std::optional<Display*> aDisplay;
|
2019-06-14 02:08:22 +00:00
|
|
|
|
2022-06-15 23:34:01 +02:00
|
|
|
#if CHECK_QT5_USING_X11
|
2019-06-14 02:08:22 +00:00
|
|
|
if (QX11Info::isPlatformX11())
|
|
|
|
{
|
2023-05-08 11:17:00 +01:00
|
|
|
nRootWindow = QX11Info::appRootWindow();
|
2019-06-14 02:08:22 +00:00
|
|
|
aDisplay = QX11Info::display();
|
|
|
|
}
|
|
|
|
#endif
|
2022-06-15 23:34:01 +02:00
|
|
|
|
2023-05-08 11:17:00 +01:00
|
|
|
m_SessionManagerInhibitor.inhibit(bStart, u"presentation", APPLICATION_INHIBIT_IDLE,
|
|
|
|
nRootWindow, aDisplay);
|
2022-06-18 21:11:28 +02:00
|
|
|
#else
|
|
|
|
Q_UNUSED(bStart)
|
|
|
|
#endif
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetAlwaysOnTop(bool bOnTop)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2019-06-02 15:38:25 +00:00
|
|
|
QWidget* const pWidget = asChild();
|
2018-09-04 09:17:11 +02:00
|
|
|
const Qt::WindowFlags flags = pWidget->windowFlags();
|
|
|
|
if (bOnTop)
|
|
|
|
pWidget->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
|
|
|
|
else
|
|
|
|
pWidget->setWindowFlags(flags & ~(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::ToTop(SalFrameToTop nFlags)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
qt: Set window title etc. in main thread
These QWidget methods need to be called
in the main thread.
Otherwise, opening the Update dialog
("Help" -> "Check for Updates", enabled
by `--enable-online-update` autogen switch)
triggers asserts like the one below with
a self-compiled Qt 6 development build
(qtbase dev branch as of
c802a9e987c9e38c01580f467eab92a651b3e033).
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp, line 537
Thread 40 "InitUpdateCheck" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff7ffff6c0 (LWP 1516868)]
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007ffff78a815f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 0x00007ffff785a472 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007ffff78444b2 in __GI_abort () at ./stdlib/abort.c:79
#4 0x00007fffe32eb45a in qAbort() () at /home/michi/development/git/qt5/qtbase/src/corelib/global/qglobal.cpp:161
#5 0x00007fffe32f9ee5 in qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&) (context=..., message=...) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:2057
#6 0x00007fffe32f620c in QMessageLogger::fatal(char const*, ...) const (this=0x7fff7fffb980, msg=0x7fffe37fd9a0 "ASSERT failure in %s: \"%s\", file %s, line %d")
at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:938
#7 0x00007fffe32e9d54 in qt_assert_x(char const*, char const*, char const*, int)
(where=0x7fffe38131e9 "QCoreApplication::sendEvent", what=0x7fff78180110 "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file=0x7fffe3812e18 "/home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp", line=537) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qassert.cpp:77
#8 0x00007fffe33a4d74 in QCoreApplicationPrivate::checkReceiverThread(QObject*) (receiver=0x55555d27d5d0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:537
#9 0x00007fffe19a3a81 in QApplication::notify(QObject*, QEvent*) (this=0x5555555fcb80, receiver=0x55555d27d5d0, e=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2584
#10 0x00007fffe33a5ed0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1125
#11 0x00007fffe33a6991 in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1559
#12 0x00007fffe1a279b4 in QWidget::setWindowTitle(QString const&) (this=0x55555d27d5d0, title=...) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidget.cpp:6119
#13 0x00007fffe3c9d4c4 in QtFrame::SetTitle(rtl::OUString const&) (this=0x555555619d20, rTitle="Check for Updates") at /home/michi/development/git/libreoffice/vcl/qt6/../qt5/QtFrame.cxx:365
#14 0x00007fffedd98d44 in vcl::Window::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/window.cxx:3042
#15 0x00007fffedd311c9 in SystemWindow::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/syswin.cxx:1048
#16 0x00007ffff048bd6b in VCLXWindow::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindow.cxx:1515
#17 0x00007ffff03e486d in VCLXContainer::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxcontainer.cxx:260
#18 0x00007ffff04dfa2c in VCLXDialog::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindows.cxx:2364
#19 0x00007ffff06a89b7 in UnoControl::ImplSetPeerProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7803b4f0, rPropName="Title", rVal=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:288
#20 0x00007ffff06aa701 in UnoControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:649
#21 0x00007ffff0531ae9 in ControlContainerBase::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/controlmodelcontainerbase.cxx:1600
#22 0x00007ffff0575a25 in UnoDialogControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:651
#23 0x00007ffff06a95f3 in UnoControl::propertiesChange(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:431
#24 0x00007ffff66bc4ee in cppu::OPropertySetHelper::firePropertiesChangeEvent(com::sun::star::uno::Sequence<rtl::OUString> const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertiesChangeListener> const&)
(this=0x7fff78006170, rPropertyNames=uno::Sequence of length 51 = {...}, rListener=uno::Reference to (UnoDialogControl *) 0x7fff7803b540) at /home/michi/development/git/libreoffice/cppuhelper/source/propshlp.cxx:961
#25 0x00007ffff06a8c6b in UnoControl::updateFromModel() (this=0x7fff7803b4f0) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:320
#26 0x00007ffff06aefc9 in UnoControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:1325
#27 0x00007ffff06c9905 in UnoControlContainer::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParent=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrolcontainer.cxx:727
#28 0x00007ffff057336d in UnoDialogControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:358
#29 0x00007fffb7264e62 in UpdateHandler::createDialog() (this=0x7fff78003aa0) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:1232
#30 0x00007fffb725b0e1 in UpdateHandler::setVisible(bool) (this=0x7fff78003aa0, bVisible=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:188
#31 0x00007fffb7235887 in UpdateCheck::showDialog(bool) (this=0x7fff78000b90, forceCheck=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheck.cxx:1171
#32 0x00007fffb7255c5e in (anonymous namespace)::InitUpdateCheckJobThread::run() (this=0x55555d192690) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheckjob.cxx:148
#33 0x00007fffb723a74a in osl::threadFunc(void*) (param=0x55555d192690) at /home/michi/development/git/libreoffice/include/osl/thread.hxx:189
#34 0x00007ffff7f3f693 in osl_thread_start_Impl(void*) (pData=0x55555d1a68b0) at /home/michi/development/git/libreoffice/sal/osl/unx/thread.cxx:237
#35 0x00007ffff78a63ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#36 0x00007ffff7926a1c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Change-Id: I6ccdee00fe26619f201459ebbe6c4d8cf8b57b45
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156426
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-01 17:50:19 +02:00
|
|
|
QtInstance* pSalInst(GetQtInstance());
|
|
|
|
assert(pSalInst);
|
|
|
|
pSalInst->RunInMainThread([this, nFlags]() {
|
|
|
|
QWidget* const pWidget = asChild();
|
|
|
|
if (isWindow() && !(nFlags & SalFrameToTop::GrabFocusOnly))
|
|
|
|
pWidget->raise();
|
|
|
|
if ((nFlags & SalFrameToTop::RestoreWhenMin) || (nFlags & SalFrameToTop::ForegroundTask))
|
|
|
|
{
|
|
|
|
if (nFlags & SalFrameToTop::RestoreWhenMin)
|
|
|
|
pWidget->setWindowState(pWidget->windowState() & ~Qt::WindowMinimized);
|
2022-04-06 18:59:10 +02:00
|
|
|
pWidget->activateWindow();
|
qt: Set window title etc. in main thread
These QWidget methods need to be called
in the main thread.
Otherwise, opening the Update dialog
("Help" -> "Check for Updates", enabled
by `--enable-online-update` autogen switch)
triggers asserts like the one below with
a self-compiled Qt 6 development build
(qtbase dev branch as of
c802a9e987c9e38c01580f467eab92a651b3e033).
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp, line 537
Thread 40 "InitUpdateCheck" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff7ffff6c0 (LWP 1516868)]
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007ffff78a815f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 0x00007ffff785a472 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007ffff78444b2 in __GI_abort () at ./stdlib/abort.c:79
#4 0x00007fffe32eb45a in qAbort() () at /home/michi/development/git/qt5/qtbase/src/corelib/global/qglobal.cpp:161
#5 0x00007fffe32f9ee5 in qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&) (context=..., message=...) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:2057
#6 0x00007fffe32f620c in QMessageLogger::fatal(char const*, ...) const (this=0x7fff7fffb980, msg=0x7fffe37fd9a0 "ASSERT failure in %s: \"%s\", file %s, line %d")
at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:938
#7 0x00007fffe32e9d54 in qt_assert_x(char const*, char const*, char const*, int)
(where=0x7fffe38131e9 "QCoreApplication::sendEvent", what=0x7fff78180110 "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file=0x7fffe3812e18 "/home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp", line=537) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qassert.cpp:77
#8 0x00007fffe33a4d74 in QCoreApplicationPrivate::checkReceiverThread(QObject*) (receiver=0x55555d27d5d0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:537
#9 0x00007fffe19a3a81 in QApplication::notify(QObject*, QEvent*) (this=0x5555555fcb80, receiver=0x55555d27d5d0, e=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2584
#10 0x00007fffe33a5ed0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1125
#11 0x00007fffe33a6991 in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1559
#12 0x00007fffe1a279b4 in QWidget::setWindowTitle(QString const&) (this=0x55555d27d5d0, title=...) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidget.cpp:6119
#13 0x00007fffe3c9d4c4 in QtFrame::SetTitle(rtl::OUString const&) (this=0x555555619d20, rTitle="Check for Updates") at /home/michi/development/git/libreoffice/vcl/qt6/../qt5/QtFrame.cxx:365
#14 0x00007fffedd98d44 in vcl::Window::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/window.cxx:3042
#15 0x00007fffedd311c9 in SystemWindow::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/syswin.cxx:1048
#16 0x00007ffff048bd6b in VCLXWindow::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindow.cxx:1515
#17 0x00007ffff03e486d in VCLXContainer::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxcontainer.cxx:260
#18 0x00007ffff04dfa2c in VCLXDialog::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindows.cxx:2364
#19 0x00007ffff06a89b7 in UnoControl::ImplSetPeerProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7803b4f0, rPropName="Title", rVal=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:288
#20 0x00007ffff06aa701 in UnoControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:649
#21 0x00007ffff0531ae9 in ControlContainerBase::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/controlmodelcontainerbase.cxx:1600
#22 0x00007ffff0575a25 in UnoDialogControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:651
#23 0x00007ffff06a95f3 in UnoControl::propertiesChange(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:431
#24 0x00007ffff66bc4ee in cppu::OPropertySetHelper::firePropertiesChangeEvent(com::sun::star::uno::Sequence<rtl::OUString> const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertiesChangeListener> const&)
(this=0x7fff78006170, rPropertyNames=uno::Sequence of length 51 = {...}, rListener=uno::Reference to (UnoDialogControl *) 0x7fff7803b540) at /home/michi/development/git/libreoffice/cppuhelper/source/propshlp.cxx:961
#25 0x00007ffff06a8c6b in UnoControl::updateFromModel() (this=0x7fff7803b4f0) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:320
#26 0x00007ffff06aefc9 in UnoControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:1325
#27 0x00007ffff06c9905 in UnoControlContainer::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParent=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrolcontainer.cxx:727
#28 0x00007ffff057336d in UnoDialogControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:358
#29 0x00007fffb7264e62 in UpdateHandler::createDialog() (this=0x7fff78003aa0) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:1232
#30 0x00007fffb725b0e1 in UpdateHandler::setVisible(bool) (this=0x7fff78003aa0, bVisible=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:188
#31 0x00007fffb7235887 in UpdateCheck::showDialog(bool) (this=0x7fff78000b90, forceCheck=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheck.cxx:1171
#32 0x00007fffb7255c5e in (anonymous namespace)::InitUpdateCheckJobThread::run() (this=0x55555d192690) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheckjob.cxx:148
#33 0x00007fffb723a74a in osl::threadFunc(void*) (param=0x55555d192690) at /home/michi/development/git/libreoffice/include/osl/thread.hxx:189
#34 0x00007ffff7f3f693 in osl_thread_start_Impl(void*) (pData=0x55555d1a68b0) at /home/michi/development/git/libreoffice/sal/osl/unx/thread.cxx:237
#35 0x00007ffff78a63ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#36 0x00007ffff7926a1c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Change-Id: I6ccdee00fe26619f201459ebbe6c4d8cf8b57b45
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156426
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
else if ((nFlags & SalFrameToTop::GrabFocus) || (nFlags & SalFrameToTop::GrabFocusOnly))
|
|
|
|
{
|
|
|
|
if (!(nFlags & SalFrameToTop::GrabFocusOnly))
|
|
|
|
pWidget->activateWindow();
|
|
|
|
pWidget->setFocus(Qt::OtherFocusReason);
|
|
|
|
}
|
|
|
|
});
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetPointer(PointerStyle ePointerStyle)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-10-30 19:32:45 +01:00
|
|
|
if (ePointerStyle == m_ePointerStyle)
|
|
|
|
return;
|
|
|
|
m_ePointerStyle = ePointerStyle;
|
|
|
|
|
2022-05-27 23:36:20 +02:00
|
|
|
m_pQWidget->setCursor(GetQtData()->getCursor(ePointerStyle));
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::CaptureMouse(bool bMouse)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2018-09-04 21:05:03 +02:00
|
|
|
static const char* pEnv = getenv("SAL_NO_MOUSEGRABS");
|
|
|
|
if (pEnv && *pEnv)
|
|
|
|
return;
|
|
|
|
|
2018-09-04 09:17:11 +02:00
|
|
|
if (bMouse)
|
2018-09-04 21:05:03 +02:00
|
|
|
m_pQWidget->grabMouse();
|
2018-09-04 09:17:11 +02:00
|
|
|
else
|
2018-09-04 21:05:03 +02:00
|
|
|
m_pQWidget->releaseMouse();
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetPointerPos(tools::Long nX, tools::Long nY)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2019-04-01 09:41:39 +02:00
|
|
|
// some cursor already exists (and it has m_ePointerStyle shape)
|
|
|
|
// so here we just reposition it
|
2022-04-04 11:25:22 +02:00
|
|
|
QCursor::setPos(m_pQWidget->mapToGlobal(QPoint(nX, nY) / devicePixelRatioF()));
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::Flush()
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2018-09-05 15:08:33 +02:00
|
|
|
// was: QGuiApplication::sync();
|
|
|
|
// but FIXME it causes too many issues, figure out sth better
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2018-09-04 09:17:11 +02:00
|
|
|
// unclear if we need to also flush cairo surface - gtk3 backend
|
2021-09-28 15:02:47 +02:00
|
|
|
// does not do it. QPainter in QtWidget::paintEvent() is
|
2018-09-04 09:17:11 +02:00
|
|
|
// destroyed, so that state should be safely flushed.
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::ShowTooltip(const OUString& rText, const tools::Rectangle& rHelpArea)
|
2018-12-11 12:12:52 +01:00
|
|
|
{
|
2019-06-22 02:25:24 +02:00
|
|
|
QRect aHelpArea(toQRect(rHelpArea));
|
|
|
|
if (QGuiApplication::isRightToLeft())
|
2022-06-02 22:42:20 +02:00
|
|
|
aHelpArea.moveLeft(maGeometry.width() - aHelpArea.width() - aHelpArea.left() - 1);
|
2022-04-12 00:29:56 +02:00
|
|
|
m_aTooltipText = rText;
|
|
|
|
m_aTooltipArea = aHelpArea;
|
2018-12-11 12:12:52 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetInputContext(SalInputContext* pContext)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2018-12-21 17:25:17 +01:00
|
|
|
if (!pContext)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!(pContext->mnOptions & InputContextFlags::Text))
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_pQWidget->setAttribute(Qt::WA_InputMethodEnabled);
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::EndExtTextInput(EndExtTextInputFlags /*nFlags*/)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2022-04-07 01:07:43 +02:00
|
|
|
if (m_pQWidget)
|
|
|
|
m_pQWidget->endExtTextInput();
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
OUString QtFrame::GetKeyName(sal_uInt16 nKeyCode)
|
2018-10-23 15:46:09 +02:00
|
|
|
{
|
|
|
|
vcl::KeyCode vclKeyCode(nKeyCode);
|
|
|
|
int nCode = vclKeyCode.GetCode();
|
|
|
|
int nRetCode = 0;
|
|
|
|
|
|
|
|
if (nCode >= KEY_0 && nCode <= KEY_9)
|
|
|
|
nRetCode = (nCode - KEY_0) + Qt::Key_0;
|
|
|
|
else if (nCode >= KEY_A && nCode <= KEY_Z)
|
|
|
|
nRetCode = (nCode - KEY_A) + Qt::Key_A;
|
|
|
|
else if (nCode >= KEY_F1 && nCode <= KEY_F26)
|
|
|
|
nRetCode = (nCode - KEY_F1) + Qt::Key_F1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (nCode)
|
|
|
|
{
|
|
|
|
case KEY_DOWN:
|
|
|
|
nRetCode = Qt::Key_Down;
|
|
|
|
break;
|
|
|
|
case KEY_UP:
|
|
|
|
nRetCode = Qt::Key_Up;
|
|
|
|
break;
|
|
|
|
case KEY_LEFT:
|
|
|
|
nRetCode = Qt::Key_Left;
|
|
|
|
break;
|
|
|
|
case KEY_RIGHT:
|
|
|
|
nRetCode = Qt::Key_Right;
|
|
|
|
break;
|
|
|
|
case KEY_HOME:
|
|
|
|
nRetCode = Qt::Key_Home;
|
|
|
|
break;
|
|
|
|
case KEY_END:
|
|
|
|
nRetCode = Qt::Key_End;
|
|
|
|
break;
|
|
|
|
case KEY_PAGEUP:
|
|
|
|
nRetCode = Qt::Key_PageUp;
|
|
|
|
break;
|
|
|
|
case KEY_PAGEDOWN:
|
|
|
|
nRetCode = Qt::Key_PageDown;
|
|
|
|
break;
|
|
|
|
case KEY_RETURN:
|
|
|
|
nRetCode = Qt::Key_Return;
|
|
|
|
break;
|
|
|
|
case KEY_ESCAPE:
|
|
|
|
nRetCode = Qt::Key_Escape;
|
|
|
|
break;
|
|
|
|
case KEY_TAB:
|
|
|
|
nRetCode = Qt::Key_Tab;
|
|
|
|
break;
|
|
|
|
case KEY_BACKSPACE:
|
|
|
|
nRetCode = Qt::Key_Backspace;
|
|
|
|
break;
|
|
|
|
case KEY_SPACE:
|
|
|
|
nRetCode = Qt::Key_Space;
|
|
|
|
break;
|
|
|
|
case KEY_INSERT:
|
|
|
|
nRetCode = Qt::Key_Insert;
|
|
|
|
break;
|
|
|
|
case KEY_DELETE:
|
|
|
|
nRetCode = Qt::Key_Delete;
|
|
|
|
break;
|
|
|
|
case KEY_ADD:
|
|
|
|
nRetCode = Qt::Key_Plus;
|
|
|
|
break;
|
|
|
|
case KEY_SUBTRACT:
|
|
|
|
nRetCode = Qt::Key_Minus;
|
|
|
|
break;
|
|
|
|
case KEY_MULTIPLY:
|
|
|
|
nRetCode = Qt::Key_Asterisk;
|
|
|
|
break;
|
|
|
|
case KEY_DIVIDE:
|
|
|
|
nRetCode = Qt::Key_Slash;
|
|
|
|
break;
|
|
|
|
case KEY_POINT:
|
|
|
|
nRetCode = Qt::Key_Period;
|
|
|
|
break;
|
|
|
|
case KEY_COMMA:
|
|
|
|
nRetCode = Qt::Key_Comma;
|
|
|
|
break;
|
|
|
|
case KEY_LESS:
|
|
|
|
nRetCode = Qt::Key_Less;
|
|
|
|
break;
|
|
|
|
case KEY_GREATER:
|
|
|
|
nRetCode = Qt::Key_Greater;
|
|
|
|
break;
|
|
|
|
case KEY_EQUAL:
|
|
|
|
nRetCode = Qt::Key_Equal;
|
|
|
|
break;
|
|
|
|
case KEY_FIND:
|
|
|
|
nRetCode = Qt::Key_Find;
|
|
|
|
break;
|
|
|
|
case KEY_CONTEXTMENU:
|
|
|
|
nRetCode = Qt::Key_Menu;
|
|
|
|
break;
|
|
|
|
case KEY_HELP:
|
|
|
|
nRetCode = Qt::Key_Help;
|
|
|
|
break;
|
|
|
|
case KEY_UNDO:
|
|
|
|
nRetCode = Qt::Key_Undo;
|
|
|
|
break;
|
|
|
|
case KEY_REPEAT:
|
|
|
|
nRetCode = Qt::Key_Redo;
|
|
|
|
break;
|
|
|
|
case KEY_TILDE:
|
|
|
|
nRetCode = Qt::Key_AsciiTilde;
|
|
|
|
break;
|
|
|
|
case KEY_QUOTELEFT:
|
|
|
|
nRetCode = Qt::Key_QuoteLeft;
|
|
|
|
break;
|
|
|
|
case KEY_BRACKETLEFT:
|
|
|
|
nRetCode = Qt::Key_BracketLeft;
|
|
|
|
break;
|
|
|
|
case KEY_BRACKETRIGHT:
|
|
|
|
nRetCode = Qt::Key_BracketRight;
|
|
|
|
break;
|
2023-10-04 15:01:38 +03:00
|
|
|
case KEY_NUMBERSIGN:
|
|
|
|
nRetCode = Qt::Key_NumberSign;
|
|
|
|
break;
|
2023-12-03 11:07:23 +01:00
|
|
|
case KEY_XF86FORWARD:
|
|
|
|
nRetCode = Qt::Key_Forward;
|
|
|
|
break;
|
|
|
|
case KEY_XF86BACK:
|
|
|
|
nRetCode = Qt::Key_Back;
|
|
|
|
break;
|
2020-01-13 20:29:20 +01:00
|
|
|
case KEY_COLON:
|
|
|
|
nRetCode = Qt::Key_Colon;
|
|
|
|
break;
|
2018-10-23 15:46:09 +02:00
|
|
|
case KEY_SEMICOLON:
|
|
|
|
nRetCode = Qt::Key_Semicolon;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Special cases
|
|
|
|
case KEY_COPY:
|
|
|
|
nRetCode = Qt::Key_Copy;
|
|
|
|
break;
|
|
|
|
case KEY_CUT:
|
|
|
|
nRetCode = Qt::Key_Cut;
|
|
|
|
break;
|
|
|
|
case KEY_PASTE:
|
|
|
|
nRetCode = Qt::Key_Paste;
|
|
|
|
break;
|
|
|
|
case KEY_OPEN:
|
|
|
|
nRetCode = Qt::Key_Open;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vclKeyCode.IsShift())
|
|
|
|
nRetCode += Qt::SHIFT;
|
|
|
|
if (vclKeyCode.IsMod1())
|
|
|
|
nRetCode += Qt::CTRL;
|
|
|
|
if (vclKeyCode.IsMod2())
|
|
|
|
nRetCode += Qt::ALT;
|
|
|
|
|
|
|
|
QKeySequence keySeq(nRetCode);
|
|
|
|
OUString sKeyName = toOUString(keySeq.toString());
|
|
|
|
|
|
|
|
return sKeyName;
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
bool QtFrame::MapUnicodeToKeyCode(sal_Unicode /*aUnicode*/, LanguageType /*aLangType*/,
|
|
|
|
vcl::KeyCode& /*rKeyCode*/)
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2018-09-04 09:17:11 +02:00
|
|
|
// not supported yet
|
2017-10-21 13:50:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
LanguageType QtFrame::GetInputLanguage() { return m_nInputLanguage; }
|
Qt5 report input method language
This is in the spirit of tdf#108151, based on the information Qt
provides for the IM setting. I don't know how correct it is,
especially looking at Caolans comment 3 in that bug report
regarding the assumed validity of GtkIMContextInfo. OTOH it seems
to work well enough for my simple tests.
Some BG info: while the QInputMethod object is a global one, it's
"bound" to the focused window. So you'll get change events, when
you change the input window, with the correct IM settings for the
new one, be it a real window or just the menu bar.
To prevent unneeded flushes of buffers and language lookup, this
caches the current IM language of a window.
The language is not affected just by changing keyboard mappings,
which the bug reporter requested! It just works with a configured
input method, like fcitx or ibus (which can have keyboard mappings
too, which work correctly).
Change-Id: Ia9133edf4d1ce77d29adbfe57c180db15db0a560
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106354
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-11-22 14:53:14 +01:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::setInputLanguage(LanguageType nInputLanguage)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
Qt5 report input method language
This is in the spirit of tdf#108151, based on the information Qt
provides for the IM setting. I don't know how correct it is,
especially looking at Caolans comment 3 in that bug report
regarding the assumed validity of GtkIMContextInfo. OTOH it seems
to work well enough for my simple tests.
Some BG info: while the QInputMethod object is a global one, it's
"bound" to the focused window. So you'll get change events, when
you change the input window, with the correct IM settings for the
new one, be it a real window or just the menu bar.
To prevent unneeded flushes of buffers and language lookup, this
caches the current IM language of a window.
The language is not affected just by changing keyboard mappings,
which the bug reporter requested! It just works with a configured
input method, like fcitx or ibus (which can have keyboard mappings
too, which work correctly).
Change-Id: Ia9133edf4d1ce77d29adbfe57c180db15db0a560
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106354
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-11-22 14:53:14 +01:00
|
|
|
if (nInputLanguage == m_nInputLanguage)
|
|
|
|
return;
|
|
|
|
m_nInputLanguage = nInputLanguage;
|
|
|
|
CallCallback(SalEvent::InputLanguageChange, nullptr);
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2018-08-09 14:51:41 +02:00
|
|
|
static Color toColor(const QColor& rColor)
|
|
|
|
{
|
|
|
|
return Color(rColor.red(), rColor.green(), rColor.blue());
|
|
|
|
}
|
|
|
|
|
2022-05-02 08:50:33 +02:00
|
|
|
static bool toVclFont(const QFont& rQFont, const css::lang::Locale& rLocale, vcl::Font& rVclFont)
|
|
|
|
{
|
2023-08-01 16:38:14 +00:00
|
|
|
FontAttributes aFA;
|
|
|
|
QtFontFace::fillAttributesFromQFont(rQFont, aFA);
|
2022-05-02 08:50:33 +02:00
|
|
|
|
2023-08-01 16:38:14 +00:00
|
|
|
bool bFound = psp::PrintFontManager::get().matchFont(aFA, rLocale);
|
2022-05-02 08:50:33 +02:00
|
|
|
SAL_INFO("vcl.qt", "font match result for '"
|
2023-08-01 16:38:14 +00:00
|
|
|
<< rQFont.family() << "': "
|
|
|
|
<< (bFound ? OUString::Concat("'") + aFA.GetFamilyName() + "'"
|
|
|
|
: OUString("failed")));
|
2022-05-02 08:50:33 +02:00
|
|
|
|
2023-08-01 16:38:14 +00:00
|
|
|
if (!bFound)
|
2022-05-02 08:50:33 +02:00
|
|
|
return false;
|
|
|
|
|
2023-08-01 16:38:14 +00:00
|
|
|
QFontInfo qFontInfo(rQFont);
|
2022-05-02 08:50:33 +02:00
|
|
|
int nPointHeight = qFontInfo.pointSize();
|
|
|
|
if (nPointHeight <= 0)
|
|
|
|
nPointHeight = rQFont.pointSize();
|
|
|
|
|
2023-08-01 16:38:14 +00:00
|
|
|
vcl::Font aFont(aFA.GetFamilyName(), Size(0, nPointHeight));
|
|
|
|
if (aFA.GetWeight() != WEIGHT_DONTKNOW)
|
|
|
|
aFont.SetWeight(aFA.GetWeight());
|
|
|
|
if (aFA.GetWidthType() != WIDTH_DONTKNOW)
|
|
|
|
aFont.SetWidthType(aFA.GetWidthType());
|
|
|
|
if (aFA.GetItalic() != ITALIC_DONTKNOW)
|
|
|
|
aFont.SetItalic(aFA.GetItalic());
|
|
|
|
if (aFA.GetPitch() != PITCH_DONTKNOW)
|
|
|
|
aFont.SetPitch(aFA.GetPitch());
|
2022-05-02 08:50:33 +02:00
|
|
|
|
|
|
|
rVclFont = aFont;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::UpdateSettings(AllSettings& rSettings)
|
2017-12-08 11:37:18 +00:00
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
if (QtData::noNativeControls())
|
2018-08-09 14:45:49 +02:00
|
|
|
return;
|
|
|
|
|
2017-12-08 11:37:18 +00:00
|
|
|
StyleSettings style(rSettings.GetStyleSettings());
|
2022-05-02 08:50:33 +02:00
|
|
|
const css::lang::Locale aLocale = rSettings.GetUILanguageTag().getLocale();
|
2017-12-08 11:37:18 +00:00
|
|
|
|
2018-08-09 14:51:41 +02:00
|
|
|
// General settings
|
|
|
|
QPalette pal = QApplication::palette();
|
|
|
|
|
|
|
|
style.SetToolbarIconSize(ToolbarIconSize::Large);
|
|
|
|
|
|
|
|
Color aFore = toColor(pal.color(QPalette::Active, QPalette::WindowText));
|
|
|
|
Color aBack = toColor(pal.color(QPalette::Active, QPalette::Window));
|
|
|
|
Color aText = toColor(pal.color(QPalette::Active, QPalette::Text));
|
|
|
|
Color aBase = toColor(pal.color(QPalette::Active, QPalette::Base));
|
|
|
|
Color aButn = toColor(pal.color(QPalette::Active, QPalette::ButtonText));
|
2020-10-23 18:43:25 +02:00
|
|
|
Color aMid = toColor(pal.color(QPalette::Active, QPalette::Mid));
|
2018-08-09 14:51:41 +02:00
|
|
|
Color aHigh = toColor(pal.color(QPalette::Active, QPalette::Highlight));
|
|
|
|
Color aHighText = toColor(pal.color(QPalette::Active, QPalette::HighlightedText));
|
2019-03-23 16:02:38 +00:00
|
|
|
Color aLink = toColor(pal.color(QPalette::Active, QPalette::Link));
|
|
|
|
Color aVisitedLink = toColor(pal.color(QPalette::Active, QPalette::LinkVisited));
|
2018-08-09 14:51:41 +02:00
|
|
|
|
|
|
|
style.SetSkipDisabledInMenus(true);
|
|
|
|
|
|
|
|
// Foreground
|
|
|
|
style.SetRadioCheckTextColor(aFore);
|
|
|
|
style.SetLabelTextColor(aFore);
|
|
|
|
style.SetDialogTextColor(aFore);
|
|
|
|
style.SetGroupTextColor(aFore);
|
|
|
|
|
|
|
|
// Text
|
|
|
|
style.SetFieldTextColor(aText);
|
|
|
|
style.SetFieldRolloverTextColor(aText);
|
2022-07-01 10:45:13 +02:00
|
|
|
style.SetListBoxWindowTextColor(aText);
|
2018-08-09 14:51:41 +02:00
|
|
|
style.SetWindowTextColor(aText);
|
|
|
|
style.SetToolTextColor(aText);
|
|
|
|
|
|
|
|
// Base
|
|
|
|
style.SetFieldColor(aBase);
|
|
|
|
style.SetWindowColor(aBase);
|
|
|
|
style.SetActiveTabColor(aBase);
|
2022-07-01 10:45:13 +02:00
|
|
|
style.SetListBoxWindowBackgroundColor(aBase);
|
2020-10-19 20:46:05 +02:00
|
|
|
style.SetAlternatingRowColor(toColor(pal.color(QPalette::Active, QPalette::AlternateBase)));
|
2018-08-09 14:51:41 +02:00
|
|
|
|
|
|
|
// Buttons
|
2020-02-23 21:11:05 +01:00
|
|
|
style.SetDefaultButtonTextColor(aButn);
|
2018-08-09 14:51:41 +02:00
|
|
|
style.SetButtonTextColor(aButn);
|
2019-11-10 12:34:54 +01:00
|
|
|
style.SetDefaultActionButtonTextColor(aButn);
|
|
|
|
style.SetActionButtonTextColor(aButn);
|
2020-02-23 21:11:05 +01:00
|
|
|
style.SetFlatButtonTextColor(aButn);
|
|
|
|
style.SetDefaultButtonRolloverTextColor(aButn);
|
2018-08-09 14:51:41 +02:00
|
|
|
style.SetButtonRolloverTextColor(aButn);
|
2020-02-23 21:11:05 +01:00
|
|
|
style.SetDefaultActionButtonRolloverTextColor(aButn);
|
|
|
|
style.SetActionButtonRolloverTextColor(aButn);
|
|
|
|
style.SetFlatButtonRolloverTextColor(aButn);
|
|
|
|
style.SetDefaultButtonPressedRolloverTextColor(aButn);
|
2018-08-09 14:51:41 +02:00
|
|
|
style.SetButtonPressedRolloverTextColor(aButn);
|
2020-02-23 21:11:05 +01:00
|
|
|
style.SetDefaultActionButtonPressedRolloverTextColor(aButn);
|
|
|
|
style.SetActionButtonPressedRolloverTextColor(aButn);
|
|
|
|
style.SetFlatButtonPressedRolloverTextColor(aButn);
|
2018-08-09 14:51:41 +02:00
|
|
|
|
|
|
|
// Tabs
|
|
|
|
style.SetTabTextColor(aButn);
|
|
|
|
style.SetTabRolloverTextColor(aButn);
|
|
|
|
style.SetTabHighlightTextColor(aButn);
|
|
|
|
|
|
|
|
// Disable color
|
|
|
|
style.SetDisableColor(toColor(pal.color(QPalette::Disabled, QPalette::WindowText)));
|
|
|
|
|
|
|
|
// Background
|
|
|
|
style.BatchSetBackgrounds(aBack);
|
|
|
|
style.SetInactiveTabColor(aBack);
|
|
|
|
|
2020-10-23 18:43:25 +02:00
|
|
|
// Workspace
|
|
|
|
style.SetWorkspaceColor(aMid);
|
|
|
|
|
2018-08-09 14:51:41 +02:00
|
|
|
// Selection
|
2023-05-17 16:48:30 +02:00
|
|
|
// https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/305
|
|
|
|
style.SetAccentColor(aHigh);
|
2018-08-09 14:51:41 +02:00
|
|
|
style.SetHighlightColor(aHigh);
|
|
|
|
style.SetHighlightTextColor(aHighText);
|
2022-07-01 10:45:13 +02:00
|
|
|
style.SetListBoxWindowHighlightColor(aHigh);
|
|
|
|
style.SetListBoxWindowHighlightTextColor(aHighText);
|
2020-10-23 18:43:25 +02:00
|
|
|
style.SetActiveColor(aHigh);
|
|
|
|
style.SetActiveTextColor(aHighText);
|
2018-08-09 14:51:41 +02:00
|
|
|
|
2019-03-23 16:02:38 +00:00
|
|
|
// Links
|
|
|
|
style.SetLinkColor(aLink);
|
|
|
|
style.SetVisitedLinkColor(aVisitedLink);
|
|
|
|
|
2018-08-09 14:51:41 +02:00
|
|
|
// Tooltip
|
|
|
|
style.SetHelpColor(toColor(QToolTip::palette().color(QPalette::Active, QPalette::ToolTipBase)));
|
|
|
|
style.SetHelpTextColor(
|
|
|
|
toColor(QToolTip::palette().color(QPalette::Active, QPalette::ToolTipText)));
|
|
|
|
|
|
|
|
// Menu
|
2019-04-12 14:17:20 +02:00
|
|
|
std::unique_ptr<QMenuBar> pMenuBar = std::make_unique<QMenuBar>();
|
2018-08-09 14:51:41 +02:00
|
|
|
QPalette qMenuCG = pMenuBar->palette();
|
|
|
|
|
|
|
|
// Menu text and background color, theme specific
|
|
|
|
Color aMenuFore = toColor(qMenuCG.color(QPalette::WindowText));
|
|
|
|
Color aMenuBack = toColor(qMenuCG.color(QPalette::Window));
|
|
|
|
|
|
|
|
style.SetMenuTextColor(aMenuFore);
|
2019-11-28 17:24:25 +01:00
|
|
|
style.SetMenuBarTextColor(style.GetPersonaMenuBarTextColor().value_or(aMenuFore));
|
2018-08-09 14:51:41 +02:00
|
|
|
style.SetMenuColor(aMenuBack);
|
|
|
|
style.SetMenuBarColor(aMenuBack);
|
|
|
|
style.SetMenuHighlightColor(toColor(qMenuCG.color(QPalette::Highlight)));
|
|
|
|
style.SetMenuHighlightTextColor(toColor(qMenuCG.color(QPalette::HighlightedText)));
|
|
|
|
|
|
|
|
// set special menubar highlight text color
|
|
|
|
if (QApplication::style()->inherits("HighContrastStyle"))
|
|
|
|
ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor
|
|
|
|
= toColor(qMenuCG.color(QPalette::HighlightedText));
|
|
|
|
else
|
|
|
|
ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = aMenuFore;
|
|
|
|
|
|
|
|
// set menubar rollover color
|
|
|
|
if (pMenuBar->style()->styleHint(QStyle::SH_MenuBar_MouseTracking))
|
|
|
|
{
|
|
|
|
style.SetMenuBarRolloverColor(toColor(qMenuCG.color(QPalette::Highlight)));
|
|
|
|
style.SetMenuBarRolloverTextColor(ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
style.SetMenuBarRolloverColor(aMenuBack);
|
|
|
|
style.SetMenuBarRolloverTextColor(aMenuFore);
|
|
|
|
}
|
|
|
|
style.SetMenuBarHighlightTextColor(style.GetMenuHighlightTextColor());
|
|
|
|
|
2022-05-02 08:50:33 +02:00
|
|
|
// Default fonts
|
|
|
|
vcl::Font aFont;
|
|
|
|
if (toVclFont(QApplication::font(), aLocale, aFont))
|
|
|
|
{
|
|
|
|
style.BatchSetFonts(aFont, aFont);
|
|
|
|
aFont.SetWeight(WEIGHT_BOLD);
|
|
|
|
style.SetTitleFont(aFont);
|
|
|
|
style.SetFloatTitleFont(aFont);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tooltip font
|
|
|
|
if (toVclFont(QToolTip::font(), aLocale, aFont))
|
|
|
|
style.SetHelpFont(aFont);
|
|
|
|
|
|
|
|
// Menu bar font
|
|
|
|
if (toVclFont(pMenuBar->font(), aLocale, aFont))
|
|
|
|
style.SetMenuFont(aFont);
|
|
|
|
|
2020-05-22 16:32:27 +03:00
|
|
|
// Icon theme
|
2023-09-02 10:37:47 +02:00
|
|
|
const bool bPreferDarkTheme = GetUseDarkMode();
|
tdf#156894 qt: Prefer dark icon theme in dark mode
When in dark mode, pass the param to prefer a dark
icon theme to
`StyleSettings::SetPreferredIconTheme`.
For Qt >= 6.5 use `QStyleHints::colorScheme`
introduced in Qt 6.5 to get the color scheme.
For older Qt versions, use the same algorithm based
on the gray value of the window background as
xdg-desktop-portal-kde does for evaluating whether
a light or dark color scheme is preferred [1].
On my Debian testing, the Breeze dark icon theme is
now used as expected with kf5 or qt6 when setting
the Global KDE Plasma theme to "Breeze Dark" and
manually setting the Icon theme to "GNOME" afterwards.
Previously, this would not use a dark icon theme and
icons would be hard to see.
Without manually setting the icon theme to "GNOME",
the Breeze Dark icon theme would already be used
before, because selecting "Breeze Dark" as the
global KDE Plasma theme also selects the "Breeze Dark"
icon theme by default, and therefore "breeze-dark"
was already passed as the first param to
`StyleSettings::SetPreferredIconTheme` and since
that icon theme is present, the `bPreferDarkTheme`
wouldn't be evaluated at all; it's only used
when determining the fallback icon theme when
the specified icon theme is not present.
(Likewise, by enabling the "Breeze Dark" global theme
and then manually setting the icon theme to "Breeze"
in Plasma System settings, the Breeze light icon theme
will be used in LibreOffice as well, resulting in hard
to see icons, but I tend to think that that behavior is
correct and works as designed - it's a misconfiguration.)
The color scheme is also specified in xdg-desktop-portal
(s. commit [2]) and can be retrived via dbus.
Example with "Breeze Light" active:
$ dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'
variant variant uint32 2
With "Breeze Dark":
$ dbus-send --session --print-reply=literal --reply-timeout=1000 --dest=org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read string:'org.freedesktop.appearance' string:'color-scheme'
variant variant uint32 1
[1] https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/blob/0a4237549debf9518f8cfbaf531456850c0729bd/src/settings.cpp#L213-227
[2] https://github.com/flatpak/xdg-desktop-portal/commit/d7a304a00697d7d608821253cd013f3b97ac0fb6
Change-Id: I8f347c6e7f775cc55377c5c84481de3051c3cf24
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156465
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-02 10:12:54 +02:00
|
|
|
style.SetPreferredIconTheme(toOUString(QIcon::themeName()), bPreferDarkTheme);
|
2020-05-22 16:32:27 +03:00
|
|
|
|
2018-08-09 14:51:41 +02:00
|
|
|
// Scroll bar size
|
|
|
|
style.SetScrollBarSize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent));
|
|
|
|
style.SetMinThumbSize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarSliderMin));
|
|
|
|
|
|
|
|
// These colors are used for the ruler text and marks
|
|
|
|
style.SetShadowColor(toColor(pal.color(QPalette::Disabled, QPalette::WindowText)));
|
|
|
|
style.SetDarkShadowColor(toColor(pal.color(QPalette::Inactive, QPalette::WindowText)));
|
|
|
|
|
2022-05-02 08:50:33 +02:00
|
|
|
// Cursor blink interval
|
|
|
|
int nFlashTime = QApplication::cursorFlashTime();
|
|
|
|
style.SetCursorBlinkTime(nFlashTime != 0 ? nFlashTime / 2 : STYLE_CURSOR_NOBLINKTIME);
|
|
|
|
|
2017-12-08 11:37:18 +00:00
|
|
|
rSettings.SetStyleSettings(style);
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::Beep() { QApplication::beep(); }
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
SalFrame::SalPointerState QtFrame::GetPointerState()
|
2017-10-21 13:50:30 +00:00
|
|
|
{
|
2017-10-30 19:55:18 +01:00
|
|
|
SalPointerState aState;
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
aState.maPos = toPoint(QCursor::pos() * devicePixelRatioF());
|
2022-06-02 22:42:20 +02:00
|
|
|
aState.maPos.Move(-maGeometry.x(), -maGeometry.y());
|
2018-01-08 09:40:00 +02:00
|
|
|
aState.mnState = GetMouseModCode(QGuiApplication::mouseButtons())
|
|
|
|
| GetKeyModCode(QGuiApplication::keyboardModifiers());
|
2017-10-30 19:55:18 +01:00
|
|
|
return aState;
|
2017-10-21 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
KeyIndicatorState QtFrame::GetIndicatorState() { return KeyIndicatorState(); }
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SimulateKeyPress(sal_uInt16 nKeyCode)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2021-10-22 14:41:21 +02:00
|
|
|
SAL_WARN("vcl.qt", "missing simulate keypress " << nKeyCode);
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
tdf#144585 Qt fix Wayland LO fake popups
So Michael Weghorn was somehow reminded of an abandoned
commit from me ("Qt5 rework parent handling") archived in
https://gerrit.libreoffice.org/c/core/+/73463.
The bug introducing the new QWidget parenting, tdf#145363, was
resolved in a better way by explicitly setting parents for the
modal dialogs, so LO doesn't break Qt anymore. The actual problem
is, that an additional modal dialog needs to be stacked to the
previous modal dialog; no "parallel" modal dialogs are allowed,
which my original fix tried to enforce by reparenting.
Then there is the problem with Qt::Popup's focus grabbing on show,
which breaks LO's editable ComboBox. So LO's popup / FLOAT windows
are mapped to Qt::ToolTip, which are automatically advertised as
tooltips via accessibility. For X11 / xcb, Qt:Window with the
Qt::BypassWindowManagerHint works well enough as an alternative,
but WASM and Wayland don't seem to implement it correctly, so this
just handles popups as Qt::ToolTip on all platforms.
This reverts commit b00a68a8e19370e106cd76258a3c1825f43613ee
("tdf#145363 Qt reparent modal dialogs on show").
In addition the popup widgets are switched back to Qt::ToolTip.
Change-Id: If726771b4e9cc3f639f21cf502b3ec5985873643
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132526
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2022-04-04 18:02:28 +02:00
|
|
|
// don't set QWidget parents; this breaks popups on Wayland, like the LO ComboBox or ColorPicker!
|
|
|
|
void QtFrame::SetParent(SalFrame* pNewParent) { m_pParent = static_cast<QtFrame*>(pNewParent); }
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetPluginParent(SystemParentData* /*pNewParent*/)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2019-07-09 15:28:29 +00:00
|
|
|
//FIXME: no SetPluginParent impl. for qt5
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::ResetClipRegion() { m_bNullRegion = true; }
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::BeginSetClipRegion(sal_uInt32)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
|
|
|
m_aRegion = QRegion(QRect(QPoint(0, 0), m_pQWidget->size()));
|
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::UnionClipRegion(tools::Long nX, tools::Long nY, tools::Long nWidth,
|
|
|
|
tools::Long nHeight)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
m_aRegion
|
|
|
|
= m_aRegion.united(scaledQRect(QRect(nX, nY, nWidth, nHeight), 1 / devicePixelRatioF()));
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::EndSetClipRegion() { m_bNullRegion = false; }
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetScreenNumber(unsigned int nScreen)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2020-08-04 09:22:10 +02:00
|
|
|
if (!isWindow())
|
|
|
|
return;
|
|
|
|
|
|
|
|
QWindow* const pWindow = windowHandle();
|
|
|
|
if (!pWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
QList<QScreen*> screens = QApplication::screens();
|
|
|
|
if (static_cast<int>(nScreen) < screens.size() || m_bFullScreenSpanAll)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2020-08-04 09:22:10 +02:00
|
|
|
QRect screenGeo;
|
2019-05-29 19:01:28 +02:00
|
|
|
|
2020-08-04 09:22:10 +02:00
|
|
|
if (!m_bFullScreenSpanAll)
|
|
|
|
{
|
2021-09-24 06:39:09 +02:00
|
|
|
screenGeo = QGuiApplication::screens().at(nScreen)->geometry();
|
2020-08-04 09:22:10 +02:00
|
|
|
pWindow->setScreen(QApplication::screens()[nScreen]);
|
|
|
|
}
|
|
|
|
else // special case: fullscreen over all available screens
|
|
|
|
{
|
|
|
|
assert(m_bFullScreen);
|
|
|
|
// left-most screen
|
2021-09-24 06:39:09 +02:00
|
|
|
QScreen* pScreen = QGuiApplication::screenAt(QPoint(0, 0));
|
2020-08-04 09:22:10 +02:00
|
|
|
// entire virtual desktop
|
2021-09-24 06:39:09 +02:00
|
|
|
screenGeo = pScreen->availableVirtualGeometry();
|
|
|
|
pWindow->setScreen(pScreen);
|
2020-08-04 09:22:10 +02:00
|
|
|
pWindow->setGeometry(screenGeo);
|
2021-09-24 06:39:09 +02:00
|
|
|
nScreen = screenNumber(pScreen);
|
2018-10-22 16:35:21 +02:00
|
|
|
}
|
2020-08-04 09:22:10 +02:00
|
|
|
|
|
|
|
// setScreen by itself has no effect, explicitly move the widget to
|
|
|
|
// the new screen
|
|
|
|
asChild()->move(screenGeo.topLeft());
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2020-08-04 09:22:10 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// index outta bounds, use primary screen
|
|
|
|
QScreen* primaryScreen = QApplication::primaryScreen();
|
|
|
|
pWindow->setScreen(primaryScreen);
|
|
|
|
nScreen = static_cast<sal_uInt32>(screenNumber(primaryScreen));
|
|
|
|
}
|
|
|
|
|
2022-06-02 22:42:20 +02:00
|
|
|
maGeometry.setScreen(nScreen);
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::SetApplicationID(const OUString& rWMClass)
|
2018-09-04 09:17:11 +02:00
|
|
|
{
|
2021-12-01 08:53:25 +01:00
|
|
|
#if CHECK_QT5_USING_X11
|
2022-05-24 18:14:16 +02:00
|
|
|
assert(m_aSystemData.platform != SystemEnvData::Platform::Invalid);
|
2021-11-17 13:03:23 +01:00
|
|
|
if (m_aSystemData.platform != SystemEnvData::Platform::Xcb || !m_pTopLevel)
|
2019-06-14 00:46:32 +00:00
|
|
|
return;
|
|
|
|
|
2022-06-15 23:34:01 +02:00
|
|
|
QtX11Support::setApplicationID(m_pTopLevel->winId(), rWMClass);
|
2019-06-14 00:46:32 +00:00
|
|
|
#else
|
2022-06-15 23:34:01 +02:00
|
|
|
Q_UNUSED(rWMClass);
|
2019-06-14 00:46:32 +00:00
|
|
|
#endif
|
2018-09-04 09:17:11 +02:00
|
|
|
}
|
2017-10-21 13:50:30 +00:00
|
|
|
|
2021-11-17 13:26:09 +01:00
|
|
|
void QtFrame::ResolveWindowHandle(SystemEnvData& rData) const
|
|
|
|
{
|
|
|
|
if (!rData.pWidget)
|
|
|
|
return;
|
2022-05-24 18:14:16 +02:00
|
|
|
assert(rData.platform != SystemEnvData::Platform::Invalid);
|
2021-11-17 13:26:09 +01:00
|
|
|
if (rData.platform != SystemEnvData::Platform::Wayland)
|
|
|
|
rData.SetWindowHandle(static_cast<QWidget*>(rData.pWidget)->winId());
|
|
|
|
}
|
|
|
|
|
tdf#155414 kf a11y: Honor KDE Plasma setting to reduce animation
When using the kf5/kf6 VCL plugin on KDE Plasma, use the animation speed
setting to determine whether animations should be disabled, in line with
what is documented in MDN docs for Firefox using for the
"prefers-reduced-motion" CSS media feature [1] and how
kde-gtk-config maps that to the "gtk-enable-animations" setting [2].
The setting can be set as described in [2]:
> In Plasma/KDE: System Settings > Workspace Behavior -> General Behavior >
> "Animation speed" is set all the way to right to "Instant".
On top of
commit 9d68c794d67259a38de1465090f6f1e7fb588d62
Author: Patrick Luby <plubius@neooffice.org>
Date: Fri Jul 21 19:55:02 2023 -0400
tdf#155414 include system "reduce animation" preferences
, this basically implements the KF5/KDE Plasma equivalent of what that change does
for macOS.
Other than Gtk, Qt does not seem to have a general way to specify
that animations should be reduced/disabled, so evaluate
that based on the desktop environment instead, and implement
for KDE Plasma for the kf5/kf6 VCL plugin only for now, which is
probably the most common use case.
Logically, this would better fit in the qt5/qt6 VCL plugin
than the kf5/kf6 one, but do it in the KF-specific code to avoid
a dependency on KF5/KF6 libraries in qt5/qt6. (And other than
qt5/qt6, kf5/kf6 are auto-selected in Qt-based desktop environments,
so it shouldn't make much of a difference in practice.)
Another alternative - should the need aries - might be to move this
from the VCL plugin to the desktop backend (`shell/source/backends/kf5be/`
for the case of KDE Plasma 5.) and introduce a new property for that.
[1] https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
[2] https://docs.gtk.org/gtk4/property.Settings.gtk-enable-animations.html
[3] https://invent.kde.org/plasma/kde-gtk-config/-/blob/881ae01ad361a03396f7f327365f225ef87688e8/kded/gtkconfig.cpp#L205
Change-Id: I35cd6c2568a3716491581e51dfaeaf32cad454aa
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154888
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-07-25 11:52:32 +02:00
|
|
|
bool QtFrame::GetUseReducedAnimation() const { return GetQtInstance()->GetUseReducedAnimation(); }
|
|
|
|
|
2018-10-04 17:12:40 +02:00
|
|
|
// Drag'n'drop foo
|
2018-12-03 16:40:27 +01:00
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::registerDragSource(QtDragSource* pDragSource)
|
2018-10-04 17:12:40 +02:00
|
|
|
{
|
|
|
|
assert(!m_pDragSource);
|
|
|
|
m_pDragSource = pDragSource;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::deregisterDragSource(QtDragSource const* pDragSource)
|
2018-10-04 17:12:40 +02:00
|
|
|
{
|
|
|
|
assert(m_pDragSource == pDragSource);
|
|
|
|
(void)pDragSource;
|
|
|
|
m_pDragSource = nullptr;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::registerDropTarget(QtDropTarget* pDropTarget)
|
2018-10-04 17:12:40 +02:00
|
|
|
{
|
|
|
|
assert(!m_pDropTarget);
|
|
|
|
m_pDropTarget = pDropTarget;
|
qt: Set window title etc. in main thread
These QWidget methods need to be called
in the main thread.
Otherwise, opening the Update dialog
("Help" -> "Check for Updates", enabled
by `--enable-online-update` autogen switch)
triggers asserts like the one below with
a self-compiled Qt 6 development build
(qtbase dev branch as of
c802a9e987c9e38c01580f467eab92a651b3e033).
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp, line 537
Thread 40 "InitUpdateCheck" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff7ffff6c0 (LWP 1516868)]
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007ffff78a815f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 0x00007ffff785a472 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007ffff78444b2 in __GI_abort () at ./stdlib/abort.c:79
#4 0x00007fffe32eb45a in qAbort() () at /home/michi/development/git/qt5/qtbase/src/corelib/global/qglobal.cpp:161
#5 0x00007fffe32f9ee5 in qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&) (context=..., message=...) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:2057
#6 0x00007fffe32f620c in QMessageLogger::fatal(char const*, ...) const (this=0x7fff7fffb980, msg=0x7fffe37fd9a0 "ASSERT failure in %s: \"%s\", file %s, line %d")
at /home/michi/development/git/qt5/qtbase/src/corelib/global/qlogging.cpp:938
#7 0x00007fffe32e9d54 in qt_assert_x(char const*, char const*, char const*, int)
(where=0x7fffe38131e9 "QCoreApplication::sendEvent", what=0x7fff78180110 "Cannot send events to objects owned by a different thread. Current thread 0x0x7fff780160e0. Receiver '' (of type 'QtWidget') was created in thread 0x0x5555555fcd30", file=0x7fffe3812e18 "/home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp", line=537) at /home/michi/development/git/qt5/qtbase/src/corelib/global/qassert.cpp:77
#8 0x00007fffe33a4d74 in QCoreApplicationPrivate::checkReceiverThread(QObject*) (receiver=0x55555d27d5d0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:537
#9 0x00007fffe19a3a81 in QApplication::notify(QObject*, QEvent*) (this=0x5555555fcb80, receiver=0x55555d27d5d0, e=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2584
#10 0x00007fffe33a5ed0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1125
#11 0x00007fffe33a6991 in QCoreApplication::sendEvent(QObject*, QEvent*) (receiver=0x55555d27d5d0, event=0x7fff7fffc0b0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1559
#12 0x00007fffe1a279b4 in QWidget::setWindowTitle(QString const&) (this=0x55555d27d5d0, title=...) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidget.cpp:6119
#13 0x00007fffe3c9d4c4 in QtFrame::SetTitle(rtl::OUString const&) (this=0x555555619d20, rTitle="Check for Updates") at /home/michi/development/git/libreoffice/vcl/qt6/../qt5/QtFrame.cxx:365
#14 0x00007fffedd98d44 in vcl::Window::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/window.cxx:3042
#15 0x00007fffedd311c9 in SystemWindow::SetText(rtl::OUString const&) (this=0x7fff7803cd90, rStr="Check for Updates") at /home/michi/development/git/libreoffice/vcl/source/window/syswin.cxx:1048
#16 0x00007ffff048bd6b in VCLXWindow::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindow.cxx:1515
#17 0x00007ffff03e486d in VCLXContainer::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxcontainer.cxx:260
#18 0x00007ffff04dfa2c in VCLXDialog::setProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7804ac00, PropertyName="Title", Value=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/awt/vclxwindows.cxx:2364
#19 0x00007ffff06a89b7 in UnoControl::ImplSetPeerProperty(rtl::OUString const&, com::sun::star::uno::Any const&) (this=0x7fff7803b4f0, rPropName="Title", rVal=uno::Any("string": "Check for Updates"))
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:288
#20 0x00007ffff06aa701 in UnoControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:649
#21 0x00007ffff0531ae9 in ControlContainerBase::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/controlmodelcontainerbase.cxx:1600
#22 0x00007ffff0575a25 in UnoDialogControl::ImplModelPropertiesChanged(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:651
#23 0x00007ffff06a95f3 in UnoControl::propertiesChange(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyChangeEvent> const&) (this=0x7fff7803b4f0, rEvents=uno::Sequence of length 51 = {...})
at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:431
#24 0x00007ffff66bc4ee in cppu::OPropertySetHelper::firePropertiesChangeEvent(com::sun::star::uno::Sequence<rtl::OUString> const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertiesChangeListener> const&)
(this=0x7fff78006170, rPropertyNames=uno::Sequence of length 51 = {...}, rListener=uno::Reference to (UnoDialogControl *) 0x7fff7803b540) at /home/michi/development/git/libreoffice/cppuhelper/source/propshlp.cxx:961
#25 0x00007ffff06a8c6b in UnoControl::updateFromModel() (this=0x7fff7803b4f0) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:320
#26 0x00007ffff06aefc9 in UnoControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrol.cxx:1325
#27 0x00007ffff06c9905 in UnoControlContainer::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParent=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/unocontrolcontainer.cxx:727
#28 0x00007ffff057336d in UnoDialogControl::createPeer(com::sun::star::uno::Reference<com::sun::star::awt::XToolkit> const&, com::sun::star::uno::Reference<com::sun::star::awt::XWindowPeer> const&)
(this=0x7fff7803b4f0, rxToolkit=empty uno::Reference, rParentPeer=empty uno::Reference) at /home/michi/development/git/libreoffice/toolkit/source/controls/dialogcontrol.cxx:358
#29 0x00007fffb7264e62 in UpdateHandler::createDialog() (this=0x7fff78003aa0) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:1232
#30 0x00007fffb725b0e1 in UpdateHandler::setVisible(bool) (this=0x7fff78003aa0, bVisible=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatehdl.cxx:188
#31 0x00007fffb7235887 in UpdateCheck::showDialog(bool) (this=0x7fff78000b90, forceCheck=true) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheck.cxx:1171
#32 0x00007fffb7255c5e in (anonymous namespace)::InitUpdateCheckJobThread::run() (this=0x55555d192690) at /home/michi/development/git/libreoffice/extensions/source/update/check/updatecheckjob.cxx:148
#33 0x00007fffb723a74a in osl::threadFunc(void*) (param=0x55555d192690) at /home/michi/development/git/libreoffice/include/osl/thread.hxx:189
#34 0x00007ffff7f3f693 in osl_thread_start_Impl(void*) (pData=0x55555d1a68b0) at /home/michi/development/git/libreoffice/sal/osl/unx/thread.cxx:237
#35 0x00007ffff78a63ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#36 0x00007ffff7926a1c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Change-Id: I6ccdee00fe26619f201459ebbe6c4d8cf8b57b45
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156426
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-09-01 17:50:19 +02:00
|
|
|
|
|
|
|
QtInstance* pSalInst(GetQtInstance());
|
|
|
|
assert(pSalInst);
|
|
|
|
pSalInst->RunInMainThread([this]() { m_pQWidget->setAcceptDrops(true); });
|
2018-10-04 17:12:40 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::deregisterDropTarget(QtDropTarget const* pDropTarget)
|
2018-10-04 17:12:40 +02:00
|
|
|
{
|
|
|
|
assert(m_pDropTarget == pDropTarget);
|
|
|
|
(void)pDropTarget;
|
|
|
|
m_pDropTarget = nullptr;
|
|
|
|
}
|
|
|
|
|
2019-08-08 17:59:20 +00:00
|
|
|
static css::uno::Reference<css::datatransfer::XTransferable>
|
|
|
|
lcl_getXTransferable(const QMimeData* pMimeData)
|
2018-10-15 14:44:29 +02:00
|
|
|
{
|
2019-08-08 17:59:20 +00:00
|
|
|
css::uno::Reference<css::datatransfer::XTransferable> xTransferable;
|
2021-09-28 15:02:47 +02:00
|
|
|
const QtMimeData* pQtMimeData = dynamic_cast<const QtMimeData*>(pMimeData);
|
|
|
|
if (!pQtMimeData)
|
|
|
|
xTransferable = new QtDnDTransferable(pMimeData);
|
2019-08-08 17:59:20 +00:00
|
|
|
else
|
2021-09-28 15:02:47 +02:00
|
|
|
xTransferable = pQtMimeData->xTransferable();
|
2019-08-08 17:59:20 +00:00
|
|
|
return xTransferable;
|
|
|
|
}
|
2018-10-15 14:44:29 +02:00
|
|
|
|
2019-08-08 17:59:20 +00:00
|
|
|
static sal_Int8 lcl_getUserDropAction(const QDropEvent* pEvent, const sal_Int8 nSourceActions,
|
|
|
|
const QMimeData* pMimeData)
|
|
|
|
{
|
qt6: Add a qt6 VCL plugin
This adds a new "qt6" VCL plugin based on Qt 6.
Building the plugin is enabled by autogen option '--enable-qt6'
(and optionally setting 'QT6DIR' as needed).
Use the 'SAL_USE_VCLPLUGIN=qt6' environment variable
before running LO to select this VCL plugin.
Taking qt6 into account at all relevant places certainly
still requires follow-up changes, but
this builds and runs with a self-compiled
qtbase from the 'dev' git branch as of commit
3ce0672143d2eb3c3809f82998a4d71c5800d77a.
I didn't see anything obviously broken
in a quick run, but didn't test much.
This reuses and shares the qt5 VCL plugin code;
the qt6 headers and sources for now just
'#include' the qt5 ones.
Version checks are used for the code places that
need different handling to be built against Qt 6.
The build system parts in this commit were mostly done by
copying the qt5 equivalents, then adapting as needed.
Some notes on things I came across while porting
to qt6:
1) At least in my self-compiled Qt versions,
'moc' (the meta-object compiler) is located
in the 'libexec' subdirectory in 'QT6DIR', while the
Qt 5 equivalent is located in the "bin" subdirectory
of 'QT5DIR', so the configure.ac check uses the former.
2) moc does not process classes from the included headers.
Since the headers in 'vcl/inc/qt6' just '#include' the ones
from 'vcl/inc/qt5', running moc on the qt6 headers doesn't work,
so moc is currently run on the qt5 headers for qt6 as well
(s. 'vcl/CustomTarget_qt6_moc.mk').
That will have to be adapted in case the qt6 VCL plugin
uses "own" headers instead of just including the qt5 ones
at some point.
3) QX11Extras has been removed from Qt 6.
[1] says:
> Changes to Qt X11 Extras
>
> The QX11Info class has been removed.
>
> Clients that still rely on the functionality can include the private
> header <QtGui/private/qtx11extras_p.h> as a stopgap solution. To enable
> private headers use QT += core-private with qmake, or add a project
> dependency to Qt::CorePrivate with CMake.
I didn't take any closer look, just dropped the use of
QtX11Extras for qt6 for now.
4) XCB_ICCCM is no longer needed.
It is only used in qt5 to workaround a Qt bug fixed in Qt 5.12, s.
commit fe2baf9e84e0ca9aeaa683e37076f57fa3f38dca
Author: Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de>
Date: Tue Dec 3 08:32:58 2019 +0100
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
5) X11-specific code is still used for key modifier handling.
Therefore, still check for the XCB headers when 'USING_X11'
is set in configure.ac, and use a 'QT6_USING_X11' define
(as qt5 uses 'QT5_USING_X11').
6) There's currently no Qt 6 video sink for GStreamer.
As of today, qt-gstreamer is unmaintained and there is no Qt 6 version.
The project's README [2] says:
> 0. Maintenance Notice
> ---------------------
>
> This code is unmaintained. You can use it at your own risk.
>
> If you want to integrate video display in your QML-based UI,
> you should consider using 'qmlglsink', from gst-plugins-good.
> This is a well supported video sink that uses the generic
> gstreamer-gl stack and is in many ways superior to 'qtquick2videosink'
> that is provided by qt-gstreamer. You can use this code as an example:
> https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/tests/examples/qt/qmlsink
>
> If you are not interested in using QML in your UI, then you
> may use one of the other elements provided by this module
> (see below). If you do that, it would be helpful to let us
> know that this code is still useful to you. We may consider
> adding these elements in one of the core gstreamer modules.
>
> If you are here for the Qt-style bindings, I'm sorry to disappoint you.
> The alternative is to use the C API, or the GStreamermm C++ API.
> Qt-style bindings are cool, but unfortunately they are very hard
> to maintain because they are written by hand. If you are interested
> in continuing this project, you are welcome to implement a
> generator for them, probably based on GObject-Introspection.
> I am happy to provide directions if you want to pursue such a thing.
Therefore, the Qt video sink handling is qt5-only and the
corresponding handling for GOBJECT (used for the GStreamer
video sink handling) was not taken over for qt6.
This presumably means that video playback in Impress presentations
does not work when using qt6 with they Qt Wayland plugin,
s. tdf#125219 for the corresponding bug for qt5/kf5.
(I did not build the qtwayland module to actually test this, though.
Video playback with the Qt xcb plugin in a Wayland session works.)
[1] https://doc-snapshots.qt.io/qt6-dev/extras-changes-qt6.html
[2] https://cgit.freedesktop.org/gstreamer/qt-gstreamer/tree/README
Change-Id: Ib105ccfb2c3630ec5d5403793a3cd9ba31d85bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122808
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2021-09-29 11:09:51 +02:00
|
|
|
// we completely ignore all proposals by the Qt event, as they don't
|
|
|
|
// match at all with the preferred LO DnD actions.
|
|
|
|
// check the key modifiers to detect a user-overridden DnD action
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
|
|
const Qt::KeyboardModifiers eKeyMod = pEvent->modifiers();
|
|
|
|
#else
|
2019-08-08 17:59:20 +00:00
|
|
|
const Qt::KeyboardModifiers eKeyMod = pEvent->keyboardModifiers();
|
qt6: Add a qt6 VCL plugin
This adds a new "qt6" VCL plugin based on Qt 6.
Building the plugin is enabled by autogen option '--enable-qt6'
(and optionally setting 'QT6DIR' as needed).
Use the 'SAL_USE_VCLPLUGIN=qt6' environment variable
before running LO to select this VCL plugin.
Taking qt6 into account at all relevant places certainly
still requires follow-up changes, but
this builds and runs with a self-compiled
qtbase from the 'dev' git branch as of commit
3ce0672143d2eb3c3809f82998a4d71c5800d77a.
I didn't see anything obviously broken
in a quick run, but didn't test much.
This reuses and shares the qt5 VCL plugin code;
the qt6 headers and sources for now just
'#include' the qt5 ones.
Version checks are used for the code places that
need different handling to be built against Qt 6.
The build system parts in this commit were mostly done by
copying the qt5 equivalents, then adapting as needed.
Some notes on things I came across while porting
to qt6:
1) At least in my self-compiled Qt versions,
'moc' (the meta-object compiler) is located
in the 'libexec' subdirectory in 'QT6DIR', while the
Qt 5 equivalent is located in the "bin" subdirectory
of 'QT5DIR', so the configure.ac check uses the former.
2) moc does not process classes from the included headers.
Since the headers in 'vcl/inc/qt6' just '#include' the ones
from 'vcl/inc/qt5', running moc on the qt6 headers doesn't work,
so moc is currently run on the qt5 headers for qt6 as well
(s. 'vcl/CustomTarget_qt6_moc.mk').
That will have to be adapted in case the qt6 VCL plugin
uses "own" headers instead of just including the qt5 ones
at some point.
3) QX11Extras has been removed from Qt 6.
[1] says:
> Changes to Qt X11 Extras
>
> The QX11Info class has been removed.
>
> Clients that still rely on the functionality can include the private
> header <QtGui/private/qtx11extras_p.h> as a stopgap solution. To enable
> private headers use QT += core-private with qmake, or add a project
> dependency to Qt::CorePrivate with CMake.
I didn't take any closer look, just dropped the use of
QtX11Extras for qt6 for now.
4) XCB_ICCCM is no longer needed.
It is only used in qt5 to workaround a Qt bug fixed in Qt 5.12, s.
commit fe2baf9e84e0ca9aeaa683e37076f57fa3f38dca
Author: Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de>
Date: Tue Dec 3 08:32:58 2019 +0100
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
5) X11-specific code is still used for key modifier handling.
Therefore, still check for the XCB headers when 'USING_X11'
is set in configure.ac, and use a 'QT6_USING_X11' define
(as qt5 uses 'QT5_USING_X11').
6) There's currently no Qt 6 video sink for GStreamer.
As of today, qt-gstreamer is unmaintained and there is no Qt 6 version.
The project's README [2] says:
> 0. Maintenance Notice
> ---------------------
>
> This code is unmaintained. You can use it at your own risk.
>
> If you want to integrate video display in your QML-based UI,
> you should consider using 'qmlglsink', from gst-plugins-good.
> This is a well supported video sink that uses the generic
> gstreamer-gl stack and is in many ways superior to 'qtquick2videosink'
> that is provided by qt-gstreamer. You can use this code as an example:
> https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/tests/examples/qt/qmlsink
>
> If you are not interested in using QML in your UI, then you
> may use one of the other elements provided by this module
> (see below). If you do that, it would be helpful to let us
> know that this code is still useful to you. We may consider
> adding these elements in one of the core gstreamer modules.
>
> If you are here for the Qt-style bindings, I'm sorry to disappoint you.
> The alternative is to use the C API, or the GStreamermm C++ API.
> Qt-style bindings are cool, but unfortunately they are very hard
> to maintain because they are written by hand. If you are interested
> in continuing this project, you are welcome to implement a
> generator for them, probably based on GObject-Introspection.
> I am happy to provide directions if you want to pursue such a thing.
Therefore, the Qt video sink handling is qt5-only and the
corresponding handling for GOBJECT (used for the GStreamer
video sink handling) was not taken over for qt6.
This presumably means that video playback in Impress presentations
does not work when using qt6 with they Qt Wayland plugin,
s. tdf#125219 for the corresponding bug for qt5/kf5.
(I did not build the qtwayland module to actually test this, though.
Video playback with the Qt xcb plugin in a Wayland session works.)
[1] https://doc-snapshots.qt.io/qt6-dev/extras-changes-qt6.html
[2] https://cgit.freedesktop.org/gstreamer/qt-gstreamer/tree/README
Change-Id: Ib105ccfb2c3630ec5d5403793a3cd9ba31d85bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122808
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2021-09-29 11:09:51 +02:00
|
|
|
#endif
|
2019-08-08 17:59:20 +00:00
|
|
|
sal_Int8 nUserDropAction = 0;
|
2019-05-23 18:11:43 +02:00
|
|
|
if ((eKeyMod & Qt::ShiftModifier) && !(eKeyMod & Qt::ControlModifier))
|
|
|
|
nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_MOVE;
|
|
|
|
else if ((eKeyMod & Qt::ControlModifier) && !(eKeyMod & Qt::ShiftModifier))
|
|
|
|
nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_COPY;
|
|
|
|
else if ((eKeyMod & Qt::ShiftModifier) && (eKeyMod & Qt::ControlModifier))
|
|
|
|
nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_LINK;
|
2019-08-15 10:35:33 +00:00
|
|
|
nUserDropAction &= nSourceActions;
|
2019-08-08 17:59:20 +00:00
|
|
|
|
|
|
|
// select the default DnD action, if there isn't a user preference
|
|
|
|
if (0 == nUserDropAction)
|
|
|
|
{
|
|
|
|
// default LO internal action is move, but default external action is copy
|
2021-09-28 15:02:47 +02:00
|
|
|
nUserDropAction = dynamic_cast<const QtMimeData*>(pMimeData)
|
2019-08-08 17:59:20 +00:00
|
|
|
? css::datatransfer::dnd::DNDConstants::ACTION_MOVE
|
|
|
|
: css::datatransfer::dnd::DNDConstants::ACTION_COPY;
|
2019-08-15 10:35:33 +00:00
|
|
|
nUserDropAction &= nSourceActions;
|
2019-08-08 17:59:20 +00:00
|
|
|
|
|
|
|
// if the default doesn't match any allowed source action, fall back to the
|
|
|
|
// preferred of all allowed source actions
|
|
|
|
if (0 == nUserDropAction)
|
|
|
|
nUserDropAction = toVclDropAction(getPreferredDropAction(nSourceActions));
|
|
|
|
|
|
|
|
// this is "our" preference, but actually we would even prefer any default,
|
|
|
|
// if there is any
|
|
|
|
nUserDropAction |= css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT;
|
|
|
|
}
|
|
|
|
return nUserDropAction;
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::handleDragMove(QDragMoveEvent* pEvent)
|
2019-08-08 17:59:20 +00:00
|
|
|
{
|
|
|
|
assert(m_pDropTarget);
|
|
|
|
|
|
|
|
// prepare our suggested drop action for the drop target
|
|
|
|
const sal_Int8 nSourceActions = toVclDropActions(pEvent->possibleActions());
|
|
|
|
const QMimeData* pMimeData = pEvent->mimeData();
|
|
|
|
const sal_Int8 nUserDropAction = lcl_getUserDropAction(pEvent, nSourceActions, pMimeData);
|
qt6: Add a qt6 VCL plugin
This adds a new "qt6" VCL plugin based on Qt 6.
Building the plugin is enabled by autogen option '--enable-qt6'
(and optionally setting 'QT6DIR' as needed).
Use the 'SAL_USE_VCLPLUGIN=qt6' environment variable
before running LO to select this VCL plugin.
Taking qt6 into account at all relevant places certainly
still requires follow-up changes, but
this builds and runs with a self-compiled
qtbase from the 'dev' git branch as of commit
3ce0672143d2eb3c3809f82998a4d71c5800d77a.
I didn't see anything obviously broken
in a quick run, but didn't test much.
This reuses and shares the qt5 VCL plugin code;
the qt6 headers and sources for now just
'#include' the qt5 ones.
Version checks are used for the code places that
need different handling to be built against Qt 6.
The build system parts in this commit were mostly done by
copying the qt5 equivalents, then adapting as needed.
Some notes on things I came across while porting
to qt6:
1) At least in my self-compiled Qt versions,
'moc' (the meta-object compiler) is located
in the 'libexec' subdirectory in 'QT6DIR', while the
Qt 5 equivalent is located in the "bin" subdirectory
of 'QT5DIR', so the configure.ac check uses the former.
2) moc does not process classes from the included headers.
Since the headers in 'vcl/inc/qt6' just '#include' the ones
from 'vcl/inc/qt5', running moc on the qt6 headers doesn't work,
so moc is currently run on the qt5 headers for qt6 as well
(s. 'vcl/CustomTarget_qt6_moc.mk').
That will have to be adapted in case the qt6 VCL plugin
uses "own" headers instead of just including the qt5 ones
at some point.
3) QX11Extras has been removed from Qt 6.
[1] says:
> Changes to Qt X11 Extras
>
> The QX11Info class has been removed.
>
> Clients that still rely on the functionality can include the private
> header <QtGui/private/qtx11extras_p.h> as a stopgap solution. To enable
> private headers use QT += core-private with qmake, or add a project
> dependency to Qt::CorePrivate with CMake.
I didn't take any closer look, just dropped the use of
QtX11Extras for qt6 for now.
4) XCB_ICCCM is no longer needed.
It is only used in qt5 to workaround a Qt bug fixed in Qt 5.12, s.
commit fe2baf9e84e0ca9aeaa683e37076f57fa3f38dca
Author: Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de>
Date: Tue Dec 3 08:32:58 2019 +0100
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
5) X11-specific code is still used for key modifier handling.
Therefore, still check for the XCB headers when 'USING_X11'
is set in configure.ac, and use a 'QT6_USING_X11' define
(as qt5 uses 'QT5_USING_X11').
6) There's currently no Qt 6 video sink for GStreamer.
As of today, qt-gstreamer is unmaintained and there is no Qt 6 version.
The project's README [2] says:
> 0. Maintenance Notice
> ---------------------
>
> This code is unmaintained. You can use it at your own risk.
>
> If you want to integrate video display in your QML-based UI,
> you should consider using 'qmlglsink', from gst-plugins-good.
> This is a well supported video sink that uses the generic
> gstreamer-gl stack and is in many ways superior to 'qtquick2videosink'
> that is provided by qt-gstreamer. You can use this code as an example:
> https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/tests/examples/qt/qmlsink
>
> If you are not interested in using QML in your UI, then you
> may use one of the other elements provided by this module
> (see below). If you do that, it would be helpful to let us
> know that this code is still useful to you. We may consider
> adding these elements in one of the core gstreamer modules.
>
> If you are here for the Qt-style bindings, I'm sorry to disappoint you.
> The alternative is to use the C API, or the GStreamermm C++ API.
> Qt-style bindings are cool, but unfortunately they are very hard
> to maintain because they are written by hand. If you are interested
> in continuing this project, you are welcome to implement a
> generator for them, probably based on GObject-Introspection.
> I am happy to provide directions if you want to pursue such a thing.
Therefore, the Qt video sink handling is qt5-only and the
corresponding handling for GOBJECT (used for the GStreamer
video sink handling) was not taken over for qt6.
This presumably means that video playback in Impress presentations
does not work when using qt6 with they Qt Wayland plugin,
s. tdf#125219 for the corresponding bug for qt5/kf5.
(I did not build the qtwayland module to actually test this, though.
Video playback with the Qt xcb plugin in a Wayland session works.)
[1] https://doc-snapshots.qt.io/qt6-dev/extras-changes-qt6.html
[2] https://cgit.freedesktop.org/gstreamer/qt-gstreamer/tree/README
Change-Id: Ib105ccfb2c3630ec5d5403793a3cd9ba31d85bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122808
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2021-09-29 11:09:51 +02:00
|
|
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
|
|
const Point aPos = toPoint(pEvent->position().toPoint() * devicePixelRatioF());
|
|
|
|
#else
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
const Point aPos = toPoint(pEvent->pos() * devicePixelRatioF());
|
qt6: Add a qt6 VCL plugin
This adds a new "qt6" VCL plugin based on Qt 6.
Building the plugin is enabled by autogen option '--enable-qt6'
(and optionally setting 'QT6DIR' as needed).
Use the 'SAL_USE_VCLPLUGIN=qt6' environment variable
before running LO to select this VCL plugin.
Taking qt6 into account at all relevant places certainly
still requires follow-up changes, but
this builds and runs with a self-compiled
qtbase from the 'dev' git branch as of commit
3ce0672143d2eb3c3809f82998a4d71c5800d77a.
I didn't see anything obviously broken
in a quick run, but didn't test much.
This reuses and shares the qt5 VCL plugin code;
the qt6 headers and sources for now just
'#include' the qt5 ones.
Version checks are used for the code places that
need different handling to be built against Qt 6.
The build system parts in this commit were mostly done by
copying the qt5 equivalents, then adapting as needed.
Some notes on things I came across while porting
to qt6:
1) At least in my self-compiled Qt versions,
'moc' (the meta-object compiler) is located
in the 'libexec' subdirectory in 'QT6DIR', while the
Qt 5 equivalent is located in the "bin" subdirectory
of 'QT5DIR', so the configure.ac check uses the former.
2) moc does not process classes from the included headers.
Since the headers in 'vcl/inc/qt6' just '#include' the ones
from 'vcl/inc/qt5', running moc on the qt6 headers doesn't work,
so moc is currently run on the qt5 headers for qt6 as well
(s. 'vcl/CustomTarget_qt6_moc.mk').
That will have to be adapted in case the qt6 VCL plugin
uses "own" headers instead of just including the qt5 ones
at some point.
3) QX11Extras has been removed from Qt 6.
[1] says:
> Changes to Qt X11 Extras
>
> The QX11Info class has been removed.
>
> Clients that still rely on the functionality can include the private
> header <QtGui/private/qtx11extras_p.h> as a stopgap solution. To enable
> private headers use QT += core-private with qmake, or add a project
> dependency to Qt::CorePrivate with CMake.
I didn't take any closer look, just dropped the use of
QtX11Extras for qt6 for now.
4) XCB_ICCCM is no longer needed.
It is only used in qt5 to workaround a Qt bug fixed in Qt 5.12, s.
commit fe2baf9e84e0ca9aeaa683e37076f57fa3f38dca
Author: Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de>
Date: Tue Dec 3 08:32:58 2019 +0100
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
5) X11-specific code is still used for key modifier handling.
Therefore, still check for the XCB headers when 'USING_X11'
is set in configure.ac, and use a 'QT6_USING_X11' define
(as qt5 uses 'QT5_USING_X11').
6) There's currently no Qt 6 video sink for GStreamer.
As of today, qt-gstreamer is unmaintained and there is no Qt 6 version.
The project's README [2] says:
> 0. Maintenance Notice
> ---------------------
>
> This code is unmaintained. You can use it at your own risk.
>
> If you want to integrate video display in your QML-based UI,
> you should consider using 'qmlglsink', from gst-plugins-good.
> This is a well supported video sink that uses the generic
> gstreamer-gl stack and is in many ways superior to 'qtquick2videosink'
> that is provided by qt-gstreamer. You can use this code as an example:
> https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/tests/examples/qt/qmlsink
>
> If you are not interested in using QML in your UI, then you
> may use one of the other elements provided by this module
> (see below). If you do that, it would be helpful to let us
> know that this code is still useful to you. We may consider
> adding these elements in one of the core gstreamer modules.
>
> If you are here for the Qt-style bindings, I'm sorry to disappoint you.
> The alternative is to use the C API, or the GStreamermm C++ API.
> Qt-style bindings are cool, but unfortunately they are very hard
> to maintain because they are written by hand. If you are interested
> in continuing this project, you are welcome to implement a
> generator for them, probably based on GObject-Introspection.
> I am happy to provide directions if you want to pursue such a thing.
Therefore, the Qt video sink handling is qt5-only and the
corresponding handling for GOBJECT (used for the GStreamer
video sink handling) was not taken over for qt6.
This presumably means that video playback in Impress presentations
does not work when using qt6 with they Qt Wayland plugin,
s. tdf#125219 for the corresponding bug for qt5/kf5.
(I did not build the qtwayland module to actually test this, though.
Video playback with the Qt xcb plugin in a Wayland session works.)
[1] https://doc-snapshots.qt.io/qt6-dev/extras-changes-qt6.html
[2] https://cgit.freedesktop.org/gstreamer/qt-gstreamer/tree/README
Change-Id: Ib105ccfb2c3630ec5d5403793a3cd9ba31d85bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122808
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2021-09-29 11:09:51 +02:00
|
|
|
#endif
|
2019-05-23 18:11:43 +02:00
|
|
|
|
2018-10-15 14:44:29 +02:00
|
|
|
css::datatransfer::dnd::DropTargetDragEnterEvent aEvent;
|
|
|
|
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(m_pDropTarget);
|
|
|
|
aEvent.Context = static_cast<css::datatransfer::dnd::XDropTargetDragContext*>(m_pDropTarget);
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
aEvent.LocationX = aPos.X();
|
|
|
|
aEvent.LocationY = aPos.Y();
|
2019-08-08 17:59:20 +00:00
|
|
|
aEvent.DropAction = nUserDropAction;
|
|
|
|
aEvent.SourceActions = nSourceActions;
|
2018-10-15 14:44:29 +02:00
|
|
|
|
2019-08-08 17:59:20 +00:00
|
|
|
// ask the drop target to accept our drop action
|
|
|
|
if (!m_bInDrag)
|
2018-10-15 14:44:29 +02:00
|
|
|
{
|
2019-08-08 17:59:20 +00:00
|
|
|
aEvent.SupportedDataFlavors = lcl_getXTransferable(pMimeData)->getTransferDataFlavors();
|
2018-10-15 14:44:29 +02:00
|
|
|
m_pDropTarget->fire_dragEnter(aEvent);
|
|
|
|
m_bInDrag = true;
|
|
|
|
}
|
2018-10-18 13:13:29 +02:00
|
|
|
else
|
|
|
|
m_pDropTarget->fire_dragOver(aEvent);
|
2019-08-08 17:59:20 +00:00
|
|
|
|
|
|
|
// the drop target accepted our drop action => inform Qt
|
|
|
|
if (m_pDropTarget->proposedDropAction() != 0)
|
|
|
|
{
|
|
|
|
pEvent->setDropAction(getPreferredDropAction(m_pDropTarget->proposedDropAction()));
|
|
|
|
pEvent->accept();
|
|
|
|
}
|
|
|
|
else // or maybe someone else likes it?
|
|
|
|
pEvent->ignore();
|
2018-10-15 14:44:29 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::handleDrop(QDropEvent* pEvent)
|
2018-10-18 01:01:14 +02:00
|
|
|
{
|
|
|
|
assert(m_pDropTarget);
|
|
|
|
|
2019-08-08 17:59:20 +00:00
|
|
|
// prepare our suggested drop action for the drop target
|
|
|
|
const sal_Int8 nSourceActions = toVclDropActions(pEvent->possibleActions());
|
|
|
|
const sal_Int8 nUserDropAction
|
|
|
|
= lcl_getUserDropAction(pEvent, nSourceActions, pEvent->mimeData());
|
qt6: Add a qt6 VCL plugin
This adds a new "qt6" VCL plugin based on Qt 6.
Building the plugin is enabled by autogen option '--enable-qt6'
(and optionally setting 'QT6DIR' as needed).
Use the 'SAL_USE_VCLPLUGIN=qt6' environment variable
before running LO to select this VCL plugin.
Taking qt6 into account at all relevant places certainly
still requires follow-up changes, but
this builds and runs with a self-compiled
qtbase from the 'dev' git branch as of commit
3ce0672143d2eb3c3809f82998a4d71c5800d77a.
I didn't see anything obviously broken
in a quick run, but didn't test much.
This reuses and shares the qt5 VCL plugin code;
the qt6 headers and sources for now just
'#include' the qt5 ones.
Version checks are used for the code places that
need different handling to be built against Qt 6.
The build system parts in this commit were mostly done by
copying the qt5 equivalents, then adapting as needed.
Some notes on things I came across while porting
to qt6:
1) At least in my self-compiled Qt versions,
'moc' (the meta-object compiler) is located
in the 'libexec' subdirectory in 'QT6DIR', while the
Qt 5 equivalent is located in the "bin" subdirectory
of 'QT5DIR', so the configure.ac check uses the former.
2) moc does not process classes from the included headers.
Since the headers in 'vcl/inc/qt6' just '#include' the ones
from 'vcl/inc/qt5', running moc on the qt6 headers doesn't work,
so moc is currently run on the qt5 headers for qt6 as well
(s. 'vcl/CustomTarget_qt6_moc.mk').
That will have to be adapted in case the qt6 VCL plugin
uses "own" headers instead of just including the qt5 ones
at some point.
3) QX11Extras has been removed from Qt 6.
[1] says:
> Changes to Qt X11 Extras
>
> The QX11Info class has been removed.
>
> Clients that still rely on the functionality can include the private
> header <QtGui/private/qtx11extras_p.h> as a stopgap solution. To enable
> private headers use QT += core-private with qmake, or add a project
> dependency to Qt::CorePrivate with CMake.
I didn't take any closer look, just dropped the use of
QtX11Extras for qt6 for now.
4) XCB_ICCCM is no longer needed.
It is only used in qt5 to workaround a Qt bug fixed in Qt 5.12, s.
commit fe2baf9e84e0ca9aeaa683e37076f57fa3f38dca
Author: Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de>
Date: Tue Dec 3 08:32:58 2019 +0100
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
5) X11-specific code is still used for key modifier handling.
Therefore, still check for the XCB headers when 'USING_X11'
is set in configure.ac, and use a 'QT6_USING_X11' define
(as qt5 uses 'QT5_USING_X11').
6) There's currently no Qt 6 video sink for GStreamer.
As of today, qt-gstreamer is unmaintained and there is no Qt 6 version.
The project's README [2] says:
> 0. Maintenance Notice
> ---------------------
>
> This code is unmaintained. You can use it at your own risk.
>
> If you want to integrate video display in your QML-based UI,
> you should consider using 'qmlglsink', from gst-plugins-good.
> This is a well supported video sink that uses the generic
> gstreamer-gl stack and is in many ways superior to 'qtquick2videosink'
> that is provided by qt-gstreamer. You can use this code as an example:
> https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/tests/examples/qt/qmlsink
>
> If you are not interested in using QML in your UI, then you
> may use one of the other elements provided by this module
> (see below). If you do that, it would be helpful to let us
> know that this code is still useful to you. We may consider
> adding these elements in one of the core gstreamer modules.
>
> If you are here for the Qt-style bindings, I'm sorry to disappoint you.
> The alternative is to use the C API, or the GStreamermm C++ API.
> Qt-style bindings are cool, but unfortunately they are very hard
> to maintain because they are written by hand. If you are interested
> in continuing this project, you are welcome to implement a
> generator for them, probably based on GObject-Introspection.
> I am happy to provide directions if you want to pursue such a thing.
Therefore, the Qt video sink handling is qt5-only and the
corresponding handling for GOBJECT (used for the GStreamer
video sink handling) was not taken over for qt6.
This presumably means that video playback in Impress presentations
does not work when using qt6 with they Qt Wayland plugin,
s. tdf#125219 for the corresponding bug for qt5/kf5.
(I did not build the qtwayland module to actually test this, though.
Video playback with the Qt xcb plugin in a Wayland session works.)
[1] https://doc-snapshots.qt.io/qt6-dev/extras-changes-qt6.html
[2] https://cgit.freedesktop.org/gstreamer/qt-gstreamer/tree/README
Change-Id: Ib105ccfb2c3630ec5d5403793a3cd9ba31d85bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122808
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2021-09-29 11:09:51 +02:00
|
|
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
|
|
const Point aPos = toPoint(pEvent->position().toPoint() * devicePixelRatioF());
|
|
|
|
#else
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
const Point aPos = toPoint(pEvent->pos() * devicePixelRatioF());
|
qt6: Add a qt6 VCL plugin
This adds a new "qt6" VCL plugin based on Qt 6.
Building the plugin is enabled by autogen option '--enable-qt6'
(and optionally setting 'QT6DIR' as needed).
Use the 'SAL_USE_VCLPLUGIN=qt6' environment variable
before running LO to select this VCL plugin.
Taking qt6 into account at all relevant places certainly
still requires follow-up changes, but
this builds and runs with a self-compiled
qtbase from the 'dev' git branch as of commit
3ce0672143d2eb3c3809f82998a4d71c5800d77a.
I didn't see anything obviously broken
in a quick run, but didn't test much.
This reuses and shares the qt5 VCL plugin code;
the qt6 headers and sources for now just
'#include' the qt5 ones.
Version checks are used for the code places that
need different handling to be built against Qt 6.
The build system parts in this commit were mostly done by
copying the qt5 equivalents, then adapting as needed.
Some notes on things I came across while porting
to qt6:
1) At least in my self-compiled Qt versions,
'moc' (the meta-object compiler) is located
in the 'libexec' subdirectory in 'QT6DIR', while the
Qt 5 equivalent is located in the "bin" subdirectory
of 'QT5DIR', so the configure.ac check uses the former.
2) moc does not process classes from the included headers.
Since the headers in 'vcl/inc/qt6' just '#include' the ones
from 'vcl/inc/qt5', running moc on the qt6 headers doesn't work,
so moc is currently run on the qt5 headers for qt6 as well
(s. 'vcl/CustomTarget_qt6_moc.mk').
That will have to be adapted in case the qt6 VCL plugin
uses "own" headers instead of just including the qt5 ones
at some point.
3) QX11Extras has been removed from Qt 6.
[1] says:
> Changes to Qt X11 Extras
>
> The QX11Info class has been removed.
>
> Clients that still rely on the functionality can include the private
> header <QtGui/private/qtx11extras_p.h> as a stopgap solution. To enable
> private headers use QT += core-private with qmake, or add a project
> dependency to Qt::CorePrivate with CMake.
I didn't take any closer look, just dropped the use of
QtX11Extras for qt6 for now.
4) XCB_ICCCM is no longer needed.
It is only used in qt5 to workaround a Qt bug fixed in Qt 5.12, s.
commit fe2baf9e84e0ca9aeaa683e37076f57fa3f38dca
Author: Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de>
Date: Tue Dec 3 08:32:58 2019 +0100
Qt5 fix missing XCB_ICCCM_WM_HINT_WINDOW_GROUP
5) X11-specific code is still used for key modifier handling.
Therefore, still check for the XCB headers when 'USING_X11'
is set in configure.ac, and use a 'QT6_USING_X11' define
(as qt5 uses 'QT5_USING_X11').
6) There's currently no Qt 6 video sink for GStreamer.
As of today, qt-gstreamer is unmaintained and there is no Qt 6 version.
The project's README [2] says:
> 0. Maintenance Notice
> ---------------------
>
> This code is unmaintained. You can use it at your own risk.
>
> If you want to integrate video display in your QML-based UI,
> you should consider using 'qmlglsink', from gst-plugins-good.
> This is a well supported video sink that uses the generic
> gstreamer-gl stack and is in many ways superior to 'qtquick2videosink'
> that is provided by qt-gstreamer. You can use this code as an example:
> https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/tests/examples/qt/qmlsink
>
> If you are not interested in using QML in your UI, then you
> may use one of the other elements provided by this module
> (see below). If you do that, it would be helpful to let us
> know that this code is still useful to you. We may consider
> adding these elements in one of the core gstreamer modules.
>
> If you are here for the Qt-style bindings, I'm sorry to disappoint you.
> The alternative is to use the C API, or the GStreamermm C++ API.
> Qt-style bindings are cool, but unfortunately they are very hard
> to maintain because they are written by hand. If you are interested
> in continuing this project, you are welcome to implement a
> generator for them, probably based on GObject-Introspection.
> I am happy to provide directions if you want to pursue such a thing.
Therefore, the Qt video sink handling is qt5-only and the
corresponding handling for GOBJECT (used for the GStreamer
video sink handling) was not taken over for qt6.
This presumably means that video playback in Impress presentations
does not work when using qt6 with they Qt Wayland plugin,
s. tdf#125219 for the corresponding bug for qt5/kf5.
(I did not build the qtwayland module to actually test this, though.
Video playback with the Qt xcb plugin in a Wayland session works.)
[1] https://doc-snapshots.qt.io/qt6-dev/extras-changes-qt6.html
[2] https://cgit.freedesktop.org/gstreamer/qt-gstreamer/tree/README
Change-Id: Ib105ccfb2c3630ec5d5403793a3cd9ba31d85bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122808
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2021-09-29 11:09:51 +02:00
|
|
|
#endif
|
2019-08-08 17:59:20 +00:00
|
|
|
|
2018-10-18 01:01:14 +02:00
|
|
|
css::datatransfer::dnd::DropTargetDropEvent aEvent;
|
|
|
|
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(m_pDropTarget);
|
|
|
|
aEvent.Context = static_cast<css::datatransfer::dnd::XDropTargetDropContext*>(m_pDropTarget);
|
tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-02-29 13:39:29 +01:00
|
|
|
aEvent.LocationX = aPos.X();
|
|
|
|
aEvent.LocationY = aPos.Y();
|
2019-08-08 17:59:20 +00:00
|
|
|
aEvent.SourceActions = nSourceActions;
|
|
|
|
aEvent.DropAction = nUserDropAction;
|
|
|
|
aEvent.Transferable = lcl_getXTransferable(pEvent->mimeData());
|
2018-10-18 01:01:14 +02:00
|
|
|
|
2019-08-08 17:59:20 +00:00
|
|
|
// ask the drop target to accept our drop action
|
2018-10-18 01:01:14 +02:00
|
|
|
m_pDropTarget->fire_drop(aEvent);
|
2018-10-18 13:13:29 +02:00
|
|
|
m_bInDrag = false;
|
|
|
|
|
2019-08-08 17:59:20 +00:00
|
|
|
const bool bDropSuccessful = m_pDropTarget->dropSuccessful();
|
|
|
|
const sal_Int8 nDropAction = m_pDropTarget->proposedDropAction();
|
|
|
|
|
|
|
|
// inform the drag source of the drag-origin frame of the drop result
|
|
|
|
if (pEvent->source())
|
2018-10-18 13:13:29 +02:00
|
|
|
{
|
2021-09-28 15:02:47 +02:00
|
|
|
QtWidget* pWidget = dynamic_cast<QtWidget*>(pEvent->source());
|
2019-08-08 17:59:20 +00:00
|
|
|
assert(pWidget); // AFAIK there shouldn't be any non-Qt5Widget as source in LO itself
|
|
|
|
if (pWidget)
|
2019-08-15 10:35:33 +00:00
|
|
|
pWidget->frame().m_pDragSource->fire_dragEnd(nDropAction, bDropSuccessful);
|
2018-10-18 13:13:29 +02:00
|
|
|
}
|
2019-08-08 17:59:20 +00:00
|
|
|
|
|
|
|
// the drop target accepted our drop action => inform Qt
|
|
|
|
if (bDropSuccessful)
|
|
|
|
{
|
|
|
|
pEvent->setDropAction(getPreferredDropAction(nDropAction));
|
|
|
|
pEvent->accept();
|
|
|
|
}
|
|
|
|
else // or maybe someone else likes it?
|
|
|
|
pEvent->ignore();
|
|
|
|
}
|
|
|
|
|
2021-09-28 15:02:47 +02:00
|
|
|
void QtFrame::handleDragLeave()
|
2019-08-08 17:59:20 +00:00
|
|
|
{
|
|
|
|
css::datatransfer::dnd::DropTargetEvent aEvent;
|
|
|
|
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(m_pDropTarget);
|
|
|
|
m_pDropTarget->fire_dragExit(aEvent);
|
|
|
|
m_bInDrag = false;
|
2018-10-18 01:01:14 +02:00
|
|
|
}
|
|
|
|
|
2017-10-21 13:50:30 +00:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|