7#include <qpa/qwindowsysteminterface.h>
9#include <qohosdisplayinfo.h>
16#include "render/qohosview.h"
18#include <multimedia/image_framework/image/pixelmap_native.h>
19#include <qarkui/qarkuiutils.h>
20#include <qguiapplication.h>
21#include <qohosapppermissions_p.h>
22#include <qohosjsutils.h>
23#include <qohospixelmapconversions.h>
24#include <qohosutils.h>
25#include <render/qwindowproxyregistry.h>
26#include <window_manager/oh_display_capture.h>
28#include <QtGui/QGuiApplication>
29#include <QtGui/QWindow>
30#include <QtCore/private/qnapi_p.h>
31#include <QtCore/private/qohoslogger_p.h>
32#include <QtGui/private/qhighdpiscaling_p.h>
33#include <QtGui/private/qwindow_p.h>
46 ::OH_PixelmapNative *pixelMapNativePtr;
48 QArkUi::callArkUiOrFailOnErrorResult(
49 Q_OHOS_NAMED_FUNC(::OH_NativeDisplayManager_CaptureScreenPixelmap),
50 static_cast<
std::uint32_t>(displayId.value()), &pixelMapNativePtr);
52 return wrapNativePixelMapPtr(pixelMapNativePtr);
57 QOhosConsumer<std::shared_ptr<::OH_PixelmapNative>> pixelMapOrNullConsumer)
59 static constexpr const char *ohosCustomScreenCapturePermission =
60 "ohos.permission.CUSTOM_SCREEN_CAPTURE";
63 jsState, ohosCustomScreenCapturePermission,
64 [pixelMapOrNullConsumer = std::move(pixelMapOrNullConsumer), displayId](
65 auto &jsState,
bool permissionGranted) {
66 if (permissionGranted) {
67 pixelMapOrNullConsumer(captureScreenPixelmap(jsState, displayId));
70 "%s: %s hasn't been granted by user. Cannot grab window.", Q_FUNC_INFO,
71 ohosCustomScreenCapturePermission);
72 pixelMapOrNullConsumer(
nullptr);
79 auto allWindows =
qApp->allWindows();
80 auto windowItByWId =
std::find_if(
81 std::begin(allWindows),
std::end(allWindows),
83 return w->winId() == wId;
86 if (windowItByWId == allWindows.end())
89 return *windowItByWId;
93 const QSize &windowSnapshotSize,
const QRect &windowSpaceCaptureRect)
96 windowSpaceCaptureRect.width() < 0
97 ? qMax(0, windowSnapshotSize.width() - windowSpaceCaptureRect.x())
98 : windowSpaceCaptureRect.width(),
99 windowSpaceCaptureRect.height() < 0
100 ? qMax(0, windowSnapshotSize.height() - windowSpaceCaptureRect.y())
101 : windowSpaceCaptureRect.height()
106 const QRect &windowSpaceCaptureRect,
const QRect &windowFragmentRect)
109 qAbs(windowSpaceCaptureRect.x() - windowFragmentRect.x()),
110 qAbs(windowSpaceCaptureRect.y() - windowFragmentRect.y()),
111 windowFragmentRect.width(),
112 windowFragmentRect.height()
118 const QRect &windowSpaceCaptureRect)
120 auto resultSize = calculateResultWindowCapturePixmapSize(
121 QHighDpi::fromNativePixels(capturedWindowPixmap.size(), platformScreen),
122 windowSpaceCaptureRect);
124 if (resultSize.isEmpty())
127 auto windowFragmentRect = capturedWindowPixmap.rect().intersected(
128 QRect(windowSpaceCaptureRect.topLeft(), resultSize));
130 if (windowFragmentRect.isEmpty())
131 return QPixmap(resultSize);
133 auto resultSpaceWindowFragmentRect =
134 calculateResultPixmapWindowFragmentRect(windowSpaceCaptureRect, windowFragmentRect);
136 QPixmap result(resultSize);
139 QHighDpi::toNativePixels(resultSpaceWindowFragmentRect, platformScreen),
140 capturedWindowPixmap,
141 QHighDpi::toNativePixels(windowFragmentRect, platformScreen));
150 switch (jsDisplayOrientation) {
152 return makeQOhosOptional(Qt::ScreenOrientation::PortraitOrientation);
154 return makeQOhosOptional(Qt::ScreenOrientation::LandscapeOrientation);
156 return makeQOhosOptional(Qt::ScreenOrientation::InvertedPortraitOrientation);
158 return makeQOhosOptional(Qt::ScreenOrientation::InvertedLandscapeOrientation);
169 , m_format(QImage::Format_ARGB32_Premultiplied)
171 , m_platformCursor(
new QOhosPlatformCursor())
172 , m_displayInfo(displayInfo)
173 , m_availableGeometry(getAvailableArea())
174 , m_platformScreenListSupplier(std::move(platformScreenListSupplier))
176 auto __dbg = make_QCScopedDebug(
"QOhosPlatformScreen::QOhosPlatformScreen");
183 auto *platformScreen = screen->handle();
184 if (Q_UNLIKELY(platformScreen ==
nullptr))
185 qOhosReportFatalErrorAndAbort(
"QScreen::handle() returned null");
191 for (
auto *platformScreen : virtualSiblings()) {
192 auto *ohosPlatformScreen =
static_cast<QOhosPlatformScreen *>(platformScreen);
194 auto windowIds = QOhosWindowProxy::queryWindowIdsByCoordinate(ohosPlatformScreen->m_displayInfo.id, p);
195 if (!windowIds.empty())
196 return QWindowProxyRegistry::instance().findQWindowByJsWindowIdOrNull(windowIds.front());
204 return m_platformCursor.data();
209 auto geometryChanged = displayInfo.displayGeometryPixels() != m_displayInfo.displayGeometryPixels();
210 auto logicalDpiChanged = displayInfo.densityDPI != m_displayInfo.densityDPI;
212 QVector<QPair<QWindow *, QOhosOptional<QRect>>> windowRectPairs;
214 if (logicalDpiChanged) {
215 for (
auto *window :
qGuiApp->allWindows()) {
216 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
217 if (platformWindow ==
nullptr || platformWindow->screen() !=
this || !window->isVisible())
220 auto *ownedView = platformWindow->ownedViewOrNull();
221 if (ownedView ==
nullptr)
224 windowRectPairs.push_back({
226 ownedView->viewType() == QOhosView::ViewType::EmbeddedWindow
227 ? makeQOhosOptional(window->geometry())
228 : makeEmptyQOhosOptional()});
232 m_displayInfo = displayInfo;
235 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
237 if (logicalDpiChanged) {
238 auto ldpi = logicalDpi();
239 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(
240 screen(), ldpi.first, ldpi.second);
242 QWindowSystemInterface::flushWindowSystemEvents();
244 for (
const auto &windowRectPair : windowRectPairs) {
245 auto *qWindow = windowRectPair.first;
246 auto *platformWindow = QOhosPlatformWindow::fromQWindow(qWindow);
247 if (windowRectPair.second.has_value())
248 qWindow->setGeometry(windowRectPair.second.value());
249 platformWindow->handleDpiChange();
256 qreal lDpi = m_displayInfo.densityPixels * ohosLogicalDpi;
257 return QDpi(lDpi, lDpi);
264 return m_displayInfo.densityPixels;
275 qAndThen(m_displayInfo.orientation, tryMapJsDisplayOrientationToQt)
276 .value_or(Qt::ScreenOrientation::PrimaryOrientation);
281 return Qt::ScreenOrientation::PrimaryOrientation;
286 return QtOhos::evalInJsThreadWithPromise<QRect>(
287 [&](QtOhos::JsState &jsState, QOhosTaskPromise<QRect> evalPromise) {
289 QNapi::Object display;
291 display = jsState.eval<QNapi::Object>(
292 "@ohos.display.getDisplayByIdSync(*)", {m_displayInfo.id.value()});
293 }
catch (
const Napi::Error &error) {
295 "%s: getDisplayByIdSync(%f) failed with error: %s",
296 Q_FUNC_INFO, m_displayInfo.id.value(), error.Message().c_str());
297 evalPromise(QRect());
301 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
302 display.evalToPromiseOrRejectOnThrow(
"getAvailableArea()")
304 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
305 auto availableArea = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
308 availableArea.get<QNapi::Number>(
"left"),
309 availableArea.get<QNapi::Number>(
"top"),
310 availableArea.get<QNapi::Number>(
"width"),
311 availableArea.get<QNapi::Number>(
"height")));
314 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
315 QtOhos::logJsCallbackError(cbInfo,
"Error occurred in JS getAvailableArea()");
316 catchPromise(QRect());
328 return m_displayInfo;
333 return m_displayInfo.displayGeometryPixels();
338 auto screenGeometry = geometry();
339 return !m_availableGeometry.isEmpty()
340 ? m_availableGeometry.translated(screenGeometry.topLeft())
356 return m_displayInfo.physicalSize();
361 if (rect != m_availableGeometry) {
362 m_availableGeometry = rect;
363 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
369 if (!m_displayInfo.isDisplayMainOrExtended())
370 return QPlatformScreen::virtualSiblings();
372 QList<QPlatformScreen *> result;
373 auto allPlatformScreens = m_platformScreenListSupplier();
375 allPlatformScreens.begin(), allPlatformScreens.end(),
376 std::back_inserter(result),
386 auto captureRect = QRect(x, y, width, height);
389 auto *window = tryFindWindowByWIdOrNull(wId);
390 if (window ==
nullptr) {
392 "%s: Cannot find window with the given WId: %lld.", Q_FUNC_INFO, wId);
395 return grabWindowFromCapturedScreenPixmap(
396 this, QOhosPlatformWindow::fromQWindow(window)->makeSnapshot(), captureRect);
399 auto capturedScreenPixmap = QtOhos::evalInJsThreadWithPromise<QPixmap>(
400 [displayId = m_displayInfo.id](
401 QtOhos::JsState &jsState, QOhosTaskPromise<QPixmap> evalPromise) {
402 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
403 tryCaptureScreenPixelmapWithPermissionCheck(
406 std::shared_ptr<::OH_PixelmapNative> optPixelMap) {
407 (*sharedEvalPromise)(
409 ? QPixmap::fromImage(createQImageFromNativePixelMap(optPixelMap.get()))
415 return capturedScreenPixmap.copy(captureRect);
420 return m_displayInfo.name;
void checkAppPermissionGrantedWithConsumer(QtOhos::JsState &jsState, const std::string &permissionName, QOhosConsumer< QtOhos::JsState &, bool > resultConsumer)
Combined button and popup list for selecting options.
QWindow * tryFindWindowByWIdOrNull(WId wId)
QRect calculateResultPixmapWindowFragmentRect(const QRect &windowSpaceCaptureRect, const QRect &windowFragmentRect)
void tryCaptureScreenPixelmapWithPermissionCheck(QtOhos::JsState &jsState, QOhosDisplayInfo::JsDisplayId displayId, QOhosConsumer< std::shared_ptr<::OH_PixelmapNative > > pixelMapOrNullConsumer)
static const int ohosLogicalDpi
QOhosOptional< Qt::ScreenOrientation > tryMapJsDisplayOrientationToQt(QOhosDisplayInfo::JsDisplayOrientation jsDisplayOrientation)
std::shared_ptr<::OH_PixelmapNative > captureScreenPixelmap(QtOhos::JsState &, QOhosDisplayInfo::JsDisplayId displayId)
QSize calculateResultWindowCapturePixmapSize(const QSize &windowSnapshotSize, const QRect &windowSpaceCaptureRect)
QPixmap grabWindowFromCapturedScreenPixmap(const QOhosPlatformScreen *platformScreen, const QPixmap &capturedWindowPixmap, const QRect &windowSpaceCaptureRect)
bool isDisplayMainOrExtended() const
QtOhos::enums::ohos::display::Orientation JsDisplayOrientation