summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_p.h2
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_static.cpp4
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp18
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp352
-rw-r--r--src/platformsupport/fbconvenience/qfbcursor.cpp18
-rw-r--r--src/platformsupport/fbconvenience/qfbcursor_p.h11
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen.cpp159
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen_p.h21
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow.cpp53
-rw-r--r--src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp36
-rw-r--r--src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h2
-rw-r--r--src/platformsupport/fontdatabases/fontdatabases.pro2
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri21
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm42
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm13
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h1
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp10
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h8
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp14
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h26
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp4
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h4
-rw-r--r--src/platformsupport/fontdatabases/windows/windows.pri1
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h4
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp4
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp4
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp4
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchfilter_p.h175
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp272
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h30
-rw-r--r--src/platformsupport/kmsconvenience/kmsconvenience.pro20
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp662
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h170
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp2
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositor_p.h1
-rw-r--r--src/platformsupport/platformsupport.pro4
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp2
-rw-r--r--src/platformsupport/themes/genericunix/genericunix.pri5
38 files changed, 1905 insertions, 276 deletions
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
index d4962fb7d6..e3c22b0b37 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_p.h
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
@@ -68,7 +68,6 @@ QT_BEGIN_NAMESPACE
class QDeviceDiscovery : public QObject
{
Q_OBJECT
- Q_ENUMS(QDeviceType)
public:
enum QDeviceType {
@@ -84,6 +83,7 @@ public:
Device_InputMask = Device_Mouse | Device_Touchpad | Device_Touchscreen | Device_Keyboard | Device_Tablet | Device_Joystick,
Device_VideoMask = Device_DRM
};
+ Q_ENUM(QDeviceType)
Q_DECLARE_FLAGS(QDeviceTypes, QDeviceType)
static QDeviceDiscovery *create(QDeviceTypes type, QObject *parent = 0);
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
index 5c72dbe7e2..a1575677f5 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
@@ -47,7 +47,11 @@
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
#include <fcntl.h>
/* android (and perhaps some other linux-derived stuff) don't define everything
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index da41cfeabf..020d035bf7 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -100,18 +100,24 @@ QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format)
configAttributes.append(EGL_ALPHA_SIZE);
configAttributes.append(alphaSize > 0 ? alphaSize : 0);
- configAttributes.append(EGL_DEPTH_SIZE);
- configAttributes.append(depthSize > 0 ? depthSize : 0);
-
- configAttributes.append(EGL_STENCIL_SIZE);
- configAttributes.append(stencilSize > 0 ? stencilSize : 0);
-
configAttributes.append(EGL_SAMPLES);
configAttributes.append(sampleCount > 0 ? sampleCount : 0);
configAttributes.append(EGL_SAMPLE_BUFFERS);
configAttributes.append(sampleCount > 0);
+ if (format.renderableType() != QSurfaceFormat::OpenVG) {
+ configAttributes.append(EGL_DEPTH_SIZE);
+ configAttributes.append(depthSize > 0 ? depthSize : 0);
+
+ configAttributes.append(EGL_STENCIL_SIZE);
+ configAttributes.append(stencilSize > 0 ? stencilSize : 0);
+ } else {
+ // OpenVG needs alpha mask for clipping
+ configAttributes.append(EGL_ALPHA_MASK_SIZE);
+ configAttributes.append(8);
+ }
+
return configAttributes;
}
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index 6a3bc25418..674ab29012 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -167,6 +167,13 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
: EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
}
}
+
+ // Special Options for OpenVG surfaces
+ if (m_format.renderableType() == QSurfaceFormat::OpenVG) {
+ contextAttrs.append(EGL_ALPHA_MASK_SIZE);
+ contextAttrs.append(8);
+ }
+
contextAttrs.append(EGL_NONE);
m_contextAttrs = contextAttrs;
@@ -450,7 +457,352 @@ QFunctionPointer QEGLPlatformContext::getProcAddress(const char *procName)
#if !defined(Q_OS_WIN) && !defined(Q_OS_INTEGRITY)
if (!proc)
proc = (QFunctionPointer) dlsym(RTLD_DEFAULT, procName);
+#elif !defined(QT_OPENGL_DYNAMIC)
+ // On systems without KHR_get_all_proc_addresses and without
+ // dynamic linking there still has to be a way to access the
+ // standard GLES functions. QOpenGL(Extra)Functions never makes
+ // direct GL API calls since Qt 5.7, so all such workarounds are
+ // expected to be handled in the platform plugin.
+ if (!proc) {
+ static struct StdFunc {
+ const char *name;
+ QFunctionPointer func;
+ } standardFuncs[] = {
+#ifdef QT_OPENGL_ES_2
+ { "glBindTexture", (QFunctionPointer) ::glBindTexture },
+ { "glBlendFunc", (QFunctionPointer) ::glBlendFunc },
+ { "glClear", (QFunctionPointer) ::glClear },
+ { "glClearColor", (QFunctionPointer) ::glClearColor },
+ { "glClearStencil", (QFunctionPointer) ::glClearStencil },
+ { "glColorMask", (QFunctionPointer) ::glColorMask },
+ { "glCopyTexImage2D", (QFunctionPointer) ::glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (QFunctionPointer) ::glCopyTexSubImage2D },
+ { "glCullFace", (QFunctionPointer) ::glCullFace },
+ { "glDeleteTextures", (QFunctionPointer) ::glDeleteTextures },
+ { "glDepthFunc", (QFunctionPointer) ::glDepthFunc },
+ { "glDepthMask", (QFunctionPointer) ::glDepthMask },
+ { "glDisable", (QFunctionPointer) ::glDisable },
+ { "glDrawArrays", (QFunctionPointer) ::glDrawArrays },
+ { "glDrawElements", (QFunctionPointer) ::glDrawElements },
+ { "glEnable", (QFunctionPointer) ::glEnable },
+ { "glFinish", (QFunctionPointer) ::glFinish },
+ { "glFlush", (QFunctionPointer) ::glFlush },
+ { "glFrontFace", (QFunctionPointer) ::glFrontFace },
+ { "glGenTextures", (QFunctionPointer) ::glGenTextures },
+ { "glGetBooleanv", (QFunctionPointer) ::glGetBooleanv },
+ { "glGetError", (QFunctionPointer) ::glGetError },
+ { "glGetFloatv", (QFunctionPointer) ::glGetFloatv },
+ { "glGetIntegerv", (QFunctionPointer) ::glGetIntegerv },
+ { "glGetString", (QFunctionPointer) ::glGetString },
+ { "glGetTexParameterfv", (QFunctionPointer) ::glGetTexParameterfv },
+ { "glGetTexParameteriv", (QFunctionPointer) ::glGetTexParameteriv },
+ { "glHint", (QFunctionPointer) ::glHint },
+ { "glIsEnabled", (QFunctionPointer) ::glIsEnabled },
+ { "glIsTexture", (QFunctionPointer) ::glIsTexture },
+ { "glLineWidth", (QFunctionPointer) ::glLineWidth },
+ { "glPixelStorei", (QFunctionPointer) ::glPixelStorei },
+ { "glPolygonOffset", (QFunctionPointer) ::glPolygonOffset },
+ { "glReadPixels", (QFunctionPointer) ::glReadPixels },
+ { "glScissor", (QFunctionPointer) ::glScissor },
+ { "glStencilFunc", (QFunctionPointer) ::glStencilFunc },
+ { "glStencilMask", (QFunctionPointer) ::glStencilMask },
+ { "glStencilOp", (QFunctionPointer) ::glStencilOp },
+ { "glTexImage2D", (QFunctionPointer) ::glTexImage2D },
+ { "glTexParameterf", (QFunctionPointer) ::glTexParameterf },
+ { "glTexParameterfv", (QFunctionPointer) ::glTexParameterfv },
+ { "glTexParameteri", (QFunctionPointer) ::glTexParameteri },
+ { "glTexParameteriv", (QFunctionPointer) ::glTexParameteriv },
+ { "glTexSubImage2D", (QFunctionPointer) ::glTexSubImage2D },
+ { "glViewport", (QFunctionPointer) ::glViewport },
+
+ { "glActiveTexture", (QFunctionPointer) ::glActiveTexture },
+ { "glAttachShader", (QFunctionPointer) ::glAttachShader },
+ { "glBindAttribLocation", (QFunctionPointer) ::glBindAttribLocation },
+ { "glBindBuffer", (QFunctionPointer) ::glBindBuffer },
+ { "glBindFramebuffer", (QFunctionPointer) ::glBindFramebuffer },
+ { "glBindRenderbuffer", (QFunctionPointer) ::glBindRenderbuffer },
+ { "glBlendColor", (QFunctionPointer) ::glBlendColor },
+ { "glBlendEquation", (QFunctionPointer) ::glBlendEquation },
+ { "glBlendEquationSeparate", (QFunctionPointer) ::glBlendEquationSeparate },
+ { "glBlendFuncSeparate", (QFunctionPointer) ::glBlendFuncSeparate },
+ { "glBufferData", (QFunctionPointer) ::glBufferData },
+ { "glBufferSubData", (QFunctionPointer) ::glBufferSubData },
+ { "glCheckFramebufferStatus", (QFunctionPointer) ::glCheckFramebufferStatus },
+ { "glCompileShader", (QFunctionPointer) ::glCompileShader },
+ { "glCompressedTexImage2D", (QFunctionPointer) ::glCompressedTexImage2D },
+ { "glCompressedTexSubImage2D", (QFunctionPointer) ::glCompressedTexSubImage2D },
+ { "glCreateProgram", (QFunctionPointer) ::glCreateProgram },
+ { "glCreateShader", (QFunctionPointer) ::glCreateShader },
+ { "glDeleteBuffers", (QFunctionPointer) ::glDeleteBuffers },
+ { "glDeleteFramebuffers", (QFunctionPointer) ::glDeleteFramebuffers },
+ { "glDeleteProgram", (QFunctionPointer) ::glDeleteProgram },
+ { "glDeleteRenderbuffers", (QFunctionPointer) ::glDeleteRenderbuffers },
+ { "glDeleteShader", (QFunctionPointer) ::glDeleteShader },
+ { "glDetachShader", (QFunctionPointer) ::glDetachShader },
+ { "glDisableVertexAttribArray", (QFunctionPointer) ::glDisableVertexAttribArray },
+ { "glEnableVertexAttribArray", (QFunctionPointer) ::glEnableVertexAttribArray },
+ { "glFramebufferRenderbuffer", (QFunctionPointer) ::glFramebufferRenderbuffer },
+ { "glFramebufferTexture2D", (QFunctionPointer) ::glFramebufferTexture2D },
+ { "glGenBuffers", (QFunctionPointer) ::glGenBuffers },
+ { "glGenerateMipmap", (QFunctionPointer) ::glGenerateMipmap },
+ { "glGenFramebuffers", (QFunctionPointer) ::glGenFramebuffers },
+ { "glGenRenderbuffers", (QFunctionPointer) ::glGenRenderbuffers },
+ { "glGetActiveAttrib", (QFunctionPointer) ::glGetActiveAttrib },
+ { "glGetActiveUniform", (QFunctionPointer) ::glGetActiveUniform },
+ { "glGetAttachedShaders", (QFunctionPointer) ::glGetAttachedShaders },
+ { "glGetAttribLocation", (QFunctionPointer) ::glGetAttribLocation },
+ { "glGetBufferParameteriv", (QFunctionPointer) ::glGetBufferParameteriv },
+ { "glGetFramebufferAttachmentParameteriv", (QFunctionPointer) ::glGetFramebufferAttachmentParameteriv },
+ { "glGetProgramiv", (QFunctionPointer) ::glGetProgramiv },
+ { "glGetProgramInfoLog", (QFunctionPointer) ::glGetProgramInfoLog },
+ { "glGetRenderbufferParameteriv", (QFunctionPointer) ::glGetRenderbufferParameteriv },
+ { "glGetShaderiv", (QFunctionPointer) ::glGetShaderiv },
+ { "glGetShaderInfoLog", (QFunctionPointer) ::glGetShaderInfoLog },
+ { "glGetShaderPrecisionFormat", (QFunctionPointer) ::glGetShaderPrecisionFormat },
+ { "glGetShaderSource", (QFunctionPointer) ::glGetShaderSource },
+ { "glGetUniformfv", (QFunctionPointer) ::glGetUniformfv },
+ { "glGetUniformiv", (QFunctionPointer) ::glGetUniformiv },
+ { "glGetUniformLocation", (QFunctionPointer) ::glGetUniformLocation },
+ { "glGetVertexAttribfv", (QFunctionPointer) ::glGetVertexAttribfv },
+ { "glGetVertexAttribiv", (QFunctionPointer) ::glGetVertexAttribiv },
+ { "glGetVertexAttribPointerv", (QFunctionPointer) ::glGetVertexAttribPointerv },
+ { "glIsBuffer", (QFunctionPointer) ::glIsBuffer },
+ { "glIsFramebuffer", (QFunctionPointer) ::glIsFramebuffer },
+ { "glIsProgram", (QFunctionPointer) ::glIsProgram },
+ { "glIsRenderbuffer", (QFunctionPointer) ::glIsRenderbuffer },
+ { "glIsShader", (QFunctionPointer) ::glIsShader },
+ { "glLinkProgram", (QFunctionPointer) ::glLinkProgram },
+ { "glReleaseShaderCompiler", (QFunctionPointer) ::glReleaseShaderCompiler },
+ { "glRenderbufferStorage", (QFunctionPointer) ::glRenderbufferStorage },
+ { "glSampleCoverage", (QFunctionPointer) ::glSampleCoverage },
+ { "glShaderBinary", (QFunctionPointer) ::glShaderBinary },
+ { "glShaderSource", (QFunctionPointer) ::glShaderSource },
+ { "glStencilFuncSeparate", (QFunctionPointer) ::glStencilFuncSeparate },
+ { "glStencilMaskSeparate", (QFunctionPointer) ::glStencilMaskSeparate },
+ { "glStencilOpSeparate", (QFunctionPointer) ::glStencilOpSeparate },
+ { "glUniform1f", (QFunctionPointer) ::glUniform1f },
+ { "glUniform1fv", (QFunctionPointer) ::glUniform1fv },
+ { "glUniform1i", (QFunctionPointer) ::glUniform1i },
+ { "glUniform1iv", (QFunctionPointer) ::glUniform1iv },
+ { "glUniform2f", (QFunctionPointer) ::glUniform2f },
+ { "glUniform2fv", (QFunctionPointer) ::glUniform2fv },
+ { "glUniform2i", (QFunctionPointer) ::glUniform2i },
+ { "glUniform2iv", (QFunctionPointer) ::glUniform2iv },
+ { "glUniform3f", (QFunctionPointer) ::glUniform3f },
+ { "glUniform3fv", (QFunctionPointer) ::glUniform3fv },
+ { "glUniform3i", (QFunctionPointer) ::glUniform3i },
+ { "glUniform3iv", (QFunctionPointer) ::glUniform3iv },
+ { "glUniform4f", (QFunctionPointer) ::glUniform4f },
+ { "glUniform4fv", (QFunctionPointer) ::glUniform4fv },
+ { "glUniform4i", (QFunctionPointer) ::glUniform4i },
+ { "glUniform4iv", (QFunctionPointer) ::glUniform4iv },
+ { "glUniformMatrix2fv", (QFunctionPointer) ::glUniformMatrix2fv },
+ { "glUniformMatrix3fv", (QFunctionPointer) ::glUniformMatrix3fv },
+ { "glUniformMatrix4fv", (QFunctionPointer) ::glUniformMatrix4fv },
+ { "glUseProgram", (QFunctionPointer) ::glUseProgram },
+ { "glValidateProgram", (QFunctionPointer) ::glValidateProgram },
+ { "glVertexAttrib1f", (QFunctionPointer) ::glVertexAttrib1f },
+ { "glVertexAttrib1fv", (QFunctionPointer) ::glVertexAttrib1fv },
+ { "glVertexAttrib2f", (QFunctionPointer) ::glVertexAttrib2f },
+ { "glVertexAttrib2fv", (QFunctionPointer) ::glVertexAttrib2fv },
+ { "glVertexAttrib3f", (QFunctionPointer) ::glVertexAttrib3f },
+ { "glVertexAttrib3fv", (QFunctionPointer) ::glVertexAttrib3fv },
+ { "glVertexAttrib4f", (QFunctionPointer) ::glVertexAttrib4f },
+ { "glVertexAttrib4fv", (QFunctionPointer) ::glVertexAttrib4fv },
+ { "glVertexAttribPointer", (QFunctionPointer) ::glVertexAttribPointer },
+
+ { "glClearDepthf", (QFunctionPointer) ::glClearDepthf },
+ { "glDepthRangef", (QFunctionPointer) ::glDepthRangef },
+#endif // QT_OPENGL_ES_2
+
+#ifdef QT_OPENGL_ES_3
+ { "glBeginQuery", (QFunctionPointer) ::glBeginQuery },
+ { "glBeginTransformFeedback", (QFunctionPointer) ::glBeginTransformFeedback },
+ { "glBindBufferBase", (QFunctionPointer) ::glBindBufferBase },
+ { "glBindBufferRange", (QFunctionPointer) ::glBindBufferRange },
+ { "glBindSampler", (QFunctionPointer) ::glBindSampler },
+ { "glBindTransformFeedback", (QFunctionPointer) ::glBindTransformFeedback },
+ { "glBindVertexArray", (QFunctionPointer) ::glBindVertexArray },
+ { "glBlitFramebuffer", (QFunctionPointer) ::glBlitFramebuffer },
+ { "glClearBufferfi", (QFunctionPointer) ::glClearBufferfi },
+ { "glClearBufferfv", (QFunctionPointer) ::glClearBufferfv },
+ { "glClearBufferiv", (QFunctionPointer) ::glClearBufferiv },
+ { "glClearBufferuiv", (QFunctionPointer) ::glClearBufferuiv },
+ { "glClientWaitSync", (QFunctionPointer) ::glClientWaitSync },
+ { "glCompressedTexImage3D", (QFunctionPointer) ::glCompressedTexImage3D },
+ { "glCompressedTexSubImage3D", (QFunctionPointer) ::glCompressedTexSubImage3D },
+ { "glCopyBufferSubData", (QFunctionPointer) ::glCopyBufferSubData },
+ { "glCopyTexSubImage3D", (QFunctionPointer) ::glCopyTexSubImage3D },
+ { "glDeleteQueries", (QFunctionPointer) ::glDeleteQueries },
+ { "glDeleteSamplers", (QFunctionPointer) ::glDeleteSamplers },
+ { "glDeleteSync", (QFunctionPointer) ::glDeleteSync },
+ { "glDeleteTransformFeedbacks", (QFunctionPointer) ::glDeleteTransformFeedbacks },
+ { "glDeleteVertexArrays", (QFunctionPointer) ::glDeleteVertexArrays },
+ { "glDrawArraysInstanced", (QFunctionPointer) ::glDrawArraysInstanced },
+ { "glDrawBuffers", (QFunctionPointer) ::glDrawBuffers },
+ { "glDrawElementsInstanced", (QFunctionPointer) ::glDrawElementsInstanced },
+ { "glDrawRangeElements", (QFunctionPointer) ::glDrawRangeElements },
+ { "glEndQuery", (QFunctionPointer) ::glEndQuery },
+ { "glEndTransformFeedback", (QFunctionPointer) ::glEndTransformFeedback },
+ { "glFenceSync", (QFunctionPointer) ::glFenceSync },
+ { "glFlushMappedBufferRange", (QFunctionPointer) ::glFlushMappedBufferRange },
+ { "glFramebufferTextureLayer", (QFunctionPointer) ::glFramebufferTextureLayer },
+ { "glGenQueries", (QFunctionPointer) ::glGenQueries },
+ { "glGenSamplers", (QFunctionPointer) ::glGenSamplers },
+ { "glGenTransformFeedbacks", (QFunctionPointer) ::glGenTransformFeedbacks },
+ { "glGenVertexArrays", (QFunctionPointer) ::glGenVertexArrays },
+ { "glGetActiveUniformBlockName", (QFunctionPointer) ::glGetActiveUniformBlockName },
+ { "glGetActiveUniformBlockiv", (QFunctionPointer) ::glGetActiveUniformBlockiv },
+ { "glGetActiveUniformsiv", (QFunctionPointer) ::glGetActiveUniformsiv },
+ { "glGetBufferParameteri64v", (QFunctionPointer) ::glGetBufferParameteri64v },
+ { "glGetBufferPointerv", (QFunctionPointer) ::glGetBufferPointerv },
+ { "glGetFragDataLocation", (QFunctionPointer) ::glGetFragDataLocation },
+ { "glGetInteger64i_v", (QFunctionPointer) ::glGetInteger64i_v },
+ { "glGetInteger64v", (QFunctionPointer) ::glGetInteger64v },
+ { "glGetIntegeri_v", (QFunctionPointer) ::glGetIntegeri_v },
+ { "glGetInternalformativ", (QFunctionPointer) ::glGetInternalformativ },
+ { "glGetProgramBinary", (QFunctionPointer) ::glGetProgramBinary },
+ { "glGetQueryObjectuiv", (QFunctionPointer) ::glGetQueryObjectuiv },
+ { "glGetQueryiv", (QFunctionPointer) ::glGetQueryiv },
+ { "glGetSamplerParameterfv", (QFunctionPointer) ::glGetSamplerParameterfv },
+ { "glGetSamplerParameteriv", (QFunctionPointer) ::glGetSamplerParameteriv },
+ { "glGetStringi", (QFunctionPointer) ::glGetStringi },
+ { "glGetSynciv", (QFunctionPointer) ::glGetSynciv },
+ { "glGetTransformFeedbackVarying", (QFunctionPointer) ::glGetTransformFeedbackVarying },
+ { "glGetUniformBlockIndex", (QFunctionPointer) ::glGetUniformBlockIndex },
+ { "glGetUniformIndices", (QFunctionPointer) ::glGetUniformIndices },
+ { "glGetUniformuiv", (QFunctionPointer) ::glGetUniformuiv },
+ { "glGetVertexAttribIiv", (QFunctionPointer) ::glGetVertexAttribIiv },
+ { "glGetVertexAttribIuiv", (QFunctionPointer) ::glGetVertexAttribIuiv },
+ { "glInvalidateFramebuffer", (QFunctionPointer) ::glInvalidateFramebuffer },
+ { "glInvalidateSubFramebuffer", (QFunctionPointer) ::glInvalidateSubFramebuffer },
+ { "glIsQuery", (QFunctionPointer) ::glIsQuery },
+ { "glIsSampler", (QFunctionPointer) ::glIsSampler },
+ { "glIsSync", (QFunctionPointer) ::glIsSync },
+ { "glIsTransformFeedback", (QFunctionPointer) ::glIsTransformFeedback },
+ { "glIsVertexArray", (QFunctionPointer) ::glIsVertexArray },
+ { "glMapBufferRange", (QFunctionPointer) ::glMapBufferRange },
+ { "glPauseTransformFeedback", (QFunctionPointer) ::glPauseTransformFeedback },
+ { "glProgramBinary", (QFunctionPointer) ::glProgramBinary },
+ { "glProgramParameteri", (QFunctionPointer) ::glProgramParameteri },
+ { "glReadBuffer", (QFunctionPointer) ::glReadBuffer },
+ { "glRenderbufferStorageMultisample", (QFunctionPointer) ::glRenderbufferStorageMultisample },
+ { "glResumeTransformFeedback", (QFunctionPointer) ::glResumeTransformFeedback },
+ { "glSamplerParameterf", (QFunctionPointer) ::glSamplerParameterf },
+ { "glSamplerParameterfv", (QFunctionPointer) ::glSamplerParameterfv },
+ { "glSamplerParameteri", (QFunctionPointer) ::glSamplerParameteri },
+ { "glSamplerParameteriv", (QFunctionPointer) ::glSamplerParameteriv },
+ { "glTexImage3D", (QFunctionPointer) ::glTexImage3D },
+ { "glTexStorage2D", (QFunctionPointer) ::glTexStorage2D },
+ { "glTexStorage3D", (QFunctionPointer) ::glTexStorage3D },
+ { "glTexSubImage3D", (QFunctionPointer) ::glTexSubImage3D },
+ { "glTransformFeedbackVaryings", (QFunctionPointer) ::glTransformFeedbackVaryings },
+ { "glUniform1ui", (QFunctionPointer) ::glUniform1ui },
+ { "glUniform1uiv", (QFunctionPointer) ::glUniform1uiv },
+ { "glUniform2ui", (QFunctionPointer) ::glUniform2ui },
+ { "glUniform2uiv", (QFunctionPointer) ::glUniform2uiv },
+ { "glUniform3ui", (QFunctionPointer) ::glUniform3ui },
+ { "glUniform3uiv", (QFunctionPointer) ::glUniform3uiv },
+ { "glUniform4ui", (QFunctionPointer) ::glUniform4ui },
+ { "glUniform4uiv", (QFunctionPointer) ::glUniform4uiv },
+ { "glUniformBlockBinding", (QFunctionPointer) ::glUniformBlockBinding },
+ { "glUniformMatrix2x3fv", (QFunctionPointer) ::glUniformMatrix2x3fv },
+ { "glUniformMatrix2x4fv", (QFunctionPointer) ::glUniformMatrix2x4fv },
+ { "glUniformMatrix3x2fv", (QFunctionPointer) ::glUniformMatrix3x2fv },
+ { "glUniformMatrix3x4fv", (QFunctionPointer) ::glUniformMatrix3x4fv },
+ { "glUniformMatrix4x2fv", (QFunctionPointer) ::glUniformMatrix4x2fv },
+ { "glUniformMatrix4x3fv", (QFunctionPointer) ::glUniformMatrix4x3fv },
+ { "glUnmapBuffer", (QFunctionPointer) ::glUnmapBuffer },
+ { "glVertexAttribDivisor", (QFunctionPointer) ::glVertexAttribDivisor },
+ { "glVertexAttribI4i", (QFunctionPointer) ::glVertexAttribI4i },
+ { "glVertexAttribI4iv", (QFunctionPointer) ::glVertexAttribI4iv },
+ { "glVertexAttribI4ui", (QFunctionPointer) ::glVertexAttribI4ui },
+ { "glVertexAttribI4uiv", (QFunctionPointer) ::glVertexAttribI4uiv },
+ { "glVertexAttribIPointer", (QFunctionPointer) ::glVertexAttribIPointer },
+ { "glWaitSync", (QFunctionPointer) ::glWaitSync },
+#endif // QT_OPENGL_ES_3
+
+#ifdef QT_OPENGL_ES_3_1
+ { "glActiveShaderProgram", (QFunctionPointer) ::glActiveShaderProgram },
+ { "glBindImageTexture", (QFunctionPointer) ::glBindImageTexture },
+ { "glBindProgramPipeline", (QFunctionPointer) ::glBindProgramPipeline },
+ { "glBindVertexBuffer", (QFunctionPointer) ::glBindVertexBuffer },
+ { "glCreateShaderProgramv", (QFunctionPointer) ::glCreateShaderProgramv },
+ { "glDeleteProgramPipelines", (QFunctionPointer) ::glDeleteProgramPipelines },
+ { "glDispatchCompute", (QFunctionPointer) ::glDispatchCompute },
+ { "glDispatchComputeIndirect", (QFunctionPointer) ::glDispatchComputeIndirect },
+ { "glDrawArraysIndirect", (QFunctionPointer) ::glDrawArraysIndirect },
+ { "glDrawElementsIndirect", (QFunctionPointer) ::glDrawElementsIndirect },
+ { "glFramebufferParameteri", (QFunctionPointer) ::glFramebufferParameteri },
+ { "glGenProgramPipelines", (QFunctionPointer) ::glGenProgramPipelines },
+ { "glGetBooleani_v", (QFunctionPointer) ::glGetBooleani_v },
+ { "glGetFramebufferParameteriv", (QFunctionPointer) ::glGetFramebufferParameteriv },
+ { "glGetMultisamplefv", (QFunctionPointer) ::glGetMultisamplefv },
+ { "glGetProgramInterfaceiv", (QFunctionPointer) ::glGetProgramInterfaceiv },
+ { "glGetProgramPipelineInfoLog", (QFunctionPointer) ::glGetProgramPipelineInfoLog },
+ { "glGetProgramPipelineiv", (QFunctionPointer) ::glGetProgramPipelineiv },
+ { "glGetProgramResourceIndex", (QFunctionPointer) ::glGetProgramResourceIndex },
+ { "glGetProgramResourceLocation", (QFunctionPointer) ::glGetProgramResourceLocation },
+ { "glGetProgramResourceName", (QFunctionPointer) ::glGetProgramResourceName },
+ { "glGetProgramResourceiv", (QFunctionPointer) ::glGetProgramResourceiv },
+ { "glGetTexLevelParameterfv", (QFunctionPointer) ::glGetTexLevelParameterfv },
+ { "glGetTexLevelParameteriv", (QFunctionPointer) ::glGetTexLevelParameteriv },
+ { "glIsProgramPipeline", (QFunctionPointer) ::glIsProgramPipeline },
+ { "glMemoryBarrier", (QFunctionPointer) ::glMemoryBarrier },
+ { "glMemoryBarrierByRegion", (QFunctionPointer) ::glMemoryBarrierByRegion },
+ { "glProgramUniform1f", (QFunctionPointer) ::glProgramUniform1f },
+ { "glProgramUniform1fv", (QFunctionPointer) ::glProgramUniform1fv },
+ { "glProgramUniform1i", (QFunctionPointer) ::glProgramUniform1i },
+ { "glProgramUniform1iv", (QFunctionPointer) ::glProgramUniform1iv },
+ { "glProgramUniform1ui", (QFunctionPointer) ::glProgramUniform1ui },
+ { "glProgramUniform1uiv", (QFunctionPointer) ::glProgramUniform1uiv },
+ { "glProgramUniform2f", (QFunctionPointer) ::glProgramUniform2f },
+ { "glProgramUniform2fv", (QFunctionPointer) ::glProgramUniform2fv },
+ { "glProgramUniform2i", (QFunctionPointer) ::glProgramUniform2i },
+ { "glProgramUniform2iv", (QFunctionPointer) ::glProgramUniform2iv },
+ { "glProgramUniform2ui", (QFunctionPointer) ::glProgramUniform2ui },
+ { "glProgramUniform2uiv", (QFunctionPointer) ::glProgramUniform2uiv },
+ { "glProgramUniform3f", (QFunctionPointer) ::glProgramUniform3f },
+ { "glProgramUniform3fv", (QFunctionPointer) ::glProgramUniform3fv },
+ { "glProgramUniform3i", (QFunctionPointer) ::glProgramUniform3i },
+ { "glProgramUniform3iv", (QFunctionPointer) ::glProgramUniform3iv },
+ { "glProgramUniform3ui", (QFunctionPointer) ::glProgramUniform3ui },
+ { "glProgramUniform3uiv", (QFunctionPointer) ::glProgramUniform3uiv },
+ { "glProgramUniform4f", (QFunctionPointer) ::glProgramUniform4f },
+ { "glProgramUniform4fv", (QFunctionPointer) ::glProgramUniform4fv },
+ { "glProgramUniform4i", (QFunctionPointer) ::glProgramUniform4i },
+ { "glProgramUniform4iv", (QFunctionPointer) ::glProgramUniform4iv },
+ { "glProgramUniform4ui", (QFunctionPointer) ::glProgramUniform4ui },
+ { "glProgramUniform4uiv", (QFunctionPointer) ::glProgramUniform4uiv },
+ { "glProgramUniformMatrix2fv", (QFunctionPointer) ::glProgramUniformMatrix2fv },
+ { "glProgramUniformMatrix2x3fv", (QFunctionPointer) ::glProgramUniformMatrix2x3fv },
+ { "glProgramUniformMatrix2x4fv", (QFunctionPointer) ::glProgramUniformMatrix2x4fv },
+ { "glProgramUniformMatrix3fv", (QFunctionPointer) ::glProgramUniformMatrix3fv },
+ { "glProgramUniformMatrix3x2fv", (QFunctionPointer) ::glProgramUniformMatrix3x2fv },
+ { "glProgramUniformMatrix3x4fv", (QFunctionPointer) ::glProgramUniformMatrix3x4fv },
+ { "glProgramUniformMatrix4fv", (QFunctionPointer) ::glProgramUniformMatrix4fv },
+ { "glProgramUniformMatrix4x2fv", (QFunctionPointer) ::glProgramUniformMatrix4x2fv },
+ { "glProgramUniformMatrix4x3fv", (QFunctionPointer) ::glProgramUniformMatrix4x3fv },
+ { "glSampleMaski", (QFunctionPointer) ::glSampleMaski },
+ { "glTexStorage2DMultisample", (QFunctionPointer) ::glTexStorage2DMultisample },
+ { "glUseProgramStages", (QFunctionPointer) ::glUseProgramStages },
+ { "glValidateProgramPipeline", (QFunctionPointer) ::glValidateProgramPipeline },
+ { "glVertexAttribBinding", (QFunctionPointer) ::glVertexAttribBinding },
+ { "glVertexAttribFormat", (QFunctionPointer) ::glVertexAttribFormat },
+ { "glVertexAttribIFormat", (QFunctionPointer) ::glVertexAttribIFormat },
+ { "glVertexBindingDivisor", (QFunctionPointer) ::glVertexBindingDivisor },
+#endif // QT_OPENGL_ES_3_1
+ };
+
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i) {
+ if (!qstrcmp(procName, standardFuncs[i].name)) {
+ proc = standardFuncs[i].func;
+ break;
+ }
+ }
+ }
#endif
+
return proc;
}
diff --git a/src/platformsupport/fbconvenience/qfbcursor.cpp b/src/platformsupport/fbconvenience/qfbcursor.cpp
index 004c586de3..7daf3f4d0c 100644
--- a/src/platformsupport/fbconvenience/qfbcursor.cpp
+++ b/src/platformsupport/fbconvenience/qfbcursor.cpp
@@ -60,8 +60,8 @@ QFbCursor::QFbCursor(QFbScreen *screen)
mScreen(screen),
mDirty(false),
mOnScreen(false),
- mGraphic(0),
- mDeviceListener(0)
+ mCursorImage(nullptr),
+ mDeviceListener(nullptr)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_FB_HIDECURSOR");
if (!hideCursorVal.isEmpty())
@@ -69,7 +69,7 @@ QFbCursor::QFbCursor(QFbScreen *screen)
if (!mVisible)
return;
- mGraphic = new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
+ mCursorImage = new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
setCursor(Qt::ArrowCursor);
mDeviceListener = new QFbCursorDeviceListener(this);
@@ -85,8 +85,8 @@ QFbCursor::~QFbCursor()
QRect QFbCursor::getCurrentRect()
{
- QRect rect = mGraphic->image()->rect().translated(-mGraphic->hotspot().x(),
- -mGraphic->hotspot().y());
+ QRect rect = mCursorImage->image()->rect().translated(-mCursorImage->hotspot().x(),
+ -mCursorImage->hotspot().y());
rect.translate(m_pos);
QPoint mScreenOffset = mScreen->geometry().topLeft();
rect.translate(-mScreenOffset); // global to local translation
@@ -133,7 +133,7 @@ QRect QFbCursor::drawCursor(QPainter & painter)
return QRect();
mPrevRect = mCurrentRect;
- painter.drawImage(mPrevRect, *mGraphic->image());
+ painter.drawImage(mPrevRect, *mCursorImage->image());
mOnScreen = true;
return mPrevRect;
}
@@ -149,17 +149,17 @@ QRect QFbCursor::dirtyRect()
void QFbCursor::setCursor(Qt::CursorShape shape)
{
- mGraphic->set(shape);
+ mCursorImage->set(shape);
}
void QFbCursor::setCursor(const QImage &image, int hotx, int hoty)
{
- mGraphic->set(image, hotx, hoty);
+ mCursorImage->set(image, hotx, hoty);
}
void QFbCursor::setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY)
{
- mGraphic->set(data, mask, width, height, hotX, hotY);
+ mCursorImage->set(data, mask, width, height, hotX, hotY);
}
#ifndef QT_NO_CURSOR
diff --git a/src/platformsupport/fbconvenience/qfbcursor_p.h b/src/platformsupport/fbconvenience/qfbcursor_p.h
index f08babd45b..beda10a5f3 100644
--- a/src/platformsupport/fbconvenience/qfbcursor_p.h
+++ b/src/platformsupport/fbconvenience/qfbcursor_p.h
@@ -87,11 +87,11 @@ public:
virtual QRect drawCursor(QPainter &painter);
// input methods
- void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
- QPoint pos() const Q_DECL_OVERRIDE;
- void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+ void pointerEvent(const QMouseEvent &event) override;
+ QPoint pos() const override;
+ void setPos(const QPoint &pos) override;
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *widgetCursor, QWindow *window) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor *widgetCursor, QWindow *window) override;
#endif
virtual void setDirty();
@@ -113,7 +113,7 @@ private:
QRect mPrevRect; // last place the cursor was drawn
bool mDirty;
bool mOnScreen;
- QPlatformCursorImage *mGraphic;
+ QPlatformCursorImage *mCursorImage;
QFbCursorDeviceListener *mDeviceListener;
QPoint m_pos;
};
@@ -121,4 +121,3 @@ private:
QT_END_NAMESPACE
#endif // QFBCURSOR_P_H
-
diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp
index 216f2722a4..2b4498157c 100644
--- a/src/platformsupport/fbconvenience/qfbscreen.cpp
+++ b/src/platformsupport/fbconvenience/qfbscreen.cpp
@@ -51,19 +51,23 @@
QT_BEGIN_NAMESPACE
-QFbScreen::QFbScreen() : mUpdatePending(false), mCursor(0), mGeometry(), mDepth(16), mFormat(QImage::Format_RGB16), mScreenImage(0), mCompositePainter(0), mIsUpToDate(false)
+QFbScreen::QFbScreen()
+ : mUpdatePending(false),
+ mCursor(0),
+ mDepth(16),
+ mFormat(QImage::Format_RGB16),
+ mPainter(nullptr)
{
}
QFbScreen::~QFbScreen()
{
- delete mCompositePainter;
- delete mScreenImage;
+ delete mPainter;
}
void QFbScreen::initializeCompositor()
{
- mScreenImage = new QImage(mGeometry.size(), mFormat);
+ mScreenImage = QImage(mGeometry.size(), mFormat);
scheduleUpdate();
}
@@ -93,7 +97,6 @@ void QFbScreen::addWindow(QFbWindow *window)
}
}
}
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -103,7 +106,6 @@ void QFbScreen::addWindow(QFbWindow *window)
void QFbScreen::removeWindow(QFbWindow *window)
{
mWindowStack.removeOne(window);
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -116,7 +118,6 @@ void QFbScreen::raise(QFbWindow *window)
if (index <= 0)
return;
mWindowStack.move(index, 0);
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -129,7 +130,6 @@ void QFbScreen::lower(QFbWindow *window)
if (index == -1 || index == (mWindowStack.size() - 1))
return;
mWindowStack.move(index, mWindowStack.size() - 1);
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -142,7 +142,7 @@ QWindow *QFbScreen::topWindow() const
if (fbw->window()->type() == Qt::Window || fbw->window()->type() == Qt::Dialog)
return fbw->window();
}
- return 0;
+ return nullptr;
}
QWindow *QFbScreen::topLevelAt(const QPoint & p) const
@@ -151,14 +151,19 @@ QWindow *QFbScreen::topLevelAt(const QPoint & p) const
if (fbw->geometry().contains(p, false) && fbw->window()->isVisible())
return fbw->window();
}
- return 0;
+ return nullptr;
+}
+
+int QFbScreen::windowCount() const
+{
+ return mWindowStack.count();
}
void QFbScreen::setDirty(const QRect &rect)
{
- QRect intersection = rect.intersected(mGeometry);
- QPoint screenOffset = mGeometry.topLeft();
- mRepaintRegion += intersection.translated(-screenOffset); // global to local translation
+ const QRect intersection = rect.intersected(mGeometry);
+ const QPoint screenOffset = mGeometry.topLeft();
+ mRepaintRegion += intersection.translated(-screenOffset); // global to local translation
scheduleUpdate();
}
@@ -177,141 +182,81 @@ void QFbScreen::setPhysicalSize(const QSize &size)
void QFbScreen::setGeometry(const QRect &rect)
{
- delete mCompositePainter;
- mCompositePainter = 0;
- delete mScreenImage;
+ delete mPainter;
+ mPainter = nullptr;
mGeometry = rect;
- mScreenImage = new QImage(mGeometry.size(), mFormat);
- invalidateRectCache();
+ mScreenImage = QImage(mGeometry.size(), mFormat);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
resizeMaximizedWindows();
}
-void QFbScreen::generateRects()
+bool QFbScreen::initialize()
{
- mCachedRects.clear();
- QPoint screenOffset = mGeometry.topLeft();
- QRegion remainingScreen(mGeometry.translated(-screenOffset)); // global to local translation
-
- for (int i = 0; i < mWindowStack.length(); i++) {
- if (remainingScreen.isEmpty())
- break;
-#if 0
- if (!mWindowStack[i]->isVisible())
- continue;
- if (mWindowStack[i]->isMinimized())
- continue;
-
- if (!mWindowStack[i]->testAttribute(Qt::WA_TranslucentBackground)) {
- QRect localGeometry = mWindowStack.at(i)->geometry().translated(-screenOffset); // global to local translation
- remainingScreen -= localGeometry;
- QRegion windowRegion(localGeometry);
- windowRegion -= remainingScreen;
- for (const QRect &rect : windowRegion)
- mCachedRects += QPair<QRect, int>(rect, i);
- }
-#endif
- }
- mCachedRects.reserve(mCachedRects.count() + remainingScreen.rectCount());
- for (const QRect &rect : remainingScreen)
- mCachedRects += QPair<QRect, int>(rect, -1);
- mIsUpToDate = true;
+ return true;
}
QRegion QFbScreen::doRedraw()
{
- QPoint screenOffset = mGeometry.topLeft();
+ const QPoint screenOffset = mGeometry.topLeft();
QRegion touchedRegion;
if (mCursor && mCursor->isDirty() && mCursor->isOnScreen()) {
- QRect lastCursor = mCursor->dirtyRect();
+ const QRect lastCursor = mCursor->dirtyRect();
mRepaintRegion += lastCursor;
}
- if (mRepaintRegion.isEmpty() && (!mCursor || !mCursor->isDirty())) {
+ if (mRepaintRegion.isEmpty() && (!mCursor || !mCursor->isDirty()))
return touchedRegion;
- }
- QVector<QRect> rects = mRepaintRegion.rects();
-
- if (!mIsUpToDate)
- generateRects();
-
- if (!mCompositePainter)
- mCompositePainter = new QPainter(mScreenImage);
+ if (!mPainter)
+ mPainter = new QPainter(&mScreenImage);
+ const QVector<QRect> rects = mRepaintRegion.rects();
+ const QRect screenRect = mGeometry.translated(-screenOffset);
for (int rectIndex = 0; rectIndex < mRepaintRegion.rectCount(); rectIndex++) {
- QRegion rectRegion = rects[rectIndex];
+ const QRect rect = rects[rectIndex].intersected(screenRect);
+ if (rect.isEmpty())
+ continue;
- for (int i = 0; i < mCachedRects.length(); i++) {
- QRect screenSubRect = mCachedRects[i].first;
- int layer = mCachedRects[i].second;
- QRegion intersect = rectRegion.intersected(screenSubRect);
+ mPainter->setCompositionMode(QPainter::CompositionMode_Source);
+ mPainter->fillRect(rect, mScreenImage.hasAlphaChannel() ? Qt::transparent : Qt::black);
- if (intersect.isEmpty())
+ for (int layerIndex = mWindowStack.size() - 1; layerIndex != -1; layerIndex--) {
+ if (!mWindowStack[layerIndex]->window()->isVisible())
continue;
- rectRegion -= intersect;
-
- // we only expect one rectangle, but defensive coding...
- for (const QRect &rect : intersect) {
- bool firstLayer = true;
- if (layer == -1) {
- mCompositePainter->setCompositionMode(QPainter::CompositionMode_Source);
- mCompositePainter->fillRect(rect, mScreenImage->hasAlphaChannel() ? Qt::transparent : Qt::black);
- firstLayer = false;
- layer = mWindowStack.size() - 1;
- }
-
- for (int layerIndex = layer; layerIndex != -1; layerIndex--) {
- if (!mWindowStack[layerIndex]->window()->isVisible())
- continue;
- // if (mWindowStack[layerIndex]->isMinimized())
- // continue;
-
- QRect windowRect = mWindowStack[layerIndex]->geometry().translated(-screenOffset);
- QRect windowIntersect = rect.translated(-windowRect.left(),
- -windowRect.top());
-
-
- QFbBackingStore *backingStore = mWindowStack[layerIndex]->backingStore();
-
- if (backingStore) {
- backingStore->lock();
- mCompositePainter->drawImage(rect, backingStore->image(), windowIntersect);
- backingStore->unlock();
- }
- if (firstLayer) {
- firstLayer = false;
- }
- }
+ const QRect windowRect = mWindowStack[layerIndex]->geometry().translated(-screenOffset);
+ const QRect windowIntersect = rect.translated(-windowRect.left(), -windowRect.top());
+ QFbBackingStore *backingStore = mWindowStack[layerIndex]->backingStore();
+ if (backingStore) {
+ backingStore->lock();
+ mPainter->drawImage(rect, backingStore->image(), windowIntersect);
+ backingStore->unlock();
}
}
}
- QRect cursorRect;
if (mCursor && (mCursor->isDirty() || mRepaintRegion.intersects(mCursor->lastPainted()))) {
- mCompositePainter->setCompositionMode(QPainter::CompositionMode_SourceOver);
- cursorRect = mCursor->drawCursor(*mCompositePainter);
- touchedRegion += cursorRect;
+ mPainter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ touchedRegion += mCursor->drawCursor(*mPainter);
}
touchedRegion += mRepaintRegion;
mRepaintRegion = QRegion();
-
-
-// qDebug() << "QFbScreen::doRedraw" << mWindowStack.size() << mScreenImage->size() << touchedRegion;
-
return touchedRegion;
}
QFbWindow *QFbScreen::windowForId(WId wid) const
{
- for (int i = 0; i < mWindowStack.count(); ++i)
+ for (int i = 0; i < mWindowStack.count(); ++i) {
if (mWindowStack[i]->winId() == wid)
return mWindowStack[i];
+ }
+ return nullptr;
+}
+QFbScreen::Flags QFbScreen::flags() const
+{
return 0;
}
QT_END_NAMESPACE
-
diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h
index e9b570aa1c..1c27a941cc 100644
--- a/src/platformsupport/fbconvenience/qfbscreen_p.h
+++ b/src/platformsupport/fbconvenience/qfbscreen_p.h
@@ -66,10 +66,18 @@ class QFbBackingStore;
class QFbScreen : public QObject, public QPlatformScreen
{
Q_OBJECT
+
public:
+ enum Flag {
+ DontForceFirstWindowToFullScreen = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
QFbScreen();
~QFbScreen();
+ virtual bool initialize();
+
QRect geometry() const Q_DECL_OVERRIDE { return mGeometry; }
int depth() const Q_DECL_OVERRIDE { return mDepth; }
QImage::Format format() const Q_DECL_OVERRIDE { return mFormat; }
@@ -85,6 +93,8 @@ public:
virtual void raise(QFbWindow *window);
virtual void lower(QFbWindow *window);
virtual void topWindowChanged(QWindow *) {}
+ virtual int windowCount() const;
+ virtual Flags flags() const;
void addPendingBackingStore(QFbBackingStore *bs) { mPendingBackingStores << bs; }
@@ -112,20 +122,17 @@ protected:
int mDepth;
QImage::Format mFormat;
QSizeF mPhysicalSize;
- QImage *mScreenImage;
+ QImage mScreenImage;
private:
- void invalidateRectCache() { mIsUpToDate = false; }
- void generateRects();
-
- QPainter *mCompositePainter;
- QVector<QPair<QRect, int> > mCachedRects;
+ QPainter *mPainter;
QList<QFbBackingStore*> mPendingBackingStores;
friend class QFbWindow;
- bool mIsUpToDate;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFbScreen::Flags)
+
QT_END_NAMESPACE
#endif // QFBSCREEN_P_H
diff --git a/src/platformsupport/fbconvenience/qfbwindow.cpp b/src/platformsupport/fbconvenience/qfbwindow.cpp
index 2d5570fe5d..7e016f2f49 100644
--- a/src/platformsupport/fbconvenience/qfbwindow.cpp
+++ b/src/platformsupport/fbconvenience/qfbwindow.cpp
@@ -66,41 +66,55 @@ void QFbWindow::setGeometry(const QRect &rect)
// store previous geometry for screen update
mOldGeometry = geometry();
- platformScreen()->invalidateRectCache();
QWindowSystemInterface::handleGeometryChange(window(), rect);
QPlatformWindow::setGeometry(rect);
+
+ if (mOldGeometry != rect)
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
}
void QFbWindow::setVisible(bool visible)
{
+ QRect newGeom;
+ QFbScreen *fbScreen = platformScreen();
if (visible) {
- if (mWindowState & Qt::WindowFullScreen)
- setGeometry(platformScreen()->geometry());
+ bool convOk = false;
+ static bool envDisableForceFullScreen = qEnvironmentVariableIntValue("QT_QPA_FB_FORCE_FULLSCREEN", &convOk) == 0 && convOk;
+ const bool platformDisableForceFullScreen = fbScreen->flags().testFlag(QFbScreen::DontForceFirstWindowToFullScreen);
+ const bool forceFullScreen = !envDisableForceFullScreen && !platformDisableForceFullScreen && fbScreen->windowCount() == 0;
+ if (forceFullScreen || (mWindowState & Qt::WindowFullScreen))
+ newGeom = platformScreen()->geometry();
else if (mWindowState & Qt::WindowMaximized)
- setGeometry(platformScreen()->availableGeometry());
+ newGeom = platformScreen()->availableGeometry();
}
QPlatformWindow::setVisible(visible);
if (visible)
- platformScreen()->addWindow(this);
+ fbScreen->addWindow(this);
else
- platformScreen()->removeWindow(this);
-}
+ fbScreen->removeWindow(this);
+ if (!newGeom.isEmpty())
+ setGeometry(newGeom); // may or may not generate an expose
+
+ if (newGeom.isEmpty() || newGeom == mOldGeometry) {
+ // QWindow::isExposed() maps to QWindow::visible() by default so simply
+ // generating an expose event regardless of this being a show or hide is
+ // just what is needed here.
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
+ }
+}
void QFbWindow::setWindowState(Qt::WindowState state)
{
QPlatformWindow::setWindowState(state);
mWindowState = state;
- platformScreen()->invalidateRectCache();
}
-
void QFbWindow::setWindowFlags(Qt::WindowFlags flags)
{
mWindowFlags = flags;
- platformScreen()->invalidateRectCache();
}
Qt::WindowFlags QFbWindow::windowFlags() const
@@ -111,29 +125,26 @@ Qt::WindowFlags QFbWindow::windowFlags() const
void QFbWindow::raise()
{
platformScreen()->raise(this);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
}
void QFbWindow::lower()
{
platformScreen()->lower(this);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
}
void QFbWindow::repaint(const QRegion &region)
{
- QRect currentGeometry = geometry();
-
- QRect dirtyClient = region.boundingRect();
- QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(),
- currentGeometry.top() + dirtyClient.top(),
- dirtyClient.width(),
- dirtyClient.height());
- QRect mOldGeometryLocal = mOldGeometry;
+ const QRect currentGeometry = geometry();
+ const QRect dirtyClient = region.boundingRect();
+ const QRect dirtyRegion = dirtyClient.translated(currentGeometry.topLeft());
+ const QRect oldGeometryLocal = mOldGeometry;
mOldGeometry = currentGeometry;
// If this is a move, redraw the previous location
- if (mOldGeometryLocal != currentGeometry)
- platformScreen()->setDirty(mOldGeometryLocal);
+ if (oldGeometryLocal != currentGeometry)
+ platformScreen()->setDirty(oldGeometryLocal);
platformScreen()->setDirty(dirtyRegion);
}
QT_END_NAMESPACE
-
diff --git a/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp
index de6da88245..03e72546eb 100644
--- a/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp
+++ b/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp
@@ -61,17 +61,19 @@
#include FT_TRUETYPE_TABLES_H
#include FT_TYPE1_TABLES_H
#include FT_GLYPH_H
+#include FT_MODULE_H
#if defined(FT_LCD_FILTER_H)
#include FT_LCD_FILTER_H
+#define QT_USE_FREETYPE_LCDFILTER
#endif
#if defined(FT_CONFIG_OPTIONS_H)
#include FT_CONFIG_OPTIONS_H
#endif
-#if defined(FT_LCD_FILTER_H)
-#define QT_USE_FREETYPE_LCDFILTER
+#if defined(FT_FONT_FORMATS_H)
+#include FT_FONT_FORMATS_H
#endif
#ifdef QT_LINUXBASE
@@ -151,6 +153,14 @@ QtFreetypeData *qt_getFreetypeData()
QtFreetypeData *&freetypeData = theFreetypeData()->localData();
if (!freetypeData)
freetypeData = new QtFreetypeData;
+ if (!freetypeData->library) {
+ FT_Init_FreeType(&freetypeData->library);
+#if defined(FT_FONT_FORMATS_H)
+ // Freetype defaults to disabling stem-darkening on CFF, we re-enable it.
+ FT_Bool no_darkening = false;
+ FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening);
+#endif
+ }
return freetypeData;
}
#endif
@@ -158,8 +168,7 @@ QtFreetypeData *qt_getFreetypeData()
FT_Library qt_getFreetype()
{
QtFreetypeData *freetypeData = qt_getFreetypeData();
- if (!freetypeData->library)
- FT_Init_FreeType(&freetypeData->library);
+ Q_ASSERT(freetypeData->library);
return freetypeData->library;
}
@@ -218,8 +227,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
return 0;
QtFreetypeData *freetypeData = qt_getFreetypeData();
- if (!freetypeData->library)
- FT_Init_FreeType(&freetypeData->library);
QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
if (freetype) {
@@ -687,6 +694,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
cacheEnabled = env.isEmpty() || env.toInt() == 0;
m_subPixelPositionCount = 4;
forceAutoHint = false;
+ stemDarkeningDriver = false;
}
QFontEngineFT::~QFontEngineFT()
@@ -798,6 +806,17 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
}
}
}
+#if defined(FT_FONT_FORMATS_H)
+ const char *fmt = FT_Get_Font_Format(face);
+ if (fmt && qstrncmp(fmt, "CFF", 4) == 0) {
+ FT_Bool no_stem_darkening = true;
+ FT_Error err = FT_Property_Get(qt_getFreetype(), "cff", "no-stem-darkening", &no_stem_darkening);
+ if (err == FT_Err_Ok)
+ stemDarkeningDriver = !no_stem_darkening;
+ else
+ stemDarkeningDriver = false;
+ }
+#endif
fontDef.styleName = QString::fromUtf8(face->style_name);
@@ -841,6 +860,11 @@ void QFontEngineFT::setDefaultHintStyle(HintStyle style)
default_hint_style = style;
}
+bool QFontEngineFT::expectsGammaCorrectedBlending() const
+{
+ return stemDarkeningDriver;
+}
+
int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
bool &hsubpixel, int &vfactor) const
{
diff --git a/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h
index c5f3b0443e..3b751eae3e 100644
--- a/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h
+++ b/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h
@@ -246,6 +246,7 @@ private:
QPoint *offset) Q_DECL_OVERRIDE;
bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; }
void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE;
+ bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE;
void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE;
int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; }
@@ -305,6 +306,7 @@ protected:
bool embeddedbitmap;
bool cacheEnabled;
bool forceAutoHint;
+ bool stemDarkeningDriver;
private:
friend class QFontEngineFTRawFont;
diff --git a/src/platformsupport/fontdatabases/fontdatabases.pro b/src/platformsupport/fontdatabases/fontdatabases.pro
index 9376c3b702..49dead4668 100644
--- a/src/platformsupport/fontdatabases/fontdatabases.pro
+++ b/src/platformsupport/fontdatabases/fontdatabases.pro
@@ -7,7 +7,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
-darwin:!if(watchos:CONFIG(simulator, simulator|device)) {
+darwin {
include($$PWD/mac/coretext.pri)
} else {
qtConfig(freetype) {
diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri
index 50dafc3f89..f73e22eb1a 100644
--- a/src/platformsupport/fontdatabases/mac/coretext.pri
+++ b/src/platformsupport/fontdatabases/mac/coretext.pri
@@ -11,6 +11,21 @@ uikit: \
# On iOS/tvOS/watchOS CoreText and CoreGraphics are stand-alone frameworks
LIBS_PRIVATE += -framework CoreText -framework CoreGraphics
else: \
- # On Mac OS they are part of the ApplicationServices umbrella framework,
- # even in 10.8 where they were also made available stand-alone.
- LIBS_PRIVATE += -framework ApplicationServices
+ # On macOS they are re-exported by the AppKit framework
+ LIBS_PRIVATE += -framework AppKit
+
+# CoreText is documented to be available on watchOS, but the headers aren't present
+# in the watchOS Simulator SDK like they are supposed to be. Work around the problem
+# by adding the device SDK's headers to the search path as a fallback.
+# rdar://25314492, rdar://27844864
+watchos:simulator {
+ simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks
+ device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
+ for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) {
+ QMAKE_CXXFLAGS += \
+ -Xarch_$${arch} \
+ -F$$simulator_system_frameworks \
+ -Xarch_$${arch} \
+ -F$$device_system_frameworks
+ }
+}
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 3d94982f60..2b9e928266 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -708,71 +708,71 @@ static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
{
switch (f) {
case QPlatformTheme::SystemFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::MenuFont:
case QPlatformTheme::MenuBarFont:
case QPlatformTheme::MenuItemFont:
- return kCTFontMenuItemFontType;
+ return kCTFontUIFontMenuItem;
case QPlatformTheme::MessageBoxFont:
- return kCTFontEmphasizedSystemFontType;
+ return kCTFontUIFontEmphasizedSystem;
case QPlatformTheme::LabelFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::TipLabelFont:
return kCTFontToolTipFontType;
case QPlatformTheme::StatusBarFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::TitleBarFont:
- return kCTFontWindowTitleFontType;
+ return kCTFontUIFontWindowTitle;
case QPlatformTheme::MdiSubWindowTitleFont:
case QPlatformTheme::DockWidgetTitleFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::PushButtonFont:
- return kCTFontPushButtonFontType;
+ return kCTFontUIFontPushButton;
case QPlatformTheme::CheckBoxFont:
case QPlatformTheme::RadioButtonFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::ToolButtonFont:
- return kCTFontSmallToolbarFontType;
+ return kCTFontUIFontSmallToolbar;
case QPlatformTheme::ItemViewFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::ListViewFont:
- return kCTFontViewsFontType;
+ return kCTFontUIFontViews;
case QPlatformTheme::HeaderViewFont:
- return kCTFontSmallSystemFontType;
+ return kCTFontUIFontSmallSystem;
case QPlatformTheme::ListBoxFont:
- return kCTFontViewsFontType;
+ return kCTFontUIFontViews;
case QPlatformTheme::ComboMenuItemFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::ComboLineEditFont:
- return kCTFontViewsFontType;
+ return kCTFontUIFontViews;
case QPlatformTheme::SmallFont:
- return kCTFontSmallSystemFontType;
+ return kCTFontUIFontSmallSystem;
case QPlatformTheme::MiniFont:
- return kCTFontMiniSystemFontType;
+ return kCTFontUIFontMiniSystem;
case QPlatformTheme::FixedFont:
- return kCTFontUserFixedPitchFontType;
+ return kCTFontUIFontUserFixedPitch;
default:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
}
}
@@ -848,7 +848,7 @@ QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
QFont QCoreTextFontDatabase::defaultFont() const
{
if (defaultFontName.isEmpty()) {
- QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 12.0, NULL);
+ QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, 12.0, NULL);
defaultFontName = (QString) QCFString(CTFontCopyFullName(font));
}
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 7a06d5f1c9..c8ae342f16 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -141,7 +141,7 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont,
{
Q_UNUSED(flags);
QVarLengthArray<CGSize> advances(len);
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), len);
for (int i = 0; i < len; ++i) {
if (glyphs->glyphs[i] & 0xff000000)
@@ -320,7 +320,7 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
return true;
QVarLengthArray<CGSize> advances(glyph_pos);
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), glyph_pos);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), glyph_pos);
for (int i = 0; i < glyph_pos; ++i) {
if (glyphs->glyphs[i] & 0xff000000)
@@ -351,7 +351,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
{
glyph_metrics_t ret;
CGGlyph g = glyph;
- CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1);
+ CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontOrientationHorizontal, &g, 0, 1);
if (synthesisFlags & QFontEngine::SynthesizedItalic) {
rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW;
}
@@ -360,7 +360,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
ret.x = QFixed::fromReal(rect.origin.x);
ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
CGSize advances[1];
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, &g, advances, 1);
ret.xoff = QFixed::fromReal(advances[0].width);
ret.yoff = QFixed::fromReal(advances[0].height);
@@ -602,6 +602,11 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed s
return br;
}
+bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const
+{
+ // Only works well when font-smoothing is enabled
+ return (glyphFormat == Format_A32) && !(fontDef.styleStrategy & (QFont::NoAntialias | QFont::NoSubpixelAntialias));
+}
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix)
{
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index d9ffbb5697..0074790e43 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -110,6 +110,7 @@ public:
void doKerning(QGlyphLayout *g, ShaperFlags flags) const Q_DECL_OVERRIDE;
bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
+ bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE;
QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
Qt::HANDLE handle() const Q_DECL_OVERRIDE;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index c457246354..d3e4daa341 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -591,12 +591,7 @@ namespace {
*/
QWindowsFontEngineData::QWindowsFontEngineData()
- : clearTypeEnabled(false)
- , fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma())
-#if !defined(QT_NO_DIRECTWRITE)
- , directWriteFactory(0)
- , directWriteGdiInterop(0)
-#endif
+ : fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma())
{
// from qapplication_win.cpp
UINT result = 0;
@@ -1221,8 +1216,6 @@ QWindowsFontEngineDataPtr sharedFontData()
}
#endif // QT_NO_THREAD
-extern Q_GUI_EXPORT bool qt_needs_a8_gamma_correction;
-
QWindowsFontDatabase::QWindowsFontDatabase()
{
// Properties accessed by QWin32PrintEngine (Qt Print Support)
@@ -1236,7 +1229,6 @@ QWindowsFontDatabase::QWindowsFontDatabase()
qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: "
<< data->clearTypeEnabled << "gamma: " << data->fontSmoothingGamma;
}
- qt_needs_a8_gamma_correction = true;
}
QWindowsFontDatabase::~QWindowsFontDatabase()
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
index 325f522335..15172c09da 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
@@ -74,12 +74,12 @@ public:
uint pow_gamma[256];
- bool clearTypeEnabled;
+ bool clearTypeEnabled = false;
qreal fontSmoothingGamma;
- HDC hdc;
+ HDC hdc = 0;
#if !defined(QT_NO_DIRECTWRITE)
- IDWriteFactory *directWriteFactory;
- IDWriteGdiInterop *directWriteGdiInterop;
+ IDWriteFactory *directWriteFactory = nullptr;
+ IDWriteGdiInterop *directWriteGdiInterop = nullptr;
#endif
};
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
index 08ebbc3be0..5f55dba9da 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
@@ -239,21 +239,9 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
: QFontEngine(Win),
m_fontEngineData(fontEngineData),
_name(name),
- hfont(0),
m_logfont(lf),
ttf(0),
- hasOutline(0),
- cmap(0),
- cmapSize(0),
- lbearing(SHRT_MIN),
- rbearing(SHRT_MIN),
- x_height(-1),
- synthesized_flags(-1),
- lineWidth(-1),
- widthCache(0),
- widthCacheSize(0),
- designAdvances(0),
- designAdvancesSize(0)
+ hasOutline(0)
{
qCDebug(lcQpaFonts) << __FUNCTION__ << name << lf.lfHeight;
hfont = CreateFontIndirect(&m_logfont);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
index 709de7d11d..5119adc0eb 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
@@ -145,29 +145,29 @@ private:
const QString _name;
QString uniqueFamilyName;
- HFONT hfont;
+ HFONT hfont = 0;
const LOGFONT m_logfont;
uint ttf : 1;
uint hasOutline : 1;
uint hasUnreliableOutline : 1;
uint cffTable : 1;
TEXTMETRIC tm;
- const unsigned char *cmap;
- int cmapSize;
+ const unsigned char *cmap = nullptr;
+ int cmapSize = 0;
QByteArray cmapTable;
- mutable qreal lbearing;
- mutable qreal rbearing;
+ mutable qreal lbearing = SHRT_MIN;
+ mutable qreal rbearing = SHRT_MIN;
QFixed designToDevice;
- int unitsPerEm;
- QFixed x_height;
+ int unitsPerEm = 0;
+ QFixed x_height = -1;
FaceId _faceId;
- mutable int synthesized_flags;
- mutable QFixed lineWidth;
- mutable unsigned char *widthCache;
- mutable uint widthCacheSize;
- mutable QFixed *designAdvances;
- mutable int designAdvancesSize;
+ mutable int synthesized_flags = -1;
+ mutable QFixed lineWidth = -1;
+ mutable unsigned char *widthCache = nullptr;
+ mutable uint widthCacheSize = 0;
+ mutable QFixed *designAdvances = nullptr;
+ mutable int designAdvancesSize = 0;
};
class QWindowsMultiFontEngine : public QFontEngineMulti
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp
index 7022615511..f8fcff952a 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp
@@ -110,9 +110,7 @@ static inline HBITMAP createDIB(HDC hdc, int width, int height,
QWindowsNativeImage::QWindowsNativeImage(int width, int height,
QImage::Format format) :
- m_hdc(createDC()),
- m_bitmap(0),
- m_null_bitmap(0)
+ m_hdc(createDC())
{
if (width != 0 && height != 0) {
uchar *bits;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
index c27c0d1e98..6c47a527d2 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
@@ -80,8 +80,8 @@ private:
const HDC m_hdc;
QImage m_image;
- HBITMAP m_bitmap;
- HBITMAP m_null_bitmap;
+ HBITMAP m_bitmap = 0;
+ HBITMAP m_null_bitmap = 0;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri
index 4ca0080ad9..0e64084cf1 100644
--- a/src/platformsupport/fontdatabases/windows/windows.pri
+++ b/src/platformsupport/fontdatabases/windows/windows.pri
@@ -26,3 +26,4 @@ qtConfig(directwrite) {
}
LIBS += -lole32 -lgdi32 -luser32 -ladvapi32
+mingw: LIBS += -luuid
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
index bc0485232d..17bf0fb797 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
@@ -52,7 +52,11 @@
//
#include "qnamespace.h"
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include "linux/input.h"
+#endif
// no QT_BEGIN_NAMESPACE, since we include it internally...
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
index 0eb6fc0847..5c87cb7c9c 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
@@ -49,7 +49,11 @@
#include <qpa/qwindowsysteminterface.h>
#include <private/qcore_unix_p.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index d5ea04bee8..9b4bcf1575 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -53,8 +53,12 @@
#include <errno.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/kd.h>
#include <linux/input.h>
+#endif
#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8)))
diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
index dc03daedda..86f8a00b13 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
+++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
@@ -45,7 +45,11 @@
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
#include <qpa/qwindowsysteminterface.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchfilter_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchfilter_p.h
new file mode 100644
index 0000000000..ff6085d725
--- /dev/null
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchfilter_p.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+struct QEvdevTouchFilter
+{
+ QEvdevTouchFilter();
+
+ void initialize(float pos, float velocity);
+ void update(float pos, float velocity, float timeDelta);
+
+ float position() const { return x.x; }
+ float velocity() const { return x.y; }
+
+private:
+ struct vec2 {
+ vec2(float x = 0.0f, float y = 0.0f) : x(x), y(y) { }
+ float x, y;
+
+ vec2 operator-(vec2 v) {
+ return vec2(x - v.x, y - v.y);
+ }
+
+ vec2 operator+(vec2 v) {
+ return vec2(x + v.x, y + v.y);
+ }
+ };
+
+ struct mat2 {
+ float a, b, c, d;
+ mat2(float a = 1.0f, float b = 0.0f, float c = 0.0f, float d = 1.0f)
+ : a(a)
+ , b(b)
+ , c(c)
+ , d(d)
+ {
+ }
+
+ mat2 transposed() const {
+ return mat2(a, c,
+ b, d);
+ }
+
+ mat2 inverted() const {
+ float det = 1.0f / (a * d - b * c);
+ return mat2( d * det, -b * det,
+ -c * det, a * det);
+ }
+
+ mat2 operator+(mat2 m) const {
+ return mat2(a + m.a, b + m.b,
+ c + m.c, d + m.d);
+ }
+
+ mat2 operator-(mat2 m) const {
+ return mat2(a - m.a, b - m.b,
+ c - m.c, d - m.d);
+ }
+
+ vec2 operator*(vec2 v) const {
+ return vec2(a * v.x + b * v.y,
+ c * v.x + d * v.y);
+ }
+
+ mat2 operator*(mat2 M) const {
+ return mat2(a * M.a + b * M.c,
+ a * M.b + b * M.d,
+ c * M.a + d * M.c,
+ c * M.b + d * M.d);
+ }
+ };
+
+ vec2 x;
+ mat2 A;
+ mat2 P;
+ mat2 Q;
+ mat2 R;
+ mat2 H;
+};
+
+inline QEvdevTouchFilter::QEvdevTouchFilter()
+{
+}
+
+inline void QEvdevTouchFilter::initialize(float pos, float velocity)
+{
+ x = vec2(pos, velocity);
+
+ P = mat2(0.0f, 0.0f,
+ 0.0f, 0.0f);
+
+ Q = mat2(0.0f, 0.0f,
+ 0.0f, 0.1f);
+ R = mat2(0.1f, 0.0f,
+ 0.0f, 0.1f);
+}
+
+inline void QEvdevTouchFilter::update(float pos, float velocity, float dT)
+{
+ A.b = dT;
+
+ // Prediction setp
+ x = A * x;
+ P = A * P * A.transposed() + Q;
+
+ // Correction step (complete with H)
+ // mat2 S = H * P * H.transposed() + R;
+ // mat2 K = P * H.transposed() * S.inverted();
+ // vec2 m(pos, velocity);
+ // vec2 y = m - H * x;
+ // x = x + K * y;
+ // P = (mat2() - K * H) * P;
+
+ // Correction step (without H as H is currently set to I, so we can ignore
+ // it in the calculations...)
+ mat2 S = P + R;
+ mat2 K = P * S.inverted();
+ vec2 m(pos, velocity);
+ vec2 y = m - x;
+ x = x + K * y;
+ P = (mat2() - K) * P;
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index d53a317fc5..11f7311bb7 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins module of the Qt Toolkit.
@@ -48,7 +49,11 @@
#include <QtCore/private/qcore_unix_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
#if QT_CONFIG(mtdev)
extern "C" {
@@ -96,6 +101,7 @@ public:
QEvdevTouchScreenHandler *q;
int m_lastEventType;
QList<QWindowSystemInterface::TouchPoint> m_touchPoints;
+ QList<QWindowSystemInterface::TouchPoint> m_lastTouchPoints;
struct Contact {
int trackingId;
@@ -114,11 +120,16 @@ public:
Contact m_currentData;
int m_currentSlot;
+ double m_timeStamp;
+ double m_lastTimeStamp;
+
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
void addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates);
void reportPoints();
void loadMultiScreenMappings();
+ QRect screenGeometry() const;
+
int hw_range_x_min;
int hw_range_x_max;
int hw_range_y_min;
@@ -132,19 +143,40 @@ public:
QTransform m_rotate;
bool m_singleTouch;
QString m_screenName;
- QPointer<QScreen> m_screen;
+ mutable QPointer<QScreen> m_screen;
+
+ // Touch filtering and prediction are part of the same thing. The default
+ // prediction is 0ms, but sensible results can be acheived by setting it
+ // to, for instance, 16ms.
+ // For filtering to work well, the QPA plugin should provide a dead-steady
+ // implementation of QPlatformWindow::requestUpdate().
+ bool m_filtered;
+ int m_prediction;
+
+ // When filtering is enabled, protect the access to current and last
+ // timeStamp and touchPoints, as these are being read on the gui thread.
+ QMutex m_mutex;
};
QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, const QStringList &args)
: q(q_ptr),
m_lastEventType(-1),
m_currentSlot(0),
+ m_timeStamp(0), m_lastTimeStamp(0),
hw_range_x_min(0), hw_range_x_max(0),
hw_range_y_min(0), hw_range_y_max(0),
hw_pressure_min(0), hw_pressure_max(0),
- m_typeB(false), m_singleTouch(false)
+ m_forceToActiveWindow(false), m_typeB(false), m_singleTouch(false),
+ m_filtered(false), m_prediction(0)
{
- m_forceToActiveWindow = args.contains(QLatin1String("force_window"));
+ for (const QString &arg : args) {
+ if (arg == QStringLiteral("force_window"))
+ m_forceToActiveWindow = true;
+ else if (arg == QStringLiteral("filtered"))
+ m_filtered = true;
+ else if (arg.startsWith(QStringLiteral("prediction=")))
+ m_prediction = arg.mid(11).toInt();
+ }
}
#define LONG_BITS (sizeof(long) << 3)
@@ -228,9 +260,14 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
#endif
d->deviceNode = device;
-
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: Protocol type %c %s (%s)", qPrintable(d->deviceNode),
- d->m_typeB ? 'B' : 'A', mtdevStr, d->m_singleTouch ? "single" : "multi");
+ qCDebug(qLcEvdevTouch,
+ "evdevtouch: %s: Protocol type %c %s (%s), filtered=%s",
+ qPrintable(d->deviceNode),
+ d->m_typeB ? 'B' : 'A', mtdevStr,
+ d->m_singleTouch ? "single" : "multi",
+ d->m_filtered ? "yes" : "no");
+ if (d->m_filtered)
+ qCDebug(qLcEvdevTouch, " - prediction=%d", d->m_prediction);
input_absinfo absInfo;
memset(&absInfo, 0, sizeof(input_absinfo));
@@ -327,6 +364,11 @@ QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler()
unregisterTouchDevice();
}
+bool QEvdevTouchScreenHandler::isFiltered() const
+{
+ return d->m_filtered;
+}
+
QTouchDevice *QEvdevTouchScreenHandler::touchDevice() const
{
return m_device;
@@ -516,6 +558,14 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (!m_contacts.isEmpty() && m_contacts.constBegin().value().trackingId == -1)
assignIds();
+ if (m_filtered)
+ m_mutex.lock();
+
+ // update timestamps
+ m_lastTimeStamp = m_timeStamp;
+ m_timeStamp = data->time.tv_sec + data->time.tv_usec / 1000000.0;
+
+ m_lastTouchPoints = m_touchPoints;
m_touchPoints.clear();
Qt::TouchPointStates combinedStates;
@@ -593,8 +643,12 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (!m_typeB && !m_singleTouch)
m_contacts.clear();
+
if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
reportPoints();
+
+ if (m_filtered)
+ m_mutex.unlock();
}
m_lastEventType = data->type;
@@ -653,41 +707,45 @@ void QEvdevTouchScreenData::assignIds()
m_contacts = newContacts;
}
-void QEvdevTouchScreenData::reportPoints()
+QRect QEvdevTouchScreenData::screenGeometry() const
{
- QRect winRect;
if (m_forceToActiveWindow) {
QWindow *win = QGuiApplication::focusWindow();
- if (!win)
- return;
- winRect = QHighDpi::toNativePixels(win->geometry(), win);
- } else {
- // Now it becomes tricky. Traditionally we picked the primaryScreen()
- // and were done with it. But then, enter multiple screens, and
- // suddenly it was all broken.
- //
- // For now we only support the display configuration of the KMS/DRM
- // backends of eglfs. See QTouchOutputMapping.
- //
- // The good news it that once winRect refers to the correct screen
- // geometry in the full virtual desktop space, there is nothing else
- // left to do since qguiapp will handle the rest.
- QScreen *screen = QGuiApplication::primaryScreen();
- if (!m_screenName.isEmpty()) {
- if (!m_screen) {
- const QList<QScreen *> screens = QGuiApplication::screens();
- for (QScreen *s : screens) {
- if (s->name() == m_screenName) {
- m_screen = s;
- break;
- }
+ return win ? QHighDpi::toNativePixels(win->geometry(), win) : QRect();
+ }
+
+ // Now it becomes tricky. Traditionally we picked the primaryScreen()
+ // and were done with it. But then, enter multiple screens, and
+ // suddenly it was all broken.
+ //
+ // For now we only support the display configuration of the KMS/DRM
+ // backends of eglfs. See QTouchOutputMapping.
+ //
+ // The good news it that once winRect refers to the correct screen
+ // geometry in the full virtual desktop space, there is nothing else
+ // left to do since qguiapp will handle the rest.
+ QScreen *screen = QGuiApplication::primaryScreen();
+ if (!m_screenName.isEmpty()) {
+ if (!m_screen) {
+ const QList<QScreen *> screens = QGuiApplication::screens();
+ for (QScreen *s : screens) {
+ if (s->name() == m_screenName) {
+ m_screen = s;
+ break;
}
}
- if (m_screen)
- screen = m_screen;
}
- winRect = QHighDpi::toNativePixels(screen->geometry(), screen);
+ if (m_screen)
+ screen = m_screen;
}
+ return QHighDpi::toNativePixels(screen->geometry(), screen);
+}
+
+void QEvdevTouchScreenData::reportPoints()
+{
+ QRect winRect = screenGeometry();
+ if (winRect.isNull())
+ return;
const int hw_w = hw_range_x_max - hw_range_x_min;
const int hw_h = hw_range_y_max - hw_range_y_min;
@@ -718,13 +776,17 @@ void QEvdevTouchScreenData::reportPoints()
}
// Let qguiapp pick the target window.
- QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, q->touchDevice(), m_touchPoints);
+ if (m_filtered)
+ emit q->touchPointsUpdated();
+ else
+ QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, q->touchDevice(), m_touchPoints);
}
-
-
QEvdevTouchScreenHandlerThread::QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent)
: QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(Q_NULLPTR), m_touchDeviceRegistered(false)
+ , m_touchUpdatePending(false)
+ , m_filterWindow(Q_NULLPTR)
+ , m_touchRate(-1)
{
start();
}
@@ -738,6 +800,10 @@ QEvdevTouchScreenHandlerThread::~QEvdevTouchScreenHandlerThread()
void QEvdevTouchScreenHandlerThread::run()
{
m_handler = new QEvdevTouchScreenHandler(m_device, m_spec);
+
+ if (m_handler->isFiltered())
+ connect(m_handler, &QEvdevTouchScreenHandler::touchPointsUpdated, this, &QEvdevTouchScreenHandlerThread::scheduleTouchPointUpdate);
+
// Report the registration to the parent thread by invoking the method asynchronously
QMetaObject::invokeMethod(this, "notifyTouchDeviceRegistered", Qt::QueuedConnection);
@@ -758,5 +824,137 @@ void QEvdevTouchScreenHandlerThread::notifyTouchDeviceRegistered()
emit touchDeviceRegistered();
}
+void QEvdevTouchScreenHandlerThread::scheduleTouchPointUpdate()
+{
+ QWindow *window = QGuiApplication::focusWindow();
+ if (window != m_filterWindow) {
+ if (m_filterWindow)
+ m_filterWindow->removeEventFilter(this);
+ m_filterWindow = window;
+ if (m_filterWindow)
+ m_filterWindow->installEventFilter(this);
+ }
+ if (m_filterWindow) {
+ m_touchUpdatePending = true;
+ m_filterWindow->requestUpdate();
+ }
+}
+
+bool QEvdevTouchScreenHandlerThread::eventFilter(QObject *object, QEvent *event)
+{
+ if (m_touchUpdatePending && object == m_filterWindow && event->type() == QEvent::UpdateRequest) {
+ m_touchUpdatePending = false;
+ filterAndSendTouchPoints();
+ }
+ return false;
+}
+
+void QEvdevTouchScreenHandlerThread::filterAndSendTouchPoints()
+{
+ QRect winRect = m_handler->d->screenGeometry();
+ if (winRect.isNull())
+ return;
+
+ float vsyncDelta = 1.0f / QGuiApplication::primaryScreen()->refreshRate();
+
+ QHash<int, FilteredTouchPoint> filteredPoints;
+
+ m_handler->d->m_mutex.lock();
+
+ double time = m_handler->d->m_timeStamp;
+ double lastTime = m_handler->d->m_lastTimeStamp;
+ double touchDelta = time - lastTime;
+ if (m_touchRate < 0 || touchDelta > vsyncDelta) {
+ // We're at the very start, with nothing to go on, so make a guess
+ // that the touch rate will be somewhere in the range of half a vsync.
+ // This doesn't have to be accurate as we will calibrate it over time,
+ // but it gives us a better starting point so calibration will be
+ // slightly quicker. If, on the other hand, we already have an
+ // estimate, we'll leave it as is and keep it.
+ if (m_touchRate < 0)
+ m_touchRate = (1.0 / QGuiApplication::primaryScreen()->refreshRate()) / 2.0;
+
+ } else {
+ // Update our estimate for the touch rate. We're making the assumption
+ // that this value will be mostly accurate with the occational bump,
+ // so we're weighting the existing value high compared to the update.
+ const double ratio = 0.9;
+ m_touchRate = sqrt(m_touchRate * m_touchRate * ratio + touchDelta * touchDelta * (1.0 - ratio));
+ }
+
+ QList<QWindowSystemInterface::TouchPoint> points = m_handler->d->m_touchPoints;
+ const QList<QWindowSystemInterface::TouchPoint> &lastPoints = m_handler->d->m_lastTouchPoints;
+
+ m_handler->d->m_mutex.unlock();
+
+ for (int i=0; i<points.size(); ++i) {
+ QWindowSystemInterface::TouchPoint &tp = points[i];
+ QPointF pos = tp.normalPosition;
+ FilteredTouchPoint f;
+
+ QWindowSystemInterface::TouchPoint ltp;
+ ltp.id = -1;
+ for (int j=0; j<lastPoints.size(); ++j) {
+ if (lastPoints.at(j).id == tp.id) {
+ ltp = lastPoints.at(j);
+ break;
+ }
+ }
+
+ QPointF velocity;
+ if (lastTime != 0 && ltp.id >= 0)
+ velocity = (pos - ltp.normalPosition) / m_touchRate;
+ if (m_filteredPoints.contains(tp.id)) {
+ f = m_filteredPoints.take(tp.id);
+ f.x.update(pos.x(), velocity.x(), vsyncDelta);
+ f.y.update(pos.y(), velocity.y(), vsyncDelta);
+ pos = QPointF(f.x.position(), f.y.position());
+ } else {
+ f.x.initialize(pos.x(), velocity.x());
+ f.y.initialize(pos.y(), velocity.y());
+ // Make sure the first instance of a touch point we send has the
+ // 'pressed' state.
+ if (tp.state != Qt::TouchPointPressed)
+ tp.state = Qt::TouchPointPressed;
+ }
+
+ tp.velocity = QVector2D(f.x.velocity() * winRect.width(), f.y.velocity() * winRect.height());
+
+ qreal filteredNormalizedX = f.x.position() + f.x.velocity() * m_handler->d->m_prediction / 1000.0;
+ qreal filteredNormalizedY = f.y.position() + f.y.velocity() * m_handler->d->m_prediction / 1000.0;
+
+ // Clamp to the screen
+ tp.normalPosition = QPointF(qBound<qreal>(0, filteredNormalizedX, 1),
+ qBound<qreal>(0, filteredNormalizedY, 1));
+
+ qreal x = winRect.x() + (tp.normalPosition.x() * (winRect.width() - 1));
+ qreal y = winRect.y() + (tp.normalPosition.y() * (winRect.height() - 1));
+
+ tp.area.moveCenter(QPointF(x, y));
+
+ // Store the touch point for later so we can release it if we've
+ // missed the actual release between our last update and this.
+ f.touchPoint = tp;
+
+ // Don't store the point for future reference if it is a release.
+ if (tp.state != Qt::TouchPointReleased)
+ filteredPoints[tp.id] = f;
+ }
+
+ for (QHash<int, FilteredTouchPoint>::const_iterator it = m_filteredPoints.constBegin(), end = m_filteredPoints.constEnd(); it != end; ++it) {
+ const FilteredTouchPoint &f = it.value();
+ QWindowSystemInterface::TouchPoint tp = f.touchPoint;
+ tp.state = Qt::TouchPointReleased;
+ tp.velocity = QVector2D();
+ points.append(tp);
+ }
+
+ m_filteredPoints = filteredPoints;
+
+ QWindowSystemInterface::handleTouchEvent(Q_NULLPTR,
+ m_handler->touchDevice(),
+ points);
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
index 6554d4998c..d22aca3266 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins module of the Qt Toolkit.
@@ -58,6 +59,7 @@
#include <QThread>
#include <QtCore/private/qthread_p.h>
#include <qpa/qwindowsysteminterface.h>
+#include "qevdevtouchfilter_p.h"
#if QT_CONFIG(mtdev)
struct mtdev;
@@ -78,10 +80,18 @@ public:
QTouchDevice *touchDevice() const;
+ bool isFiltered() const;
+
private slots:
void readData();
+signals:
+ void touchPointsUpdated();
+
private:
+ friend class QEvdevTouchScreenData;
+ friend class QEvdevTouchScreenHandlerThread;
+
void registerTouchDevice();
void unregisterTouchDevice();
@@ -104,16 +114,36 @@ public:
bool isTouchDeviceRegistered() const;
+ bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE;
+
+public slots:
+ void scheduleTouchPointUpdate();
+
signals:
void touchDeviceRegistered();
private:
Q_INVOKABLE void notifyTouchDeviceRegistered();
+ void filterAndSendTouchPoints();
+ QRect targetScreenGeometry() const;
+
QString m_device;
QString m_spec;
QEvdevTouchScreenHandler *m_handler;
bool m_touchDeviceRegistered;
+
+ bool m_touchUpdatePending;
+ QWindow *m_filterWindow;
+
+ struct FilteredTouchPoint {
+ QEvdevTouchFilter x;
+ QEvdevTouchFilter y;
+ QWindowSystemInterface::TouchPoint touchPoint;
+ };
+ QHash<int, FilteredTouchPoint> m_filteredPoints;
+
+ float m_touchRate;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/kmsconvenience/kmsconvenience.pro b/src/platformsupport/kmsconvenience/kmsconvenience.pro
new file mode 100644
index 0000000000..d0ff0d4efb
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/kmsconvenience.pro
@@ -0,0 +1,20 @@
+TARGET = QtKmsSupport
+MODULE = kms_support
+
+QT = core-private gui-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+HEADERS +=
+ qkmsdevice_p.h
+
+SOURCES += \
+ qkmsdevice.cpp
+
+QMAKE_USE += drm
+
+LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
+
+load(qt_module)
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
new file mode 100644
index 0000000000..669abab331
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -0,0 +1,662 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkmsdevice_p.h"
+
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtCore/QFile>
+#include <QtCore/QLoggingCategory>
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcKmsDebug, "qt.qpa.eglfs.kms")
+
+enum OutputConfiguration {
+ OutputConfigOff,
+ OutputConfigPreferred,
+ OutputConfigCurrent,
+ OutputConfigMode,
+ OutputConfigModeline
+};
+
+int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector)
+{
+ for (int i = 0; i < connector->count_encoders; i++) {
+ drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]);
+ if (!encoder) {
+ qWarning("Failed to get encoder");
+ continue;
+ }
+
+ quint32 possibleCrtcs = encoder->possible_crtcs;
+ drmModeFreeEncoder(encoder);
+
+ for (int j = 0; j < resources->count_crtcs; j++) {
+ bool isPossible = possibleCrtcs & (1 << j);
+ bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]);
+
+ if (isPossible && isAvailable)
+ return j;
+ }
+ }
+
+ return -1;
+}
+
+static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_*
+ "None",
+ "VGA",
+ "DVI",
+ "DVI",
+ "DVI",
+ "Composite",
+ "TV",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+ "TV",
+ "eDP",
+ "Virtual",
+ "DSI"
+};
+
+static QByteArray nameForConnector(const drmModeConnectorPtr connector)
+{
+ QByteArray connectorName("UNKNOWN");
+
+ if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
+ connectorName = connector_type_names[connector->connector_type];
+
+ connectorName += QByteArray::number(connector->connector_type_id);
+
+ return connectorName;
+}
+
+static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
+{
+ char hsync[16];
+ char vsync[16];
+ float fclock;
+
+ mode->type = DRM_MODE_TYPE_USERDEF;
+ mode->hskew = 0;
+ mode->vscan = 0;
+ mode->vrefresh = 0;
+ mode->flags = 0;
+
+ if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
+ &fclock,
+ &mode->hdisplay,
+ &mode->hsync_start,
+ &mode->hsync_end,
+ &mode->htotal,
+ &mode->vdisplay,
+ &mode->vsync_start,
+ &mode->vsync_end,
+ &mode->vtotal, hsync, vsync) != 11)
+ return false;
+
+ mode->clock = fclock * 1000;
+
+ if (strcmp(hsync, "+hsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else if (strcmp(hsync, "-hsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_NHSYNC;
+ else
+ return false;
+
+ if (strcmp(vsync, "+vsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else if (strcmp(vsync, "-vsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_NVSYNC;
+ else
+ return false;
+
+ return true;
+}
+
+QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
+ drmModeConnectorPtr connector,
+ VirtualDesktopInfo *vinfo)
+{
+ const QByteArray connectorName = nameForConnector(connector);
+
+ const int crtc = crtcForConnector(resources, connector);
+ if (crtc < 0) {
+ qWarning() << "No usable crtc/encoder pair for connector" << connectorName;
+ return Q_NULLPTR;
+ }
+
+ OutputConfiguration configuration;
+ QSize configurationSize;
+ drmModeModeInfo configurationModeline;
+
+ auto userConfig = m_screenConfig->outputSettings();
+ auto userConnectorConfig = userConfig.value(QString::fromUtf8(connectorName));
+ // default to the preferred mode unless overridden in the config
+ const QByteArray mode = userConnectorConfig.value(QStringLiteral("mode"), QStringLiteral("preferred"))
+ .toByteArray().toLower();
+ if (mode == "off") {
+ configuration = OutputConfigOff;
+ } else if (mode == "preferred") {
+ configuration = OutputConfigPreferred;
+ } else if (mode == "current") {
+ configuration = OutputConfigCurrent;
+ } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
+ configuration = OutputConfigMode;
+ } else if (parseModeline(mode, &configurationModeline)) {
+ configuration = OutputConfigModeline;
+ } else {
+ qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
+ configuration = OutputConfigPreferred;
+ }
+ if (vinfo) {
+ *vinfo = VirtualDesktopInfo();
+ vinfo->virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
+ if (userConnectorConfig.contains(QStringLiteral("virtualPos"))) {
+ const QByteArray vpos = userConnectorConfig.value(QStringLiteral("virtualPos")).toByteArray();
+ const QByteArrayList vposComp = vpos.split(',');
+ if (vposComp.count() == 2)
+ vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
+ }
+ if (userConnectorConfig.value(QStringLiteral("primary")).toBool())
+ vinfo->isPrimary = true;
+ }
+
+ const uint32_t crtc_id = resources->crtcs[crtc];
+
+ if (configuration == OutputConfigOff) {
+ qCDebug(qLcKmsDebug) << "Turning off output" << connectorName;
+ drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR);
+ return Q_NULLPTR;
+ }
+
+ // Skip disconnected output
+ if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) {
+ qCDebug(qLcKmsDebug) << "Skipping disconnected output" << connectorName;
+ return Q_NULLPTR;
+ }
+
+ // Get the current mode on the current crtc
+ drmModeModeInfo crtc_mode;
+ memset(&crtc_mode, 0, sizeof crtc_mode);
+ if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) {
+ drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id);
+ drmModeFreeEncoder(encoder);
+
+ if (!crtc)
+ return Q_NULLPTR;
+
+ if (crtc->mode_valid)
+ crtc_mode = crtc->mode;
+
+ drmModeFreeCrtc(crtc);
+ }
+
+ QList<drmModeModeInfo> modes;
+ modes.reserve(connector->count_modes);
+ qCDebug(qLcKmsDebug) << connectorName << "mode count:" << connector->count_modes;
+ for (int i = 0; i < connector->count_modes; i++) {
+ const drmModeModeInfo &mode = connector->modes[i];
+ qCDebug(qLcKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay
+ << '@' << mode.vrefresh << "hz";
+ modes << connector->modes[i];
+ }
+
+ int preferred = -1;
+ int current = -1;
+ int configured = -1;
+ int best = -1;
+
+ for (int i = modes.size() - 1; i >= 0; i--) {
+ const drmModeModeInfo &m = modes.at(i);
+
+ if (configuration == OutputConfigMode &&
+ m.hdisplay == configurationSize.width() &&
+ m.vdisplay == configurationSize.height()) {
+ configured = i;
+ }
+
+ if (!memcmp(&crtc_mode, &m, sizeof m))
+ current = i;
+
+ if (m.type & DRM_MODE_TYPE_PREFERRED)
+ preferred = i;
+
+ best = i;
+ }
+
+ if (configuration == OutputConfigModeline) {
+ modes << configurationModeline;
+ configured = modes.size() - 1;
+ }
+
+ if (current < 0 && crtc_mode.clock != 0) {
+ modes << crtc_mode;
+ current = mode.size() - 1;
+ }
+
+ if (configuration == OutputConfigCurrent)
+ configured = current;
+
+ int selected_mode = -1;
+
+ if (configured >= 0)
+ selected_mode = configured;
+ else if (preferred >= 0)
+ selected_mode = preferred;
+ else if (current >= 0)
+ selected_mode = current;
+ else if (best >= 0)
+ selected_mode = best;
+
+ if (selected_mode < 0) {
+ qWarning() << "No modes available for output" << connectorName;
+ return Q_NULLPTR;
+ } else {
+ int width = modes[selected_mode].hdisplay;
+ int height = modes[selected_mode].vdisplay;
+ int refresh = modes[selected_mode].vrefresh;
+ qCDebug(qLcKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height
+ << '@' << refresh << "hz for output" << connectorName;
+ }
+
+ // physical size from connector < config values < env vars
+ int pwidth = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
+ if (!pwidth)
+ pwidth = qEnvironmentVariableIntValue("QT_QPA_PHYSICAL_WIDTH");
+ int pheight = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
+ if (!pheight)
+ pheight = qEnvironmentVariableIntValue("QT_QPA_PHYSICAL_HEIGHT");
+ QSizeF physSize(pwidth, pheight);
+ if (physSize.isEmpty()) {
+ physSize = QSize(userConnectorConfig.value(QStringLiteral("physicalWidth")).toInt(),
+ userConnectorConfig.value(QStringLiteral("physicalHeight")).toInt());
+ if (physSize.isEmpty()) {
+ physSize.setWidth(connector->mmWidth);
+ physSize.setHeight(connector->mmHeight);
+ }
+ }
+ qCDebug(qLcKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName;
+
+ QKmsOutput output = {
+ QString::fromUtf8(connectorName),
+ connector->connector_id,
+ crtc_id,
+ physSize,
+ selected_mode,
+ false,
+ drmModeGetCrtc(m_dri_fd, crtc_id),
+ modes,
+ connector->subpixel,
+ connectorProperty(connector, QByteArrayLiteral("DPMS")),
+ false,
+ 0,
+ false
+ };
+
+ bool ok;
+ int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_PLANE_INDEX", &ok);
+ if (ok) {
+ drmModePlaneRes *planeResources = drmModeGetPlaneResources(m_dri_fd);
+ if (planeResources) {
+ if (idx >= 0 && idx < int(planeResources->count_planes)) {
+ drmModePlane *plane = drmModeGetPlane(m_dri_fd, planeResources->planes[idx]);
+ if (plane) {
+ output.wants_plane = true;
+ output.plane_id = plane->plane_id;
+ qCDebug(qLcKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)",
+ idx, plane->plane_id, plane->crtc_id);
+ drmModeFreePlane(plane);
+ }
+ } else {
+ qWarning("Invalid plane index %d, must be between 0 and %u", idx, planeResources->count_planes - 1);
+ }
+ }
+ }
+
+ m_crtc_allocator |= (1 << output.crtc_id);
+ m_connector_allocator |= (1 << output.connector_id);
+
+ return createScreen(output);
+}
+
+drmModePropertyPtr QKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
+{
+ drmModePropertyPtr prop;
+
+ for (int i = 0; i < connector->count_props; i++) {
+ prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
+ if (!prop)
+ continue;
+ if (strcmp(prop->name, name.constData()) == 0)
+ return prop;
+ drmModeFreeProperty(prop);
+ }
+
+ return Q_NULLPTR;
+}
+
+QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : m_screenConfig(screenConfig)
+ , m_path(path)
+ , m_dri_fd(-1)
+ , m_crtc_allocator(0)
+ , m_connector_allocator(0)
+{
+ if (m_path.isEmpty()) {
+ m_path = m_screenConfig->devicePath();
+ qCDebug(qLcKmsDebug, "Using DRM device %s specified in config file", qPrintable(m_path));
+ if (m_path.isEmpty())
+ qFatal("No DRM device given");
+ } else {
+ qCDebug(qLcKmsDebug, "Using backend-provided DRM device %s", qPrintable(m_path));
+ }
+}
+
+QKmsDevice::~QKmsDevice()
+{
+}
+
+struct OrderedScreen
+{
+ OrderedScreen() : screen(nullptr) { }
+ OrderedScreen(QPlatformScreen *screen, const QKmsDevice::VirtualDesktopInfo &vinfo)
+ : screen(screen), vinfo(vinfo) { }
+ QPlatformScreen *screen;
+ QKmsDevice::VirtualDesktopInfo vinfo;
+};
+
+QDebug operator<<(QDebug dbg, const OrderedScreen &s)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "OrderedScreen(QPlatformScreen=" << s.screen << " (" << s.screen->name() << ") : "
+ << s.vinfo.virtualIndex
+ << " / " << s.vinfo.virtualPos
+ << " / primary: " << s.vinfo.isPrimary
+ << ")";
+ return dbg;
+}
+
+static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
+{
+ return a.vinfo.virtualIndex < b.vinfo.virtualIndex;
+}
+
+void QKmsDevice::createScreens()
+{
+ drmModeResPtr resources = drmModeGetResources(m_dri_fd);
+ if (!resources) {
+ qWarning("drmModeGetResources failed");
+ return;
+ }
+
+ QVector<OrderedScreen> screens;
+
+ int wantedConnectorIndex = -1;
+ bool ok;
+ int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_CONNECTOR_INDEX", &ok);
+ if (ok) {
+ if (idx >= 0 && idx < resources->count_connectors)
+ wantedConnectorIndex = idx;
+ else
+ qWarning("Invalid connector index %d, must be between 0 and %u", idx, resources->count_connectors - 1);
+ }
+
+ for (int i = 0; i < resources->count_connectors; i++) {
+ if (wantedConnectorIndex >= 0 && i != wantedConnectorIndex)
+ continue;
+
+ drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
+ if (!connector)
+ continue;
+
+ VirtualDesktopInfo vinfo;
+ QPlatformScreen *screen = createScreenForConnector(resources, connector, &vinfo);
+ if (screen)
+ screens.append(OrderedScreen(screen, vinfo));
+
+ drmModeFreeConnector(connector);
+ }
+
+ drmModeFreeResources(resources);
+
+ // Use stable sort to preserve the original (DRM connector) order
+ // for outputs with unspecified indices.
+ std::stable_sort(screens.begin(), screens.end(), orderedScreenLessThan);
+ qCDebug(qLcKmsDebug) << "Sorted screen list:" << screens;
+
+ QPoint pos(0, 0);
+ QList<QPlatformScreen *> siblings;
+ QVector<QPoint> virtualPositions;
+ int primarySiblingIdx = -1;
+
+ for (const OrderedScreen &orderedScreen : screens) {
+ QPlatformScreen *s = orderedScreen.screen;
+ QPoint virtualPos(0, 0);
+ // set up a horizontal or vertical virtual desktop
+ if (orderedScreen.vinfo.virtualPos.isNull()) {
+ virtualPos = pos;
+ if (m_screenConfig->virtualDesktopLayout() == QKmsScreenConfig::VirtualDesktopLayoutVertical)
+ pos.ry() += s->geometry().height();
+ else
+ pos.rx() += s->geometry().width();
+ } else {
+ virtualPos = orderedScreen.vinfo.virtualPos;
+ }
+ qCDebug(qLcKmsDebug) << "Adding QPlatformScren" << s << "(" << s->name() << ")"
+ << "to QPA with geometry" << s->geometry()
+ << "and isPrimary=" << orderedScreen.vinfo.isPrimary;
+ // The order in qguiapp's screens list will match the order set by
+ // virtualIndex. This is not only handy but also required since for instance
+ // evdevtouch relies on it when performing touch device - screen mapping.
+ if (!m_screenConfig->separateScreens()) {
+ siblings.append(s);
+ virtualPositions.append(virtualPos);
+ if (orderedScreen.vinfo.isPrimary)
+ primarySiblingIdx = siblings.count() - 1;
+ } else {
+ registerScreen(s, orderedScreen.vinfo.isPrimary, virtualPos, QList<QPlatformScreen *>() << s);
+ }
+ }
+
+ if (!m_screenConfig->separateScreens()) {
+ // enable the virtual desktop
+ for (int i = 0; i < siblings.count(); ++i)
+ registerScreen(siblings[i], i == primarySiblingIdx, virtualPositions[i], siblings);
+ }
+}
+
+int QKmsDevice::fd() const
+{
+ return m_dri_fd;
+}
+
+QString QKmsDevice::devicePath() const
+{
+ return m_path;
+}
+
+void QKmsDevice::setFd(int fd)
+{
+ m_dri_fd = fd;
+}
+
+QKmsScreenConfig *QKmsDevice::screenConfig() const
+{
+ return m_screenConfig;
+}
+
+QKmsScreenConfig::QKmsScreenConfig()
+ : m_hwCursor(true)
+ , m_separateScreens(false)
+ , m_pbuffers(false)
+ , m_virtualDesktopLayout(VirtualDesktopLayoutHorizontal)
+{
+ loadConfig();
+}
+
+void QKmsScreenConfig::loadConfig()
+{
+ QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
+ if (json.isEmpty()) {
+ json = qgetenv("QT_QPA_KMS_CONFIG");
+ if (json.isEmpty())
+ return;
+ }
+
+ qCDebug(qLcKmsDebug) << "Loading KMS setup from" << json;
+
+ QFile file(QString::fromUtf8(json));
+ if (!file.open(QFile::ReadOnly)) {
+ qCWarning(qLcKmsDebug) << "Could not open config file"
+ << json << "for reading";
+ return;
+ }
+
+ const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
+ if (!doc.isObject()) {
+ qCWarning(qLcKmsDebug) << "Invalid config file" << json
+ << "- no top-level JSON object";
+ return;
+ }
+
+ const QJsonObject object = doc.object();
+
+ m_hwCursor = object.value(QLatin1String("hwcursor")).toBool(m_hwCursor);
+ m_pbuffers = object.value(QLatin1String("pbuffers")).toBool(m_pbuffers);
+ m_devicePath = object.value(QLatin1String("device")).toString();
+ m_separateScreens = object.value(QLatin1String("separateScreens")).toBool(m_separateScreens);
+
+ const QString vdOriString = object.value(QLatin1String("virtualDesktopLayout")).toString();
+ if (!vdOriString.isEmpty()) {
+ if (vdOriString == QLatin1String("horizontal"))
+ m_virtualDesktopLayout = VirtualDesktopLayoutHorizontal;
+ else if (vdOriString == QLatin1String("vertical"))
+ m_virtualDesktopLayout = VirtualDesktopLayoutVertical;
+ else
+ qCWarning(qLcKmsDebug) << "Unknown virtualDesktopOrientation value" << vdOriString;
+ }
+
+ const QJsonArray outputs = object.value(QLatin1String("outputs")).toArray();
+ for (int i = 0; i < outputs.size(); i++) {
+ const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
+
+ if (outputSettings.contains(QStringLiteral("name"))) {
+ const QString name = outputSettings.value(QStringLiteral("name")).toString();
+
+ if (m_outputSettings.contains(name)) {
+ qCDebug(qLcKmsDebug) << "Output" << name << "configured multiple times!";
+ }
+
+ m_outputSettings.insert(name, outputSettings);
+ }
+ }
+
+ qCDebug(qLcKmsDebug) << "Requested configuration (some settings may be ignored):\n"
+ << "\thwcursor:" << m_hwCursor << "\n"
+ << "\tpbuffers:" << m_pbuffers << "\n"
+ << "\tseparateScreens:" << m_separateScreens << "\n"
+ << "\tvirtualDesktopLayout:" << m_virtualDesktopLayout << "\n"
+ << "\toutputs:" << m_outputSettings;
+}
+
+void QKmsOutput::restoreMode(QKmsDevice *device)
+{
+ if (mode_set && saved_crtc) {
+ drmModeSetCrtc(device->fd(),
+ saved_crtc->crtc_id,
+ saved_crtc->buffer_id,
+ 0, 0,
+ &connector_id, 1,
+ &saved_crtc->mode);
+ mode_set = false;
+ }
+}
+
+void QKmsOutput::cleanup(QKmsDevice *device)
+{
+ if (dpms_prop) {
+ drmModeFreeProperty(dpms_prop);
+ dpms_prop = nullptr;
+ }
+
+ restoreMode(device);
+
+ if (saved_crtc) {
+ drmModeFreeCrtc(saved_crtc);
+ saved_crtc = nullptr;
+ }
+}
+
+QPlatformScreen::SubpixelAntialiasingType QKmsOutput::subpixelAntialiasingTypeHint() const
+{
+ switch (subpixel) {
+ default:
+ case DRM_MODE_SUBPIXEL_UNKNOWN:
+ case DRM_MODE_SUBPIXEL_NONE:
+ return QPlatformScreen::Subpixel_None;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
+ return QPlatformScreen::Subpixel_RGB;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
+ return QPlatformScreen::Subpixel_BGR;
+ case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
+ return QPlatformScreen::Subpixel_VRGB;
+ case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
+ return QPlatformScreen::Subpixel_VBGR;
+ }
+}
+
+void QKmsOutput::setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state)
+{
+ if (dpms_prop)
+ drmModeConnectorSetProperty(device->fd(), connector_id,
+ dpms_prop->prop_id, (int) state);
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
new file mode 100644
index 0000000000..35a51c18b1
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKMSDEVICE_P_H
+#define QKMSDEVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformscreen.h>
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsDevice;
+
+class QKmsScreenConfig
+{
+public:
+ enum VirtualDesktopLayout {
+ VirtualDesktopLayoutHorizontal,
+ VirtualDesktopLayoutVertical
+ };
+
+ QKmsScreenConfig();
+
+ QString devicePath() const { return m_devicePath; }
+
+ bool hwCursor() const { return m_hwCursor; }
+ bool separateScreens() const { return m_separateScreens; }
+ bool supportsPBuffers() const { return m_pbuffers; }
+ VirtualDesktopLayout virtualDesktopLayout() const { return m_virtualDesktopLayout; }
+
+ QMap<QString, QVariantMap> outputSettings() const { return m_outputSettings; }
+
+private:
+ void loadConfig();
+
+ QString m_devicePath;
+ bool m_hwCursor;
+ bool m_separateScreens;
+ bool m_pbuffers;
+ VirtualDesktopLayout m_virtualDesktopLayout;
+ QMap<QString, QVariantMap> m_outputSettings;
+};
+
+struct QKmsOutput
+{
+ QString name;
+ uint32_t connector_id;
+ uint32_t crtc_id;
+ QSizeF physical_size;
+ int mode; // index of selected mode in list below
+ bool mode_set;
+ drmModeCrtcPtr saved_crtc;
+ QList<drmModeModeInfo> modes;
+ int subpixel;
+ drmModePropertyPtr dpms_prop;
+ bool wants_plane;
+ uint32_t plane_id;
+ bool plane_set;
+
+ void restoreMode(QKmsDevice *device);
+ void cleanup(QKmsDevice *device);
+ QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const;
+ void setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state);
+};
+
+class QKmsDevice
+{
+public:
+ struct VirtualDesktopInfo {
+ VirtualDesktopInfo() : virtualIndex(0), isPrimary(false) { }
+ int virtualIndex;
+ QPoint virtualPos;
+ bool isPrimary;
+ };
+
+ QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path = QString());
+ virtual ~QKmsDevice();
+
+ virtual bool open() = 0;
+ virtual void close() = 0;
+ virtual void *nativeDisplay() const = 0;
+
+ void createScreens();
+
+ int fd() const;
+ QString devicePath() const;
+
+ QKmsScreenConfig *screenConfig() const;
+
+protected:
+ virtual QPlatformScreen *createScreen(const QKmsOutput &output) = 0;
+ virtual void registerScreen(QPlatformScreen *screen,
+ bool isPrimary,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings) = 0;
+
+ void setFd(int fd);
+ int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
+ QPlatformScreen *createScreenForConnector(drmModeResPtr resources,
+ drmModeConnectorPtr connector,
+ VirtualDesktopInfo *vinfo);
+ drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
+
+ QKmsScreenConfig *m_screenConfig;
+ QString m_path;
+ int m_dri_fd;
+
+ quint32 m_crtc_allocator;
+ quint32 m_connector_allocator;
+
+private:
+ Q_DISABLE_COPY(QKmsDevice)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 70c4aa563c..6561e95a0d 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -1398,7 +1398,7 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message, QVariant::fromValue(
QDBusVariant(QVariant::fromValue(QSpiObjectReference(connection, QDBusObjectPath(path))))));
} else if (function == QLatin1String("GetChildAtIndex")) {
- int index = message.arguments().first().toInt();
+ const int index = message.arguments().at(0).toInt();
if (index < 0) {
sendReply(connection, message, QVariant::fromValue(
QSpiObjectReference(connection, QDBusObjectPath(ATSPI_DBUS_PATH_NULL))));
diff --git a/src/platformsupport/platformcompositor/qopenglcompositor_p.h b/src/platformsupport/platformcompositor/qopenglcompositor_p.h
index dece41f676..41a3288240 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositor_p.h
+++ b/src/platformsupport/platformcompositor/qopenglcompositor_p.h
@@ -65,6 +65,7 @@ class QPlatformTextureList;
class QOpenGLCompositorWindow
{
public:
+ virtual ~QOpenGLCompositorWindow() { }
virtual QWindow *sourceWindow() const = 0;
virtual const QPlatformTextureList *textures() const = 0;
virtual void beginCompositing() { }
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 09e2922505..7a97a12bae 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -7,7 +7,7 @@ SUBDIRS = \
fbconvenience \
themes
-qtConfig(freetype)|if(darwin:!if(watchos:CONFIG(simulator, simulator|device)))|win32: \
+qtConfig(freetype)|darwin|win32: \
SUBDIRS += fontdatabases
qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput) {
@@ -24,6 +24,8 @@ qtConfig(egl): \
SUBDIRS += eglconvenience
qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2): \
SUBDIRS += glxconvenience
+qtConfig(kms): \
+ SUBDIRS += kmsconvenience
qtConfig(accessibility) {
SUBDIRS += accessibility
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
index 352e4dfd56..09470bccc6 100644
--- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
@@ -37,6 +37,8 @@
**
****************************************************************************/
+#include <QtGui/qtgui-config.h>
+
#ifndef QT_NO_SYSTEMTRAYICON
#include "qdbustrayicon_p.h"
#endif
diff --git a/src/platformsupport/themes/genericunix/genericunix.pri b/src/platformsupport/themes/genericunix/genericunix.pri
index 27019b4aa2..11da533bc4 100644
--- a/src/platformsupport/themes/genericunix/genericunix.pri
+++ b/src/platformsupport/themes/genericunix/genericunix.pri
@@ -3,5 +3,8 @@ SOURCES += $$PWD/qgenericunixthemes.cpp
qtConfig(dbus) {
include(dbusmenu/dbusmenu.pri)
- include(dbustray/dbustray.pri)
+
+ qtConfig(systemtrayicon) {
+ include(dbustray/dbustray.pri)
+ }
}