7#include <qpa/qwindowsysteminterface.h>
9#include <qohosdisplayinfo.h>
16#include "render/qohosview.h"
18#include <multimedia/image_framework/image/pixelmap_native.h>
20#include <qarkui/qarkuiutils.h>
21#include <qguiapplication.h>
22#include <qohosapppermissions_p.h>
23#include <qohosjsutils.h>
24#include <QtGui/private/qohosimageconversions_p.h>
25#include <qohospixelmapconversions.h>
26#include <qohosutils.h>
27#include <render/qwindowproxyregistry.h>
28#include <window_manager/oh_display_capture.h>
30#include <QtGui/QGuiApplication>
31#include <QtGui/QWindow>
32#include <QtCore/private/qnapi_p.h>
33#include <QtCore/private/qohoslogger_p.h>
34#include <QtGui/private/qhighdpiscaling_p.h>
35#include <QtGui/private/qwindow_p.h>
48 ::OH_PixelmapNative *pixelMapNativePtr;
50 QArkUi::callArkUiOrFailOnErrorResult(
51 Q_OHOS_NAMED_FUNC(::OH_NativeDisplayManager_CaptureScreenPixelmap),
52 static_cast<
std::uint32_t>(displayId.value()), &pixelMapNativePtr);
54 return wrapOhosNativePixelMapPtr(pixelMapNativePtr);
59 QOhosConsumer<std::shared_ptr<::OH_PixelmapNative>> pixelMapOrNullConsumer)
61 static constexpr const char *ohosCustomScreenCapturePermission =
62 "ohos.permission.CUSTOM_SCREEN_CAPTURE";
65 jsState, ohosCustomScreenCapturePermission,
66 [pixelMapOrNullConsumer = std::move(pixelMapOrNullConsumer), displayId](
67 auto &jsState,
bool permissionGranted) {
68 if (permissionGranted) {
69 pixelMapOrNullConsumer(captureScreenPixelmap(jsState, displayId));
72 "%s: %s hasn't been granted by user. Cannot grab window.", Q_FUNC_INFO,
73 ohosCustomScreenCapturePermission);
74 pixelMapOrNullConsumer(
nullptr);
81 auto allWindows =
qApp->allWindows();
82 auto windowItByWId =
std::find_if(
83 std::begin(allWindows),
std::end(allWindows),
85 return w->winId() == wId;
88 if (windowItByWId == allWindows.end())
91 return *windowItByWId;
95 const QSize &windowSnapshotSize,
const QRect &windowSpaceCaptureRect)
98 windowSpaceCaptureRect.width() < 0
99 ? qMax(0, windowSnapshotSize.width() - windowSpaceCaptureRect.x())
100 : windowSpaceCaptureRect.width(),
101 windowSpaceCaptureRect.height() < 0
102 ? qMax(0, windowSnapshotSize.height() - windowSpaceCaptureRect.y())
103 : windowSpaceCaptureRect.height()
108 const QRect &windowSpaceCaptureRect,
const QRect &windowFragmentRect)
111 qAbs(windowSpaceCaptureRect.x() - windowFragmentRect.x()),
112 qAbs(windowSpaceCaptureRect.y() - windowFragmentRect.y()),
113 windowFragmentRect.width(),
114 windowFragmentRect.height()
120 const QRect &windowSpaceCaptureRect)
122 auto resultSize = calculateResultWindowCapturePixmapSize(
123 QHighDpi::fromNativePixels(capturedWindowPixmap.size(), platformScreen),
124 windowSpaceCaptureRect);
126 if (resultSize.isEmpty())
129 auto windowFragmentRect = capturedWindowPixmap.rect().intersected(
130 QRect(windowSpaceCaptureRect.topLeft(), resultSize));
132 if (windowFragmentRect.isEmpty())
133 return QPixmap(resultSize);
135 auto resultSpaceWindowFragmentRect =
136 calculateResultPixmapWindowFragmentRect(windowSpaceCaptureRect, windowFragmentRect);
138 QPixmap result(resultSize);
141 QHighDpi::toNativePixels(resultSpaceWindowFragmentRect, platformScreen),
142 capturedWindowPixmap,
143 QHighDpi::toNativePixels(windowFragmentRect, platformScreen));
152 switch (jsDisplayOrientation) {
153 case JsDisplayOrientation::PORTRAIT:
154 return Qt::ScreenOrientation::PortraitOrientation;
155 case JsDisplayOrientation::LANDSCAPE:
156 return Qt::ScreenOrientation::LandscapeOrientation;
157 case JsDisplayOrientation::PORTRAIT_INVERTED:
158 return Qt::ScreenOrientation::InvertedPortraitOrientation;
159 case JsDisplayOrientation::LANDSCAPE_INVERTED:
160 return Qt::ScreenOrientation::InvertedLandscapeOrientation;
171 , m_format(QImage::Format_ARGB32_Premultiplied)
173 , m_platformCursor(
new QOhosPlatformCursor())
174 , m_displayInfo(displayInfo)
175 , m_availableGeometry(getAvailableArea())
176 , m_platformScreenListSupplier(std::move(platformScreenListSupplier))
178 auto __dbg = make_QCScopedDebug(
"QOhosPlatformScreen::QOhosPlatformScreen");
185 auto *platformScreen = screen->handle();
186 if (Q_UNLIKELY(platformScreen ==
nullptr))
187 qOhosReportFatalErrorAndAbort(
"QScreen::handle() returned null");
193 for (
auto *platformScreen : virtualSiblings()) {
194 auto *ohosPlatformScreen =
static_cast<QOhosPlatformScreen *>(platformScreen);
196 auto windowIds = QOhosWindowProxy::queryWindowIdsByCoordinate(ohosPlatformScreen->m_displayInfo.id, p);
197 if (!windowIds.empty())
198 return QWindowProxyRegistry::instance().findQWindowByJsWindowIdOrNull(windowIds.front());
206 return m_platformCursor.data();
211 auto geometryChanged = displayInfo.displayGeometryPixels() != m_displayInfo.displayGeometryPixels();
212 auto logicalDpiChanged = displayInfo.densityDPI != m_displayInfo.densityDPI;
214 QVector<QPair<QWindow *, std::optional<QRect>>> windowRectPairs;
216 if (logicalDpiChanged) {
217 for (
auto *window :
qGuiApp->allWindows()) {
218 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
219 if (platformWindow ==
nullptr || platformWindow->screen() !=
this || !window->isVisible())
222 auto *ownedView = platformWindow->ownedViewOrNull();
223 if (ownedView ==
nullptr)
226 windowRectPairs.push_back({
228 ownedView->viewType() == QOhosView::ViewType::EmbeddedWindow
229 ? std::optional(window->geometry())
234 m_displayInfo = displayInfo;
237 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
239 if (logicalDpiChanged) {
240 auto ldpi = logicalDpi();
241 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(
242 screen(), ldpi.first, ldpi.second);
244 QWindowSystemInterface::flushWindowSystemEvents();
246 for (
const auto &windowRectPair : windowRectPairs) {
247 auto *qWindow = windowRectPair.first;
248 auto *platformWindow = QOhosPlatformWindow::fromQWindow(qWindow);
249 if (windowRectPair.second.has_value())
250 qWindow->setGeometry(windowRectPair.second.value());
251 platformWindow->handleDpiChange();
258 qreal lDpi = m_displayInfo.densityPixels * ohosLogicalDpi;
259 return QDpi(lDpi, lDpi);
266 return m_displayInfo.densityPixels;
271 return m_displayInfo.refreshRate;
282 qAndThen(m_displayInfo.orientation, tryMapJsDisplayOrientationToQt)
283 .value_or(Qt::ScreenOrientation::PrimaryOrientation);
288 return Qt::ScreenOrientation::PrimaryOrientation;
293 return QtOhos::evalInJsThreadWithPromise<QRect>(
294 [&](QtOhos::JsState &jsState, QOhosTaskPromise<QRect> evalPromise) {
296 QNapi::Object display;
298 display = jsState.eval<QNapi::Object>(
299 "@ohos.display.getDisplayByIdSync(*)", {m_displayInfo.id.value()});
300 }
catch (
const Napi::Error &error) {
302 "%s: getDisplayByIdSync(%f) failed with error: %s",
303 Q_FUNC_INFO, m_displayInfo.id.value(), error.Message().c_str());
304 evalPromise(QRect());
308 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
309 display.evalToPromiseOrRejectOnThrow(
"getAvailableArea()")
311 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
312 auto availableArea = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
315 availableArea.get<QNapi::Number>(
"left"),
316 availableArea.get<QNapi::Number>(
"top"),
317 availableArea.get<QNapi::Number>(
"width"),
318 availableArea.get<QNapi::Number>(
"height")));
321 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
322 QtOhos::logJsCallbackError(cbInfo,
"Error occurred in JS getAvailableArea()");
323 catchPromise(QRect());
335 return m_displayInfo;
340 return m_displayInfo.id.value();
345 return m_displayInfo.displayGeometryPixels();
350 auto screenGeometry = geometry();
351 return !m_availableGeometry.isEmpty()
352 ? m_availableGeometry.translated(screenGeometry.topLeft())
368 return m_displayInfo.physicalSize();
373 if (rect != m_availableGeometry) {
374 m_availableGeometry = rect;
375 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
381 if (!m_displayInfo.isDisplayMainOrExtended())
382 return QPlatformScreen::virtualSiblings();
384 QList<QPlatformScreen *> result;
385 auto allPlatformScreens = m_platformScreenListSupplier();
387 allPlatformScreens.begin(), allPlatformScreens.end(),
388 std::back_inserter(result),
398 auto captureRect = QRect(x, y, width, height);
401 auto *window = tryFindWindowByWIdOrNull(wId);
402 if (window ==
nullptr) {
404 "%s: Cannot find window with the given WId: %lld.", Q_FUNC_INFO, wId);
407 return grabWindowFromCapturedScreenPixmap(
408 this, QOhosPlatformWindow::fromQWindow(window)->makeSnapshot(), captureRect);
411 auto capturedScreenPixmap = QtOhos::evalInJsThreadWithPromise<QPixmap>(
412 [displayId = m_displayInfo.id](
413 QtOhos::JsState &jsState, QOhosTaskPromise<QPixmap> evalPromise) {
414 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
415 tryCaptureScreenPixelmapWithPermissionCheck(
418 std::shared_ptr<::OH_PixelmapNative> optPixelMap) {
419 (*sharedEvalPromise)(
421 ? QPixmap::fromImage(createQImageFromNativePixelMap(optPixelMap.get()))
427 return capturedScreenPixmap.copy(captureRect);
432 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)
std::optional< Qt::ScreenOrientation > tryMapJsDisplayOrientationToQt(QOhosDisplayInfo::JsDisplayOrientation jsDisplayOrientation)
void tryCaptureScreenPixelmapWithPermissionCheck(QtOhos::JsState &jsState, QOhosDisplayInfo::JsDisplayId displayId, QOhosConsumer< std::shared_ptr<::OH_PixelmapNative > > pixelMapOrNullConsumer)
static const int ohosLogicalDpi
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