How do I toggle 'always on top' for a QMainWindow in Qt without causing a flicker or a flash?

前端 未结 4 1120
猫巷女王i
猫巷女王i 2020-12-28 15:07
void MainWindow::on_actionAlways_on_Top_triggered(bool checked)
{
    Qt::WindowFlags flags = this->windowFlags();
    if (checked)
    {
        this->setWind         


        
4条回答
  •  不知归路
    2020-12-28 15:31

    Since i recently ran into the same issue:

    You can do it by bypassing Qt. For the windows part see @JakePetroules answer.
    XCB (X11) version i use:

    #ifdef Q_OS_LINUX
    #include 
    #include 
    
    // Just a simple atom cache helper
    xcb_atom_t xcb_get_atom(const char *name){
        if (!QX11Info::isPlatformX11()){
            return XCB_ATOM_NONE;
        }
        auto key = QString(name);
        if(_xcb_atom_cache.contains(key)){
            return _xcb_atom_cache[key];
        }
        xcb_connection_t *connection = QX11Info::connection();
        xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name);
        xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL);
        if(!reply){
            return XCB_ATOM_NONE;
        }
        xcb_atom_t atom = reply->atom;
        if(atom == XCB_ATOM_NONE){
            DEBUG("Unknown Atom response from XServer: " << name);
        } else {
            _xcb_atom_cache.insert(key, atom);
        }
        free(reply);
        return atom;
    }
    
    void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2)
    {
        auto connection = QX11Info::connection();
        xcb_atom_t type_atom = xcb_get_atom(type);
        xcb_atom_t prop_atom = xcb_get_atom(prop);
        xcb_client_message_event_t event;
        event.response_type = XCB_CLIENT_MESSAGE;
        event.format = 32;
        event.sequence = 0;
        event.window = window;
        event.type = type_atom;
        event.data.data32[0] = set ? 1 : 0;
        event.data.data32[1] = prop_atom;
        event.data.data32[2] = prop2 ? xcb_get_atom(prop2) : 0;
        event.data.data32[3] = 0;
        event.data.data32[4] = 0;
    
        xcb_send_event(connection, 0, window,
                       XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_PROPERTY_CHANGE,
                       (const char *)&event);
        xcb_flush(connection);
    }
    #endif
    

    Use like: xcb_update_prop(true, window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");

    Its a bit hackish, but it worked fine on Mate, KDE, GNOME3, XFCE and openbox.

提交回复
热议问题