File indexing completed on 2024-11-10 04:57:42
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "cursor.h" 0011 // kwin 0012 #include "compositor.h" 0013 #include "core/output.h" 0014 #include "cursorsource.h" 0015 #include "input.h" 0016 #include "keyboard_input.h" 0017 #include "main.h" 0018 #include "scene/workspacescene.h" 0019 #include "utils/common.h" 0020 #include "utils/xcbutils.h" 0021 // KDE 0022 #include <KConfig> 0023 #include <KConfigGroup> 0024 // Qt 0025 #include <QAbstractEventDispatcher> 0026 #include <QDBusConnection> 0027 #include <QScreen> 0028 #include <QTimer> 0029 0030 #include <xcb/xcb_cursor.h> 0031 0032 namespace KWin 0033 { 0034 Cursors *Cursors::s_self = nullptr; 0035 Cursors *Cursors::self() 0036 { 0037 if (!s_self) { 0038 s_self = new Cursors; 0039 } 0040 return s_self; 0041 } 0042 0043 void Cursors::addCursor(Cursor *cursor) 0044 { 0045 Q_ASSERT(!m_cursors.contains(cursor)); 0046 m_cursors += cursor; 0047 0048 connect(cursor, &Cursor::posChanged, this, [this, cursor](const QPointF &pos) { 0049 setCurrentCursor(cursor); 0050 Q_EMIT positionChanged(cursor, pos); 0051 }); 0052 } 0053 0054 void Cursors::removeCursor(Cursor *cursor) 0055 { 0056 m_cursors.removeOne(cursor); 0057 if (m_currentCursor == cursor) { 0058 if (m_cursors.isEmpty()) { 0059 m_currentCursor = nullptr; 0060 } else { 0061 setCurrentCursor(m_cursors.constFirst()); 0062 } 0063 } 0064 if (m_mouse == cursor) { 0065 m_mouse = nullptr; 0066 } 0067 } 0068 0069 void Cursors::hideCursor() 0070 { 0071 m_cursorHideCounter++; 0072 if (m_cursorHideCounter == 1) { 0073 Q_EMIT hiddenChanged(); 0074 } 0075 } 0076 0077 void Cursors::showCursor() 0078 { 0079 m_cursorHideCounter--; 0080 if (m_cursorHideCounter == 0) { 0081 Q_EMIT hiddenChanged(); 0082 } 0083 } 0084 0085 bool Cursors::isCursorHidden() const 0086 { 0087 return m_cursorHideCounter > 0; 0088 } 0089 0090 void Cursors::setCurrentCursor(Cursor *cursor) 0091 { 0092 if (m_currentCursor == cursor) { 0093 return; 0094 } 0095 0096 Q_ASSERT(m_cursors.contains(cursor) || !cursor); 0097 0098 if (m_currentCursor) { 0099 disconnect(m_currentCursor, &Cursor::cursorChanged, this, &Cursors::emitCurrentCursorChanged); 0100 } 0101 m_currentCursor = cursor; 0102 connect(m_currentCursor, &Cursor::cursorChanged, this, &Cursors::emitCurrentCursorChanged); 0103 0104 Q_EMIT currentCursorChanged(m_currentCursor); 0105 } 0106 0107 void Cursors::emitCurrentCursorChanged() 0108 { 0109 Q_EMIT currentCursorChanged(m_currentCursor); 0110 } 0111 0112 Cursor::Cursor() 0113 : m_mousePollingCounter(0) 0114 , m_cursorTrackingCounter(0) 0115 , m_themeName(defaultThemeName()) 0116 , m_themeSize(defaultThemeSize()) 0117 { 0118 loadThemeSettings(); 0119 QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KGlobalSettings"), QStringLiteral("org.kde.KGlobalSettings"), 0120 QStringLiteral("notifyChange"), this, SLOT(slotKGlobalSettingsNotifyChange(int, int))); 0121 0122 if (kwinApp()->operationMode() != Application::OperationModeWaylandOnly) { 0123 connect(kwinApp(), &Application::x11ConnectionChanged, this, [this]() { 0124 m_cursors.clear(); 0125 }); 0126 } 0127 } 0128 0129 Cursor::~Cursor() 0130 { 0131 Cursors::self()->removeCursor(this); 0132 } 0133 0134 void Cursor::loadThemeSettings() 0135 { 0136 QString themeName = QString::fromUtf8(qgetenv("XCURSOR_THEME")); 0137 bool ok = false; 0138 // XCURSOR_SIZE might not be set (e.g. by startkde) 0139 const uint themeSize = qEnvironmentVariableIntValue("XCURSOR_SIZE", &ok); 0140 if (!themeName.isEmpty() && ok) { 0141 updateTheme(themeName, themeSize); 0142 return; 0143 } 0144 // didn't get from environment variables, read from config file 0145 loadThemeFromKConfig(); 0146 } 0147 0148 void Cursor::loadThemeFromKConfig() 0149 { 0150 KConfigGroup mousecfg(kwinApp()->inputConfig(), QStringLiteral("Mouse")); 0151 const QString themeName = mousecfg.readEntry("cursorTheme", defaultThemeName()); 0152 const uint themeSize = mousecfg.readEntry("cursorSize", defaultThemeSize()); 0153 updateTheme(themeName, themeSize); 0154 } 0155 0156 void Cursor::updateTheme(const QString &name, int size) 0157 { 0158 if (m_themeName != name || m_themeSize != size) { 0159 m_themeName = name; 0160 m_themeSize = size; 0161 m_cursors.clear(); 0162 Q_EMIT themeChanged(); 0163 } 0164 } 0165 0166 void Cursor::slotKGlobalSettingsNotifyChange(int type, int arg) 0167 { 0168 if (type == 5 /*CursorChanged*/) { 0169 kwinApp()->inputConfig()->reparseConfiguration(); 0170 loadThemeFromKConfig(); 0171 } 0172 } 0173 0174 bool Cursor::isOnOutput(Output *output) const 0175 { 0176 if (Cursors::self()->isCursorHidden()) { 0177 return false; 0178 } 0179 return geometry().intersects(output->geometry()); 0180 } 0181 0182 QPointF Cursor::hotspot() const 0183 { 0184 if (Q_UNLIKELY(!m_source)) { 0185 return QPointF(); 0186 } 0187 return m_source->hotspot(); 0188 } 0189 0190 QRectF Cursor::geometry() const 0191 { 0192 return rect().translated(m_pos - hotspot()); 0193 } 0194 0195 QRectF Cursor::rect() const 0196 { 0197 if (Q_UNLIKELY(!m_source)) { 0198 return QRectF(); 0199 } else { 0200 return QRectF(QPointF(0, 0), m_source->size()); 0201 } 0202 } 0203 0204 QPointF Cursor::pos() 0205 { 0206 doGetPos(); 0207 return m_pos; 0208 } 0209 0210 void Cursor::setPos(const QPointF &pos) 0211 { 0212 // first query the current pos to not warp to the already existing pos 0213 if (pos == m_pos) { 0214 return; 0215 } 0216 m_pos = pos; 0217 doSetPos(); 0218 } 0219 0220 void Cursor::markAsRendered(std::chrono::milliseconds timestamp) 0221 { 0222 Q_EMIT rendered(timestamp); 0223 } 0224 0225 xcb_cursor_t Cursor::x11Cursor(CursorShape shape) 0226 { 0227 return x11Cursor(shape.name()); 0228 } 0229 0230 xcb_cursor_t Cursor::x11Cursor(const QByteArray &name) 0231 { 0232 Q_ASSERT(kwinApp()->x11Connection()); 0233 auto it = m_cursors.constFind(name); 0234 if (it != m_cursors.constEnd()) { 0235 return it.value(); 0236 } 0237 0238 if (name.isEmpty()) { 0239 return XCB_CURSOR_NONE; 0240 } 0241 0242 xcb_cursor_context_t *ctx; 0243 if (xcb_cursor_context_new(kwinApp()->x11Connection(), Xcb::defaultScreen(), &ctx) < 0) { 0244 return XCB_CURSOR_NONE; 0245 } 0246 0247 xcb_cursor_t cursor = xcb_cursor_load_cursor(ctx, name.constData()); 0248 if (cursor == XCB_CURSOR_NONE) { 0249 const auto &names = CursorShape::alternatives(name); 0250 for (const QByteArray &cursorName : names) { 0251 cursor = xcb_cursor_load_cursor(ctx, cursorName.constData()); 0252 if (cursor != XCB_CURSOR_NONE) { 0253 break; 0254 } 0255 } 0256 } 0257 if (cursor != XCB_CURSOR_NONE) { 0258 m_cursors.insert(name, cursor); 0259 } 0260 0261 xcb_cursor_context_free(ctx); 0262 return cursor; 0263 } 0264 0265 void Cursor::doSetPos() 0266 { 0267 Q_EMIT posChanged(m_pos); 0268 } 0269 0270 void Cursor::doGetPos() 0271 { 0272 } 0273 0274 void Cursor::updatePos(const QPointF &pos) 0275 { 0276 if (m_pos == pos) { 0277 return; 0278 } 0279 m_pos = pos; 0280 Q_EMIT posChanged(m_pos); 0281 } 0282 0283 void Cursor::startMousePolling() 0284 { 0285 ++m_mousePollingCounter; 0286 if (m_mousePollingCounter == 1) { 0287 doStartMousePolling(); 0288 } 0289 } 0290 0291 void Cursor::stopMousePolling() 0292 { 0293 Q_ASSERT(m_mousePollingCounter > 0); 0294 --m_mousePollingCounter; 0295 if (m_mousePollingCounter == 0) { 0296 doStopMousePolling(); 0297 } 0298 } 0299 0300 void Cursor::doStartMousePolling() 0301 { 0302 } 0303 0304 void Cursor::doStopMousePolling() 0305 { 0306 } 0307 0308 void Cursor::startCursorTracking() 0309 { 0310 ++m_cursorTrackingCounter; 0311 if (m_cursorTrackingCounter == 1) { 0312 doStartCursorTracking(); 0313 } 0314 } 0315 0316 void Cursor::stopCursorTracking() 0317 { 0318 Q_ASSERT(m_cursorTrackingCounter > 0); 0319 --m_cursorTrackingCounter; 0320 if (m_cursorTrackingCounter == 0) { 0321 doStopCursorTracking(); 0322 } 0323 } 0324 0325 void Cursor::doStartCursorTracking() 0326 { 0327 } 0328 0329 void Cursor::doStopCursorTracking() 0330 { 0331 } 0332 0333 QString Cursor::defaultThemeName() 0334 { 0335 return QStringLiteral("default"); 0336 } 0337 0338 int Cursor::defaultThemeSize() 0339 { 0340 return 24; 0341 } 0342 0343 QList<QByteArray> CursorShape::alternatives(const QByteArray &name) 0344 { 0345 static const QHash<QByteArray, QList<QByteArray>> alternatives = { 0346 { 0347 QByteArrayLiteral("crosshair"), 0348 { 0349 QByteArrayLiteral("cross"), 0350 QByteArrayLiteral("diamond-cross"), 0351 QByteArrayLiteral("cross-reverse"), 0352 }, 0353 }, 0354 { 0355 QByteArrayLiteral("default"), 0356 { 0357 QByteArrayLiteral("left_ptr"), 0358 QByteArrayLiteral("arrow"), 0359 QByteArrayLiteral("dnd-none"), 0360 QByteArrayLiteral("op_left_arrow"), 0361 }, 0362 }, 0363 { 0364 QByteArrayLiteral("up-arrow"), 0365 { 0366 QByteArrayLiteral("up_arrow"), 0367 QByteArrayLiteral("sb_up_arrow"), 0368 QByteArrayLiteral("center_ptr"), 0369 QByteArrayLiteral("centre_ptr"), 0370 }, 0371 }, 0372 { 0373 QByteArrayLiteral("wait"), 0374 { 0375 QByteArrayLiteral("watch"), 0376 QByteArrayLiteral("progress"), 0377 }, 0378 }, 0379 { 0380 QByteArrayLiteral("text"), 0381 { 0382 QByteArrayLiteral("ibeam"), 0383 QByteArrayLiteral("xterm"), 0384 }, 0385 }, 0386 { 0387 QByteArrayLiteral("all-scroll"), 0388 { 0389 QByteArrayLiteral("size_all"), 0390 QByteArrayLiteral("fleur"), 0391 }, 0392 }, 0393 { 0394 QByteArrayLiteral("pointer"), 0395 { 0396 QByteArrayLiteral("pointing_hand"), 0397 QByteArrayLiteral("hand2"), 0398 QByteArrayLiteral("hand"), 0399 QByteArrayLiteral("hand1"), 0400 QByteArrayLiteral("e29285e634086352946a0e7090d73106"), 0401 QByteArrayLiteral("9d800788f1b08800ae810202380a0822"), 0402 }, 0403 }, 0404 { 0405 QByteArrayLiteral("ns-resize"), 0406 { 0407 QByteArrayLiteral("size_ver"), 0408 QByteArrayLiteral("00008160000006810000408080010102"), 0409 QByteArrayLiteral("sb_v_double_arrow"), 0410 QByteArrayLiteral("v_double_arrow"), 0411 QByteArrayLiteral("n-resize"), 0412 QByteArrayLiteral("s-resize"), 0413 QByteArrayLiteral("col-resize"), 0414 QByteArrayLiteral("top_side"), 0415 QByteArrayLiteral("bottom_side"), 0416 QByteArrayLiteral("base_arrow_up"), 0417 QByteArrayLiteral("base_arrow_down"), 0418 QByteArrayLiteral("based_arrow_down"), 0419 QByteArrayLiteral("based_arrow_up"), 0420 }, 0421 }, 0422 { 0423 QByteArrayLiteral("ew-resize"), 0424 { 0425 QByteArrayLiteral("size_hor"), 0426 QByteArrayLiteral("028006030e0e7ebffc7f7070c0600140"), 0427 QByteArrayLiteral("sb_h_double_arrow"), 0428 QByteArrayLiteral("h_double_arrow"), 0429 QByteArrayLiteral("e-resize"), 0430 QByteArrayLiteral("w-resize"), 0431 QByteArrayLiteral("row-resize"), 0432 QByteArrayLiteral("right_side"), 0433 QByteArrayLiteral("left_side"), 0434 }, 0435 }, 0436 { 0437 QByteArrayLiteral("nesw-resize"), 0438 { 0439 QByteArrayLiteral("size_bdiag"), 0440 QByteArrayLiteral("fcf1c3c7cd4491d801f1e1c78f100000"), 0441 QByteArrayLiteral("fd_double_arrow"), 0442 QByteArrayLiteral("bottom_left_corner"), 0443 QByteArrayLiteral("top_right_corner"), 0444 }, 0445 }, 0446 { 0447 QByteArrayLiteral("nwse-resize"), 0448 { 0449 QByteArrayLiteral("size_fdiag"), 0450 QByteArrayLiteral("c7088f0f3e6c8088236ef8e1e3e70000"), 0451 QByteArrayLiteral("bd_double_arrow"), 0452 QByteArrayLiteral("bottom_right_corner"), 0453 QByteArrayLiteral("top_left_corner"), 0454 }, 0455 }, 0456 { 0457 QByteArrayLiteral("help"), 0458 { 0459 QByteArrayLiteral("whats_this"), 0460 QByteArrayLiteral("d9ce0ab605698f320427677b458ad60b"), 0461 QByteArrayLiteral("left_ptr_help"), 0462 QByteArrayLiteral("question_arrow"), 0463 QByteArrayLiteral("dnd-ask"), 0464 QByteArrayLiteral("5c6cd98b3f3ebcb1f9c7f1c204630408"), 0465 }, 0466 }, 0467 { 0468 QByteArrayLiteral("col-resize"), 0469 { 0470 QByteArrayLiteral("split_h"), 0471 QByteArrayLiteral("14fef782d02440884392942c11205230"), 0472 QByteArrayLiteral("size_hor"), 0473 }, 0474 }, 0475 { 0476 QByteArrayLiteral("row-resize"), 0477 { 0478 QByteArrayLiteral("split_v"), 0479 QByteArrayLiteral("2870a09082c103050810ffdffffe0204"), 0480 QByteArrayLiteral("size_ver"), 0481 }, 0482 }, 0483 { 0484 QByteArrayLiteral("not-allowed"), 0485 { 0486 QByteArrayLiteral("forbidden"), 0487 QByteArrayLiteral("03b6e0fcb3499374a867c041f52298f0"), 0488 QByteArrayLiteral("circle"), 0489 QByteArrayLiteral("dnd-no-drop"), 0490 }, 0491 }, 0492 { 0493 QByteArrayLiteral("progress"), 0494 { 0495 QByteArrayLiteral("left_ptr_watch"), 0496 QByteArrayLiteral("3ecb610c1bf2410f44200f48c40d3599"), 0497 QByteArrayLiteral("00000000000000020006000e7e9ffc3f"), 0498 QByteArrayLiteral("08e8e1c95fe2fc01f976f1e063a24ccd"), 0499 }, 0500 }, 0501 { 0502 QByteArrayLiteral("grab"), 0503 { 0504 QByteArrayLiteral("openhand"), 0505 QByteArrayLiteral("9141b49c8149039304290b508d208c40"), 0506 QByteArrayLiteral("all_scroll"), 0507 QByteArrayLiteral("all-scroll"), 0508 }, 0509 }, 0510 { 0511 QByteArrayLiteral("grabbing"), 0512 { 0513 QByteArrayLiteral("closedhand"), 0514 QByteArrayLiteral("05e88622050804100c20044008402080"), 0515 QByteArrayLiteral("4498f0e0c1937ffe01fd06f973665830"), 0516 QByteArrayLiteral("9081237383d90e509aa00f00170e968f"), 0517 QByteArrayLiteral("fcf21c00b30f7e3f83fe0dfd12e71cff"), 0518 }, 0519 }, 0520 { 0521 QByteArrayLiteral("alias"), 0522 { 0523 QByteArrayLiteral("link"), 0524 QByteArrayLiteral("dnd-link"), 0525 QByteArrayLiteral("3085a0e285430894940527032f8b26df"), 0526 QByteArrayLiteral("640fb0e74195791501fd1ed57b41487f"), 0527 QByteArrayLiteral("a2a266d0498c3104214a47bd64ab0fc8"), 0528 }, 0529 }, 0530 { 0531 QByteArrayLiteral("copy"), 0532 { 0533 QByteArrayLiteral("dnd-copy"), 0534 QByteArrayLiteral("1081e37283d90000800003c07f3ef6bf"), 0535 QByteArrayLiteral("6407b0e94181790501fd1e167b474872"), 0536 QByteArrayLiteral("b66166c04f8c3109214a4fbd64a50fc8"), 0537 }, 0538 }, 0539 { 0540 QByteArrayLiteral("move"), 0541 { 0542 QByteArrayLiteral("dnd-move"), 0543 }, 0544 }, 0545 { 0546 QByteArrayLiteral("sw-resize"), 0547 { 0548 QByteArrayLiteral("size_bdiag"), 0549 QByteArrayLiteral("fcf1c3c7cd4491d801f1e1c78f100000"), 0550 QByteArrayLiteral("fd_double_arrow"), 0551 QByteArrayLiteral("bottom_left_corner"), 0552 }, 0553 }, 0554 { 0555 QByteArrayLiteral("se-resize"), 0556 { 0557 QByteArrayLiteral("size_fdiag"), 0558 QByteArrayLiteral("c7088f0f3e6c8088236ef8e1e3e70000"), 0559 QByteArrayLiteral("bd_double_arrow"), 0560 QByteArrayLiteral("bottom_right_corner"), 0561 }, 0562 }, 0563 { 0564 QByteArrayLiteral("ne-resize"), 0565 { 0566 QByteArrayLiteral("size_bdiag"), 0567 QByteArrayLiteral("fcf1c3c7cd4491d801f1e1c78f100000"), 0568 QByteArrayLiteral("fd_double_arrow"), 0569 QByteArrayLiteral("top_right_corner"), 0570 }, 0571 }, 0572 { 0573 QByteArrayLiteral("nw-resize"), 0574 { 0575 QByteArrayLiteral("size_fdiag"), 0576 QByteArrayLiteral("c7088f0f3e6c8088236ef8e1e3e70000"), 0577 QByteArrayLiteral("bd_double_arrow"), 0578 QByteArrayLiteral("top_left_corner"), 0579 }, 0580 }, 0581 { 0582 QByteArrayLiteral("n-resize"), 0583 { 0584 QByteArrayLiteral("size_ver"), 0585 QByteArrayLiteral("00008160000006810000408080010102"), 0586 QByteArrayLiteral("sb_v_double_arrow"), 0587 QByteArrayLiteral("v_double_arrow"), 0588 QByteArrayLiteral("col-resize"), 0589 QByteArrayLiteral("top_side"), 0590 }, 0591 }, 0592 { 0593 QByteArrayLiteral("e-resize"), 0594 { 0595 QByteArrayLiteral("size_hor"), 0596 QByteArrayLiteral("028006030e0e7ebffc7f7070c0600140"), 0597 QByteArrayLiteral("sb_h_double_arrow"), 0598 QByteArrayLiteral("h_double_arrow"), 0599 QByteArrayLiteral("row-resize"), 0600 QByteArrayLiteral("left_side"), 0601 }, 0602 }, 0603 { 0604 QByteArrayLiteral("s-resize"), 0605 { 0606 QByteArrayLiteral("size_ver"), 0607 QByteArrayLiteral("00008160000006810000408080010102"), 0608 QByteArrayLiteral("sb_v_double_arrow"), 0609 QByteArrayLiteral("v_double_arrow"), 0610 QByteArrayLiteral("col-resize"), 0611 QByteArrayLiteral("bottom_side"), 0612 }, 0613 }, 0614 { 0615 QByteArrayLiteral("w-resize"), 0616 { 0617 QByteArrayLiteral("size_hor"), 0618 QByteArrayLiteral("028006030e0e7ebffc7f7070c0600140"), 0619 QByteArrayLiteral("sb_h_double_arrow"), 0620 QByteArrayLiteral("h_double_arrow"), 0621 QByteArrayLiteral("right_side"), 0622 }, 0623 }, 0624 }; 0625 auto it = alternatives.find(name); 0626 if (it != alternatives.end()) { 0627 return it.value(); 0628 } 0629 return QList<QByteArray>(); 0630 } 0631 0632 QByteArray CursorShape::name() const 0633 { 0634 switch (m_shape) { 0635 case Qt::ArrowCursor: 0636 return QByteArrayLiteral("default"); 0637 case Qt::UpArrowCursor: 0638 return QByteArrayLiteral("up-arrow"); 0639 case Qt::CrossCursor: 0640 return QByteArrayLiteral("crosshair"); 0641 case Qt::WaitCursor: 0642 return QByteArrayLiteral("wait"); 0643 case Qt::IBeamCursor: 0644 return QByteArrayLiteral("text"); 0645 case Qt::SizeVerCursor: 0646 return QByteArrayLiteral("ns-resize"); 0647 case Qt::SizeHorCursor: 0648 return QByteArrayLiteral("ew-resize"); 0649 case Qt::SizeBDiagCursor: 0650 return QByteArrayLiteral("nesw-resize"); 0651 case Qt::SizeFDiagCursor: 0652 return QByteArrayLiteral("nwse-resize"); 0653 case Qt::SizeAllCursor: 0654 return QByteArrayLiteral("all-scroll"); 0655 case Qt::SplitVCursor: 0656 return QByteArrayLiteral("row-resize"); 0657 case Qt::SplitHCursor: 0658 return QByteArrayLiteral("col-resize"); 0659 case Qt::PointingHandCursor: 0660 return QByteArrayLiteral("pointer"); 0661 case Qt::ForbiddenCursor: 0662 return QByteArrayLiteral("not-allowed"); 0663 case Qt::OpenHandCursor: 0664 return QByteArrayLiteral("grab"); 0665 case Qt::ClosedHandCursor: 0666 return QByteArrayLiteral("grabbing"); 0667 case Qt::WhatsThisCursor: 0668 return QByteArrayLiteral("help"); 0669 case Qt::BusyCursor: 0670 return QByteArrayLiteral("progress"); 0671 case Qt::DragMoveCursor: 0672 return QByteArrayLiteral("move"); 0673 case Qt::DragCopyCursor: 0674 return QByteArrayLiteral("copy"); 0675 case Qt::DragLinkCursor: 0676 return QByteArrayLiteral("alias"); 0677 case KWin::ExtendedCursor::SizeNorthEast: 0678 return QByteArrayLiteral("ne-resize"); 0679 case KWin::ExtendedCursor::SizeNorth: 0680 return QByteArrayLiteral("n-resize"); 0681 case KWin::ExtendedCursor::SizeNorthWest: 0682 return QByteArrayLiteral("nw-resize"); 0683 case KWin::ExtendedCursor::SizeEast: 0684 return QByteArrayLiteral("e-resize"); 0685 case KWin::ExtendedCursor::SizeWest: 0686 return QByteArrayLiteral("w-resize"); 0687 case KWin::ExtendedCursor::SizeSouthEast: 0688 return QByteArrayLiteral("se-resize"); 0689 case KWin::ExtendedCursor::SizeSouth: 0690 return QByteArrayLiteral("s-resize"); 0691 case KWin::ExtendedCursor::SizeSouthWest: 0692 return QByteArrayLiteral("sw-resize"); 0693 default: 0694 return QByteArray(); 0695 } 0696 } 0697 0698 CursorSource *Cursor::source() const 0699 { 0700 return m_source; 0701 } 0702 0703 void Cursor::setSource(CursorSource *source) 0704 { 0705 if (m_source == source) { 0706 return; 0707 } 0708 if (m_source) { 0709 disconnect(m_source, &CursorSource::changed, this, &Cursor::cursorChanged); 0710 } 0711 m_source = source; 0712 connect(m_source, &CursorSource::changed, this, &Cursor::cursorChanged); 0713 Q_EMIT cursorChanged(); 0714 } 0715 0716 } // namespace 0717 0718 #include "moc_cursor.cpp"