From eff681c9e56f6044852779b61fbe701e623f2f3a Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 30 Aug 2017 07:04:44 -0400 Subject: Finish up all the mouse focus handling for embedded windows. Works beautifully now. --- src-qt5/core/libLumina/NativeEmbedWidget.cpp | 37 +++++++++++++++++++++++----- src-qt5/core/libLumina/NativeEmbedWidget.h | 7 +++++- src-qt5/core/libLumina/RootSubWindow.cpp | 15 +++++++---- src-qt5/core/libLumina/RootSubWindow.h | 7 ++++-- src-qt5/core/libLumina/RootWindow.cpp | 32 +++++++++++++++++++++++- src-qt5/core/libLumina/RootWindow.h | 4 ++- 6 files changed, 86 insertions(+), 16 deletions(-) (limited to 'src-qt5/core/libLumina') diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.cpp b/src-qt5/core/libLumina/NativeEmbedWidget.cpp index 3472c61e..fbf06aaa 100644 --- a/src-qt5/core/libLumina/NativeEmbedWidget.cpp +++ b/src-qt5/core/libLumina/NativeEmbedWidget.cpp @@ -163,6 +163,11 @@ void NativeEmbedWidget::raiseWindow(){ xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); } +void NativeEmbedWidget::lowerWindow(){ + uint32_t val = XCB_STACK_MODE_BELOW; + xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); +} + // ============== // PUBLIC SLOTS // ============== @@ -280,16 +285,36 @@ void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ void NativeEmbedWidget::enterEvent(QEvent *ev){ QWidget::enterEvent(ev); - //this->grabMouse(); //xcb_grab_pointer_unchecked(QX11Info::connection(), ); + //qDebug() << "Enter Embed Widget"; + //raiseWindow(); //this->grabMouse(); } void NativeEmbedWidget::leaveEvent(QEvent *ev){ QWidget::leaveEvent(ev); - //this->releaseMouse(); //xcb_ungrab_pointer(QX11Info::connection(), XCB_CURRENT_TIME); + /*qDebug() << "Leave Embed Widget"; + QPoint pt = QCursor::pos(); + QPoint relpt = this->parentWidget()->mapFromGlobal(pt); + qDebug() << " - Geom:" << this->geometry() << "Global pt:" << pt << "Relative pt:" << relpt; + if(!this->geometry().contains(relpt) ){ lowerWindow(); }*/ } -bool NativeEmbedWidget::nativeEvent(const QByteArray &eventType, void *message, long *result){ - /*if(eventType=="xcb_generic_event_t" && WIN!=0){ +void NativeEmbedWidget::mouseMoveEvent(QMouseEvent *ev){ + QWidget::mouseMoveEvent(ev); + //Forward this event on to the window +} + +void NativeEmbedWidget::mousePressEvent(QMouseEvent *ev){ + QWidget::mousePressEvent(ev); + //Forward this event on to the window +} + +void NativeEmbedWidget::mouseReleaseEvent(QMouseEvent *ev){ + QWidget::mouseReleaseEvent(ev); + //Forward this event on to the window +} + +/*bool NativeEmbedWidget::nativeEvent(const QByteArray &eventType, void *message, long *result){ + if(eventType=="xcb_generic_event_t" && WIN!=0){ //Convert to known event type (for X11 systems) xcb_generic_event_t *ev = static_cast(message); //qDebug() << "Got Embed Window Event:" << xcb_event_get_label(ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) << xcb_event_get_request_label(ev->response_type); @@ -326,6 +351,6 @@ bool NativeEmbedWidget::nativeEvent(const QByteArray &eventType, void *message, xcb_send_event(QX11Info::connection(), true, WIN->id(),mask, (char*) ev); return true; } - }*/ + } return false; -} +}*/ diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.h b/src-qt5/core/libLumina/NativeEmbedWidget.h index 7e129fa3..532db9b9 100644 --- a/src-qt5/core/libLumina/NativeEmbedWidget.h +++ b/src-qt5/core/libLumina/NativeEmbedWidget.h @@ -18,6 +18,7 @@ #include #include #include +#include class NativeEmbedWidget : public QWidget{ Q_OBJECT @@ -45,6 +46,7 @@ public: public slots: void raiseWindow(); + void lowerWindow(); //Pause/resume void pause(); @@ -61,7 +63,10 @@ protected: void paintEvent(QPaintEvent *ev); void enterEvent(QEvent *ev); void leaveEvent(QEvent *ev); - bool nativeEvent(const QByteArray &eventType, void *message, long *result); + void mouseMoveEvent(QMouseEvent *ev); + void mousePressEvent(QMouseEvent *ev); + void mouseReleaseEvent(QMouseEvent *ev); + //bool nativeEvent(const QByteArray &eventType, void *message, long *result); }; #endif diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp index fba02e96..29c615c5 100644 --- a/src-qt5/core/libLumina/RootSubWindow.cpp +++ b/src-qt5/core/libLumina/RootSubWindow.cpp @@ -295,7 +295,7 @@ void RootSubWindow::toggleSticky(){ } void RootSubWindow::activate(){ - WinWidget->raiseWindow(); + //WinWidget->raiseWindow(); WIN->requestProperty(NativeWindow::Active, true, true); } @@ -373,7 +373,7 @@ void RootSubWindow::propertiesChanged(QList props, QList WinWidget->setMaximumSize(vals[i].toSize()); break; case NativeWindow::Active: - if(vals[i].toBool()){ WinWidget->raiseWindow(); } + //if(vals[i].toBool()){ WinWidget->raiseWindow(); } break; /*case NativeWindow::FrameExtents: qDebug() << " - FRAME CHANGE"; @@ -397,7 +397,7 @@ void RootSubWindow::propertiesChanged(QList props, QList void RootSubWindow::mousePressEvent(QMouseEvent *ev){ activate(); this->raise(); - WinWidget->raiseWindow(); + //WinWidget->raiseWindow(); //qDebug() << "Frame Mouse Press Event"; offset.setX(0); offset.setY(0); if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse @@ -518,12 +518,17 @@ void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){ QTimer::singleShot(0, WinWidget, SLOT(raiseWindow()) ); } -void RootSubWindow::leaveEvent(QEvent *ev){ +/*void RootSubWindow::enterEvent(QEvent *ev){ + QFrame::enterEvent(ev); + WinWidget->raiseWindow(); +}*/ +/*void RootSubWindow::leaveEvent(QEvent *ev){ QFrame::leaveEvent(ev); if(activeState == Normal){ setMouseCursor(Normal); } -} + if(!QRect(QPoint(0,0),this->size()).contains( this->mapFromGlobal(QCursor::pos())) ){ WinWidget->lowerWindow(); } +}*/ void RootSubWindow::moveEvent(QMoveEvent *ev){ //qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry(); diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h index 0af77009..d8b8fd33 100644 --- a/src-qt5/core/libLumina/RootSubWindow.h +++ b/src-qt5/core/libLumina/RootSubWindow.h @@ -65,6 +65,9 @@ private: static QStringList validAnimations(NativeWindow::Property); public slots: + void giveMouseFocus(){ WinWidget->raiseWindow(); } + void removeMouseFocus(){ WinWidget->lowerWindow(); } + void clientClosed(); void LoadAllProperties(); @@ -91,8 +94,8 @@ protected: void mousePressEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*); void mouseReleaseEvent(QMouseEvent*); - void leaveEvent(QEvent *ev); - + //void leaveEvent(QEvent *ev); + //void enterEvent(QEvent *ev); void moveEvent(QMoveEvent *ev); diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/RootWindow.cpp index 952e246b..ccda47e8 100644 --- a/src-qt5/core/libLumina/RootWindow.cpp +++ b/src-qt5/core/libLumina/RootWindow.cpp @@ -16,6 +16,8 @@ RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){ qRegisterMetaType("WId"); autoResizeTimer = 0; + lastActiveMouse = 0; + mouseFocusTimer = 0; this->setMouseTracking(true); } @@ -33,6 +35,12 @@ void RootWindow::start(){ connect(QApplication::desktop(), SIGNAL(resized(int)), autoResizeTimer, SLOT(start()) ); connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), autoResizeTimer, SLOT(start()) ); } + if(mouseFocusTimer==0){ + mouseFocusTimer = new QTimer(this); + mouseFocusTimer->setInterval(100); + connect(mouseFocusTimer, SIGNAL(timeout()), this, SLOT(checkMouseFocus()) ); + + } this->show(); ResizeRoot(); emit RegisterVirtualRoot(this->winId()); @@ -192,6 +200,21 @@ void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QStrin } +void RootWindow::checkMouseFocus(){ + QWidget *child = this->childAt(QCursor::pos()); + while(child!=0 && child->whatsThis()!="RootSubWindow"){ + child = child->parentWidget(); + if(child==this){ child = 0;} //end of the line + } + if(child==lastActiveMouse){ return; } //nothing new to do + //Make sure the child is actually a RootSubWindow + if(lastActiveMouse!=0){ lastActiveMouse->removeMouseFocus(); lastActiveMouse = 0; } + if(child!=0){ + lastActiveMouse = static_cast(child); + lastActiveMouse->giveMouseFocus(); + } +} + void RootWindow::NewWindow(NativeWindow *win){ RootSubWindow *subwin = 0; //qDebug() << "Got New Window:" << win->property(NativeWindow::Title); @@ -200,6 +223,7 @@ void RootWindow::NewWindow(NativeWindow *win){ } if(subwin==0){ subwin = new RootSubWindow(this, win); + subwin->setWhatsThis("RootSubWindow"); connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) ); WINDOWS << subwin; } @@ -207,12 +231,18 @@ void RootWindow::NewWindow(NativeWindow *win){ //win->setProperty(NativeWindow::Visible, true); //win->requestProperty( NativeWindow::Active, true); win->requestProperties(QList() << NativeWindow::Visible << NativeWindow::Active, QList() << true << true); + if(!mouseFocusTimer->isActive()){ mouseFocusTimer->start(); } } void RootWindow::CloseWindow(WId win){ for(int i=0; iid() == win){ WINDOWS.takeAt(i)->clientClosed(); break; } + if(WINDOWS[i]->id() == win){ + if(lastActiveMouse==WINDOWS[i]){ lastActiveMouse = 0; } //no longer valid + WINDOWS.takeAt(i)->clientClosed(); + break; + } } + if(WINDOWS.isEmpty()){ mouseFocusTimer->stop(); } //no windows to look for } // === PRIVATE SLOTS === diff --git a/src-qt5/core/libLumina/RootWindow.h b/src-qt5/core/libLumina/RootWindow.h index 5f11fd6d..725a0430 100644 --- a/src-qt5/core/libLumina/RootWindow.h +++ b/src-qt5/core/libLumina/RootWindow.h @@ -45,7 +45,8 @@ private: ScaleType scale; QPixmap wallpaper; //Note: This pixmap will always be the same size as "area" }; - QTimer *autoResizeTimer; + QTimer *autoResizeTimer, *mouseFocusTimer; + RootSubWindow *lastActiveMouse; QList WALLPAPERS; void updateScreenPixmap(screeninfo *info); //used for recalculating the wallpaper pixmap based on file/area/scale as needed @@ -62,6 +63,7 @@ public slots: void ResizeRoot(); void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file); //Note: for "SingleColor" scaling the "file" variable should be "rgb(R,G,B)" or "#hexcode" + void checkMouseFocus(); void NewWindow(NativeWindow*); void CloseWindow(WId); //automatically connected for any new native window -- cgit