Changeset View
Changeset View
Standalone View
Standalone View
src/PlatformBackends/KWinWaylandImageGrabber.cpp
Show First 20 Lines • Show All 72 Lines • ▼ Show 20 Line(s) | |||||
73 | 73 | | |||
74 | bool KWinWaylandImageGrabber::onClickGrabSupported() const | 74 | bool KWinWaylandImageGrabber::onClickGrabSupported() const | ||
75 | { | 75 | { | ||
76 | return true; | 76 | return true; | ||
77 | } | 77 | } | ||
78 | 78 | | |||
79 | void KWinWaylandImageGrabber::grabFullScreen() | 79 | void KWinWaylandImageGrabber::grabFullScreen() | ||
80 | { | 80 | { | ||
81 | grab(Mode::FullScreen, mCapturePointer); | 81 | grab(Mode::FullScreen, [this](QPixmap pixmap) { | ||
abalaji: `pixmap` should be a reference to avoid copying | |||||
82 | emit pixmapChanged(pixmap); | ||||
83 | }, mCapturePointer); | ||||
82 | } | 84 | } | ||
83 | 85 | | |||
84 | void KWinWaylandImageGrabber::grabCurrentScreen() | 86 | void KWinWaylandImageGrabber::grabCurrentScreen() | ||
85 | { | 87 | { | ||
86 | grab(Mode::CurrentScreen, mCapturePointer); | 88 | grab(Mode::CurrentScreen, [this](QPixmap pixmap) { | ||
abalaji: `pixmap` should be a reference to avoid copying | |||||
89 | emit pixmapChanged(pixmap); | ||||
90 | }, mCapturePointer); | ||||
87 | } | 91 | } | ||
88 | 92 | | |||
89 | void KWinWaylandImageGrabber::grabActiveWindow() | 93 | void KWinWaylandImageGrabber::grabActiveWindow() | ||
90 | { | 94 | { | ||
91 | // unsupported | 95 | // unsupported | ||
92 | emit pixmapChanged(QPixmap()); | 96 | emit pixmapChanged(QPixmap()); | ||
93 | } | 97 | } | ||
94 | 98 | | |||
99 | void KWinWaylandImageGrabber::rectangleSelectionCancelled() | ||||
100 | { | ||||
101 | QObject *sender = QObject::sender(); | ||||
102 | sender->disconnect(); | ||||
103 | sender->deleteLater(); | ||||
104 | | ||||
105 | emit imageGrabFailed(); | ||||
106 | } | ||||
107 | | ||||
108 | void KWinWaylandImageGrabber::rectangleSelectionConfirmed(const QPixmap &pixmap) | ||||
109 | { | ||||
110 | QObject *sender = QObject::sender(); | ||||
111 | sender->disconnect(); | ||||
112 | sender->deleteLater(); | ||||
113 | | ||||
114 | mPixmap = pixmap; | ||||
115 | emit pixmapChanged(mPixmap); | ||||
116 | } | ||||
117 | | ||||
95 | void KWinWaylandImageGrabber::grabRectangularRegion() | 118 | void KWinWaylandImageGrabber::grabRectangularRegion() | ||
96 | { | 119 | { | ||
97 | // unsupported | 120 | grab(Mode::FullScreen, [this](QPixmap pixmap) { | ||
abalaji: `pixmap` should be a reference to avoid copying | |||||
98 | emit pixmapChanged(QPixmap()); | 121 | if (!pixmap.isNull()) { | ||
122 | QuickEditor *editor = new QuickEditor(pixmap, this); | ||||
123 | | ||||
124 | connect(editor, &QuickEditor::grabDone, this, &KWinWaylandImageGrabber::rectangleSelectionConfirmed); | ||||
125 | connect(editor, &QuickEditor::grabCancelled, this, &KWinWaylandImageGrabber::rectangleSelectionCancelled); | ||||
126 | } else { | ||||
127 | emit pixmapChanged(pixmap); | ||||
128 | } | ||||
129 | }, mCapturePointer); | ||||
99 | } | 130 | } | ||
100 | 131 | | |||
101 | void KWinWaylandImageGrabber::grabWindowUnderCursor() | 132 | void KWinWaylandImageGrabber::grabWindowUnderCursor() | ||
102 | { | 133 | { | ||
103 | int mask = 0; | 134 | int mask = 0; | ||
104 | if (mCaptureDecorations) { | 135 | if (mCaptureDecorations) { | ||
105 | mask = 1; | 136 | mask = 1; | ||
106 | } | 137 | } | ||
107 | if (mCapturePointer) { | 138 | if (mCapturePointer) { | ||
108 | mask |= 1 << 1; | 139 | mask |= 1 << 1; | ||
109 | } | 140 | } | ||
110 | grab(Mode::Window, mask); | 141 | grab(Mode::Window, [this](QPixmap pixmap) { | ||
abalaji: `pixmap` should be a reference to avoid copying | |||||
142 | emit pixmapChanged(pixmap); | ||||
143 | }, mask); | ||||
111 | } | 144 | } | ||
112 | 145 | | |||
113 | void KWinWaylandImageGrabber::grabTransientWithParent() | 146 | void KWinWaylandImageGrabber::grabTransientWithParent() | ||
114 | { | 147 | { | ||
115 | // unsupported, perform grab window under cursor | 148 | // unsupported, perform grab window under cursor | ||
116 | grabWindowUnderCursor(); | 149 | grabWindowUnderCursor(); | ||
117 | } | 150 | } | ||
118 | 151 | | |||
119 | QPixmap KWinWaylandImageGrabber::blendCursorImage(const QPixmap &pixmap, int x, int y, int width, int height) | 152 | QPixmap KWinWaylandImageGrabber::blendCursorImage(const QPixmap &pixmap, int x, int y, int width, int height) | ||
120 | { | 153 | { | ||
121 | Q_UNUSED(x) | 154 | Q_UNUSED(x) | ||
122 | Q_UNUSED(y) | 155 | Q_UNUSED(y) | ||
123 | Q_UNUSED(width) | 156 | Q_UNUSED(width) | ||
124 | Q_UNUSED(height) | 157 | Q_UNUSED(height) | ||
125 | return pixmap; | 158 | return pixmap; | ||
126 | } | 159 | } | ||
127 | 160 | | |||
128 | void KWinWaylandImageGrabber::startReadImage(int readPipe) | 161 | void KWinWaylandImageGrabber::startReadImage(int readPipe, std::function<void(QPixmap)> const& cb) | ||
129 | { | 162 | { | ||
130 | QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this); | 163 | QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this); | ||
131 | QObject::connect(watcher, &QFutureWatcher<QImage>::finished, this, | 164 | QObject::connect(watcher, &QFutureWatcher<QImage>::finished, this, | ||
132 | [watcher, this] { | 165 | [watcher, cb] { | ||
133 | watcher->deleteLater(); | 166 | watcher->deleteLater(); | ||
134 | const QImage img = watcher->result(); | 167 | const QImage img = watcher->result(); | ||
135 | emit pixmapChanged(QPixmap::fromImage(img)); | 168 | cb(QPixmap::fromImage(img)); | ||
136 | } | 169 | } | ||
137 | ); | 170 | ); | ||
138 | watcher->setFuture(QtConcurrent::run(readImage, readPipe)); | 171 | watcher->setFuture(QtConcurrent::run(readImage, readPipe)); | ||
139 | } | 172 | } | ||
140 | 173 | | |||
141 | template <typename T> | 174 | template <typename T> | ||
142 | void KWinWaylandImageGrabber::callDBus(Mode mode, int writeFd, T argument) | 175 | void KWinWaylandImageGrabber::callDBus(Mode mode, int writeFd, T argument) | ||
143 | { | 176 | { | ||
144 | QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); | 177 | QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); | ||
145 | static const QMap<Mode, QString> s_hash = { | 178 | static const QMap<Mode, QString> s_hash = { | ||
146 | {Mode::Window, QStringLiteral("interactive")}, | 179 | {Mode::Window, QStringLiteral("interactive")}, | ||
147 | {Mode::CurrentScreen, QStringLiteral("screenshotScreen")}, | 180 | {Mode::CurrentScreen, QStringLiteral("screenshotScreen")}, | ||
148 | {Mode::FullScreen, QStringLiteral("screenshotFullscreen")} | 181 | {Mode::FullScreen, QStringLiteral("screenshotFullscreen")} | ||
149 | }; | 182 | }; | ||
150 | auto it = s_hash.find(mode); | 183 | auto it = s_hash.find(mode); | ||
151 | Q_ASSERT(it != s_hash.end()); | 184 | Q_ASSERT(it != s_hash.end()); | ||
152 | interface.asyncCall(it.value(), QVariant::fromValue(QDBusUnixFileDescriptor(writeFd)), argument); | 185 | interface.asyncCall(it.value(), QVariant::fromValue(QDBusUnixFileDescriptor(writeFd)), argument); | ||
153 | } | 186 | } | ||
154 | 187 | | |||
155 | template <typename T> | 188 | template <typename T> | ||
156 | void KWinWaylandImageGrabber::grab(Mode mode, T argument) | 189 | void KWinWaylandImageGrabber::grab(Mode mode, std::function<void(QPixmap)> const& cb, T argument) | ||
157 | { | 190 | { | ||
158 | int pipeFds[2]; | 191 | int pipeFds[2]; | ||
159 | if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) { | 192 | if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) { | ||
160 | emit imageGrabFailed(); | 193 | emit imageGrabFailed(); | ||
161 | return; | 194 | return; | ||
162 | } | 195 | } | ||
163 | 196 | | |||
164 | callDBus(mode, pipeFds[1], argument); | 197 | callDBus(mode, pipeFds[1], argument); | ||
165 | startReadImage(pipeFds[0]); | 198 | startReadImage(pipeFds[0], cb); | ||
166 | 199 | | |||
167 | close(pipeFds[1]); | 200 | close(pipeFds[1]); | ||
168 | } | 201 | } |
pixmap should be a reference to avoid copying