316 lines
10 KiB
C++
316 lines
10 KiB
C++
#include "screenoverlay.hpp"
|
|
|
|
#include "screenoverlaysettings.hpp"
|
|
#include <QApplication>
|
|
#include <QCursor>
|
|
#include <QGraphicsSceneMouseEvent>
|
|
#include <QGraphicsView>
|
|
#include <QKeyEvent>
|
|
#include <QMenu>
|
|
#include <settings.hpp>
|
|
#include <utils.hpp>
|
|
|
|
ScreenOverlay::ScreenOverlay(QPixmap pixmap, QObject *parent) : QGraphicsScene(parent), _pixmap(pixmap) {
|
|
setCursorPos(QCursor::pos());
|
|
addPixmap(pixmap)->setZValue(-1);
|
|
QPolygonF cursorPoly;
|
|
cursorPoly << QPoint(-10, 0) //
|
|
<< QPoint(10, 0) //
|
|
<< QPoint(0, 0) //
|
|
<< QPoint(0, 10) //
|
|
<< QPoint(0, -10) //
|
|
<< QPoint(0, 0);
|
|
|
|
cursorItem = addPolygon(cursorPoly, QPen(Qt::white));
|
|
cursorItem->setZValue(199);
|
|
|
|
magnifier = addPixmap(QPixmap(110, 110));
|
|
magnifierBox = addRect(magnifier->boundingRect(), QPen(highlight()));
|
|
magnifier->setZValue(199);
|
|
magnifierBox->setZValue(199);
|
|
magnifierBox->setParentItem(magnifier);
|
|
magnifierHint = addText("ptr: (0, 0)\nsel: (-1, -1, 0, 0)");
|
|
magnifierHint->setParentItem(magnifier);
|
|
magnifierHint->setY(magnifier->boundingRect().height());
|
|
QColor c(highlight());
|
|
c.setAlphaF(.25);
|
|
magnifierHintBox = addRect(magnifierHint->boundingRect(), Qt::NoPen, c);
|
|
magnifierHintBox->setParentItem(magnifierHint);
|
|
magnifierHintBox->setZValue(199);
|
|
magnifierHint->setZValue(199);
|
|
updateMag();
|
|
loadSettings();
|
|
}
|
|
|
|
void ScreenOverlay::wheelEvent(QGraphicsSceneWheelEvent *e) {
|
|
int pixCnt = settings::settings().value("magnifierPixelCount", 11).toInt();
|
|
if (pixCnt % 2 == 0) pixCnt++;
|
|
if (pixCnt > 20) return;
|
|
if (e->delta() > 0 && pixCnt < 19)
|
|
settings::settings().setValue("magnifierPixelCount", pixCnt += 2);
|
|
else if (pixCnt > 1)
|
|
settings::settings().setValue("magnifierPixelCount", pixCnt -= 2);
|
|
|
|
for (auto item : gridRectsX) delete item;
|
|
gridRectsX.clear();
|
|
for (auto item : gridRectsY) delete item;
|
|
gridRectsY.clear();
|
|
|
|
if (grid()) updateMagnifierGrid();
|
|
updateMag();
|
|
|
|
QGraphicsScene::wheelEvent(e);
|
|
}
|
|
|
|
void ScreenOverlay::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
|
QPointF delta = e->scenePos() - cursorPos();
|
|
if (e->modifiers() & Qt::ShiftModifier) {
|
|
setCursorPos(cursorPos() + (delta / 2));
|
|
QCursor::setPos(views()[0]->mapToGlobal(cursorPos().toPoint()));
|
|
} else
|
|
setCursorPos(e->scenePos());
|
|
updateMag();
|
|
mouseMoved(e, cursorPos(), delta);
|
|
}
|
|
|
|
void ScreenOverlay::moveMouse(QPoint newPos, bool spaceHeld) {
|
|
QMouseEvent eve(QEvent::MouseMove, newPos, spaceHeld ? Qt::LeftButton : Qt::NoButton,
|
|
spaceHeld ? Qt::LeftButton : Qt::NoButton, Qt::NoModifier);
|
|
for (auto &v : views()) {
|
|
QCursor::setPos(v->mapToGlobal(newPos));
|
|
QApplication::sendEvent(v->viewport(), &eve);
|
|
}
|
|
}
|
|
|
|
void ScreenOverlay::moveMouseBy(QPoint delta, bool spaceHeld) {
|
|
moveMouse(cursorPos().toPoint() + delta, spaceHeld);
|
|
}
|
|
|
|
void ScreenOverlay::hideMag() {
|
|
setMagVisibility(false);
|
|
}
|
|
|
|
void ScreenOverlay::setMagVisibility(bool visible) {
|
|
magnifier->setVisible(visible);
|
|
cursorItem->setVisible(visible);
|
|
magnifierBox->setVisible(visible);
|
|
magnifierHint->setVisible(visible);
|
|
magnifierHintBox->setVisible(visible);
|
|
for (auto *view : views()) {
|
|
view->setCursor(visible ? Qt::BlankCursor : Qt::ArrowCursor);
|
|
}
|
|
}
|
|
|
|
void ScreenOverlay::showMag() {
|
|
setMagVisibility(true);
|
|
}
|
|
|
|
void ScreenOverlay::updateMagnifierGrid() {
|
|
if (!grid()) return;
|
|
int pixCnt = settings::settings().value("magnifierPixelCount", 11).toInt();
|
|
if (pixCnt % 2 == 0) pixCnt++;
|
|
if (gridRectsX.size() == gridRectsY.size() && gridRectsY.size() == pixCnt) return;
|
|
|
|
QColor c(highlight());
|
|
c.setAlphaF(.25);
|
|
for (int i = 0; i < pixCnt; i++) {
|
|
auto gridRectX = addRect(0, i * 110. / pixCnt, 110, 110. / pixCnt, QPen(Qt::black, 0.5));
|
|
auto gridRectY = addRect(i * 110. / pixCnt, 0, 110. / pixCnt, 110, QPen(Qt::black, 0.5));
|
|
gridRectX->setParentItem(magnifierBox);
|
|
gridRectY->setParentItem(magnifierBox);
|
|
gridRectX->setZValue(199);
|
|
gridRectY->setZValue(199);
|
|
gridRectsX.append(gridRectX);
|
|
gridRectsY.append(gridRectY);
|
|
if (i == (pixCnt / 2)) {
|
|
gridRectX->setBrush(c);
|
|
gridRectY->setBrush(c);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScreenOverlay::updateMag() {
|
|
updateMagnifierGrid();
|
|
QString hint = generateHint();
|
|
magnifierHint->setVisible(!hint.isEmpty());
|
|
magnifierHintBox->setVisible(!hint.isEmpty());
|
|
magnifierHint->setPlainText(hint);
|
|
magnifierHintBox->setRect(magnifierHint->boundingRect());
|
|
|
|
int pixCnt = settings::settings().value("magnifierPixelCount", 11).toInt();
|
|
if (pixCnt % 2 == 0) pixCnt++;
|
|
QPointF magnifierTopLeft = cursorPos() - QPointF(pixCnt / 2, pixCnt / 2);
|
|
QPointF magnifierPos = cursorPos() + QPointF(5, 5);
|
|
|
|
magnifier->setPos(magnifierPos);
|
|
magnifier->setPixmap(utils::extend(pixmap(), pixCnt, foreground())
|
|
.copy(magnifierTopLeft.x() + pixCnt, magnifierTopLeft.y() + pixCnt, pixCnt, pixCnt)
|
|
.scaled(110, 110));
|
|
QPointF bottomRight = magnifierHintBox->sceneBoundingRect().bottomRight();
|
|
if (magnifier->sceneBoundingRect().bottom() > bottomRight.y())
|
|
bottomRight.setY(magnifier->sceneBoundingRect().bottom());
|
|
|
|
if (magnifier->sceneBoundingRect().right() > bottomRight.x())
|
|
bottomRight.setX(magnifier->sceneBoundingRect().right());
|
|
|
|
if (bottomRight.x() > sceneRect().right())
|
|
magnifierPos -= QPointF(qMax(130., magnifierHintBox->boundingRect().width()), 0);
|
|
if (bottomRight.y() > sceneRect().bottom())
|
|
magnifierPos -= QPointF(0, 130 + magnifierHintBox->boundingRect().height());
|
|
magnifier->setPos(magnifierPos);
|
|
cursorItem->setPos(cursorPos());
|
|
}
|
|
|
|
void ScreenOverlay::setHighlight(QColor highlight) {
|
|
_highlight = highlight;
|
|
QColor c = highlight;
|
|
c.setAlphaF(.4);
|
|
magnifierHintBox->setBrush(c);
|
|
magnifierBox->setPen(c);
|
|
if (grid()) setGrid(true);
|
|
int i = settings::settings().value("magnifierPixelCount", 11).toInt() / 2;
|
|
if (gridRectsX.isEmpty() || gridRectsY.isEmpty()) return;
|
|
gridRectsX[i]->setBrush(c);
|
|
gridRectsY[i]->setBrush(c);
|
|
updateMag();
|
|
highlightChanged(highlight);
|
|
}
|
|
|
|
void ScreenOverlay::keyPressEvent(QKeyEvent *e) {
|
|
if (e->key() == Qt::Key_Space) {
|
|
selectActive = !selectActive;
|
|
if (!selectActive) {
|
|
for (auto *v : views()) {
|
|
QMouseEvent eve(QEvent::MouseButtonRelease, cursorPos(), Qt::LeftButton, Qt::LeftButton, e->modifiers());
|
|
QApplication::sendEvent(v->viewport(), &eve);
|
|
}
|
|
}
|
|
}
|
|
|
|
int modifier = 1;
|
|
if(e->modifiers() == Qt::ShiftModifier) modifier = 10;
|
|
|
|
switch (movementPattern()) {
|
|
case MP_JKL:
|
|
if (e->key() == Qt::Key_J)
|
|
moveMouseBy(QPoint(-1 * modifier, 0), selectActive);
|
|
else if (e->key() == Qt::Key_K)
|
|
moveMouseBy(QPoint(0, 1 * modifier), selectActive);
|
|
else if (e->key() == Qt::Key_L)
|
|
moveMouseBy(QPoint(0, -1 * modifier), selectActive);
|
|
else if (e->key() == Qt::Key_Semicolon)
|
|
moveMouseBy(QPoint(1 * modifier, 0), selectActive);
|
|
break;
|
|
case MP_HJKL:
|
|
if (e->key() == Qt::Key_H)
|
|
moveMouseBy(QPoint(-1 * modifier, 0), selectActive);
|
|
else if (e->key() == Qt::Key_J)
|
|
moveMouseBy(QPoint(0, 1 * modifier), selectActive);
|
|
else if (e->key() == Qt::Key_K)
|
|
moveMouseBy(QPoint(0, -1 * modifier), selectActive);
|
|
else if (e->key() == Qt::Key_L)
|
|
moveMouseBy(QPoint(1 * modifier, 0), selectActive);
|
|
break;
|
|
case MP_ARROWS:
|
|
if (e->key() == Qt::Key_Left)
|
|
moveMouseBy(QPoint(-1 * modifier, 0), selectActive);
|
|
else if (e->key() == Qt::Key_Down)
|
|
moveMouseBy(QPoint(0, 1 * modifier), selectActive);
|
|
else if (e->key() == Qt::Key_Up)
|
|
moveMouseBy(QPoint(0, -1 * modifier), selectActive);
|
|
else if (e->key() == Qt::Key_Right)
|
|
moveMouseBy(QPoint(1 * modifier, 0), selectActive);
|
|
break;
|
|
}
|
|
e->accept();
|
|
}
|
|
|
|
void ScreenOverlay::hide() {
|
|
for (auto &v : views()) {
|
|
v->hide();
|
|
}
|
|
}
|
|
|
|
void ScreenOverlay::show() {
|
|
for (auto &v : views()) {
|
|
if (QApplication::screens().size() > 1)
|
|
v->show();
|
|
else
|
|
v->showFullScreen();
|
|
}
|
|
}
|
|
|
|
void ScreenOverlay::showSettings() {
|
|
hide();
|
|
ScreenOverlaySettings(this).exec();
|
|
show();
|
|
}
|
|
|
|
void ScreenOverlay::loadSettings() {
|
|
setHighlight(settings::settings().value("highlightColor", QColor(Qt::cyan)).value<QColor>());
|
|
setMovementPattern(settings::settings().value("movementPattern", MP_HJKL).value<MovementPattern>());
|
|
setGrid(settings::settings().value("gridEnabled", true).toBool());
|
|
setForeground(settings::settings().value("foregroundColor", QColor(Qt::white)).value<QColor>());
|
|
}
|
|
|
|
void ScreenOverlay::contextMenuEvent(QGraphicsSceneContextMenuEvent *e) {
|
|
QMenu menu(e->widget());
|
|
connect(menu.addAction("Screen overlay settings"), &QAction::triggered, this, &ScreenOverlay::showSettings);
|
|
customizeContextMenu(e, &menu);
|
|
menu.exec(e->screenPos());
|
|
}
|
|
|
|
void ScreenOverlay::setCursorPos(QPointF cursorPos) {
|
|
if (!pixmap().rect().contains(cursorPos.toPoint())) return;
|
|
_cursorPos = cursorPos;
|
|
}
|
|
|
|
QPointF ScreenOverlay::cursorPos() {
|
|
return _cursorPos;
|
|
}
|
|
|
|
void ScreenOverlay::setGrid(bool grid) {
|
|
_grid = grid;
|
|
if (grid) {
|
|
updateMagnifierGrid();
|
|
} else {
|
|
for (auto r : gridRectsX) delete r;
|
|
gridRectsX.clear();
|
|
for (auto r : gridRectsY) delete r;
|
|
gridRectsY.clear();
|
|
}
|
|
}
|
|
|
|
bool ScreenOverlay::grid() {
|
|
return _grid;
|
|
}
|
|
|
|
QColor ScreenOverlay::highlight() {
|
|
return _highlight;
|
|
}
|
|
|
|
QPixmap &ScreenOverlay::pixmap() {
|
|
return _pixmap;
|
|
}
|
|
|
|
void ScreenOverlay::setMovementPattern(MovementPattern nmp) {
|
|
_movementPattern = nmp;
|
|
}
|
|
|
|
ScreenOverlay::MovementPattern ScreenOverlay::movementPattern() {
|
|
return _movementPattern;
|
|
}
|
|
|
|
bool ScreenOverlay::keyboardActiveSelection() {
|
|
return selectActive;
|
|
}
|
|
|
|
QColor ScreenOverlay::foreground() {
|
|
return _foreground;
|
|
}
|
|
|
|
void ScreenOverlay::setForeground(QColor fg) {
|
|
_foreground = fg;
|
|
magnifierHint->setDefaultTextColor(fg);
|
|
}
|