Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
361 views
in Technique[技术] by (71.8m points)

c++ - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...