Desktop and Mouse event



  • Hello, good afternoon,

    I am trying to determine when the mouse passes over the edge of the desktop, for this I am using QDesktopWidget

    With QDesktopWidget screen I get the QWidget on the desktop, I've created a descendant class of QWidget and reimplement the mouseMoveEvent event but it does not capture anything.

    If you would like I can determine the position of the mouse on the desktop?

    Thanks a lot

    Best regards

    Dario.


  • Moderators



  • Hello Krzysztof Kawa,

    I am trying to determine when the mouse passes over the edge of the desktop via an event

    Best regards


  • Moderators

    I don't think you can do it via events. QDesktopWidget is not a "real" widget, it just has a widget-like interface so it's based on QWidget. I don't believe you can get any mouse events from it.

    What you might try though is to use QCursor::pos() with a QTimer to periodically poll for the mouse position. You can wrap it in a class and generate events of your own if you really want to.



  • Hello Krzysztof Kawa,

    I can't find documentation that shows me if there is an event to detect the position of the mouse on the desktop (outside the application). I was testing the consumption of resources with a timer as you propose and believe that it is the most viable option.

    Many thanks for the reply,

    Best regards

    Dario.





  • Hello dvez43,

    In the Qt documentation says:

    "This widget receives all mouse events until releaseMouse() is called; other widgets get no mouse events at all."
    [ . . . ]
    "Only visible widgets can grab mouse input."

    I think that the only ways to get the mouse position are:

    1. With a QTimer and QCursor:pos ();
    2. With a QWidget transparent to full screen
    3. Place a QWidget of 1 px on the edge of the desktop and capture the mouseMove

    I understand that Qt does not have a solution to this by porting issues

    Thanks a lot

    Best regards
    Dario.



  • The timer seems like the most logical. What OS are you using? WinAPI as well as the X11 have the solution your looking for. Your best bet is to use conditional groups with respect the platform. Sorry I couldn't be of much help!


  • Moderators

    There's no need to go to platform specific apis. QTimer provides platform independent timer and QCursor provides platform independent cursor position.

    The 2 option is not so good because your widget will block input to anything that is under it and won't receive input from anything above it without some tricky message forwarding that is hard to do correctly and impossible to do platform agnostic.
    The 3 option has similar issues. By grabbing a mouse you are effectively blocking input to any other app or system gui which on its own should light up all sorts of red bulbs in your mind :)



  • Option 3 is with an almost transparent QWidget OnTop borderless 1 px x the length of the desktop, also this option I don't like because it should add an event to detect the change of resolution, which means more resources used

    Option 1 reminds me of the anti kickback code for microcontrollers, but is the only feasible


  • Moderators

    Well it's not perfect because you have to adjust the poll interval so that it is not too short(which would hinder performance) and not too long(which could introduce skipping movement glitches).
    Ideally you would adjust it to be around mouse resolution, but getting that value becomes platform specific again.



  • In my case I set it to 400 ms, and if it detects a mouseOver on the edge, change to 100 ms to confirm, that would give me a 1/2 second time "from the user's view"

    It is a very precarious algorithm because if the user positions the pointer over the edge 200 ms after released the QTimer event, it will respond to the 300 ms, but I do not have an event, the user must be happy: D



  • Hello again,

    Here are the definition and implementation to detect the position of the mouse on the edges of the desktop that I will use. Criticisms and suggestions welcome.

    It is a QMainWindow with a QTextEdit and a QStatusBar.

    The definition:
    @
    #define TIMER_INT_NORMAL 500
    #define TIMER_INT_REBOTE 50

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    friend class Widget;
    
    QRect                   dimEscr;
    bool                    bordeIzqActivo;
    bool                    bordeDerActivo;
    bool                    bordeSupActivo;
    bool                    bordeInfActivo;
    
    QTimer                  *cronom;
    

    public:

    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    

    private:

    Ui::MainWindow *ui;
    
    
    void obtenerDimensionesDelEscritorio(void);
    void mostrarInformacionDelEscritorio(void);
    void procesarMouseEnBorde(QPoint ubic);
    

    private slots:

    void suenaAlarma(void);
    

    };
    @

    Implementation:
    @
    //-----------------------------------------------------------------------------

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    bordeIzqActivo = true;
    bordeDerActivo = true;
    bordeSupActivo = true;
    bordeInfActivo = true;
    
    obtenerDimensionesDelEscritorio();
    mostrarInformacionDelEscritorio();
    
    cronom = new QTimer(this);
    
    connect(
                cronom,
                SIGNAL(timeout()),
                this,
                SLOT(suenaAlarma())
           );
    
    cronom->setSingleShot(false);
    cronom->setInterval(500);
    cronom->start();
    
    //QWidget::setWindowFlags(Qt::Popup);
    //QWidget::setWindowFlags(Qt::ToolTip|Qt::WindowStaysOnTopHint);
    

    }

    //-----------------------------------------------------------------------------

    MainWindow::~MainWindow()
    {
    cronom->stop();
    delete ui;
    }

    //-----------------------------------------------------------------------------

    void MainWindow::obtenerDimensionesDelEscritorio()
    {
    if ( QApplication::desktop()->isVirtualDesktop() )
    dimEscr = QApplication::desktop()->screen(0)->rect();
    else
    {
    int _w=0, _h=0;

        for ( int i=0; i<QApplication::desktop()->screenCount(); i++ )
        {
            _w += QApplication::desktop()->screenGeometry(i).width();
            if ( QApplication::desktop()->screenGeometry(i).height() > _h )
                _h = QApplication::desktop()->screenGeometry(i).height();
        }
        dimEscr.setWidth(  _w );
        dimEscr.setHeight( _h );
    }
    

    }

    //-----------------------------------------------------------------------------

    void MainWindow::mostrarInformacionDelEscritorio()
    {
    ui->text->append( "¿Maneja escritorios virtuales? " +
    QString( QApplication::desktop()->isVirtualDesktop()?"Si":"No" ) );

    for ( int i=0; i<QApplication::desktop()->screenCount(); i++ )
    {
        QRect rct = QApplication::desktop()->screenGeometry(i);
        ui->text->append( QString("Resolución escritorio %1 : %2 x %3").arg(i).arg(
                              rct.width()).arg(
                              rct.height()) );
    }
    
    ui->text->append( QString("Resolución del escritorio virtual : %1 x %2").arg(
                          dimEscr.width()).arg(dimEscr.height()) );
    

    }

    //-----------------------------------------------------------------------------

    void MainWindow::suenaAlarma()
    {
    QPoint ubicMouse = QCursor::pos();

    if ( ( ubicMouse.x() == 0                    && bordeIzqActivo ) ||
         ( ubicMouse.x() == (dimEscr.width()-1)  && bordeDerActivo ) ||
         ( ubicMouse.y() == 0                    && bordeSupActivo ) ||
         ( ubicMouse.y() == (dimEscr.height()-1) && bordeInfActivo ) )
        procesarMouseEnBorde(ubicMouse);
    else
        cronom->setInterval(TIMER_INT_NORMAL);
    
    ui->statusBar->showMessage( QString("Mouse.Pos X( %1 ) Y( %2 )").arg(
                                    ubicMouse.x() ).arg( ubicMouse.y() ) );
    

    }

    //-----------------------------------------------------------------------------

    void MainWindow::procesarMouseEnBorde(QPoint ubic)
    {
    if ( cronom->interval() == TIMER_INT_REBOTE )
    {
    QDesktopWidget *escritorio = QApplication::desktop();
    int incrXescr = 0;

        for ( int i=0; i<escritorio->screenCount(); i++ )
        {
            if ( (ubic.x() >= incrXescr) &&
                 (ubic.x() <=incrXescr+escritorio->screenGeometry(i).width()) )
                ui->text->append( QString("Ventana en escritorio %1 activada X %2  Y %3").arg(
                                      i).arg(ubic.x()).arg(ubic.y()) );
            incrXescr += escritorio->screenGeometry(i).width();
        }
    
        cronom->setInterval(TIMER_INT_NORMAL);
    }
    else
        cronom->setInterval(TIMER_INT_REBOTE);
    

    }

    //-----------------------------------------------------------------------------
    @

    QDesktopWidget::resized signal attention is pending, but in my case no I implement it to conserve resources.

    I speak of reserve resources because of the way in which I implemented it only I have to process all the desktop as virtual, if bit change of resolution of monitors for each timer event should check the position of the cursor to each of the monitors and their resolutions.

    Best regards

    Dario.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.