Changeset View
Changeset View
Standalone View
Standalone View
src/server/seat_interface.cpp
Show First 20 Lines • Show All 286 Lines • ▼ Show 20 Line(s) | 265 | { | |||
---|---|---|---|---|---|
287 | ); | 287 | ); | ||
288 | QObject::connect(dataDevice, &DataDeviceInterface::selectionCleared, q, | 288 | QObject::connect(dataDevice, &DataDeviceInterface::selectionCleared, q, | ||
289 | [this, dataDevice] { | 289 | [this, dataDevice] { | ||
290 | updateSelection(dataDevice, false); | 290 | updateSelection(dataDevice, false); | ||
291 | } | 291 | } | ||
292 | ); | 292 | ); | ||
293 | QObject::connect(dataDevice, &DataDeviceInterface::dragStarted, q, | 293 | QObject::connect(dataDevice, &DataDeviceInterface::dragStarted, q, | ||
294 | [this, dataDevice] { | 294 | [this, dataDevice] { | ||
295 | if (q->hasImplicitPointerGrab(dataDevice->dragImplicitGrabSerial())) { | 295 | const auto dragSerial = dataDevice->dragImplicitGrabSerial(); | ||
296 | auto *dragSurface = dataDevice->origin(); | ||||
297 | if (q->hasImplicitPointerGrab(dragSerial)) { | ||||
296 | drag.mode = Drag::Mode::Pointer; | 298 | drag.mode = Drag::Mode::Pointer; | ||
299 | drag.sourcePointer = interfaceForSurface(dragSurface, pointers); | ||||
300 | drag.transformation = globalPointer.focus.transformation; | ||||
301 | } else if (q->hasImplicitTouchGrab(dragSerial)) { | ||||
302 | drag.mode = Drag::Mode::Touch; | ||||
303 | drag.sourceTouch = interfaceForSurface(dragSurface, touchs); | ||||
304 | // TODO: touch transformation | ||||
297 | } else { | 305 | } else { | ||
298 | // TODO: touch | 306 | // no implicit grab, abort drag | ||
299 | return; | 307 | return; | ||
300 | } | 308 | } | ||
301 | drag.source = dataDevice; | 309 | drag.source = dataDevice; | ||
302 | drag.target = dataDevice; | 310 | drag.target = dataDevice; | ||
303 | drag.surface = dataDevice->origin(); | 311 | drag.surface = dragSurface; | ||
304 | drag.sourcePointer = interfaceForSurface(drag.surface, pointers); | | |||
305 | // TODO: transformation needs to be either pointer or touch | | |||
306 | drag.transformation = globalPointer.focus.transformation; | | |||
307 | drag.destroyConnection = QObject::connect(dataDevice, &QObject::destroyed, q, | 312 | drag.destroyConnection = QObject::connect(dataDevice, &QObject::destroyed, q, | ||
308 | [this] { | 313 | [this] { | ||
309 | endDrag(display->nextSerial()); | 314 | endDrag(display->nextSerial()); | ||
310 | } | 315 | } | ||
311 | ); | 316 | ); | ||
312 | if (dataDevice->dragSource()) { | 317 | if (dataDevice->dragSource()) { | ||
313 | drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &Resource::aboutToBeUnbound, q, | 318 | drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &Resource::aboutToBeUnbound, q, | ||
314 | [this] { | 319 | [this] { | ||
▲ Show 20 Lines • Show All 325 Lines • ▼ Show 20 Line(s) | 644 | if (surface == d->drag.surface) { | |||
640 | // no change | 645 | // no change | ||
641 | return; | 646 | return; | ||
642 | } | 647 | } | ||
643 | const quint32 serial = d->display->nextSerial(); | 648 | const quint32 serial = d->display->nextSerial(); | ||
644 | if (d->drag.target) { | 649 | if (d->drag.target) { | ||
645 | d->drag.target->updateDragTarget(nullptr, serial); | 650 | d->drag.target->updateDragTarget(nullptr, serial); | ||
646 | } | 651 | } | ||
647 | d->drag.target = d->dataDeviceForSurface(surface); | 652 | d->drag.target = d->dataDeviceForSurface(surface); | ||
648 | // TODO: update touch | | |||
649 | if (d->drag.mode == Private::Drag::Mode::Pointer) { | 653 | if (d->drag.mode == Private::Drag::Mode::Pointer) { | ||
650 | setPointerPos(globalPosition); | 654 | setPointerPos(globalPosition); | ||
655 | } else if (d->drag.mode == Private::Drag::Mode::Touch && | ||||
656 | d->globalTouch.focus.firstTouchPos != globalPosition) { | ||||
657 | touchMove(d->globalTouch.ids.first(), globalPosition); | ||||
651 | } | 658 | } | ||
652 | if (d->drag.target) { | 659 | if (d->drag.target) { | ||
653 | d->drag.surface = surface; | 660 | d->drag.surface = surface; | ||
654 | d->drag.transformation = inputTransformation; | 661 | d->drag.transformation = inputTransformation; | ||
655 | d->drag.target->updateDragTarget(surface, serial); | 662 | d->drag.target->updateDragTarget(surface, serial); | ||
656 | } else { | 663 | } else { | ||
657 | d->drag.surface = nullptr; | 664 | d->drag.surface = nullptr; | ||
658 | } | 665 | } | ||
659 | emit dragSurfaceChanged(); | 666 | emit dragSurfaceChanged(); | ||
660 | return; | 667 | return; | ||
661 | } | 668 | } | ||
662 | 669 | | |||
663 | void SeatInterface::setDragTarget(SurfaceInterface *surface, const QMatrix4x4 &inputTransformation) | 670 | void SeatInterface::setDragTarget(SurfaceInterface *surface, const QMatrix4x4 &inputTransformation) | ||
664 | { | 671 | { | ||
665 | // TODO: handle touch | 672 | Q_D(); | ||
673 | if (d->drag.mode == Private::Drag::Mode::Pointer) { | ||||
666 | setDragTarget(surface, pointerPos(), inputTransformation); | 674 | setDragTarget(surface, pointerPos(), inputTransformation); | ||
675 | } else { | ||||
676 | Q_ASSERT(d->drag.mode == Private::Drag::Mode::Touch); | ||||
677 | setDragTarget(surface, d->globalTouch.focus.firstTouchPos, inputTransformation); | ||||
678 | } | ||||
679 | | ||||
667 | } | 680 | } | ||
668 | 681 | | |||
669 | SurfaceInterface *SeatInterface::focusedPointerSurface() const | 682 | SurfaceInterface *SeatInterface::focusedPointerSurface() const | ||
670 | { | 683 | { | ||
671 | Q_D(); | 684 | Q_D(); | ||
672 | return d->globalPointer.focus.surface; | 685 | return d->globalPointer.focus.surface; | ||
673 | } | 686 | } | ||
674 | 687 | | |||
▲ Show 20 Lines • Show All 573 Lines • ▼ Show 20 Line(s) | |||||
1248 | } | 1261 | } | ||
1249 | 1262 | | |||
1250 | void SeatInterface::cancelTouchSequence() | 1263 | void SeatInterface::cancelTouchSequence() | ||
1251 | { | 1264 | { | ||
1252 | Q_D(); | 1265 | Q_D(); | ||
1253 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | 1266 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | ||
1254 | (*it)->cancel(); | 1267 | (*it)->cancel(); | ||
1255 | } | 1268 | } | ||
1269 | if (d->drag.mode == Private::Drag::Mode::Touch) { | ||||
1270 | // cancel the drag, don't drop. | ||||
1271 | if (d->drag.target) { | ||||
1272 | // remove the current target | ||||
1273 | d->drag.target->updateDragTarget(nullptr, 0); | ||||
1274 | d->drag.target = nullptr; | ||||
1275 | } | ||||
1276 | // and end the drag for the source, serial does not matter | ||||
1277 | d->endDrag(0); | ||||
1278 | } | ||||
1256 | d->globalTouch.ids.clear(); | 1279 | d->globalTouch.ids.clear(); | ||
1257 | } | 1280 | } | ||
1258 | 1281 | | |||
1259 | TouchInterface *SeatInterface::focusedTouch() const | 1282 | TouchInterface *SeatInterface::focusedTouch() const | ||
1260 | { | 1283 | { | ||
1261 | Q_D(); | 1284 | Q_D(); | ||
1262 | if (d->globalTouch.focus.touchs.isEmpty()) { | 1285 | if (d->globalTouch.focus.touchs.isEmpty()) { | ||
1263 | return nullptr; | 1286 | return nullptr; | ||
Show All 20 Lines | |||||
1284 | } | 1307 | } | ||
1285 | 1308 | | |||
1286 | void SeatInterface::setFocusedTouchSurface(SurfaceInterface *surface, const QPointF &surfacePosition) | 1309 | void SeatInterface::setFocusedTouchSurface(SurfaceInterface *surface, const QPointF &surfacePosition) | ||
1287 | { | 1310 | { | ||
1288 | if (isTouchSequence()) { | 1311 | if (isTouchSequence()) { | ||
1289 | // changing surface not allowed during a touch sequence | 1312 | // changing surface not allowed during a touch sequence | ||
1290 | return; | 1313 | return; | ||
1291 | } | 1314 | } | ||
1315 | Q_ASSERT(!isDragTouch()); | ||||
1292 | Q_D(); | 1316 | Q_D(); | ||
1293 | if (d->globalTouch.focus.surface) { | 1317 | if (d->globalTouch.focus.surface) { | ||
1294 | disconnect(d->globalTouch.focus.destroyConnection); | 1318 | disconnect(d->globalTouch.focus.destroyConnection); | ||
1295 | } | 1319 | } | ||
1296 | d->globalTouch.focus = Private::Touch::Focus(); | 1320 | d->globalTouch.focus = Private::Touch::Focus(); | ||
1297 | d->globalTouch.focus.surface = surface; | 1321 | d->globalTouch.focus.surface = surface; | ||
1298 | d->globalTouch.focus.offset = surfacePosition; | 1322 | d->globalTouch.focus.offset = surfacePosition; | ||
1299 | d->globalTouch.focus.touchs = d->touchsForSurface(surface); | 1323 | d->globalTouch.focus.touchs = d->touchsForSurface(surface); | ||
Show All 17 Lines | |||||
1317 | { | 1341 | { | ||
1318 | Q_D(); | 1342 | Q_D(); | ||
1319 | d->globalTouch.focus.offset = surfacePosition; | 1343 | d->globalTouch.focus.offset = surfacePosition; | ||
1320 | } | 1344 | } | ||
1321 | 1345 | | |||
1322 | qint32 SeatInterface::touchDown(const QPointF &globalPosition) | 1346 | qint32 SeatInterface::touchDown(const QPointF &globalPosition) | ||
1323 | { | 1347 | { | ||
1324 | Q_D(); | 1348 | Q_D(); | ||
1325 | const qint32 id = d->globalTouch.ids.isEmpty() ? 0 : d->globalTouch.ids.last() + 1; | 1349 | const qint32 id = d->globalTouch.ids.isEmpty() ? 0 : d->globalTouch.ids.last() + 1; | ||
davidedmundson: If I add 2 IDs
[0,1]
then remove ID 0
[1]
with the old code I would get the ID 2, with… | |||||
Redid this one too many times and overlooked this obvious problem. I will just use the last() call of the QMap instead of size(). Thanks! romangg: Redid this one too many times and overlooked this obvious problem. I will just use the last()… | |||||
1326 | const qint32 serial = display()->nextSerial(); | 1350 | const qint32 serial = display()->nextSerial(); | ||
1327 | const auto pos = globalPosition - d->globalTouch.focus.offset; | 1351 | const auto pos = globalPosition - d->globalTouch.focus.offset; | ||
1328 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | 1352 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | ||
1329 | (*it)->down(id, serial, pos); | 1353 | (*it)->down(id, serial, pos); | ||
1330 | } | 1354 | } | ||
1331 | 1355 | | |||
1356 | if (id == 0) { | ||||
1357 | d->globalTouch.focus.firstTouchPos = globalPosition; | ||||
1358 | } | ||||
1359 | | ||||
1332 | #if HAVE_LINUX_INPUT_H | 1360 | #if HAVE_LINUX_INPUT_H | ||
1333 | if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { | 1361 | if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { | ||
1334 | // If the client did not bind the touch interface fall back | 1362 | // If the client did not bind the touch interface fall back | ||
1335 | // to at least emulating touch through pointer events. | 1363 | // to at least emulating touch through pointer events. | ||
1336 | forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers, | 1364 | forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers, | ||
1337 | [this, pos, serial] (PointerInterface *p) { | 1365 | [this, pos, serial] (PointerInterface *p) { | ||
1338 | wl_pointer_send_enter(p->resource(), serial, | 1366 | wl_pointer_send_enter(p->resource(), serial, | ||
1339 | focusedTouchSurface()->resource(), | 1367 | focusedTouchSurface()->resource(), | ||
1340 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | 1368 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | ||
1341 | wl_pointer_send_motion(p->resource(), timestamp(), | 1369 | wl_pointer_send_motion(p->resource(), timestamp(), | ||
1342 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | 1370 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | ||
1343 | 1371 | | |||
1344 | wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); | 1372 | wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); | ||
1345 | p->d_func()->sendFrame(); | 1373 | p->d_func()->sendFrame(); | ||
1346 | } | 1374 | } | ||
1347 | ); | 1375 | ); | ||
1348 | } | 1376 | } | ||
1349 | #endif | 1377 | #endif | ||
1350 | 1378 | | |||
1351 | d->globalTouch.ids << id; | 1379 | d->globalTouch.ids[id] = serial; | ||
1352 | return id; | 1380 | return id; | ||
1353 | } | 1381 | } | ||
1354 | 1382 | | |||
1355 | void SeatInterface::touchMove(qint32 id, const QPointF &globalPosition) | 1383 | void SeatInterface::touchMove(qint32 id, const QPointF &globalPosition) | ||
1356 | { | 1384 | { | ||
1357 | Q_D(); | 1385 | Q_D(); | ||
1358 | Q_ASSERT(d->globalTouch.ids.contains(id)); | 1386 | Q_ASSERT(d->globalTouch.ids.contains(id)); | ||
1359 | const auto pos = globalPosition - d->globalTouch.focus.offset; | 1387 | const auto pos = globalPosition - d->globalTouch.focus.offset; | ||
1360 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | 1388 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | ||
1361 | (*it)->move(id, pos); | 1389 | (*it)->move(id, pos); | ||
1362 | } | 1390 | } | ||
1363 | 1391 | | |||
1392 | if (id == 0) { | ||||
1393 | d->globalTouch.focus.firstTouchPos = globalPosition; | ||||
1394 | } | ||||
1395 | | ||||
1364 | if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { | 1396 | if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { | ||
1365 | // Client did not bind touch, fall back to emulating with pointer events. | 1397 | // Client did not bind touch, fall back to emulating with pointer events. | ||
1366 | forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers, | 1398 | forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers, | ||
1367 | [this, pos] (PointerInterface *p) { | 1399 | [this, pos] (PointerInterface *p) { | ||
1368 | wl_pointer_send_motion(p->resource(), timestamp(), | 1400 | wl_pointer_send_motion(p->resource(), timestamp(), | ||
1369 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | 1401 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | ||
1370 | } | 1402 | } | ||
1371 | ); | 1403 | ); | ||
1372 | } | 1404 | } | ||
1405 | emit touchMoved(id, d->globalTouch.ids[id], globalPosition); | ||||
1373 | } | 1406 | } | ||
1374 | 1407 | | |||
1375 | void SeatInterface::touchUp(qint32 id) | 1408 | void SeatInterface::touchUp(qint32 id) | ||
1376 | { | 1409 | { | ||
1377 | Q_D(); | 1410 | Q_D(); | ||
1378 | Q_ASSERT(d->globalTouch.ids.contains(id)); | 1411 | Q_ASSERT(d->globalTouch.ids.contains(id)); | ||
1379 | const qint32 serial = display()->nextSerial(); | 1412 | const qint32 serial = display()->nextSerial(); | ||
1413 | if (d->drag.mode == Private::Drag::Mode::Touch && | ||||
davidedmundson: I expect you need this in touchCancel too | |||||
1414 | d->drag.source->dragImplicitGrabSerial() == d->globalTouch.ids.value(id)) { | ||||
1415 | // the implicitly grabbing touch point has been upped | ||||
1416 | d->endDrag(serial); | ||||
1417 | } | ||||
1380 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | 1418 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | ||
1381 | (*it)->up(id, serial); | 1419 | (*it)->up(id, serial); | ||
1382 | } | 1420 | } | ||
1383 | 1421 | | |||
1384 | #if HAVE_LINUX_INPUT_H | 1422 | #if HAVE_LINUX_INPUT_H | ||
1385 | if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { | 1423 | if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { | ||
1386 | // Client did not bind touch, fall back to emulating with pointer events. | 1424 | // Client did not bind touch, fall back to emulating with pointer events. | ||
1387 | const quint32 serial = display()->nextSerial(); | 1425 | const quint32 serial = display()->nextSerial(); | ||
Show All 11 Lines | |||||
1399 | void SeatInterface::touchFrame() | 1437 | void SeatInterface::touchFrame() | ||
1400 | { | 1438 | { | ||
1401 | Q_D(); | 1439 | Q_D(); | ||
1402 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | 1440 | for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) { | ||
1403 | (*it)->frame(); | 1441 | (*it)->frame(); | ||
1404 | } | 1442 | } | ||
1405 | } | 1443 | } | ||
1406 | 1444 | | |||
1445 | bool SeatInterface::hasImplicitTouchGrab(quint32 serial) const | ||||
1446 | { | ||||
1447 | Q_D(); | ||||
1448 | if (!d->globalTouch.focus.surface) { | ||||
1449 | // origin surface has been destroyed | ||||
1450 | return false; | ||||
1451 | } | ||||
1452 | return d->globalTouch.ids.key(serial, -1) != -1; | ||||
1453 | } | ||||
1454 | | ||||
1407 | bool SeatInterface::isDrag() const | 1455 | bool SeatInterface::isDrag() const | ||
1408 | { | 1456 | { | ||
1409 | Q_D(); | 1457 | Q_D(); | ||
1410 | return d->drag.mode != Private::Drag::Mode::None; | 1458 | return d->drag.mode != Private::Drag::Mode::None; | ||
1411 | } | 1459 | } | ||
1412 | 1460 | | |||
1413 | bool SeatInterface::isDragPointer() const | 1461 | bool SeatInterface::isDragPointer() const | ||
1414 | { | 1462 | { | ||
▲ Show 20 Lines • Show All 124 Lines • Show Last 20 Lines |
If I add 2 IDs
[0,1]
then remove ID 0
[1]
with the old code I would get the ID 2, with this I'll get a second ID 1