File indexing completed on 2025-03-23 08:10:38
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 = Cursor::cursorAlternativeNames(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 QList<QByteArray> Cursor::cursorAlternativeNames(const QByteArray &name) 0334 { 0335 static const QHash<QByteArray, QList<QByteArray>> alternatives = { 0336 { 0337 QByteArrayLiteral("crosshair"), 0338 { 0339 QByteArrayLiteral("cross"), 0340 QByteArrayLiteral("diamond-cross"), 0341 QByteArrayLiteral("cross-reverse"), 0342 }, 0343 }, 0344 { 0345 QByteArrayLiteral("default"), 0346 { 0347 QByteArrayLiteral("left_ptr"), 0348 QByteArrayLiteral("arrow"), 0349 QByteArrayLiteral("dnd-none"), 0350 QByteArrayLiteral("op_left_arrow"), 0351 }, 0352 }, 0353 { 0354 QByteArrayLiteral("up-arrow"), 0355 { 0356 QByteArrayLiteral("up_arrow"), 0357 QByteArrayLiteral("sb_up_arrow"), 0358 QByteArrayLiteral("center_ptr"), 0359 QByteArrayLiteral("centre_ptr"), 0360 }, 0361 }, 0362 { 0363 QByteArrayLiteral("wait"), 0364 { 0365 QByteArrayLiteral("watch"), 0366 QByteArrayLiteral("progress"), 0367 }, 0368 }, 0369 { 0370 QByteArrayLiteral("text"), 0371 { 0372 QByteArrayLiteral("ibeam"), 0373 QByteArrayLiteral("xterm"), 0374 }, 0375 }, 0376 { 0377 QByteArrayLiteral("all-scroll"), 0378 { 0379 QByteArrayLiteral("size_all"), 0380 QByteArrayLiteral("fleur"), 0381 }, 0382 }, 0383 { 0384 QByteArrayLiteral("pointer"), 0385 { 0386 QByteArrayLiteral("pointing_hand"), 0387 QByteArrayLiteral("hand2"), 0388 QByteArrayLiteral("hand"), 0389 QByteArrayLiteral("hand1"), 0390 QByteArrayLiteral("e29285e634086352946a0e7090d73106"), 0391 QByteArrayLiteral("9d800788f1b08800ae810202380a0822"), 0392 }, 0393 }, 0394 { 0395 QByteArrayLiteral("ns-resize"), 0396 { 0397 QByteArrayLiteral("size_ver"), 0398 QByteArrayLiteral("00008160000006810000408080010102"), 0399 QByteArrayLiteral("sb_v_double_arrow"), 0400 QByteArrayLiteral("v_double_arrow"), 0401 QByteArrayLiteral("n-resize"), 0402 QByteArrayLiteral("s-resize"), 0403 QByteArrayLiteral("col-resize"), 0404 QByteArrayLiteral("top_side"), 0405 QByteArrayLiteral("bottom_side"), 0406 QByteArrayLiteral("base_arrow_up"), 0407 QByteArrayLiteral("base_arrow_down"), 0408 QByteArrayLiteral("based_arrow_down"), 0409 QByteArrayLiteral("based_arrow_up"), 0410 }, 0411 }, 0412 { 0413 QByteArrayLiteral("ew-resize"), 0414 { 0415 QByteArrayLiteral("size_hor"), 0416 QByteArrayLiteral("028006030e0e7ebffc7f7070c0600140"), 0417 QByteArrayLiteral("sb_h_double_arrow"), 0418 QByteArrayLiteral("h_double_arrow"), 0419 QByteArrayLiteral("e-resize"), 0420 QByteArrayLiteral("w-resize"), 0421 QByteArrayLiteral("row-resize"), 0422 QByteArrayLiteral("right_side"), 0423 QByteArrayLiteral("left_side"), 0424 }, 0425 }, 0426 { 0427 QByteArrayLiteral("nesw-resize"), 0428 { 0429 QByteArrayLiteral("size_bdiag"), 0430 QByteArrayLiteral("fcf1c3c7cd4491d801f1e1c78f100000"), 0431 QByteArrayLiteral("fd_double_arrow"), 0432 QByteArrayLiteral("bottom_left_corner"), 0433 QByteArrayLiteral("top_right_corner"), 0434 }, 0435 }, 0436 { 0437 QByteArrayLiteral("nwse-resize"), 0438 { 0439 QByteArrayLiteral("size_fdiag"), 0440 QByteArrayLiteral("c7088f0f3e6c8088236ef8e1e3e70000"), 0441 QByteArrayLiteral("bd_double_arrow"), 0442 QByteArrayLiteral("bottom_right_corner"), 0443 QByteArrayLiteral("top_left_corner"), 0444 }, 0445 }, 0446 { 0447 QByteArrayLiteral("help"), 0448 { 0449 QByteArrayLiteral("whats_this"), 0450 QByteArrayLiteral("d9ce0ab605698f320427677b458ad60b"), 0451 QByteArrayLiteral("left_ptr_help"), 0452 QByteArrayLiteral("question_arrow"), 0453 QByteArrayLiteral("dnd-ask"), 0454 QByteArrayLiteral("5c6cd98b3f3ebcb1f9c7f1c204630408"), 0455 }, 0456 }, 0457 { 0458 QByteArrayLiteral("col-resize"), 0459 { 0460 QByteArrayLiteral("split_h"), 0461 QByteArrayLiteral("14fef782d02440884392942c11205230"), 0462 QByteArrayLiteral("size_hor"), 0463 }, 0464 }, 0465 { 0466 QByteArrayLiteral("row-resize"), 0467 { 0468 QByteArrayLiteral("split_v"), 0469 QByteArrayLiteral("2870a09082c103050810ffdffffe0204"), 0470 QByteArrayLiteral("size_ver"), 0471 }, 0472 }, 0473 { 0474 QByteArrayLiteral("not-allowed"), 0475 { 0476 QByteArrayLiteral("forbidden"), 0477 QByteArrayLiteral("03b6e0fcb3499374a867c041f52298f0"), 0478 QByteArrayLiteral("circle"), 0479 QByteArrayLiteral("dnd-no-drop"), 0480 }, 0481 }, 0482 { 0483 QByteArrayLiteral("progress"), 0484 { 0485 QByteArrayLiteral("left_ptr_watch"), 0486 QByteArrayLiteral("3ecb610c1bf2410f44200f48c40d3599"), 0487 QByteArrayLiteral("00000000000000020006000e7e9ffc3f"), 0488 QByteArrayLiteral("08e8e1c95fe2fc01f976f1e063a24ccd"), 0489 }, 0490 }, 0491 { 0492 QByteArrayLiteral("grab"), 0493 { 0494 QByteArrayLiteral("openhand"), 0495 QByteArrayLiteral("9141b49c8149039304290b508d208c40"), 0496 QByteArrayLiteral("all_scroll"), 0497 QByteArrayLiteral("all-scroll"), 0498 }, 0499 }, 0500 { 0501 QByteArrayLiteral("grabbing"), 0502 { 0503 QByteArrayLiteral("closedhand"), 0504 QByteArrayLiteral("05e88622050804100c20044008402080"), 0505 QByteArrayLiteral("4498f0e0c1937ffe01fd06f973665830"), 0506 QByteArrayLiteral("9081237383d90e509aa00f00170e968f"), 0507 QByteArrayLiteral("fcf21c00b30f7e3f83fe0dfd12e71cff"), 0508 }, 0509 }, 0510 { 0511 QByteArrayLiteral("alias"), 0512 { 0513 QByteArrayLiteral("link"), 0514 QByteArrayLiteral("dnd-link"), 0515 QByteArrayLiteral("3085a0e285430894940527032f8b26df"), 0516 QByteArrayLiteral("640fb0e74195791501fd1ed57b41487f"), 0517 QByteArrayLiteral("a2a266d0498c3104214a47bd64ab0fc8"), 0518 }, 0519 }, 0520 { 0521 QByteArrayLiteral("copy"), 0522 { 0523 QByteArrayLiteral("dnd-copy"), 0524 QByteArrayLiteral("1081e37283d90000800003c07f3ef6bf"), 0525 QByteArrayLiteral("6407b0e94181790501fd1e167b474872"), 0526 QByteArrayLiteral("b66166c04f8c3109214a4fbd64a50fc8"), 0527 }, 0528 }, 0529 { 0530 QByteArrayLiteral("move"), 0531 { 0532 QByteArrayLiteral("dnd-move"), 0533 }, 0534 }, 0535 { 0536 QByteArrayLiteral("sw-resize"), 0537 { 0538 QByteArrayLiteral("size_bdiag"), 0539 QByteArrayLiteral("fcf1c3c7cd4491d801f1e1c78f100000"), 0540 QByteArrayLiteral("fd_double_arrow"), 0541 QByteArrayLiteral("bottom_left_corner"), 0542 }, 0543 }, 0544 { 0545 QByteArrayLiteral("se-resize"), 0546 { 0547 QByteArrayLiteral("size_fdiag"), 0548 QByteArrayLiteral("c7088f0f3e6c8088236ef8e1e3e70000"), 0549 QByteArrayLiteral("bd_double_arrow"), 0550 QByteArrayLiteral("bottom_right_corner"), 0551 }, 0552 }, 0553 { 0554 QByteArrayLiteral("ne-resize"), 0555 { 0556 QByteArrayLiteral("size_bdiag"), 0557 QByteArrayLiteral("fcf1c3c7cd4491d801f1e1c78f100000"), 0558 QByteArrayLiteral("fd_double_arrow"), 0559 QByteArrayLiteral("top_right_corner"), 0560 }, 0561 }, 0562 { 0563 QByteArrayLiteral("nw-resize"), 0564 { 0565 QByteArrayLiteral("size_fdiag"), 0566 QByteArrayLiteral("c7088f0f3e6c8088236ef8e1e3e70000"), 0567 QByteArrayLiteral("bd_double_arrow"), 0568 QByteArrayLiteral("top_left_corner"), 0569 }, 0570 }, 0571 { 0572 QByteArrayLiteral("n-resize"), 0573 { 0574 QByteArrayLiteral("size_ver"), 0575 QByteArrayLiteral("00008160000006810000408080010102"), 0576 QByteArrayLiteral("sb_v_double_arrow"), 0577 QByteArrayLiteral("v_double_arrow"), 0578 QByteArrayLiteral("col-resize"), 0579 QByteArrayLiteral("top_side"), 0580 }, 0581 }, 0582 { 0583 QByteArrayLiteral("e-resize"), 0584 { 0585 QByteArrayLiteral("size_hor"), 0586 QByteArrayLiteral("028006030e0e7ebffc7f7070c0600140"), 0587 QByteArrayLiteral("sb_h_double_arrow"), 0588 QByteArrayLiteral("h_double_arrow"), 0589 QByteArrayLiteral("row-resize"), 0590 QByteArrayLiteral("left_side"), 0591 }, 0592 }, 0593 { 0594 QByteArrayLiteral("s-resize"), 0595 { 0596 QByteArrayLiteral("size_ver"), 0597 QByteArrayLiteral("00008160000006810000408080010102"), 0598 QByteArrayLiteral("sb_v_double_arrow"), 0599 QByteArrayLiteral("v_double_arrow"), 0600 QByteArrayLiteral("col-resize"), 0601 QByteArrayLiteral("bottom_side"), 0602 }, 0603 }, 0604 { 0605 QByteArrayLiteral("w-resize"), 0606 { 0607 QByteArrayLiteral("size_hor"), 0608 QByteArrayLiteral("028006030e0e7ebffc7f7070c0600140"), 0609 QByteArrayLiteral("sb_h_double_arrow"), 0610 QByteArrayLiteral("h_double_arrow"), 0611 QByteArrayLiteral("right_side"), 0612 }, 0613 }, 0614 }; 0615 auto it = alternatives.find(name); 0616 if (it != alternatives.end()) { 0617 return it.value(); 0618 } 0619 return QList<QByteArray>(); 0620 } 0621 0622 QString Cursor::defaultThemeName() 0623 { 0624 return QStringLiteral("default"); 0625 } 0626 0627 int Cursor::defaultThemeSize() 0628 { 0629 return 24; 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"