#include "frameless.h" FrameLess::FrameLess(QWidget *target) : _target(target), _cursorchanged(false), _leftButtonPressed(false), _borderWidth(5), _dragPos(QPoint()) { _target->setMouseTracking(true); _target->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); _target->setAttribute(Qt::WA_Hover); _target->installEventFilter(this); _rubberband = new QRubberBand(QRubberBand::Rectangle); } bool FrameLess::eventFilter(QObject *o, QEvent*e) { switch (e->type()) { case QEvent::MouseMove: mouseMove(static_cast(e)); return true; case QEvent::HoverMove: mouseHover(static_cast(e)); return true; case QEvent::Leave: mouseLeave(e); return true; case QEvent::MouseButtonPress: mousePress(static_cast(e)); return true; case QEvent::MouseButtonRelease: mouseRealese(static_cast(e)); return true; default: return _target->eventFilter(o, e); } } void FrameLess::mouseHover(QHoverEvent *e) { updateCursorShape(_target->mapToGlobal(e->pos())); } void FrameLess::mouseLeave(QEvent *e) { if (!_leftButtonPressed) { _target->unsetCursor(); } } void FrameLess::mousePress(QMouseEvent *e) { if (e->button() & Qt::LeftButton) { _leftButtonPressed = true; calculateCursorPosition(e->globalPos(), _target->frameGeometry(), _mousePress); if (!_mousePress.testFlag(Edge::None)) { _rubberband->setGeometry(_target->frameGeometry()); } if (_target->rect().marginsRemoved(QMargins(borderWidth(), borderWidth(), borderWidth(), borderWidth())).contains(e->pos())) { _dragStart = true; _dragPos = e->pos(); } } } void FrameLess::mouseRealese(QMouseEvent *e) { if (e->button() & Qt::LeftButton) { _leftButtonPressed = false; _dragStart = false; } } void FrameLess::mouseMove(QMouseEvent *e) { if (_leftButtonPressed) { if (_dragStart) { _target->move(_target->frameGeometry().topLeft() + (e->pos() - _dragPos)); } if (!_mousePress.testFlag(Edge::None)) { int left = _rubberband->frameGeometry().left(); int top = _rubberband->frameGeometry().top(); int right = _rubberband->frameGeometry().right(); int bottom = _rubberband->frameGeometry().bottom(); switch (_mousePress) { case Edge::Top: top = e->globalPos().y(); break; case Edge::Bottom: bottom = e->globalPos().y(); break; case Edge::Left: left = e->globalPos().x(); break; case Edge::Right: right = e->globalPos().x(); break; case Edge::TopLeft: top = e->globalPos().y(); left = e->globalPos().x(); break; case Edge::TopRight: right = e->globalPos().x(); top = e->globalPos().y(); break; case Edge::BottomLeft: bottom = e->globalPos().y(); left = e->globalPos().x(); break; case Edge::BottomRight: bottom = e->globalPos().y(); right = e->globalPos().x(); break; } QRect newRect(QPoint(left, top), QPoint(right, bottom)); if (newRect.width() < _target->minimumWidth()) { left = _target->frameGeometry().x(); } else if (newRect.height() < _target->minimumHeight()) { top = _target->frameGeometry().y(); } _target->setGeometry(QRect(QPoint(left, top), QPoint(right, bottom))); _rubberband->setGeometry(QRect(QPoint(left, top), QPoint(right, bottom))); } } else { updateCursorShape(e->globalPos()); } } void FrameLess::updateCursorShape(const QPoint &pos) { if (_target->isFullScreen() || _target->isMaximized()) { if (_cursorchanged) { _target->unsetCursor(); } return; } if (!_leftButtonPressed) { calculateCursorPosition(pos, _target->frameGeometry(), _mouseMove); _cursorchanged = true; if (_mouseMove.testFlag(Edge::Top) || _mouseMove.testFlag(Edge::Bottom)) { _target->setCursor(Qt::SizeVerCursor); } else if (_mouseMove.testFlag(Edge::Left) || _mouseMove.testFlag(Edge::Right)) { _target->setCursor(Qt::SizeHorCursor); } else if (_mouseMove.testFlag(Edge::TopLeft) || _mouseMove.testFlag(Edge::BottomRight)) { _target->setCursor(Qt::SizeFDiagCursor); } else if (_mouseMove.testFlag(Edge::TopRight) || _mouseMove.testFlag(Edge::BottomLeft)) { _target->setCursor(Qt::SizeBDiagCursor); } else if (_cursorchanged) { _target->unsetCursor(); _cursorchanged = false; } } } void FrameLess::calculateCursorPosition(const QPoint &pos, const QRect &framerect, Edges &_edge) { bool onLeft = pos.x() >= framerect.x() - _borderWidth && pos.x() <= framerect.x() + _borderWidth && pos.y() <= framerect.y() + framerect.height() - _borderWidth && pos.y() >= framerect.y() + _borderWidth; bool onRight = pos.x() >= framerect.x() + framerect.width() - _borderWidth && pos.x() <= framerect.x() + framerect.width() && pos.y() >= framerect.y() + _borderWidth && pos.y() <= framerect.y() + framerect.height() - _borderWidth; bool onBottom = pos.x() >= framerect.x() + _borderWidth && pos.x() <= framerect.x() + framerect.width() - _borderWidth && pos.y() >= framerect.y() + framerect.height() - _borderWidth && pos.y() <= framerect.y() + framerect.height(); bool onTop = pos.x() >= framerect.x() + _borderWidth && pos.x() <= framerect.x() + framerect.width() - _borderWidth && pos.y() >= framerect.y() && pos.y() <= framerect.y() + _borderWidth; bool onBottomLeft = pos.x() <= framerect.x() + _borderWidth && pos.x() >= framerect.x() && pos.y() <= framerect.y() + framerect.height() && pos.y() >= framerect.y() + framerect.height() - _borderWidth; bool onBottomRight = pos.x() >= framerect.x() + framerect.width() - _borderWidth && pos.x() <= framerect.x() + framerect.width() && pos.y() >= framerect.y() + framerect.height() - _borderWidth && pos.y() <= framerect.y() + framerect.height(); bool onTopRight = pos.x() >= framerect.x() + framerect.width() - _borderWidth && pos.x() <= framerect.x() + framerect.width() && pos.y() >= framerect.y() && pos.y() <= framerect.y() + _borderWidth; bool onTopLeft = pos.x() >= framerect.x() && pos.x() <= framerect.x() + _borderWidth && pos.y() >= framerect.y() && pos.y() <= framerect.y() + _borderWidth; if (onLeft) { _edge = Left; } else if (onRight) { _edge = Right; } else if (onBottom) { _edge = Bottom; } else if (onTop) { _edge = Top; } else if (onBottomLeft) { _edge = BottomLeft; } else if (onBottomRight) { _edge = BottomRight; } else if (onTopRight) { _edge = TopRight; } else if (onTopLeft) { _edge = TopLeft; } else { _edge = None; } }