|
| 1 | +#include "Frameless/TaoFrameLessView.h" |
| 2 | +#include <QGuiApplication> |
| 3 | +#include <QQuickItem> |
| 4 | +#include <QScreen> |
| 5 | +#include <QWindow> |
| 6 | + |
| 7 | +struct TaoFrameLessViewPrivate |
| 8 | +{ |
| 9 | + uint32_t mPressedEdge; |
| 10 | + QRect mPressedGeometry; |
| 11 | +}; |
| 12 | +TaoFrameLessView::TaoFrameLessView(QWindow* parent) |
| 13 | + : Super(parent) |
| 14 | + , d(std::make_unique<TaoFrameLessViewPrivate>()) |
| 15 | +{ |
| 16 | + setFlags(flags() | Qt::FramelessWindowHint | Qt::Window); |
| 17 | + setResizeMode(SizeRootObjectToView); |
| 18 | +} |
| 19 | +TaoFrameLessView::~TaoFrameLessView() { } |
| 20 | +QRect TaoFrameLessView::calcCenterGeo(const QRect& screenGeo, const QSize& normalSize) |
| 21 | +{ |
| 22 | + int w = normalSize.width(); |
| 23 | + int h = normalSize.height(); |
| 24 | + int x = screenGeo.x() + (screenGeo.width() - w) / 2; |
| 25 | + int y = screenGeo.y() + (screenGeo.height() - h) / 2; |
| 26 | + if (screenGeo.width() < w) |
| 27 | + { |
| 28 | + x = screenGeo.x(); |
| 29 | + w = screenGeo.width(); |
| 30 | + } |
| 31 | + if (screenGeo.height() < h) |
| 32 | + { |
| 33 | + y = screenGeo.y(); |
| 34 | + h = screenGeo.height(); |
| 35 | + } |
| 36 | + |
| 37 | + return { x, y, w, h }; |
| 38 | +} |
| 39 | +void TaoFrameLessView::moveToScreenCenter() |
| 40 | +{ |
| 41 | + auto geo = calcCenterGeo(screen()->availableGeometry(), size()); |
| 42 | + if (minimumWidth() > geo.width() || minimumHeight() > geo.height()) |
| 43 | + { |
| 44 | + setMinimumSize(geo.size()); |
| 45 | + } |
| 46 | + setGeometry(geo); |
| 47 | + update(); |
| 48 | +} |
| 49 | + |
| 50 | +void TaoFrameLessView::move(int x, int y) |
| 51 | +{ |
| 52 | + setPosition(x, y); |
| 53 | +} |
| 54 | + |
| 55 | +QPoint TaoFrameLessView::mousePosition() const |
| 56 | +{ |
| 57 | + return QCursor::pos(); |
| 58 | +} |
| 59 | + |
| 60 | +QPoint TaoFrameLessView::globalPosToWindowPos(const QPoint& pos) const |
| 61 | +{ |
| 62 | + return mapFromGlobal(pos); |
| 63 | +} |
| 64 | + |
| 65 | +void TaoFrameLessView::mousePressEvent(QMouseEvent* event) |
| 66 | +{ |
| 67 | + auto mousePos = event->pos(); |
| 68 | + emit mousePressed(mousePos.x(), mousePos.y(), event->button()); |
| 69 | + d->mPressedEdge = getPosEdges(mousePos); |
| 70 | + if (d->mPressedEdge) |
| 71 | + { |
| 72 | + d->mPressedGeometry = geometry(); |
| 73 | + } |
| 74 | + Super::mousePressEvent(event); |
| 75 | +} |
| 76 | + |
| 77 | +void TaoFrameLessView::mouseReleaseEvent(QMouseEvent* event) |
| 78 | +{ |
| 79 | + d->mPressedEdge = 0; |
| 80 | + d->mPressedGeometry = {}; |
| 81 | + Super::mouseReleaseEvent(event); |
| 82 | +} |
| 83 | + |
| 84 | +void TaoFrameLessView::mouseMoveEvent(QMouseEvent* event) |
| 85 | +{ |
| 86 | + { |
| 87 | + // 实时计算光标 |
| 88 | + auto edges = getPosEdges(event->pos()); |
| 89 | + auto shape = getCursorShapeByEdge(edges); |
| 90 | + setCursor(shape); |
| 91 | + } |
| 92 | + { |
| 93 | + // 根据按下时位置执行move |
| 94 | + if (d->mPressedEdge) |
| 95 | + { |
| 96 | + doMoveTo(event->pos()); |
| 97 | + } |
| 98 | + } |
| 99 | + Super::mouseMoveEvent(event); |
| 100 | +} |
| 101 | +Qt::CursorShape TaoFrameLessView::getCursorShapeByEdge(const Qt::Edges& edges) |
| 102 | +{ |
| 103 | + switch (edges) |
| 104 | + { |
| 105 | + case Qt::Edge::TopEdge: |
| 106 | + case Qt::Edge::BottomEdge: { |
| 107 | + return Qt::CursorShape::SizeVerCursor; |
| 108 | + break; |
| 109 | + } |
| 110 | + case Qt::Edge::LeftEdge: |
| 111 | + case Qt::Edge::RightEdge: { |
| 112 | + return Qt::CursorShape::SizeHorCursor; |
| 113 | + break; |
| 114 | + } |
| 115 | + case (Qt::Edge::TopEdge | Qt::Edge::LeftEdge): |
| 116 | + case (Qt::Edge::BottomEdge | Qt::Edge::RightEdge): { |
| 117 | + return Qt::CursorShape::SizeFDiagCursor; |
| 118 | + break; |
| 119 | + } |
| 120 | + case (Qt::Edge::TopEdge | Qt::Edge::RightEdge): |
| 121 | + case (Qt::Edge::BottomEdge | Qt::Edge::LeftEdge): { |
| 122 | + return Qt::CursorShape::SizeBDiagCursor; |
| 123 | + break; |
| 124 | + } |
| 125 | + default: |
| 126 | + break; |
| 127 | + } |
| 128 | + return Qt::CursorShape::ArrowCursor; |
| 129 | +} |
| 130 | + |
| 131 | +void TaoFrameLessView::doMoveTo(const QPoint& nowPos) |
| 132 | +{ |
| 133 | + switch (d->mPressedEdge) |
| 134 | + { |
| 135 | + case Qt::Edge::TopEdge: { |
| 136 | + auto gPos = mapToGlobal(nowPos); |
| 137 | + auto newGeo = d->mPressedGeometry.adjusted(0, gPos.y() - d->mPressedGeometry.top(), 0, 0); |
| 138 | + // setGeometry(newGeo); |
| 139 | + setY(newGeo.y()); |
| 140 | + setHeight(newGeo.height()); |
| 141 | + break; |
| 142 | + } |
| 143 | + case Qt::Edge::BottomEdge: { |
| 144 | + auto gPos = mapToGlobal(nowPos); |
| 145 | + auto newGeo = d->mPressedGeometry.adjusted(0, 0, 0, gPos.y() - d->mPressedGeometry.bottom()); |
| 146 | + setGeometry(newGeo); |
| 147 | + break; |
| 148 | + } |
| 149 | + case Qt::Edge::LeftEdge: { |
| 150 | + auto gPos = mapToGlobal(nowPos); |
| 151 | + auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), 0, 0, 0); |
| 152 | + setGeometry(newGeo); |
| 153 | + break; |
| 154 | + } |
| 155 | + case Qt::Edge::RightEdge: { |
| 156 | + auto gPos = mapToGlobal(nowPos); |
| 157 | + auto newGeo = d->mPressedGeometry.adjusted(0, 0, gPos.x() - d->mPressedGeometry.right(), 0); |
| 158 | + setGeometry(newGeo); |
| 159 | + break; |
| 160 | + } |
| 161 | + case (Qt::Edge::TopEdge | Qt::Edge::LeftEdge): { |
| 162 | + auto gPos = mapToGlobal(nowPos); |
| 163 | + auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), gPos.y() - d->mPressedGeometry.top(), 0, 0); |
| 164 | + setGeometry(newGeo); |
| 165 | + break; |
| 166 | + } |
| 167 | + case (Qt::Edge::BottomEdge | Qt::Edge::RightEdge): { |
| 168 | + auto gPos = mapToGlobal(nowPos); |
| 169 | + auto newGeo = d->mPressedGeometry.adjusted(0, 0, gPos.x() - d->mPressedGeometry.right(), gPos.y() - d->mPressedGeometry.bottom()); |
| 170 | + setGeometry(newGeo); |
| 171 | + break; |
| 172 | + } |
| 173 | + case (Qt::Edge::TopEdge | Qt::Edge::RightEdge): { |
| 174 | + auto gPos = mapToGlobal(nowPos); |
| 175 | + auto newGeo = d->mPressedGeometry.adjusted(0, gPos.y() - d->mPressedGeometry.top(), gPos.x() - d->mPressedGeometry.right(), 0); |
| 176 | + setGeometry(newGeo); |
| 177 | + break; |
| 178 | + } |
| 179 | + case (Qt::Edge::BottomEdge | Qt::Edge::LeftEdge): { |
| 180 | + auto gPos = mapToGlobal(nowPos); |
| 181 | + auto newGeo = d->mPressedGeometry.adjusted(gPos.x() - d->mPressedGeometry.left(), 0, 0, gPos.y() - d->mPressedGeometry.bottom()); |
| 182 | + setGeometry(newGeo); |
| 183 | + break; |
| 184 | + } |
| 185 | + default: |
| 186 | + break; |
| 187 | + } |
| 188 | +} |
| 189 | +Qt::Edges TaoFrameLessView::getPosEdges(const QPoint& pos) const |
| 190 | +{ |
| 191 | + uint32_t edges = 0; |
| 192 | + if (pos.x() < 0 || pos.x() > width()) |
| 193 | + { |
| 194 | + return (Qt::Edges)edges; |
| 195 | + } |
| 196 | + if (pos.y() < 0 || pos.y() > height()) |
| 197 | + { |
| 198 | + return (Qt::Edges)edges; |
| 199 | + } |
| 200 | + if (pos.x() <= borderWidth()) |
| 201 | + { |
| 202 | + edges |= Qt::Edge::LeftEdge; |
| 203 | + } |
| 204 | + else if (width() - borderWidth() <= pos.x()) |
| 205 | + { |
| 206 | + edges |= Qt::Edge::RightEdge; |
| 207 | + } |
| 208 | + if (pos.y() <= borderWidth()) |
| 209 | + { |
| 210 | + edges |= Qt::Edge::TopEdge; |
| 211 | + } |
| 212 | + else if (height() - borderWidth() <= pos.y()) |
| 213 | + { |
| 214 | + edges |= Qt::Edge::BottomEdge; |
| 215 | + } |
| 216 | + return (Qt::Edges)edges; |
| 217 | +} |
0 commit comments