Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Mouse cursor changes to 'resize' on inner widgets
QtWS25 Last Chance

Mouse cursor changes to 'resize' on inner widgets

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 2 Posters 5.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mrjjM Offline
    mrjjM Offline
    mrjj
    Lifetime Qt Champion
    wrote on last edited by mrjj
    #6

    Hi
    Well it sounds like sometimes, you experience a situation that is not properly
    covered by the logic and maybe _cursorchanged or _leftButtonPressed is not
    in expected state and the cursor is not reset.

    This one
    https://github.com/dfct/TrueFramelessWindow `?

    1 Reply Last reply
    1
    • michalosM Offline
      michalosM Offline
      michalos
      wrote on last edited by
      #7

      @mrjj

      I will debug the code some more and try to find the conditions this happens.

      as to the code, it's not the TrueFramelessWindow. I've tried to find it, but it's as if someone removed it..

      mrjjM 1 Reply Last reply
      1
      • michalosM michalos

        @mrjj

        I will debug the code some more and try to find the conditions this happens.

        as to the code, it's not the TrueFramelessWindow. I've tried to find it, but it's as if someone removed it..

        mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by
        #8

        @michalos
        super.
        I would insert
        qDebug() in a few places so I could run the app with no break points and still see what is going on.

        1 Reply Last reply
        1
        • michalosM Offline
          michalosM Offline
          michalos
          wrote on last edited by michalos
          #9

          Hi again.
          It took me awhile to check this code thoroughly, because of other projects, but I've checked it now.
          The results are strange:
          When I comment out the line responsible for mouse cursor change, the error does not occur.
          When I enable the code, but add qDebug info one line above (before code execution), then the error occurs, but I don't get any debug info about it.
          Any ideas on how is this possible?

          I wanted to take a screenshot of this error, but the mose is not visible on the screenshot.

          and here's the whole code, as it is right now:

          
          #include <QDateTime>
          #include <QDebug>
          
          FrameLess::FrameLess(QWidget *parent) :
              QObject(parent),
              _parent(parent),
              _cursorchanged(false),
              _leftButtonPressed(false),
              _borderWidth(3),
              _dragPos(QPoint())
          {
              _parent->setMouseTracking(true);
              _parent->setWindowFlags(Qt::FramelessWindowHint);
              _parent->setAttribute(Qt::WA_Hover);
              _parent->installEventFilter(this);
              _rubberband = new QRubberBand(QRubberBand::Rectangle, parent);
          }
          
          bool FrameLess::eventFilter(QObject *o, QEvent*e) {
              if (e->type() == QEvent::MouseMove ||
                  e->type() == QEvent::HoverMove ||
                  e->type() == QEvent::Leave ||
                  e->type() == QEvent::MouseButtonPress ||
                  e->type() == QEvent::MouseButtonRelease) {
          
                  switch (e->type()) {
                  case QEvent::MouseMove:
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::eventFilter : QEvent::MouseMove";
                      mouseMove(static_cast<QMouseEvent*>(e));
                      return true;
                      break;
                  case QEvent::HoverMove:
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::eventFilter : QEvent::HoverMove";
                      mouseHover(static_cast<QHoverEvent*>(e));
                      return true;
                      break;
                  case QEvent::Leave:
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::eventFilter : QEvent::Leave";
                      mouseLeave(e);
                      return true;
                      break;
                  case QEvent::MouseButtonPress:
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::eventFilter : QEvent::MouseButtonPress";
                      mousePress(static_cast<QMouseEvent*>(e));
                      return true;
                      break;
                  case QEvent::MouseButtonRelease:
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::eventFilter : QEvent::MouseButtonRelease";
                      mouseRealese(static_cast<QMouseEvent*>(e));
                      return true;
                      break;
                  default:
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::eventFilter : default:";
                      mouseRealese(static_cast<QMouseEvent*>(e));  //default was just the return false; - I've added the mouseRelalese();
                      return false;
                      break;
                  }
              } else {
                  return _parent->eventFilter(o, e);
              }
          }
          
          void FrameLess::mouseHover(QHoverEvent *e) {
              updateCursorShape(_parent->mapToGlobal(e->pos()));
          }
          
          void FrameLess::mouseLeave(QEvent *e) {
              if (!_leftButtonPressed) {
                  _parent->unsetCursor();
              }
          }
          
          void FrameLess::mousePress(QMouseEvent *e) {
              if (e->button() & Qt::LeftButton) {
                  _leftButtonPressed = true;
                  calculateCursorPosition(e->globalPos(), _parent->frameGeometry(), _mousePress);
                  if (!_mousePress.testFlag(Edge::None)) {
                      _rubberband->setGeometry(_parent->frameGeometry());
                  }
                  if (_parent->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) {  //i've commented it
                  _leftButtonPressed = false;
                  _dragStart = false;
          //    }
          }
          
          void FrameLess::mouseMove(QMouseEvent *e) {
              if (_leftButtonPressed) {
                  if (_dragStart) {
                      _parent->move(_parent->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() < _parent->minimumWidth()) {
                          left = _parent->frameGeometry().x();
                      } else if (newRect.height() < _parent->minimumHeight()) {
                          top = _parent->frameGeometry().y();
                      }
                      _parent->setGeometry(QRect(QPoint(left, top), QPoint(right, bottom)));
                      _rubberband->setGeometry(QRect(QPoint(left, top), QPoint(right, bottom)));
                  } else {   /////I've added the whole else
                      updateCursorShape(e->globalPos());
                  }
              } else {
                  updateCursorShape(e->globalPos());
              }
          }
          
          void FrameLess::updateCursorShape(const QPoint &pos) {
              if (_parent->isFullScreen() || _parent->isMaximized()) {
                  if (_cursorchanged) {
                      _parent->unsetCursor();
                  }
                  return;
              }
              if (!_leftButtonPressed) {
                  calculateCursorPosition(pos, _parent->frameGeometry(), _mouseMove);
                  _cursorchanged = true;
                  if (_mouseMove.testFlag(Edge::Top) || _mouseMove.testFlag(Edge::Bottom)) {
                      _parent->setCursor(Qt::SizeVerCursor);
                  } else if (_mouseMove.testFlag(Edge::Left) || _mouseMove.testFlag(Edge::Right)) {
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::updateCursorShape : _parent->setCursor(Qt::SizeHorCursor)";
                      _parent->setCursor(Qt::SizeHorCursor);  //commenting out helps for the error
                  } else if (_mouseMove.testFlag(Edge::TopLeft) || _mouseMove.testFlag(Edge::BottomRight)) {
                      _parent->setCursor(Qt::SizeFDiagCursor);
                  } else if (_mouseMove.testFlag(Edge::TopRight) || _mouseMove.testFlag(Edge::BottomLeft)) {
                      _parent->setCursor(Qt::SizeBDiagCursor);
          //        } else if (_cursorchanged) {
                  } else {
                      qDebug() << QDateTime::currentDateTime() << "FrameLess::updateCursorShape : _parent->unsetCursor()";
                      _parent->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;
              }
          }
          
          void FrameLess::setBorderWidth(int borderWidth) {
              _borderWidth = borderWidth;
          }
          
          int FrameLess::borderWidth() const {
              return _borderWidth;
          }
          
          1 Reply Last reply
          0
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #10

            @michalos said in Mouse cursor changes to 'resize' on inner widgets:

            QEvent::Leave:

            When you move away from the widget, QEvent::Leave should show its debug. ?
            Else it wont be reset again. it seems.

            1 Reply Last reply
            0
            • michalosM Offline
              michalosM Offline
              michalos
              wrote on last edited by michalos
              #11

              @mrjj But the QEvent::Leave only happens when I leave the widget.
              The error occurs on the child widgets, so I don't get the QEvent::Leave.
              I don't get any debug info, when the error occurs.

              mrjjM 1 Reply Last reply
              0
              • michalosM michalos

                @mrjj But the QEvent::Leave only happens when I leave the widget.
                The error occurs on the child widgets, so I don't get the QEvent::Leave.
                I don't get any debug info, when the error occurs.

                mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by
                #12

                @michalos

                When the cursor chances. is the _cursorchanged then true?

                1 Reply Last reply
                1
                • michalosM Offline
                  michalosM Offline
                  michalos
                  wrote on last edited by michalos
                  #13

                  @mrjj Yes. The _cursorchanged = true and I get a QEvent::CursorChange.
                  Do you think it could be because of thin side borders?
                  I did a test and also added a debug message when any event occures. It's like once in two three tries the _cursorchanged variable is not switched to false

                  This is how the window looks like. I needet to do a photo with my phone, because with a standard print-screen the mouse cursor wasn't visible.
                  alt text

                  1 Reply Last reply
                  0
                  • mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on last edited by
                    #14

                    @michalos said in Mouse cursor changes to 'resize' on inner widgets:

                    Do you think it could be because of thin side borders?

                    Well if it tries to detect the cursor leaving such small area, then yes.
                    Its very possible to skip a mouse pos now and then.
                    I made an app where i detected mouse moving out of app.
                    If i did it fast enough, sometimes it would not see it.

                    Can u test by making border much bigger?

                    1 Reply Last reply
                    1
                    • michalosM Offline
                      michalosM Offline
                      michalos
                      wrote on last edited by
                      #15

                      @mrjj I've made the borders bigger and the problem stoped. So this seemst to be the source of the problem.
                      Fortunately I have only two child widgets, and both are custom, so I've just added a signal to their enterEvent() and connected the signal to a slot in the resizing class, that resets the mouse cursors shape.
                      Thank You so much for your help. I wouldn't have solved it on my own.

                      mrjjM 1 Reply Last reply
                      1
                      • michalosM michalos

                        @mrjj I've made the borders bigger and the problem stoped. So this seemst to be the source of the problem.
                        Fortunately I have only two child widgets, and both are custom, so I've just added a signal to their enterEvent() and connected the signal to a slot in the resizing class, that resets the mouse cursors shape.
                        Thank You so much for your help. I wouldn't have solved it on my own.

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by mrjj
                        #16

                        @michalos
                        Heh well you actually did find it on your own :)
                        So good work :\o/

                        1 Reply Last reply
                        1

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved