Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Mouse cursor changes to 'resize' on inner widgets

    General and Desktop
    2
    16
    4033
    Loading More Posts
    • 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.
    • michalos
      michalos last edited by michalos

      Hi,
      I have a GUI, that has a tab widget.
      On every tab there is a tree view and a editor widget.
      Editor is shown only when I hover over an item, in the tree view.

      Sometimes when I hover over the tree views empty space, or editors push buttons, the mouse cursor changes from the normal arrow, to the horizontal resize arrows (horizontal line with an arrow on each side).
      It happens only from time to time.

      My main window is frameless (Qt::FramelessWindowHint) and I do the resizing manualy. I've set breakpoints on the code, where I change the mouse coursor to the resize one, but It looks like it's not related to my code (doesn't execute this code when the problem occurs).

      I can supply all the code you need, but its a complex application and I'm not sure where to look.

      Could someone give me some hints on where to look for the cause of the problem?

      One dependency I found is, that when I do something else in a seperate program, and then hover the mouse over the app.

      What helps is to switch vews (from one tab in a tab widget, to another, and then back)

      1 Reply Last reply Reply Quote 0
      • mrjj
        mrjj Lifetime Qt Champion last edited by

        Hi
        Can it be a hidden splitter ?

        If you // out any use of setCursor, does it still happen?

        1 Reply Last reply Reply Quote 0
        • michalos
          michalos last edited by

          @mrjj thank you for your answer.

          I do not have any splitters in those widgets.
          I did not try to comment out the setCursor, but I did place a breakpoint on the code, where I change the cursor to a resize cursor.

          I will try to comment out setCursor.

          mrjj 1 Reply Last reply Reply Quote 0
          • mrjj
            mrjj Lifetime Qt Champion @michalos last edited by

            @michalos

            I cant think of any other widgets (besides as a window) that would use the
            resize cursor. alt text

            1 Reply Last reply Reply Quote 0
            • michalos
              michalos last edited by

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

              nt think of any other widgets (besides as a window) that

              I will do some more testing, because the problem only happens form time to time, but it seems, that code from a class I borowed from github seems to be the problem:

              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)) {
                          _parent->setCursor(Qt::SizeHorCursor);
                      } 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) {
                          _parent->unsetCursor();
                          _cursorchanged = false;
                      }
                  }
              }
              
              

              When I comment out the _parent->setCursor() the problem stopped.

              Any idea why the coursor only locks it selve on the Qt::SizeHorCursor?

              
              void FrameLess::mouseHover(QHoverEvent *e) {
                  updateCursorShape(_parent->mapToGlobal(e->pos()));
              }
              
              void FrameLess::mouseLeave(QEvent *e) {
                  if (!_leftButtonPressed) {
                      _parent->unsetCursor();
                  }
              }
              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 {
                      updateCursorShape(e->globalPos());
                  }
              }
              
              1 Reply Last reply Reply Quote 0
              • mrjj
                mrjj Lifetime Qt Champion last edited by mrjj

                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 Reply Quote 1
                • michalos
                  michalos last edited by

                  @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..

                  mrjj 1 Reply Last reply Reply Quote 1
                  • mrjj
                    mrjj Lifetime Qt Champion @michalos last edited by

                    @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 Reply Quote 1
                    • michalos
                      michalos last edited by michalos

                      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 Reply Quote 0
                      • mrjj
                        mrjj Lifetime Qt Champion last edited by

                        @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 Reply Quote 0
                        • michalos
                          michalos last edited by 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.

                          mrjj 1 Reply Last reply Reply Quote 0
                          • mrjj
                            mrjj Lifetime Qt Champion @michalos last edited by

                            @michalos

                            When the cursor chances. is the _cursorchanged then true?

                            1 Reply Last reply Reply Quote 1
                            • michalos
                              michalos last edited by michalos

                              @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 Reply Quote 0
                              • mrjj
                                mrjj Lifetime Qt Champion last edited by

                                @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 Reply Quote 1
                                • michalos
                                  michalos last edited by

                                  @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.

                                  mrjj 1 Reply Last reply Reply Quote 1
                                  • mrjj
                                    mrjj Lifetime Qt Champion @michalos last edited by mrjj

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

                                    1 Reply Last reply Reply Quote 1
                                    • First post
                                      Last post