Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QWidget on Mac OS X not focusing in Qt 5.x

I have QSystemTrayIcon with QAction that opens new window of type QWebView. When the window loses focus and I select the QAction again, the window should regain focus. It does on Linux, but doesn't on Mac OS X. The problem is, that when I have another window open and active, let's say Google Chrome, when I call show() on the window I'm trying to open, it always gets opened under the Google Chrome, so I don't see it. The same goes for focusing, when I have multiple windows open, and my QWebView might be the last one in the order, when I click the QAction to focus the window, it will always be under the Google Chrome window. My guess is, that when I click the QAction, which is the part of my application's process, it will try to open/focus the window, but in the middle of the operation, the Google Chrome window gets scheduled and gains focus, since QSystemTrayIcon cannot hold focus. Because of that, when the window gets opened/focused, it will not steal the focus from Google Chrome, because the operating system does not allow it, so it will be placed under currently focused window.

Here how I create/focus the window:

// ...
QPointer<QWebView> view;
// ...

void TrayIcon::webView() {
  if (!this->view) {
    this->view = new QWebView();
    this->view->load("http://example.com");
    this->view->show();
  } else {
    this->view->activateWindow();
    this->view->raise();
  }
}

Is there something I do incorrectly or is there any known workaround?

like image 753
stepanbujnak Avatar asked Jul 01 '13 11:07

stepanbujnak


1 Answers

A bit offtopic, but it may be usefull for some users:

My proposal is to create platform-depended code to force raising of window. There are same problem on Windows platform, so I'm using next hack:

    void Utils::forceForegroundWindow( WId winId )
    {
#ifdef Q_OS_WIN
        HWND hWnd = winId;

        if ( ::IsWindow( hWnd ) )
        {
            HWND hCurrWnd;
            int iMyTID;
            int iCurrTID;

            hCurrWnd = ::GetForegroundWindow();
            iMyTID   = ::GetCurrentThreadId();
            iCurrTID = ::GetWindowThreadProcessId( hCurrWnd, 0 );

            ::AttachThreadInput( iMyTID, iCurrTID, TRUE );

            ::ShowWindow( hWnd, SW_SHOWNORMAL );
            ::SetForegroundWindow( hWnd );

            ::AttachThreadInput( iMyTID, iCurrTID, FALSE );
        }

#endif
    }

I still not provide Mac OS compatibility in my project, so this code has no functionality for non-win platforms.

Another idea: you should always keep focused visible window. Try to do one with WA_TranslucentBackground | WA_TransparentForMouseEvents attributes + FramelessWindowHint flag. So your application will never loose focus.

like image 66
Dmitry Sazonov Avatar answered Oct 23 '22 12:10

Dmitry Sazonov