Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom window frame behaving differently across qt builds (ANGLE vs OpenGL)

My task is to create a window for QtQuick with possibility to use it like a common window but with custom frame look (not the default system decoration). I would like to achieve effect similar to Visual Studio window or something like this.

Code that allows me to achieve that goal is shown below:

main.cpp

#include <QtQuick/qquickpainteditem.h>
#include <qapplication.h>
#include <qqmlengine.h>
#include <QtQuick/qquickwindow.h>

class frameLess :
    public QQuickWindow
{
public:
    frameLess(QWindow *parent = 0) :QQuickWindow(parent) { }

    bool nativeEvent(const QByteArray& eventType, void* message, long* result)
    {
        MSG *msg = static_cast<MSG *>(message);

        switch (msg->message)
        {
        case WM_SHOWWINDOW:
            // after that call Qt considers window as frameless
            setFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
            // that call force the Windows to serve users mouse events like in standard window
            SetWindowLongPtr(msg->hwnd, GWL_STYLE, WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
            return false;

        case WM_NCCALCSIZE:
            // prevent the Windows from painting the frame
            *result = 0;
            return true;

        default:
            break;
        }

        return false;
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    qmlRegisterType<frameLess>("fb", 1, 0, "FrameLess");

    QQmlEngine engine;
    QQmlComponent *component = new QQmlComponent(&engine);

    QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));

    component->loadUrl(QUrl("qrc:////main.qml"));

    if (!component->isReady())
    {
        qWarning("%s", qPrintable(component->errorString()));
        return -1;
    }

    QObject *topLevel = component->create();
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);

    QSurfaceFormat surfaceFormat = window->requestedFormat();
    window->setFormat(surfaceFormat);
    window->show();

    return app.exec();
}

main.qml

import fb 1.0
import QtQuick 2.2
import QtQuick.Controls 1.1

FrameLess {
    color:"lightgray"
    Rectangle {
        width: 45
        height: 45
        color: "green"
        anchors {
            top: parent.top
            left: parent.left
        }

        MouseArea {
            anchors.fill: parent
            hoverEnabled: true;
            onEntered: parent.color="red"
            onExited: parent.color="green"
        }
    }
}

As a result, frameless window with green rectangle in the upper left corner should appear. Furthermore, that rectangle should change color to red when hovered by mouse.

When I'm building that with ANGLE-based Qt build, everything works as expected.

Window which is expected

However, my team is using OpenGL-based Qt build. The problem is that when my code is linked against such version of Qt, painting area is shifted by the size of window frame:

Window with shifted painting area

What is more, only painting area is shifted. For example, mouse hitboxes are in proper place. Because of that hitboxes and scene items coordinates are desynchronized. (the interactive area of MouseArea lies in a different place than the Rectangle it fills)

Window with shifted painting area and hovered rectangle hitbox

My expectations was that using a different Qt builds should not affect the resulting application.

My question is why using the OpenGL-based Qt build does affect the window looks and how can I achieve portably (across windows Qt builds) the expected behavior.

The build I was using are:

  • Qt 5.3.1 for Windows 32-bit (VS 2013, OpenGL, 557 MB)
  • Qt 5.3.1 for Windows 32-bit (VS 2013, 559 MB)

I am using Windows 8.1 for testing

Update: It seems that this bug is fixed in Qt 5.4.0

like image 359
Marek Wawrzos Avatar asked Jul 28 '14 11:07

Marek Wawrzos


1 Answers

This is a Qt bug. Please report as such. You shouldn't need to do anything special in your code for this to behave properly.

like image 109
Kuba hasn't forgotten Monica Avatar answered Nov 07 '22 20:11

Kuba hasn't forgotten Monica