From 18922e13163a90098cb7fe65df331e382d864cd7 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Tue, 31 Mar 2020 19:54:30 +0100 Subject: [PATCH] NewMainWindow resizing .. frameless window so we need to do it all ourselves. Works ok, so time to move onto titlebar with Mac. --- src/Gui/NewMainWindow.cpp | 186 ++++++++++++++++++++++++++++++++++++-- src/Gui/NewMainWindow.h | 12 ++- 2 files changed, 186 insertions(+), 12 deletions(-) diff --git a/src/Gui/NewMainWindow.cpp b/src/Gui/NewMainWindow.cpp index 5afe874af..220367e20 100644 --- a/src/Gui/NewMainWindow.cpp +++ b/src/Gui/NewMainWindow.cpp @@ -9,12 +9,13 @@ constexpr double gl_minwidth = 1024; constexpr double gl_minheight = 768; constexpr double gl_toolbarheight = 50; -constexpr double gl_searchwidth = 350; +constexpr double gl_searchwidth = 500; constexpr double gl_searchheight = 38; constexpr double gl_quitheight = 38; constexpr double gl_quitwidth = 38; +constexpr double gl_hoverzone = 10; // how many px to be hovering on an edge? -NewMainWindow::NewMainWindow(QApplication *app) : QMainWindow(NULL), app(app), state(None) +NewMainWindow::NewMainWindow(QApplication *app) : QMainWindow(NULL), state(Inactive), resize(None), app(app) { // setup main = new QWidget(this); @@ -28,10 +29,13 @@ NewMainWindow::NewMainWindow(QApplication *app) : QMainWindow(NULL), app(app), s // toolbar setupToolbar(); - // more to come... // set geometry etc initialPosition(); + + // mouse tracking + setMouseTracking(true); + qApp->installEventFilter(this); } void @@ -51,9 +55,9 @@ NewMainWindow::setupToolbar() searchbox->setFixedWidth(gl_searchwidth * dpiXFactor); searchbox->setFixedHeight(gl_searchheight * dpiXFactor); searchbox->setFrame(QFrame::NoFrame); - searchbox->setStyleSheet("QLineEdit { background: #eeeeee; border-radius: 7px; }" + searchbox->setStyleSheet("QLineEdit { background: #eeeeee; border-radius: 7px; padding-left: 10px;}" //XXX hidpi constants "QLineEdit:focus { background: white; }"); - searchbox->setPlaceholderText(tr(" Search or type a command ")); + searchbox->setPlaceholderText(tr(" Search or type a command ")); // spacer to balance the minimize and close buttons QWidget *balanceSpacer = new QWidget(this); @@ -139,32 +143,194 @@ NewMainWindow::initialPosition() // start with drag, but will need resize at some // point too. bool -NewMainWindow::isHotSpot(QPoint pos) +NewMainWindow::isDragHotSpot(QPoint pos) { - if (pos.y() < gl_toolbarheight * dpiYFactor) return true; + if (pos.y() > gl_hoverzone && pos.y() < gl_toolbarheight * dpiYFactor) return true; return false; } +int +NewMainWindow::isResizeHotSpot(QPoint pos) +{ + int returning = None; + + if (pos.y() < gl_hoverzone) { + returning = Top; + if (pos.x() < gl_hoverzone) returning = TL; + if (pos.x() > width()-gl_hoverzone) returning = TR; + } else if (pos.y() > height() -gl_hoverzone) { + returning = Bottom; + if (pos.x() < gl_hoverzone) returning = BL; + if (pos.x() > width()-gl_hoverzone) returning = BR; + } else if (pos.x() width()-gl_hoverzone) { + returning = Right; + } + + return returning; +} + void NewMainWindow::mousePressEvent(QMouseEvent *event) { - if (isHotSpot(event->pos())) { + // always grab focus, user is 'clicking away' from a widget + setFocus(); + + if (state == EdgeHover) { + clickPos.setX(event->x()); clickPos.setY(event->y()); + clickGeom=geometry(); + state = Resize; + resize = static_cast(isResizeHotSpot(event->pos())); + + } else if (isDragHotSpot(event->pos())) { + + clickPos.setX(event->x()); + clickPos.setY(event->y()); + clickGeom=geometry(); state = Drag; } } void NewMainWindow::mouseReleaseEvent(QMouseEvent *) { - state = None; + + state = Inactive; + setCursor(Qt::ArrowCursor); +} + +bool +NewMainWindow::eventFilter(QObject *, QEvent *e) +{ + if (e->type() == QEvent::MouseMove) this->mouseMoveEvent(static_cast(e)); + + // we must NEVER steal events, this is on the entire app + return false; } void NewMainWindow::mouseMoveEvent(QMouseEvent *event) { - if (state == Drag) move(event->globalX()-clickPos.x(),event->globalY()-clickPos.y()); + int hotspot=None; + + if (state == Drag) { + + move(event->globalX()-clickPos.x(),event->globalY()-clickPos.y()); + + } else if (state == Resize) { + + this->setUpdatesEnabled(false); + + QRect geom = geometry(); + switch(resize) { + case None: + // should never get here ! + state = Inactive; + break; + case BR: + QMainWindow::resize(event->globalX()-geom.x(),event->globalY()-geom.y()); + break; + case Right: + QMainWindow::resize(event->globalX()-geom.x(),geom.height()); + break; + case Bottom: + QMainWindow::resize(geom.width(),event->globalY()-geom.y()); + break; + case TR: + { + int newwidth = event->globalX()-geom.x(); + newwidth = newwidth > minimumWidth() ? newwidth : minimumWidth(); + int newheight = clickGeom.height() + (clickGeom.y() - event->globalY()); + newheight = newheight > minimumHeight() ? newheight : minimumHeight(); + + QMainWindow::resize(newwidth, newheight); + move(clickGeom.bottomLeft().x(),clickGeom.bottomLeft().y()-newheight); + } + break; + case TL: + { + int newwidth = clickGeom.width() + (clickGeom.x() - event->globalX()); + newwidth = newwidth > minimumWidth() ? newwidth : minimumWidth(); + int newheight = clickGeom.height() + (clickGeom.y() - event->globalY()); + newheight = newheight > minimumHeight() ? newheight : minimumHeight(); + + QMainWindow::resize(newwidth, newheight); + move(clickGeom.bottomRight().x()-newwidth,clickGeom.bottomRight().y()-newheight); + } + break; + case BL: + { + int newwidth = clickGeom.width() + (clickGeom.x() - event->globalX()); + newwidth = newwidth > minimumWidth() ? newwidth : minimumWidth(); + int newheight = event->globalY()-geom.y(); + newheight = newheight > minimumHeight() ? newheight : minimumHeight(); + + QMainWindow::resize(newwidth, newheight); + move(clickGeom.bottomRight().x()-newwidth,clickGeom.y()); + } + break; + + case Left: + { + int newwidth = clickGeom.width() + (clickGeom.x() - event->globalX()); + newwidth = newwidth > minimumWidth() ? newwidth : minimumWidth(); + + QMainWindow::resize(newwidth, clickGeom.height()); + move(clickGeom.bottomRight().x()-newwidth,clickGeom.y()); + } + break; + + case Top: + { + int newheight = clickGeom.height() + (clickGeom.y() - event->globalY()); + newheight = newheight > minimumHeight() ? newheight : minimumHeight(); + + QMainWindow::resize(clickGeom.width(), newheight); + move(clickGeom.x(),clickGeom.bottomRight().y()-newheight); + } + break; + + default: + break; + } + + this->setUpdatesEnabled(true); + + } else if (state != Resize && state != Drag) { + + hotspot=isResizeHotSpot(event->pos()); + + switch (hotspot) { + case None: + + // unhover + setCursor(Qt::ArrowCursor); + break; + case Top: + case Bottom: + setCursor(Qt::SizeVerCursor); + break; + case Left: + case Right: + setCursor(Qt::SizeHorCursor); + break; + case TL: + case BR: + setCursor(Qt::SizeFDiagCursor); + break; + case TR: + case BL: + setCursor(Qt::SizeBDiagCursor); + break; + } + + // state transition + if (state != EdgeHover && hotspot != None) state = EdgeHover; + if (state == EdgeHover && hotspot == None) state = Inactive; + } } void diff --git a/src/Gui/NewMainWindow.h b/src/Gui/NewMainWindow.h index 71da384e4..88ec057f8 100644 --- a/src/Gui/NewMainWindow.h +++ b/src/Gui/NewMainWindow.h @@ -11,6 +11,12 @@ class NewMainWindow : public QMainWindow public: NewMainWindow(QApplication *app); + // we are frameless, so we handle functions that + // would normally be performed by the window manager + // in exchange we get to handle all the aesthetics + enum { Inactive, Drag, EdgeHover, Resize } state; + enum ResizeType { None, Top, Left, Right, Bottom, TL, TR, BL, BR } resize; + // initially lets just do this, the code will // get more complex over time, but lets start // with the simplest methods for dragging a @@ -19,7 +25,9 @@ class NewMainWindow : public QMainWindow void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); - bool isHotSpot(QPoint); + bool eventFilter(QObject *oj, QEvent *e); + bool isDragHotSpot(QPoint); + int isResizeHotSpot(QPoint); protected: @@ -43,5 +51,5 @@ class NewMainWindow : public QMainWindow QPushButton *quitbutton, *minimisebutton; QPoint clickPos; - enum { None, Drag, Resize } state; + QRect clickGeom; };