moved Windows build to Qt 5.5.1

This commit is contained in:
John Preston 2015-10-19 01:00:06 +02:00
parent 938f6edf38
commit 12a2c5e80e
81 changed files with 710 additions and 75688 deletions

View file

@ -69,7 +69,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>AL_LIBTYPE_STATIC;UNICODE;WIN32;WIN64;HAVE_STDINT_H;ZLIB_WINAPI;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.\..\..\Libraries\lzma\C;.\..\..\Libraries\libexif-0.6.20;.\..\..\Libraries\zlib-1.2.8;.\..\..\Libraries\OpenSSL-Win32\include;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\openal-soft\include;.\SourceFiles;.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.0\QtCore;.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.0\QtGui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>.\..\..\Libraries\lzma\C;.\..\..\Libraries\libexif-0.6.20;.\..\..\Libraries\zlib-1.2.8;.\..\..\Libraries\OpenSSL-Win32\include;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\openal-soft\include;.\SourceFiles;.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.1\QtCore;.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.1\QtGui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>

View file

@ -1,147 +0,0 @@
#
# qmake configuration for Microsoft Visual Studio C/C++ Compiler
# This mkspec is used for all win32-msvcXXXX specs
#
isEmpty(MSC_VER)|isEmpty(MSVC_VER): error("Source mkspec must set both MSC_VER and MSVC_VER.")
#
# Baseline: Visual Studio 2005 (8.0), VC++ 14.0
#
MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
QMAKE_COMPILER = msvc
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
QMAKE_COMPILER_DEFINES += _MSC_VER=$$MSC_VER _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
QMAKE_COMPILER_DEFINES += _WIN64
}
QMAKE_CC = cl
QMAKE_LEX = flex
QMAKE_LEXFLAGS =
QMAKE_YACC = byacc
QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS = -nologo -Zc:wchar_t
QMAKE_CFLAGS_WARN_ON = -W3
QMAKE_CFLAGS_WARN_OFF = -W0
QMAKE_CFLAGS_RELEASE = -O2 -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi
QMAKE_CFLAGS_DEBUG = -Zi -MTd
QMAKE_CFLAGS_YACC =
QMAKE_CFLAGS_LTCG = -GL
QMAKE_CFLAGS_SSE2 = -arch:SSE2
QMAKE_CFLAGS_SSE3 = -arch:SSE2
QMAKE_CFLAGS_SSSE3 = -arch:SSE2
QMAKE_CFLAGS_SSE4_1 = -arch:SSE2
QMAKE_CFLAGS_SSE4_2 = -arch:SSE2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -w34100 -w34189 -w44996
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_CXXFLAGS_STL_ON = -EHsc
QMAKE_CXXFLAGS_STL_OFF =
QMAKE_CXXFLAGS_RTTI_ON = -GR
QMAKE_CXXFLAGS_RTTI_OFF =
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc
QMAKE_CXXFLAGS_EXCEPTIONS_OFF =
QMAKE_INCDIR =
QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$obj $src
QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
QMAKE_RUN_CC_IMP_BATCH = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ @<<
QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$obj $src
QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<<
QMAKE_LINK = link
QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT
QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO
QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF /INCREMENTAL:NO
QMAKE_LFLAGS_DEBUG = /DEBUG
QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS
QMAKE_LFLAGS_EXE = \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\"
QMAKE_LFLAGS_DLL = /DLL
QMAKE_LFLAGS_LTCG = /LTCG
QMAKE_EXTENSION_STATICLIB = lib
QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib
QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib ws2_32.lib ole32.lib user32.lib advapi32.lib
QMAKE_LIBS_NETWORK = ws2_32.lib
QMAKE_LIBS_OPENGL = glu32.lib opengl32.lib gdi32.lib user32.lib
QMAKE_LIBS_OPENGL_ES2 = libEGL.lib libGLESv2.lib gdi32.lib user32.lib
QMAKE_LIBS_OPENGL_ES2_DEBUG = libEGLd.lib libGLESv2d.lib gdi32.lib user32.lib
QMAKE_LIBS_COMPAT = advapi32.lib shell32.lib comdlg32.lib user32.lib gdi32.lib ws2_32.lib
QMAKE_LIBS_QT_ENTRY = -lqtmain
QMAKE_IDL = midl
QMAKE_LIB = lib /NOLOGO
QMAKE_RC = rc
VCPROJ_EXTENSION = .vcproj
VCSOLUTION_EXTENSION = .sln
VCPROJ_KEYWORD = Qt4VSv1.0
#
# Version-specific changes
#
greaterThan(MSC_VER, 1499) {
# Visual Studio 2008 (9.0) / Visual C++ 15.0 and up
QMAKE_CFLAGS_MP = -MP
QMAKE_CXXFLAGS_MP = $$QMAKE_CFLAGS_MP
}
greaterThan(MSC_VER, 1599) {
# Visual Studio 2010 (10.0) / Visual C++ 16.0 and up
MAKEFILE_GENERATOR = MSBUILD
QMAKE_CFLAGS_AVX = -arch:AVX
QMAKE_CFLAGS_AVX2 = -arch:AVX
VCPROJ_EXTENSION = .vcxproj
}
greaterThan(MSC_VER, 1699) {
# Visual Studio 2012 (11.0) / Visual C++ 17.0 and up
QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -D_HAS_EXCEPTIONS=0
QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE@QMAKE_SUBSYSTEM_SUFFIX@
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS@QMAKE_SUBSYSTEM_SUFFIX@
QT_CONFIG += c++11
CONFIG += c++11
}
greaterThan(MSC_VER, 1799) {
# Visual Studio 2013 (12.0) / Visual C++ 18.0 and up
QMAKE_CFLAGS += -FS
QMAKE_CXXFLAGS += -FS
equals(MSC_VER, 1800) {
QMAKE_CFLAGS_RELEASE += -Zc:strictStrings
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -Zc:strictStrings
QMAKE_CXXFLAGS_RELEASE += -Zc:strictStrings
QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += -Zc:strictStrings
}
}
greaterThan(MSC_VER, 1899) {
# Visual Studio 2015 (14.0) / Visual C++ 19.0 and up
QMAKE_CFLAGS += -Zc:strictStrings
QMAKE_CFLAGS_WARN_ON += -w44456 -w44457 -w44458
QMAKE_CFLAGS_AVX2 = -arch:AVX2
QMAKE_CXXFLAGS += -Zc:strictStrings
QMAKE_CXXFLAGS_WARN_ON += -w44456 -w44457 -w44458
}
unset(MSC_VER)

File diff suppressed because it is too large Load diff

View file

@ -1,137 +0,0 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2013 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
/* This module contains an internal function for validating UTF-16 character
strings. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Generate code with 16 bit character support. */
#define COMPILE_PCRE16
#include "pcre_internal.h"
/*************************************************
* Validate a UTF-16 string *
*************************************************/
/* This function is called (optionally) at the start of compile or match, to
check that a supposed UTF-16 string is actually valid. The early check means
that subsequent code can assume it is dealing with a valid string. The check
can be turned off for maximum performance, but the consequences of supplying an
invalid string are then undefined.
From release 8.21 more information about the details of the error are passed
back in the returned value:
PCRE_UTF16_ERR0 No error
PCRE_UTF16_ERR1 Missing low surrogate at the end of the string
PCRE_UTF16_ERR2 Invalid low surrogate
PCRE_UTF16_ERR3 Isolated low surrogate
PCRE_UTF16_ERR4 Unused (was non-character)
Arguments:
string points to the string
length length of string, or -1 if the string is zero-terminated
errp pointer to an error position offset variable
Returns: = 0 if the string is a valid UTF-16 string
> 0 otherwise, setting the offset of the bad character
*/
int
PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
{
#ifdef SUPPORT_UTF
register PCRE_PUCHAR p;
register pcre_uint32 c;
if (length < 0)
{
for (p = string; *p != 0; p++);
length = p - string;
}
for (p = string; length-- > 0; p++)
{
c = *p;
if ((c & 0xf800) != 0xd800)
{
/* Normal UTF-16 code point. Neither high nor low surrogate. */
}
else if ((c & 0xfc00) == 0xd800)
{
/* High surrogate. Must be a followed by a low surrogate. */
if (length == 0)
{
*erroroffset = p - string;
return PCRE_UTF16_ERR1;
}
p++;
length--;
if ((*p & 0xfc00) != 0xdc00)
{
*erroroffset = p - string;
return PCRE_UTF16_ERR2;
}
}
else
{
/* Isolated low surrogate. Always an error. */
*erroroffset = p - string;
return PCRE_UTF16_ERR3;
}
}
#else /* SUPPORT_UTF */
(void)(string); /* Keep picky compilers happy */
(void)(length);
(void)(erroroffset);
#endif /* SUPPORT_UTF */
return PCRE_UTF16_ERR0; /* This indicates success */
}
/* End of pcre16_valid_utf16.c */

View file

@ -1,898 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "private/qbmphandler_p.h"
#ifndef QT_NO_IMAGEFORMAT_BMP
#include <qimage.h>
#include <qvariant.h>
#include <qvector.h>
QT_BEGIN_NAMESPACE
static void swapPixel01(QImage *image) // 1-bpp: swap 0 and 1 pixels
{
int i;
if (image->depth() == 1 && image->colorCount() == 2) {
uint *p = (uint *)image->bits();
int nbytes = image->byteCount();
for (i=0; i<nbytes/4; i++) {
*p = ~*p;
p++;
}
uchar *p2 = (uchar *)p;
for (i=0; i<(nbytes&3); i++) {
*p2 = ~*p2;
p2++;
}
QRgb t = image->color(0); // swap color 0 and 1
image->setColor(0, image->color(1));
image->setColor(1, t);
}
}
/*
QImageIO::defineIOHandler("BMP", "^BM", 0,
read_bmp_image, write_bmp_image);
*/
/*****************************************************************************
BMP (DIB) image read/write functions
*****************************************************************************/
const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data
static QDataStream &operator>>(QDataStream &s, BMP_FILEHDR &bf)
{ // read file header
s.readRawData(bf.bfType, 2);
s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits;
return s;
}
static QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf)
{ // write file header
s.writeRawData(bf.bfType, 2);
s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits;
return s;
}
const int BMP_OLD = 12; // old Windows/OS2 BMP size
const int BMP_WIN = 40; // Windows BMP v3 size
const int BMP_OS2 = 64; // new OS/2 BMP size
const int BMP_WIN4 = 108; // Windows BMP v4 size
const int BMP_WIN5 = 124; // Windows BMP v5 size
const int BMP_RGB = 0; // no compression
const int BMP_RLE8 = 1; // run-length encoded, 8 bits
const int BMP_RLE4 = 2; // run-length encoded, 4 bits
const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
{
s >> bi.biSize;
if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 || bi.biSize == BMP_WIN4 || bi.biSize == BMP_WIN5) {
s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
s >> bi.biCompression >> bi.biSizeImage;
s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
s >> bi.biClrUsed >> bi.biClrImportant;
}
else { // probably old Windows format
qint16 w, h;
s >> w >> h >> bi.biPlanes >> bi.biBitCount;
bi.biWidth = w;
bi.biHeight = h;
bi.biCompression = BMP_RGB; // no compression
bi.biSizeImage = 0;
bi.biXPelsPerMeter = bi.biYPelsPerMeter = 0;
bi.biClrUsed = bi.biClrImportant = 0;
}
return s;
}
static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
{
s << bi.biSize;
s << bi.biWidth << bi.biHeight;
s << bi.biPlanes;
s << bi.biBitCount;
s << bi.biCompression;
s << bi.biSizeImage;
s << bi.biXPelsPerMeter << bi.biYPelsPerMeter;
s << bi.biClrUsed << bi.biClrImportant;
return s;
}
static int calc_shift(uint mask)
{
int result = 0;
while (mask && !(mask & 1)) {
result++;
mask >>= 1;
}
return result;
}
static bool read_dib_fileheader(QDataStream &s, BMP_FILEHDR &bf)
{
// read BMP file header
s >> bf;
if (s.status() != QDataStream::Ok)
return false;
// check header
if (qstrncmp(bf.bfType,"BM",2) != 0)
return false;
return true;
}
static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi)
{
s >> bi; // read BMP info header
if (s.status() != QDataStream::Ok)
return false;
int nbits = bi.biBitCount;
int comp = bi.biCompression;
if (!(nbits == 1 || nbits == 4 || nbits == 8 || nbits == 16 || nbits == 24 || nbits == 32) ||
bi.biPlanes != 1 || comp > BMP_BITFIELDS)
return false; // weird BMP image
if (!(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) ||
(nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)))
return false; // weird compression type
return true;
}
static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int startpos, QImage &image)
{
QIODevice* d = s.device();
if (d->atEnd()) // end of stream/file
return false;
#if 0
qDebug("offset...........%d", offset);
qDebug("startpos.........%d", startpos);
qDebug("biSize...........%d", bi.biSize);
qDebug("biWidth..........%d", bi.biWidth);
qDebug("biHeight.........%d", bi.biHeight);
qDebug("biPlanes.........%d", bi.biPlanes);
qDebug("biBitCount.......%d", bi.biBitCount);
qDebug("biCompression....%d", bi.biCompression);
qDebug("biSizeImage......%d", bi.biSizeImage);
qDebug("biXPelsPerMeter..%d", bi.biXPelsPerMeter);
qDebug("biYPelsPerMeter..%d", bi.biYPelsPerMeter);
qDebug("biClrUsed........%d", bi.biClrUsed);
qDebug("biClrImportant...%d", bi.biClrImportant);
#endif
int w = bi.biWidth, h = bi.biHeight, nbits = bi.biBitCount;
int t = bi.biSize, comp = bi.biCompression;
uint red_mask = 0;
uint green_mask = 0;
uint blue_mask = 0;
uint alpha_mask = 0;
int red_shift = 0;
int green_shift = 0;
int blue_shift = 0;
int alpha_shift = 0;
int red_scale = 0;
int green_scale = 0;
int blue_scale = 0;
int alpha_scale = 0;
if (!d->isSequential())
d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4 ? BMP_WIN : bi.biSize)); // goto start of colormap
if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
return false;
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
return false;
// Read BMP v4+ header
if (bi.biSize >= BMP_WIN4) {
int CSType = 0;
int gamma_red = 0;
int gamma_green = 0;
int gamma_blue = 0;
int endpoints[9];
if (d->read((char *)&alpha_mask, sizeof(alpha_mask)) != sizeof(alpha_mask))
return false;
if (d->read((char *)&CSType, sizeof(CSType)) != sizeof(CSType))
return false;
if (d->read((char *)&endpoints, sizeof(endpoints)) != sizeof(endpoints))
return false;
if (d->read((char *)&gamma_red, sizeof(gamma_red)) != sizeof(gamma_red))
return false;
if (d->read((char *)&gamma_green, sizeof(gamma_green)) != sizeof(gamma_green))
return false;
if (d->read((char *)&gamma_blue, sizeof(gamma_blue)) != sizeof(gamma_blue))
return false;
if (bi.biSize == BMP_WIN5) {
qint32 intent = 0;
qint32 profileData = 0;
qint32 profileSize = 0;
qint32 reserved = 0;
if (d->read((char *)&intent, sizeof(intent)) != sizeof(intent))
return false;
if (d->read((char *)&profileData, sizeof(profileData)) != sizeof(profileData))
return false;
if (d->read((char *)&profileSize, sizeof(profileSize)) != sizeof(profileSize))
return false;
if (d->read((char *)&reserved, sizeof(reserved)) != sizeof(reserved) || reserved != 0)
return false;
}
}
}
bool transp = (comp == BMP_BITFIELDS) && alpha_mask;
int ncols = 0;
int depth = 0;
QImage::Format format;
switch (nbits) {
case 32:
case 24:
case 16:
depth = 32;
format = transp ? QImage::Format_ARGB32 : QImage::Format_RGB32;
break;
case 8:
case 4:
depth = 8;
format = QImage::Format_Indexed8;
break;
default:
depth = 1;
format = QImage::Format_Mono;
}
if (bi.biHeight < 0)
h = -h; // support images with negative height
if (image.size() != QSize(w, h) || image.format() != format) {
image = QImage(w, h, format);
if (image.isNull()) // could not create image
return false;
}
if (depth != 32) {
ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
if (ncols > 256) // sanity check - don't run out of mem if color table is broken
return false;
image.setColorCount(ncols);
}
image.setDotsPerMeterX(bi.biXPelsPerMeter);
image.setDotsPerMeterY(bi.biYPelsPerMeter);
if (ncols > 0) { // read color table
uchar rgb[4];
int rgb_len = t == BMP_OLD ? 3 : 4;
for (int i=0; i<ncols; i++) {
if (d->read((char *)rgb, rgb_len) != rgb_len)
return false;
image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0]));
if (d->atEnd()) // truncated file
return false;
}
} else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
red_shift = calc_shift(red_mask);
if (((red_mask >> red_shift) + 1) == 0)
return false;
red_scale = 256 / ((red_mask >> red_shift) + 1);
green_shift = calc_shift(green_mask);
if (((green_mask >> green_shift) + 1) == 0)
return false;
green_scale = 256 / ((green_mask >> green_shift) + 1);
blue_shift = calc_shift(blue_mask);
if (((blue_mask >> blue_shift) + 1) == 0)
return false;
blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
alpha_shift = calc_shift(alpha_mask);
if (((alpha_mask >> alpha_shift) + 1) == 0)
return false;
alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
} else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
blue_mask = 0x000000ff;
green_mask = 0x0000ff00;
red_mask = 0x00ff0000;
blue_shift = 0;
green_shift = 8;
red_shift = 16;
blue_scale = green_scale = red_scale = 1;
} else if (comp == BMP_RGB && nbits == 16) {
blue_mask = 0x001f;
green_mask = 0x03e0;
red_mask = 0x7c00;
blue_shift = 0;
green_shift = 2;
red_shift = 7;
red_scale = 1;
green_scale = 1;
blue_scale = 8;
}
#if 0
qDebug("Rmask: %08x Rshift: %08x Rscale:%08x", red_mask, red_shift, red_scale);
qDebug("Gmask: %08x Gshift: %08x Gscale:%08x", green_mask, green_shift, green_scale);
qDebug("Bmask: %08x Bshift: %08x Bscale:%08x", blue_mask, blue_shift, blue_scale);
qDebug("Amask: %08x Ashift: %08x Ascale:%08x", alpha_mask, alpha_shift, alpha_scale);
#endif
// offset can be bogus, be careful
if (offset>=0 && startpos + offset > d->pos()) {
if (!d->isSequential())
d->seek(startpos + offset); // start of image data
}
int bpl = image.bytesPerLine();
uchar *data = image.bits();
if (nbits == 1) { // 1 bit BMP image
while (--h >= 0) {
if (d->read((char*)(data + h*bpl), bpl) != bpl)
break;
}
if (ncols == 2 && qGray(image.color(0)) < qGray(image.color(1)))
swapPixel01(&image); // pixel 0 is white!
}
else if (nbits == 4) { // 4 bit BMP image
int buflen = ((w+7)/8)*4;
uchar *buf = new uchar[buflen];
if (comp == BMP_RLE4) { // run length compression
int x=0, y=0, c, i;
quint8 b;
uchar *p = data + (h-1)*bpl;
const uchar *endp = p + w;
while (y < h) {
if (!d->getChar((char *)&b))
break;
if (b == 0) { // escape code
if (!d->getChar((char *)&b) || b == 1) {
y = h; // exit loop
} else switch (b) {
case 0: // end of line
x = 0;
y++;
p = data + (h-y-1)*bpl;
break;
case 2: // delta (jump)
{
quint8 tmp;
d->getChar((char *)&tmp);
x += tmp;
d->getChar((char *)&tmp);
y += tmp;
}
// Protection
if ((uint)x >= (uint)w)
x = w-1;
if ((uint)y >= (uint)h)
y = h-1;
p = data + (h-y-1)*bpl + x;
break;
default: // absolute mode
// Protection
if (p + b > endp)
b = endp-p;
i = (c = b)/2;
while (i--) {
d->getChar((char *)&b);
*p++ = b >> 4;
*p++ = b & 0x0f;
}
if (c & 1) {
unsigned char tmp;
d->getChar((char *)&tmp);
*p++ = tmp >> 4;
}
if ((((c & 3) + 1) & 2) == 2)
d->getChar(0); // align on word boundary
x += c;
}
} else { // encoded mode
// Protection
if (p + b > endp)
b = endp-p;
i = (c = b)/2;
d->getChar((char *)&b); // 2 pixels to be repeated
while (i--) {
*p++ = b >> 4;
*p++ = b & 0x0f;
}
if (c & 1)
*p++ = b >> 4;
x += c;
}
}
} else if (comp == BMP_RGB) { // no compression
memset(data, 0, h*bpl);
while (--h >= 0) {
if (d->read((char*)buf,buflen) != buflen)
break;
uchar *p = data + h*bpl;
uchar *b = buf;
for (int i=0; i<w/2; i++) { // convert nibbles to bytes
*p++ = *b >> 4;
*p++ = *b++ & 0x0f;
}
if (w & 1) // the last nibble
*p = *b >> 4;
}
}
delete [] buf;
}
else if (nbits == 8) { // 8 bit BMP image
if (comp == BMP_RLE8) { // run length compression
int x=0, y=0;
quint8 b;
uchar *p = data + (h-1)*bpl;
const uchar *endp = p + w;
while (y < h) {
if (!d->getChar((char *)&b))
break;
if (b == 0) { // escape code
if (!d->getChar((char *)&b) || b == 1) {
y = h; // exit loop
} else switch (b) {
case 0: // end of line
x = 0;
y++;
p = data + (h-y-1)*bpl;
break;
case 2: // delta (jump)
{
quint8 tmp;
d->getChar((char *)&tmp);
x += tmp;
d->getChar((char *)&tmp);
y += tmp;
}
// Protection
if ((uint)x >= (uint)w)
x = w-1;
if ((uint)y >= (uint)h)
y = h-1;
p = data + (h-y-1)*bpl + x;
break;
default: // absolute mode
// Protection
if (p + b > endp)
b = endp-p;
if (d->read((char *)p, b) != b)
return false;
if ((b & 1) == 1)
d->getChar(0); // align on word boundary
x += b;
p += b;
}
} else { // encoded mode
// Protection
if (p + b > endp)
b = endp-p;
char tmp;
d->getChar(&tmp);
memset(p, tmp, b); // repeat pixel
x += b;
p += b;
}
}
} else if (comp == BMP_RGB) { // uncompressed
while (--h >= 0) {
if (d->read((char *)data + h*bpl, bpl) != bpl)
break;
}
}
}
else if (nbits == 16 || nbits == 24 || nbits == 32) { // 16,24,32 bit BMP image
QRgb *p;
QRgb *end;
uchar *buf24 = new uchar[bpl];
int bpl24 = ((w*nbits+31)/32)*4;
uchar *b;
int c;
while (--h >= 0) {
p = (QRgb *)(data + h*bpl);
end = p + w;
if (d->read((char *)buf24,bpl24) != bpl24)
break;
b = buf24;
while (p < end) {
c = *(uchar*)b | (*(uchar*)(b+1)<<8);
if (nbits > 16)
c |= *(uchar*)(b+2)<<16;
if (nbits > 24)
c |= *(uchar*)(b+3)<<24;
*p++ = qRgba(((c & red_mask) >> red_shift) * red_scale,
((c & green_mask) >> green_shift) * green_scale,
((c & blue_mask) >> blue_shift) * blue_scale,
transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff);
b += nbits/8;
}
}
delete[] buf24;
}
if (bi.biHeight < 0) {
// Flip the image
uchar *buf = new uchar[bpl];
h = -bi.biHeight;
for (int y = 0; y < h/2; ++y) {
memcpy(buf, data + y*bpl, bpl);
memcpy(data + y*bpl, data + (h-y-1)*bpl, bpl);
memcpy(data + (h-y-1)*bpl, buf, bpl);
}
delete [] buf;
}
return true;
}
// this is also used in qmime_win.cpp
bool qt_write_dib(QDataStream &s, QImage image)
{
int nbits;
int bpl_bmp;
int bpl = image.bytesPerLine();
QIODevice* d = s.device();
if (!d->isWritable())
return false;
if (image.depth() == 8 && image.colorCount() <= 16) {
bpl_bmp = (((bpl+1)/2+3)/4)*4;
nbits = 4;
} else if (image.depth() == 32) {
bpl_bmp = ((image.width()*24+31)/32)*4;
nbits = 24;
} else {
bpl_bmp = bpl;
nbits = image.depth();
}
BMP_INFOHDR bi;
bi.biSize = BMP_WIN; // build info header
bi.biWidth = image.width();
bi.biHeight = image.height();
bi.biPlanes = 1;
bi.biBitCount = nbits;
bi.biCompression = BMP_RGB;
bi.biSizeImage = bpl_bmp*image.height();
bi.biXPelsPerMeter = image.dotsPerMeterX() ? image.dotsPerMeterX()
: 2834; // 72 dpi default
bi.biYPelsPerMeter = image.dotsPerMeterY() ? image.dotsPerMeterY() : 2834;
bi.biClrUsed = image.colorCount();
bi.biClrImportant = image.colorCount();
s << bi; // write info header
if (s.status() != QDataStream::Ok)
return false;
if (image.depth() != 32) { // write color table
uchar *color_table = new uchar[4*image.colorCount()];
uchar *rgb = color_table;
QVector<QRgb> c = image.colorTable();
for (int i=0; i<image.colorCount(); i++) {
*rgb++ = qBlue (c[i]);
*rgb++ = qGreen(c[i]);
*rgb++ = qRed (c[i]);
*rgb++ = 0;
}
if (d->write((char *)color_table, 4*image.colorCount()) == -1) {
delete [] color_table;
return false;
}
delete [] color_table;
}
if (image.format() == QImage::Format_MonoLSB)
image = image.convertToFormat(QImage::Format_Mono);
int y;
if (nbits == 1 || nbits == 8) { // direct output
for (y=image.height()-1; y>=0; y--) {
if (d->write((const char*)image.constScanLine(y), bpl) == -1)
return false;
}
return true;
}
uchar *buf = new uchar[bpl_bmp];
uchar *b, *end;
const uchar *p;
memset(buf, 0, bpl_bmp);
for (y=image.height()-1; y>=0; y--) { // write the image bits
if (nbits == 4) { // convert 8 -> 4 bits
p = image.constScanLine(y);
b = buf;
end = b + image.width()/2;
while (b < end) {
*b++ = (*p << 4) | (*(p+1) & 0x0f);
p += 2;
}
if (image.width() & 1)
*b = *p << 4;
} else { // 32 bits
const QRgb *p = (const QRgb *)image.constScanLine(y);
const QRgb *end = p + image.width();
b = buf;
while (p < end) {
*b++ = qBlue(*p);
*b++ = qGreen(*p);
*b++ = qRed(*p);
p++;
}
}
if (bpl_bmp != d->write((char*)buf, bpl_bmp)) {
delete[] buf;
return false;
}
}
delete[] buf;
return true;
}
// this is also used in qmime_win.cpp
bool qt_read_dib(QDataStream &s, QImage &image)
{
BMP_INFOHDR bi;
if (!read_dib_infoheader(s, bi))
return false;
return read_dib_body(s, bi, -1, -BMP_FILEHDR_SIZE, image);
}
QBmpHandler::QBmpHandler(InternalFormat fmt) :
m_format(fmt), state(Ready)
{
}
QByteArray QBmpHandler::formatName() const
{
return m_format == BmpFormat ? "bmp" : "dib";
}
bool QBmpHandler::readHeader()
{
state = Error;
QIODevice *d = device();
QDataStream s(d);
startpos = d->pos();
// Intel byte order
s.setByteOrder(QDataStream::LittleEndian);
// read BMP file header
if (m_format == BmpFormat && !read_dib_fileheader(s, fileHeader))
return false;
// read BMP info header
if (!read_dib_infoheader(s, infoHeader))
return false;
state = ReadHeader;
return true;
}
bool QBmpHandler::canRead() const
{
if (m_format == BmpFormat && state == Ready && !canRead(device()))
return false;
if (state != Error) {
setFormat(formatName());
return true;
}
return false;
}
bool QBmpHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("QBmpHandler::canRead() called with 0 pointer");
return false;
}
char head[2];
if (device->peek(head, sizeof(head)) != sizeof(head))
return false;
return (qstrncmp(head, "BM", 2) == 0);
}
bool QBmpHandler::read(QImage *image)
{
if (state == Error)
return false;
if (!image) {
qWarning("QBmpHandler::read: cannot read into null pointer");
return false;
}
if (state == Ready && !readHeader()) {
state = Error;
return false;
}
QIODevice *d = device();
QDataStream s(d);
// Intel byte order
s.setByteOrder(QDataStream::LittleEndian);
// read image
const bool readSuccess = m_format == BmpFormat ?
read_dib_body(s, infoHeader, fileHeader.bfOffBits, startpos, *image) :
read_dib_body(s, infoHeader, -1, startpos - BMP_FILEHDR_SIZE, *image);
if (!readSuccess)
return false;
state = Ready;
return true;
}
bool QBmpHandler::write(const QImage &img)
{
if (m_format == DibFormat) {
QDataStream dibStream(device());
dibStream.setByteOrder(QDataStream::LittleEndian); // Intel byte order
return qt_write_dib(dibStream, img);
}
QImage image;
switch (img.format()) {
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
case QImage::Format_Indexed8:
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
image = img;
break;
case QImage::Format_Alpha8:
case QImage::Format_Grayscale8:
image = img.convertToFormat(QImage::Format_Indexed8);
break;
default:
if (img.hasAlphaChannel())
image = img.convertToFormat(QImage::Format_ARGB32);
else
image = img.convertToFormat(QImage::Format_RGB32);
break;
}
QIODevice *d = device();
QDataStream s(d);
BMP_FILEHDR bf;
int bpl_bmp;
int bpl = image.bytesPerLine();
// Code partially repeated in qt_write_dib
if (image.depth() == 8 && image.colorCount() <= 16) {
bpl_bmp = (((bpl+1)/2+3)/4)*4;
} else if (image.depth() == 32) {
bpl_bmp = ((image.width()*24+31)/32)*4;
} else {
bpl_bmp = bpl;
}
// Intel byte order
s.setByteOrder(QDataStream::LittleEndian);
// build file header
memcpy(bf.bfType, "BM", 2);
// write file header
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = BMP_FILEHDR_SIZE + BMP_WIN + image.colorCount() * 4;
bf.bfSize = bf.bfOffBits + bpl_bmp*image.height();
s << bf;
// write image
return qt_write_dib(s, image);
}
bool QBmpHandler::supportsOption(ImageOption option) const
{
return option == Size
|| option == ImageFormat;
}
QVariant QBmpHandler::option(ImageOption option) const
{
if (option == Size) {
if (state == Error)
return QVariant();
if (state == Ready && !const_cast<QBmpHandler*>(this)->readHeader())
return QVariant();
return QSize(infoHeader.biWidth, infoHeader.biHeight);
} else if (option == ImageFormat) {
if (state == Error)
return QVariant();
if (state == Ready && !const_cast<QBmpHandler*>(this)->readHeader())
return QVariant();
QImage::Format format;
switch (infoHeader.biBitCount) {
case 32:
case 24:
case 16:
format = QImage::Format_RGB32;
break;
case 8:
case 4:
format = QImage::Format_Indexed8;
break;
default:
format = QImage::Format_Mono;
}
return format;
}
return QVariant();
}
void QBmpHandler::setOption(ImageOption option, const QVariant &value)
{
Q_UNUSED(option);
Q_UNUSED(value);
}
QByteArray QBmpHandler::name() const
{
return formatName();
}
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_BMP

View file

@ -1,443 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPLATFORMDIALOGHELPER_H
#define QPLATFORMDIALOGHELPER_H
//
// W A R N I N G
// -------------
//
// This file is part of the QPA API and is not meant to be used
// in applications. Usage of this API may make your code
// source and binary incompatible with future versions of Qt.
//
#include <QtCore/QtGlobal>
#include <QtCore/QObject>
#include <QtCore/QList>
#include <QtCore/QSharedDataPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtGui/QRgb>
QT_BEGIN_NAMESPACE
class QString;
class QColor;
class QFont;
class QWindow;
class QVariant;
class QUrl;
class QColorDialogOptionsPrivate;
class QFontDialogOptionsPrivate;
class QFileDialogOptionsPrivate;
class QMessageDialogOptionsPrivate;
class Q_GUI_EXPORT QPlatformDialogHelper : public QObject
{
Q_OBJECT
public:
enum StyleHint {
};
enum DialogCode { Rejected, Accepted };
enum StandardButton {
// keep this in sync with QDialogButtonBox::StandardButton and QMessageBox::StandardButton
NoButton = 0x00000000,
Ok = 0x00000400,
Save = 0x00000800,
SaveAll = 0x00001000,
Open = 0x00002000,
Yes = 0x00004000,
YesToAll = 0x00008000,
No = 0x00010000,
NoToAll = 0x00020000,
Abort = 0x00040000,
Retry = 0x00080000,
Ignore = 0x00100000,
Close = 0x00200000,
Cancel = 0x00400000,
Discard = 0x00800000,
Help = 0x01000000,
Apply = 0x02000000,
Reset = 0x04000000,
RestoreDefaults = 0x08000000,
FirstButton = Ok, // internal
LastButton = RestoreDefaults, // internal
LowestBit = 10, // internal: log2(FirstButton)
HighestBit = 27 // internal: log2(LastButton)
};
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
enum ButtonRole {
// keep this in sync with QDialogButtonBox::ButtonRole and QMessageBox::ButtonRole
// TODO Qt 6: make the enum copies explicit, and make InvalidRole == 0 so that
// AcceptRole can be or'ed with flags, and EOL can be the same as InvalidRole (null-termination)
InvalidRole = -1,
AcceptRole,
RejectRole,
DestructiveRole,
ActionRole,
HelpRole,
YesRole,
NoRole,
ResetRole,
ApplyRole,
NRoles,
RoleMask = 0x0FFFFFFF,
AlternateRole = 0x10000000,
Stretch = 0x20000000,
Reverse = 0x40000000,
EOL = InvalidRole
};
enum ButtonLayout {
// keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout
UnknownLayout = -1,
WinLayout,
MacLayout,
KdeLayout,
GnomeLayout,
MacModelessLayout
};
QPlatformDialogHelper();
virtual ~QPlatformDialogHelper();
virtual QVariant styleHint(StyleHint hint) const;
virtual void exec() = 0;
virtual bool show(Qt::WindowFlags windowFlags,
Qt::WindowModality windowModality,
QWindow *parent) = 0;
virtual void hide() = 0;
static QVariant defaultStyleHint(QPlatformDialogHelper::StyleHint hint);
static const int *buttonLayout(Qt::Orientation orientation = Qt::Horizontal, ButtonLayout policy = UnknownLayout);
static ButtonRole buttonRole(StandardButton button);
Q_SIGNALS:
void accept();
void reject();
};
class Q_GUI_EXPORT QColorDialogOptions
{
public:
enum ColorDialogOption {
ShowAlphaChannel = 0x00000001,
NoButtons = 0x00000002,
DontUseNativeDialog = 0x00000004
};
Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
QColorDialogOptions();
QColorDialogOptions(const QColorDialogOptions &rhs);
QColorDialogOptions &operator=(const QColorDialogOptions &rhs);
~QColorDialogOptions();
void swap(QColorDialogOptions &other) { qSwap(d, other.d); }
QString windowTitle() const;
void setWindowTitle(const QString &);
void setOption(ColorDialogOption option, bool on = true);
bool testOption(ColorDialogOption option) const;
void setOptions(ColorDialogOptions options);
ColorDialogOptions options() const;
static int customColorCount();
static QRgb customColor(int index);
static QRgb *customColors();
static void setCustomColor(int index, QRgb color);
static QRgb *standardColors();
static QRgb standardColor(int index);
static void setStandardColor(int index, QRgb color);
private:
QSharedDataPointer<QColorDialogOptionsPrivate> d;
};
Q_DECLARE_SHARED(QColorDialogOptions)
class Q_GUI_EXPORT QPlatformColorDialogHelper : public QPlatformDialogHelper
{
Q_OBJECT
public:
const QSharedPointer<QColorDialogOptions> &options() const;
void setOptions(const QSharedPointer<QColorDialogOptions> &options);
virtual void setCurrentColor(const QColor &) = 0;
virtual QColor currentColor() const = 0;
Q_SIGNALS:
void currentColorChanged(const QColor &color);
void colorSelected(const QColor &color);
private:
QSharedPointer<QColorDialogOptions> m_options;
};
class Q_GUI_EXPORT QFontDialogOptions
{
public:
enum FontDialogOption {
NoButtons = 0x00000001,
DontUseNativeDialog = 0x00000002,
ScalableFonts = 0x00000004,
NonScalableFonts = 0x00000008,
MonospacedFonts = 0x00000010,
ProportionalFonts = 0x00000020
};
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
QFontDialogOptions();
QFontDialogOptions(const QFontDialogOptions &rhs);
QFontDialogOptions &operator=(const QFontDialogOptions &rhs);
~QFontDialogOptions();
void swap(QFontDialogOptions &other) { qSwap(d, other.d); }
QString windowTitle() const;
void setWindowTitle(const QString &);
void setOption(FontDialogOption option, bool on = true);
bool testOption(FontDialogOption option) const;
void setOptions(FontDialogOptions options);
FontDialogOptions options() const;
private:
QSharedDataPointer<QFontDialogOptionsPrivate> d;
};
Q_DECLARE_SHARED(QFontDialogOptions)
class Q_GUI_EXPORT QPlatformFontDialogHelper : public QPlatformDialogHelper
{
Q_OBJECT
public:
virtual void setCurrentFont(const QFont &) = 0;
virtual QFont currentFont() const = 0;
const QSharedPointer<QFontDialogOptions> &options() const;
void setOptions(const QSharedPointer<QFontDialogOptions> &options);
Q_SIGNALS:
void currentFontChanged(const QFont &font);
void fontSelected(const QFont &font);
private:
QSharedPointer<QFontDialogOptions> m_options;
};
class Q_GUI_EXPORT QFileDialogOptions
{
public:
enum ViewMode { Detail, List };
enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
enum AcceptMode { AcceptOpen, AcceptSave };
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount };
enum FileDialogOption
{
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
DontUseSheet = 0x00000008,
DontUseNativeDialog = 0x00000010,
ReadOnly = 0x00000020,
HideNameFilterDetails = 0x00000040,
DontUseCustomDirectoryIcons = 0x00000080
};
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
QFileDialogOptions();
QFileDialogOptions(const QFileDialogOptions &rhs);
QFileDialogOptions &operator=(const QFileDialogOptions &rhs);
~QFileDialogOptions();
void swap(QFileDialogOptions &other) { qSwap(d, other.d); }
QString windowTitle() const;
void setWindowTitle(const QString &);
void setOption(FileDialogOption option, bool on = true);
bool testOption(FileDialogOption option) const;
void setOptions(FileDialogOptions options);
FileDialogOptions options() const;
QDir::Filters filter() const;
void setFilter(QDir::Filters filters);
void setViewMode(ViewMode mode);
ViewMode viewMode() const;
void setFileMode(FileMode mode);
FileMode fileMode() const;
void setAcceptMode(AcceptMode mode);
AcceptMode acceptMode() const;
void setSidebarUrls(const QList<QUrl> &urls);
QList<QUrl> sidebarUrls() const;
void setNameFilters(const QStringList &filters);
QStringList nameFilters() const;
void setMimeTypeFilters(const QStringList &filters);
QStringList mimeTypeFilters() const;
void setDefaultSuffix(const QString &suffix);
QString defaultSuffix() const;
void setHistory(const QStringList &paths);
QStringList history() const;
void setLabelText(DialogLabel label, const QString &text);
QString labelText(DialogLabel label) const;
bool isLabelExplicitlySet(DialogLabel label);
QUrl initialDirectory() const;
void setInitialDirectory(const QUrl &);
QString initiallySelectedNameFilter() const;
void setInitiallySelectedNameFilter(const QString &);
QList<QUrl> initiallySelectedFiles() const;
void setInitiallySelectedFiles(const QList<QUrl> &);
private:
QSharedDataPointer<QFileDialogOptionsPrivate> d;
};
Q_DECLARE_SHARED(QFileDialogOptions)
class Q_GUI_EXPORT QPlatformFileDialogHelper : public QPlatformDialogHelper
{
Q_OBJECT
public:
virtual bool defaultNameFilterDisables() const = 0;
virtual void setDirectory(const QUrl &directory) = 0;
virtual QUrl directory() const = 0;
virtual void selectFile(const QUrl &filename) = 0;
virtual QList<QUrl> selectedFiles() const = 0;
virtual QByteArray selectedRemoteContent() const { return QByteArray(); }
virtual void setFilter() = 0;
virtual void selectNameFilter(const QString &filter) = 0;
virtual QString selectedNameFilter() const = 0;
virtual bool isSupportedUrl(const QUrl &url) const;
const QSharedPointer<QFileDialogOptions> &options() const;
void setOptions(const QSharedPointer<QFileDialogOptions> &options);
static QStringList cleanFilterList(const QString &filter);
static const char *filterRegExp;
Q_SIGNALS:
void fileSelected(const QUrl &file);
void filesSelected(const QList<QUrl> &files);
void currentChanged(const QUrl &path);
void directoryEntered(const QUrl &directory);
void filterSelected(const QString &filter);
private:
QSharedPointer<QFileDialogOptions> m_options;
};
class Q_GUI_EXPORT QMessageDialogOptions
{
public:
// Keep in sync with QMessageBox::Icon
enum Icon { NoIcon, Information, Warning, Critical, Question };
QMessageDialogOptions();
QMessageDialogOptions(const QMessageDialogOptions &rhs);
QMessageDialogOptions &operator=(const QMessageDialogOptions &rhs);
~QMessageDialogOptions();
void swap(QMessageDialogOptions &other) { qSwap(d, other.d); }
QString windowTitle() const;
void setWindowTitle(const QString &);
void setIcon(Icon icon);
Icon icon() const;
void setText(const QString &text);
QString text() const;
void setInformativeText(const QString &text);
QString informativeText() const;
void setDetailedText(const QString &text);
QString detailedText() const;
void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons);
QPlatformDialogHelper::StandardButtons standardButtons() const;
private:
QSharedDataPointer<QMessageDialogOptionsPrivate> d;
};
Q_DECLARE_SHARED(QMessageDialogOptions)
class Q_GUI_EXPORT QPlatformMessageDialogHelper : public QPlatformDialogHelper
{
Q_OBJECT
public:
const QSharedPointer<QMessageDialogOptions> &options() const;
void setOptions(const QSharedPointer<QMessageDialogOptions> &options);
Q_SIGNALS:
void clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role);
private:
QSharedPointer<QMessageDialogOptions> m_options;
};
QT_END_NAMESPACE
#endif // QPLATFORMDIALOGHELPER_H

View file

@ -1,285 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qbackingstore.h>
#include <qwindow.h>
#include <qpixmap.h>
#include <qpa/qplatformbackingstore.h>
#include <qpa/qplatformintegration.h>
#include <qscreen.h>
#include <qdebug.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
QT_BEGIN_NAMESPACE
class QBackingStorePrivate
{
public:
QBackingStorePrivate(QWindow *w)
: window(w)
{
}
QWindow *window;
QPlatformBackingStore *platformBackingStore;
QRegion staticContents;
QSize size;
};
/*!
\class QBackingStore
\since 5.0
\inmodule QtGui
\brief The QBackingStore class provides a drawing area for QWindow.
QBackingStore enables the use of QPainter to paint on a QWindow with type
RasterSurface. The other way of rendering to a QWindow is through the use
of OpenGL with QOpenGLContext.
A QBackingStore contains a buffered representation of the window contents,
and thus supports partial updates by using QPainter to only update a sub
region of the window contents.
QBackingStore might be used by an application that wants to use QPainter
without OpenGL acceleration and without the extra overhead of using the
QWidget or QGraphicsView UI stacks. For an example of how to use
QBackingStore see the \l{Raster Window Example}.
*/
/*!
Flushes the given \a region from the specified window \a win onto the
screen.
Note that the \a offset parameter is currently unused.
*/
void QBackingStore::flush(const QRegion &region, QWindow *win, const QPoint &offset)
{
if (!win)
win = window();
if (!win->handle()) {
qWarning() << "QBackingStore::flush() called for "
<< win << " which does not have a handle.";
return;
}
#ifdef QBACKINGSTORE_DEBUG
if (win && win->isTopLevel() && !qt_window_private(win)->receivedExpose) {
qWarning().nospace() << "QBackingStore::flush() called with non-exposed window "
<< win << ", behavior is undefined";
}
#endif
d_ptr->platformBackingStore->flush(win, region, offset);
}
/*!
\fn QPaintDevice* QBackingStore::paintDevice()
Implement this function to return the appropriate paint device.
*/
QPaintDevice *QBackingStore::paintDevice()
{
return d_ptr->platformBackingStore->paintDevice();
}
/*!
Constructs an empty surface for the given top-level \a window.
*/
QBackingStore::QBackingStore(QWindow *window)
: d_ptr(new QBackingStorePrivate(window))
{
d_ptr->platformBackingStore = QGuiApplicationPrivate::platformIntegration()->createPlatformBackingStore(window);
}
/*!
Destroys this surface.
*/
QBackingStore::~QBackingStore()
{
delete d_ptr->platformBackingStore;
}
/*!
Returns a pointer to the top-level window associated with this
surface.
*/
QWindow* QBackingStore::window() const
{
return d_ptr->window;
}
/*!
This function is called before painting onto the surface begins,
with the \a region in which the painting will occur.
\sa endPaint(), paintDevice()
*/
void QBackingStore::beginPaint(const QRegion &region)
{
d_ptr->platformBackingStore->beginPaint(region);
}
void QBackingStore::beforeBeginPaint(QWindow *win)
{
if (!win)
win = window();
if (!win->handle())
return;
d_ptr->platformBackingStore->beforeBeginPaint(win);
}
/*!
This function is called after painting onto the surface has ended.
\sa beginPaint(), paintDevice()
*/
void QBackingStore::endPaint()
{
d_ptr->platformBackingStore->endPaint();
}
void QBackingStore::afterEndPaint(QWindow *win)
{
if (!win)
win = window();
if (!win->handle())
return;
d_ptr->platformBackingStore->afterEndPaint(win);
}
/*!
Sets the size of the windowsurface to be \a size.
\sa size()
*/
void QBackingStore::resize(const QSize &size)
{
d_ptr->size = size;
d_ptr->platformBackingStore->resize(size, d_ptr->staticContents);
}
/*!
Returns the current size of the windowsurface.
*/
QSize QBackingStore::size() const
{
return d_ptr->size;
}
/*!
Scrolls the given \a area \a dx pixels to the right and \a dy
downward; both \a dx and \a dy may be negative.
Returns \c true if the area was scrolled successfully; false otherwise.
*/
bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
{
Q_UNUSED(area);
Q_UNUSED(dx);
Q_UNUSED(dy);
return d_ptr->platformBackingStore->scroll(area, dx, dy);
}
void QBackingStore::setStaticContents(const QRegion &region)
{
d_ptr->staticContents = region;
}
QRegion QBackingStore::staticContents() const
{
return d_ptr->staticContents;
}
bool QBackingStore::hasStaticContents() const
{
return !d_ptr->staticContents.isEmpty();
}
void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
{
// make sure we don't detach
uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
int lineskip = img.bytesPerLine();
int depth = img.depth() >> 3;
const QRect imageRect(0, 0, img.width(), img.height());
const QRect r = rect & imageRect & imageRect.translated(-offset);
const QPoint p = rect.topLeft() + offset;
if (r.isEmpty())
return;
const uchar *src;
uchar *dest;
if (r.top() < p.y()) {
src = mem + r.bottom() * lineskip + r.left() * depth;
dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
lineskip = -lineskip;
} else {
src = mem + r.top() * lineskip + r.left() * depth;
dest = mem + p.y() * lineskip + p.x() * depth;
}
const int w = r.width();
int h = r.height();
const int bytes = w * depth;
// overlapping segments?
if (offset.y() == 0 && qAbs(offset.x()) < w) {
do {
::memmove(dest, src, bytes);
dest += lineskip;
src += lineskip;
} while (--h);
} else {
do {
::memcpy(dest, src, bytes);
dest += lineskip;
src += lineskip;
} while (--h);
}
}
QPlatformBackingStore *QBackingStore::handle() const
{
return d_ptr->platformBackingStore;
}
QT_END_NAMESPACE

View file

@ -1,88 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QBACKINGSTORE_H
#define QBACKINGSTORE_H
#include <QtCore/qrect.h>
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
QT_BEGIN_NAMESPACE
class QRegion;
class QRect;
class QPoint;
class QImage;
class QBackingStorePrivate;
class QPlatformBackingStore;
class Q_GUI_EXPORT QBackingStore
{
public:
explicit QBackingStore(QWindow *window);
~QBackingStore();
QWindow *window() const;
QPaintDevice *paintDevice();
// 'window' can be a child window, in which case 'region' is in child window coordinates and
// offset is the (child) window's offset in relation to the window surface.
void flush(const QRegion &region, QWindow *window = 0, const QPoint &offset = QPoint());
void resize(const QSize &size);
QSize size() const;
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &);
void beforeBeginPaint(QWindow *window);
void endPaint();
void afterEndPaint(QWindow *window);
void setStaticContents(const QRegion &region);
QRegion staticContents() const;
bool hasStaticContents() const;
QPlatformBackingStore *handle() const;
private:
QScopedPointer<QBackingStorePrivate> d_ptr;
};
QT_END_NAMESPACE
#endif // QBACKINGSTORE_H

View file

@ -1,748 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <private/qimagescale_p.h>
#include <private/qdrawhelper_p.h>
#include "qimage.h"
#include "qcolor.h"
QT_BEGIN_NAMESPACE
/*
* Copyright (C) 2004, 2005 Daniel M. Duley
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* OTHER CREDITS:
*
* This is the normal smoothscale method, based on Imlib2's smoothscale.
*
* Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
* optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
* C algorithm and it ran at about the same speed as my MMX optimized one...
* Finally I ported Imlib's MMX version and it ran in less than half the
* time as my MMX algorithm, (taking only a quarter of the time Qt does).
* After further optimization it seems to run at around 1/6th.
*
* Changes include formatting, namespaces and other C++'ings, removal of old
* #ifdef'ed code, and removal of unneeded border calculation code.
*
* Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
* is by Willem Monsuwe <willem@stack.nl>. All other modifications are
* (C) Daniel M. Duley.
*/
namespace QImageScale {
const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
int* qimageCalcXPoints(int sw, int dw);
int* qimageCalcApoints(int s, int d, int up);
QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh,
int dw, int dh, char aa);
}
using namespace QImageScale;
//
// Code ported from Imlib...
//
const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int sw, int sh, int dh)
{
const unsigned int **p;
int j = 0, rv = 0;
qint64 val, inc;
if(dh < 0){
dh = -dh;
rv = 1;
}
p = new const unsigned int* [dh+1];
int up = qAbs(dh) >= sh;
val = up ? 0x8000 * sh / dh - 0x8000 : 0;
inc = (((qint64)sh) << 16) / dh;
for (int i = 0; i < dh; i++) {
p[j++] = src + qMax(0LL, val >> 16) * sw;
val += inc;
}
if (rv) {
for (int i = dh / 2; --i >= 0; ) {
const unsigned int *tmp = p[i];
p[i] = p[dh - i - 1];
p[dh - i - 1] = tmp;
}
}
return(p);
}
int* QImageScale::qimageCalcXPoints(int sw, int dw)
{
int *p, j = 0, rv = 0;
qint64 val, inc;
if(dw < 0){
dw = -dw;
rv = 1;
}
p = new int[dw+1];
int up = qAbs(dw) >= sw;
val = up ? 0x8000 * sw / dw - 0x8000 : 0;
inc = (((qint64)sw) << 16) / dw;
for (int i = 0; i < dw; i++) {
p[j++] = qMax(0LL, val >> 16);
val += inc;
}
if (rv) {
for (int i = dw / 2; --i >= 0; ) {
int tmp = p[i];
p[i] = p[dw - i - 1];
p[dw - i - 1] = tmp;
}
}
return(p);
}
int* QImageScale::qimageCalcApoints(int s, int d, int up)
{
int *p, j = 0, rv = 0;
if(d < 0){
rv = 1;
d = -d;
}
p = new int[d];
/* scaling up */
if(up){
qint64 val, inc;
val = 0x8000 * s / d - 0x8000;
inc = (((qint64)s) << 16) / d;
for (int i = 0; i < d; i++) {
int pos = val >> 16;
if (pos < 0)
p[j++] = 0;
else if (pos >= (s - 1))
p[j++] = 0;
else
p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
val += inc;
}
}
/* scaling down */
else {
qint64 val = 0;
qint64 inc = (((qint64)s) << 16) / d;
int Cp = (((d << 14) + s - 1) / s);
for (int i = 0; i < d; i++) {
int ap = ((0x10000 - (val & 0xffff)) * Cp) >> 16;
p[j] = ap | (Cp << 16);
j++;
val += inc;
}
}
if(rv){
int tmp;
for (int i = d / 2; --i >= 0; ) {
tmp = p[i];
p[i] = p[d - i - 1];
p[d - i - 1] = tmp;
}
}
return p;
}
QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
{
if(isi){
delete[] isi->xpoints;
delete[] isi->ypoints;
delete[] isi->xapoints;
delete[] isi->yapoints;
delete isi;
}
return 0;
}
QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
int sw, int sh,
int dw, int dh, char aa)
{
QImageScaleInfo *isi;
int scw, sch;
scw = dw * qlonglong(img.width()) / sw;
sch = dh * qlonglong(img.height()) / sh;
isi = new QImageScaleInfo;
if(!isi)
return 0;
memset(isi, 0, sizeof(QImageScaleInfo));
isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
isi->xpoints = qimageCalcXPoints(img.width(), scw);
if(!isi->xpoints)
return(qimageFreeScaleInfo(isi));
isi->ypoints = qimageCalcYPoints((const unsigned int *)img.scanLine(0),
img.bytesPerLine() / 4, img.height(), sch);
if (!isi->ypoints)
return(qimageFreeScaleInfo(isi));
if(aa) {
isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
if(!isi->xapoints)
return(qimageFreeScaleInfo(isi));
isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
if(!isi->yapoints)
return(qimageFreeScaleInfo(isi));
}
return(isi);
}
static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow);
static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow);
static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow);
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
template<bool RGB>
void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow);
template<bool RGB>
void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow);
template<bool RGB>
void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow);
#endif
static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
/* calculate the source line we'll scan from */
const unsigned int *sptr = ypoints[dyy + y];
unsigned int *dptr = dest + dx + ((y + dy) * dow);
const int yap = yapoints[dyy + y];
if (yap > 0) {
for (int x = dxx; x < end; x++) {
const unsigned int *pix = sptr + xpoints[x];
const int xap = xapoints[x];
if (xap > 0)
*dptr = interpolate_4_pixels(pix[0], pix[1], pix[sow], pix[sow + 1], xap, yap);
else
*dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap);
dptr++;
}
} else {
for (int x = dxx; x < end; x++) {
const unsigned int *pix = sptr + xpoints[x];
const int xap = xapoints[x];
if (xap > 0)
*dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
else
*dptr = pix[0];
dptr++;
}
}
}
}
/* scale by area sampling */
static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow)
{
/* scaling up both ways */
if (isi->xup_yup == 3){
qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down vertically */
else if (isi->xup_yup == 1) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
else
#endif
qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally */
else if (isi->xup_yup == 2) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
else
#endif
qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally & vertically */
else {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
else
#endif
qt_qimageScaleAARGBA_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
}
inline static void qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b, int &a)
{
r = qRed(*pix) * xyap;
g = qGreen(*pix) * xyap;
b = qBlue(*pix) * xyap;
a = qAlpha(*pix) * xyap;
int j;
for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
pix += step;
r += qRed(*pix) * Cxy;
g += qGreen(*pix) * Cxy;
b += qBlue(*pix) * Cxy;
a += qAlpha(*pix) * Cxy;
}
pix += step;
r += qRed(*pix) * j;
g += qGreen(*pix) * j;
b += qBlue(*pix) * j;
a += qAlpha(*pix) * j;
}
static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
int Cy = (yapoints[dyy + y]) >> 16;
int yap = (yapoints[dyy + y]) & 0xffff;
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b, a;
qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, r, g, b, a);
int xap = xapoints[x];
if (xap > 0) {
int rr, gg, bb, aa;
qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
r = r * (256 - xap);
g = g * (256 - xap);
b = b * (256 - xap);
a = a * (256 - xap);
r = (r + (rr * xap)) >> 8;
g = (g + (gg * xap)) >> 8;
b = (b + (bb * xap)) >> 8;
a = (a + (aa * xap)) >> 8;
}
*dptr++ = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
}
}
}
static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b, a;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, r, g, b, a);
int yap = yapoints[dyy + y];
if (yap > 0) {
int rr, gg, bb, aa;
qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
r = r * (256 - yap);
g = g * (256 - yap);
b = b * (256 - yap);
a = a * (256 - yap);
r = (r + (rr * yap)) >> 8;
g = (g + (gg * yap)) >> 8;
b = (b + (bb * yap)) >> 8;
a = (a + (aa * yap)) >> 8;
}
*dptr = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
dptr++;
}
}
}
static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
for (int y = 0; y < dh; y++) {
int Cy = (yapoints[dyy + y]) >> 16;
int yap = (yapoints[dyy + y]) & 0xffff;
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int rx, gx, bx, ax;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
int r = ((rx>>4) * yap);
int g = ((gx>>4) * yap);
int b = ((bx>>4) * yap);
int a = ((ax>>4) * yap);
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * Cy);
g += ((gx>>4) * Cy);
b += ((bx>>4) * Cy);
a += ((ax>>4) * Cy);
}
sptr += sow;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * j);
g += ((gx>>4) * j);
b += ((bx>>4) * j);
a += ((ax>>4) * j);
*dptr = qRgba(r >> 24, g >> 24, b >> 24, a >> 24);
dptr++;
}
}
}
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow);
static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow);
static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow);
/* scale by area sampling - IGNORE the ALPHA byte*/
static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy,
int dw, int dh, int dow, int sow)
{
/* scaling up both ways */
if (isi->xup_yup == 3) {
qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down vertically */
else if (isi->xup_yup == 1) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
else
#endif
qt_qimageScaleAARGB_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally */
else if (isi->xup_yup == 2) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
else
#endif
qt_qimageScaleAARGB_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally & vertically */
else {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
else
#endif
qt_qimageScaleAARGB_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
}
inline static void qt_qimageScaleAARGB_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b)
{
r = qRed(*pix) * xyap;
g = qGreen(*pix) * xyap;
b = qBlue(*pix) * xyap;
int j;
for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
pix += step;
r += qRed(*pix) * Cxy;
g += qGreen(*pix) * Cxy;
b += qBlue(*pix) * Cxy;
}
pix += step;
r += qRed(*pix) * j;
g += qGreen(*pix) * j;
b += qBlue(*pix) * j;
}
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
int Cy = (yapoints[dyy + y]) >> 16;
int yap = (yapoints[dyy + y]) & 0xffff;
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b;
qt_qimageScaleAARGB_helper(sptr, yap, Cy, sow, r, g, b);
int xap = xapoints[x];
if (xap > 0) {
int rr, bb, gg;
qt_qimageScaleAARGB_helper(sptr + 1, yap, Cy, sow, rr, gg, bb);
r = r * (256 - xap);
g = g * (256 - xap);
b = b * (256 - xap);
r = (r + (rr * xap)) >> 8;
g = (g + (gg * xap)) >> 8;
b = (b + (bb * xap)) >> 8;
}
*dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
}
}
}
static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, r, g, b);
int yap = yapoints[dyy + y];
if (yap > 0) {
int rr, bb, gg;
qt_qimageScaleAARGB_helper(sptr + sow, xap, Cx, 1, rr, gg, bb);
r = r * (256 - yap);
g = g * (256 - yap);
b = b * (256 - yap);
r = (r + (rr * yap)) >> 8;
g = (g + (gg * yap)) >> 8;
b = (b + (bb * yap)) >> 8;
}
*dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
}
}
}
static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
int end = dxx + dw;
for (int y = 0; y < dh; y++) {
int Cy = (yapoints[dyy + y]) >> 16;
int yap = (yapoints[dyy + y]) & 0xffff;
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int rx, gx, bx;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
int r = (rx >> 4) * yap;
int g = (gx >> 4) * yap;
int b = (bx >> 4) * yap;
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * Cy;
g += (gx >> 4) * Cy;
b += (bx >> 4) * Cy;
}
sptr += sow;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * j;
g += (gx >> 4) * j;
b += (bx >> 4) * j;
*dptr = qRgb(r >> 24, g >> 24, b >> 24);
dptr++;
}
}
}
QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
{
QImage buffer;
if (src.isNull() || dw <= 0 || dh <= 0)
return buffer;
int w = src.width();
int h = src.height();
QImageScaleInfo *scaleinfo =
qimageCalcScaleInfo(src, w, h, dw, dh, true);
if (!scaleinfo)
return buffer;
buffer = QImage(dw, dh, src.format());
if (buffer.isNull()) {
qWarning("QImage: out of memory, returning null");
qimageFreeScaleInfo(scaleinfo);
return QImage();
}
if (src.hasAlphaChannel())
qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
else
qt_qimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0),
0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
qimageFreeScaleInfo(scaleinfo);
return buffer;
}
QT_END_NAMESPACE

View file

@ -1,127 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPAINTENGINE_P_H
#define QPAINTENGINE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtGui/qpainter.h"
#include "QtGui/qpaintengine.h"
#include "QtGui/qregion.h"
#include "private/qobject_p.h"
QT_BEGIN_NAMESPACE
class QPaintDevice;
class Q_GUI_EXPORT QPaintEnginePrivate
{
Q_DECLARE_PUBLIC(QPaintEngine)
public:
QPaintEnginePrivate() : pdev(0), q_ptr(0), currentClipDevice(0), hasSystemTransform(0),
hasSystemViewport(0) {}
virtual ~QPaintEnginePrivate() { }
QPaintDevice *pdev;
QPaintEngine *q_ptr;
QRegion systemClip;
QRect systemRect;
QRegion systemViewport;
QTransform systemTransform;
QPaintDevice *currentClipDevice;
uint hasSystemTransform : 1;
uint hasSystemViewport : 1;
inline void transformSystemClip()
{
if (systemClip.isEmpty())
return;
if (hasSystemTransform) {
if (systemTransform.type() <= QTransform::TxTranslate)
systemClip.translate(qRound(systemTransform.dx()), qRound(systemTransform.dy()));
else {
// Transform the system clip region back from device pixels to device-independent pixels before
// applying systemTransform, which already has transform from device-independent pixels to device pixels
#ifdef Q_OS_MAC
QTransform scaleTransform;
const qreal invDevicePixelRatio = 1. / pdev->devicePixelRatio();
scaleTransform.scale(invDevicePixelRatio, invDevicePixelRatio);
systemClip = systemTransform.map(scaleTransform.map(systemClip));
#else
systemClip = systemTransform.map(systemClip);
#endif
}
}
// Make sure we're inside the viewport.
if (hasSystemViewport) {
systemClip &= systemViewport;
if (systemClip.isEmpty()) {
// We don't want to paint without system clip, so set it to 1 pixel :)
systemClip = QRect(systemViewport.boundingRect().topLeft(), QSize(1, 1));
}
}
}
inline void setSystemTransform(const QTransform &xform)
{
systemTransform = xform;
if ((hasSystemTransform = !xform.isIdentity()) || hasSystemViewport)
transformSystemClip();
systemStateChanged();
}
inline void setSystemViewport(const QRegion &region)
{
systemViewport = region;
hasSystemViewport = !systemViewport.isEmpty();
}
virtual void systemStateChanged() { }
void drawBoxTextItem(const QPointF &p, const QTextItemInt &ti);
};
QT_END_NAMESPACE
#endif // QPAINTENGINE_P_H

View file

@ -1,150 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPLATFORMBACKINGSTORE_H
#define QPLATFORMBACKINGSTORE_H
//
// W A R N I N G
// -------------
//
// This file is part of the QPA API and is not meant to be used
// in applications. Usage of this API may make your code
// source and binary incompatible with future versions of Qt.
//
#include <QtCore/qrect.h>
#include <QtCore/qobject.h>
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
class QRegion;
class QRect;
class QPoint;
class QImage;
class QPlatformBackingStorePrivate;
class QPlatformWindow;
class QPlatformTextureList;
class QPlatformTextureListPrivate;
class QOpenGLContext;
class QPlatformGraphicsBuffer;
#ifndef QT_NO_OPENGL
class Q_GUI_EXPORT QPlatformTextureList : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QPlatformTextureList)
public:
enum Flag {
StacksOnTop = 0x01
};
Q_DECLARE_FLAGS(Flags, Flag)
explicit QPlatformTextureList(QObject *parent = 0);
~QPlatformTextureList();
int count() const;
bool isEmpty() const { return count() == 0; }
GLuint textureId(int index) const;
QRect geometry(int index) const;
QRect clipRect(int index) const;
void *source(int index);
Flags flags(int index) const;
void lock(bool on);
bool isLocked() const;
void appendTexture(void *source, GLuint textureId, const QRect &geometry,
const QRect &clipRect = QRect(), Flags flags = 0);
void clear();
Q_SIGNALS:
void locked(bool);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformTextureList::Flags)
#endif
class Q_GUI_EXPORT QPlatformBackingStore
{
public:
explicit QPlatformBackingStore(QWindow *window);
virtual ~QPlatformBackingStore();
QWindow *window() const;
virtual QPaintDevice *paintDevice() = 0;
// 'window' can be a child window, in which case 'region' is in child window coordinates and
// offset is the (child) window's offset in relation to the window surface.
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset) = 0;
#ifndef QT_NO_OPENGL
virtual void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
QPlatformTextureList *textures, QOpenGLContext *context,
bool translucentBackground);
virtual QImage toImage() const;
enum TextureFlag {
TextureSwizzle = 0x01,
TextureFlip = 0x02
};
Q_DECLARE_FLAGS(TextureFlags, TextureFlag)
virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
#endif
virtual QPlatformGraphicsBuffer *graphicsBuffer() const;
virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
virtual bool scroll(const QRegion &area, int dx, int dy);
virtual void beginPaint(const QRegion &);
virtual void beforeBeginPaint(QWindow *window) {
}
virtual void endPaint();
virtual void afterEndPaint(QWindow *window) {
}
private:
QPlatformBackingStorePrivate *d_ptr;
};
#ifndef QT_NO_OPENGL
Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformBackingStore::TextureFlags)
#endif
QT_END_NAMESPACE
#endif // QPLATFORMBACKINGSTORE_H

File diff suppressed because it is too large Load diff

View file

@ -1,260 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTLAYOUT_H
#define QTEXTLAYOUT_H
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qrect.h>
#include <QtCore/qvector.h>
#include <QtGui/qcolor.h>
#include <QtCore/qobject.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
#include <QtGui/qglyphrun.h>
#include <QtGui/qtextcursor.h>
QT_BEGIN_NAMESPACE
class QTextEngine;
class QFont;
#ifndef QT_NO_RAWFONT
class QRawFont;
#endif
class QRect;
class QRegion;
class QTextFormat;
class QPalette;
class QPainter;
class Q_GUI_EXPORT QTextInlineObject
{
public:
QTextInlineObject(int i, QTextEngine *e) : itm(i), eng(e) {}
inline QTextInlineObject() : itm(0), eng(0) {}
inline bool isValid() const { return eng; }
QRectF rect() const;
qreal width() const;
qreal ascent() const;
qreal descent() const;
qreal height() const;
Qt::LayoutDirection textDirection() const;
void setWidth(qreal w);
void setAscent(qreal a);
void setDescent(qreal d);
int textPosition() const;
int formatIndex() const;
QTextFormat format() const;
private:
friend class QTextLayout;
int itm;
QTextEngine *eng;
};
class QPaintDevice;
class QTextFormat;
class QTextLine;
class QTextBlock;
class QTextOption;
class Q_GUI_EXPORT QTextLayout
{
public:
// does itemization
QTextLayout();
QTextLayout(const QString& text);
QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice = 0);
QTextLayout(const QTextBlock &b);
~QTextLayout();
void setFont(const QFont &f);
QFont font() const;
#ifndef QT_NO_RAWFONT
void setRawFont(const QRawFont &rawFont);
#endif
void setText(const QString& string);
QString text() const;
void setTextOption(const QTextOption &option);
const QTextOption &textOption() const;
void setPreeditArea(int position, const QString &text);
int preeditAreaPosition() const;
QString preeditAreaText() const;
struct FormatRange {
int start;
int length;
QTextCharFormat format;
};
void setAdditionalFormats(const QList<FormatRange> &overrides);
QList<FormatRange> additionalFormats() const;
void clearAdditionalFormats();
void setCacheEnabled(bool enable);
bool cacheEnabled() const;
void setCursorMoveStyle(Qt::CursorMoveStyle style);
Qt::CursorMoveStyle cursorMoveStyle() const;
void beginLayout();
void endLayout();
void clearLayout();
QTextLine createLine();
int lineCount() const;
QTextLine lineAt(int i) const;
QTextLine lineForTextPosition(int pos) const;
enum CursorMode {
SkipCharacters,
SkipWords
};
bool isValidCursorPosition(int pos) const;
int nextCursorPosition(int oldPos, CursorMode mode = SkipCharacters) const;
int previousCursorPosition(int oldPos, CursorMode mode = SkipCharacters) const;
int leftCursorPosition(int oldPos) const;
int rightCursorPosition(int oldPos) const;
void draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections = QVector<FormatRange>(),
const QRectF &clip = QRectF()) const;
void drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const;
void drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const;
QPointF position() const;
void setPosition(const QPointF &p);
QRectF boundingRect() const;
qreal minimumWidth() const;
qreal maximumWidth() const;
#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
#endif
QTextEngine *engine() const { return d; }
void setFlags(int flags);
private:
QTextLayout(QTextEngine *e) : d(e) {}
Q_DISABLE_COPY(QTextLayout)
friend class QPainter;
friend class QGraphicsSimpleTextItemPrivate;
friend class QGraphicsSimpleTextItem;
friend void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *, const QString& str,
QRectF *brect, int tabstops, int* tabarray, int tabarraylen,
QPainter *painter);
QTextEngine *d;
friend class TextBlock;
};
class Q_GUI_EXPORT QTextLine
{
public:
inline QTextLine() : index(0), eng(0) {}
inline bool isValid() const { return eng; }
QRectF rect() const;
qreal x() const;
qreal y() const;
qreal width() const;
qreal ascent() const;
qreal descent() const;
qreal height() const;
qreal leading() const;
void setLeadingIncluded(bool included);
bool leadingIncluded() const;
qreal naturalTextWidth() const;
qreal horizontalAdvance() const;
QRectF naturalTextRect() const;
enum Edge {
Leading,
Trailing
};
enum CursorPosition {
CursorBetweenCharacters,
CursorOnCharacter
};
/* cursorPos gets set to the valid position */
qreal cursorToX(int *cursorPos, Edge edge = Leading) const;
inline qreal cursorToX(int cursorPos, Edge edge = Leading) const { return cursorToX(&cursorPos, edge); }
int xToCursor(qreal x, CursorPosition = CursorBetweenCharacters) const;
void setLineWidth(qreal width);
void setNumColumns(int columns);
void setNumColumns(int columns, qreal alignmentWidth);
void setPosition(const QPointF &pos);
QPointF position() const;
int textStart() const;
int textLength() const;
int lineNumber() const { return index; }
void draw(QPainter *p, const QPointF &point, const QTextLayout::FormatRange *selection = 0) const;
#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
#endif
private:
QTextLine(int line, QTextEngine *e) : index(line), eng(e) {}
void layout_helper(int numGlyphs);
friend class QTextLayout;
friend class QTextFragment;
int index;
QTextEngine *eng;
};
QT_END_NAMESPACE
#endif // QTEXTLAYOUT_H

View file

@ -1,377 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qbasicfontdatabase_p.h"
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformscreen.h>
#include <QtCore/QFile>
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
#include <QtCore/QUuid>
#include <QtCore/QtEndian>
#undef QT_NO_FREETYPE
#include <QtGui/private/qfontengine_ft_p.h>
#include <QtGui/private/qfontengine_p.h>
#include <ft2build.h>
#include FT_TRUETYPE_TABLES_H
#include FT_ERRORS_H
QT_BEGIN_NAMESPACE
void QBasicFontDatabase::populateFontDatabase()
{
QString fontpath = fontDir();
if(!QFile::exists(fontpath)) {
qWarning("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?",
qPrintable(fontpath));
return;
}
QDir dir(fontpath);
dir.setNameFilters(QStringList() << QLatin1String("*.ttf")
<< QLatin1String("*.ttc") << QLatin1String("*.pfa")
<< QLatin1String("*.pfb")
<< QLatin1String("*.otf"));
dir.refresh();
for (int i = 0; i < int(dir.count()); ++i) {
const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i]));
// qDebug() << "looking at" << file;
addTTFile(QByteArray(), file);
}
}
inline static void setHintingPreference(QFontEngine *engine, QFont::HintingPreference hintingPreference)
{
switch (hintingPreference) {
case QFont::PreferNoHinting:
engine->setDefaultHintStyle(QFontEngineFT::HintNone);
break;
case QFont::PreferFullHinting:
engine->setDefaultHintStyle(QFontEngineFT::HintFull);
break;
case QFont::PreferVerticalHinting:
engine->setDefaultHintStyle(QFontEngineFT::HintLight);
break;
case QFont::PreferDefaultHinting:
// Leave it as it is
break;
}
}
QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr)
{
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
QFontEngineFT *engine = new QFontEngineFT(fontDef);
QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono;
if (antialias) {
QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint();
if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
format = QFontEngineFT::Format_A8;
engine->subpixelType = QFontEngine::Subpixel_None;
} else {
format = QFontEngineFT::Format_A32;
engine->subpixelType = subpixelType;
}
}
if (!engine->init(fid, antialias, format) || engine->invalid()) {
delete engine;
engine = 0;
} else {
setHintingPreference(engine, static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
}
return engine;
}
namespace {
class QFontEngineFTRawData: public QFontEngineFT
{
public:
QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef)
{
}
void updateFamilyNameAndStyle()
{
fontDef.family = QString::fromLatin1(freetype->face->family_name);
if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)
fontDef.style = QFont::StyleItalic;
if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD)
fontDef.weight = QFont::Bold;
}
bool initFromData(const QByteArray &fontData)
{
FaceId faceId;
faceId.filename = "";
faceId.index = 0;
faceId.uuid = QUuid::createUuid().toByteArray();
return init(faceId, true, Format_None, fontData);
}
};
}
QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
QFontDef fontDef;
fontDef.pixelSize = pixelSize;
fontDef.hintingPreference = hintingPreference;
QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef);
if (!fe->initFromData(fontData)) {
delete fe;
return 0;
}
fe->updateFamilyNameAndStyle();
setHintingPreference(fe, hintingPreference);
return fe;
}
QStringList QBasicFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
Q_UNUSED(family);
Q_UNUSED(style);
Q_UNUSED(script);
Q_UNUSED(styleHint);
return QStringList();
}
QStringList QBasicFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
{
return addTTFile(fontData,fileName.toLocal8Bit());
}
void QBasicFontDatabase::releaseHandle(void *handle)
{
FontFile *file = static_cast<FontFile *>(handle);
delete file;
}
extern FT_Library qt_getFreetype();
// copied from freetype with some modifications
#ifndef FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY
#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY FT_MAKE_TAG('i', 'g', 'p', 'f')
#endif
#ifndef FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY
#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY FT_MAKE_TAG('i', 'g', 'p', 's')
#endif
/* there's a Mac-specific extended implementation of FT_New_Face() */
/* in src/base/ftmac.c */
#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
/* documentation is in freetype.h */
FT_Error __ft_New_Face(FT_Library library, const char* pathname, FT_Long face_index, FT_Face *aface) {
FT_Open_Args args;
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
if (!pathname)
return FT_Err_Invalid_Argument;
FT_Parameter params[2];
params[0].tag = FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY;
params[0].data = 0;
params[1].tag = FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY;
params[1].data = 0;
args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;
args.pathname = (char*)pathname;
args.stream = NULL;
args.num_params = 2;
args.params = params;
return FT_Open_Face(library, &args, face_index, aface);
}
#else
FT_Error __ft_New_Face(FT_Library library, const char* pathname, FT_Long face_index, FT_Face *aface) {
return FT_New_Face(library, pathname, face_index, aface);
}
#endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
/* documentation is in freetype.h */
FT_Error __ft_New_Memory_Face(FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface) {
FT_Open_Args args;
/* test for valid `library' and `face' delayed to FT_Open_Face() */
if (!file_base)
return FT_Err_Invalid_Argument;
FT_Parameter params[2];
params[0].tag = FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY;
params[0].data = 0;
params[1].tag = FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY;
params[1].data = 0;
args.flags = FT_OPEN_MEMORY | FT_OPEN_PARAMS;
args.memory_base = file_base;
args.memory_size = file_size;
args.stream = NULL;
args.num_params = 2;
args.params = params;
return FT_Open_Face(library, &args, face_index, aface);
}
// end
QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file, QSupportedWritingSystems *supportedWritingSystems)
{
FT_Library library = qt_getFreetype();
int index = 0;
int numFaces = 0;
QStringList families;
do {
FT_Face face;
FT_Error error;
if (!fontData.isEmpty()) {
error = __ft_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
} else {
error = __ft_New_Face(library, file.constData(), index, &face);
}
if (error != FT_Err_Ok) {
qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
break;
}
numFaces = face->num_faces;
QFont::Weight weight = QFont::Normal;
QFont::Style style = QFont::StyleNormal;
if (face->style_flags & FT_STYLE_FLAG_ITALIC)
style = QFont::StyleItalic;
if (face->style_flags & FT_STYLE_FLAG_BOLD)
weight = QFont::Bold;
bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
QSupportedWritingSystems writingSystems;
// detect symbol fonts
for (int i = 0; i < face->num_charmaps; ++i) {
FT_CharMap cm = face->charmaps[i];
if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM
|| cm->encoding == FT_ENCODING_MS_SYMBOL) {
writingSystems.setSupported(QFontDatabase::Symbol);
if (supportedWritingSystems)
supportedWritingSystems->setSupported(QFontDatabase::Symbol);
break;
}
}
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
if (os2) {
quint32 unicodeRange[4] = {
quint32(os2->ulUnicodeRange1),
quint32(os2->ulUnicodeRange2),
quint32(os2->ulUnicodeRange3),
quint32(os2->ulUnicodeRange4)
};
quint32 codePageRange[2] = {
quint32(os2->ulCodePageRange1),
quint32(os2->ulCodePageRange2)
};
writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
if (supportedWritingSystems)
*supportedWritingSystems = writingSystems;
if (os2->usWeightClass) {
weight = QPlatformFontDatabase::weightFromInteger(os2->usWeightClass);
} else if (os2->panose[2]) {
int w = os2->panose[2];
if (w <= 1)
weight = QFont::Thin;
else if (w <= 2)
weight = QFont::ExtraLight;
else if (w <= 3)
weight = QFont::Light;
else if (w <= 5)
weight = QFont::Normal;
else if (w <= 6)
weight = QFont::Medium;
else if (w <= 7)
weight = QFont::DemiBold;
else if (w <= 8)
weight = QFont::Bold;
else if (w <= 9)
weight = QFont::ExtraBold;
else if (w <= 10)
weight = QFont::Black;
}
}
QString family = QString::fromLatin1(face->family_name);
FontFile *fontFile = new FontFile;
fontFile->fileName = QFile::decodeName(file);
fontFile->indexValue = index;
QFont::Stretch stretch = QFont::Unstretched;
registerFont(family,QString::fromLatin1(face->style_name),QString(),weight,style,stretch,true,true,0,fixedPitch,writingSystems,fontFile);
families.append(family);
FT_Done_Face(face);
++index;
} while (index < numFaces);
return families;
}
QT_END_NAMESPACE

View file

@ -1,954 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qfontconfigdatabase_p.h"
#include "qfontenginemultifontconfig_p.h"
#include <QtCore/QList>
#include <QtCore/QElapsedTimer>
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformservices.h>
#include <QtGui/private/qfontengine_ft_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qguiapplication.h>
#include <fontconfig/fontconfig.h>
#if FC_VERSION >= 20402
#include <fontconfig/fcfreetype.h>
#endif
QT_BEGIN_NAMESPACE
static const int maxWeight = 99;
static inline int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, int qtLower, int qtUpper)
{
return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower);
}
static inline bool requiresOpenType(int writingSystem)
{
return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
|| writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
}
static inline int weightFromFcWeight(int fcweight)
{
// Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from
// 0 to 99. The spacing between the values for the enums are uneven so a linear mapping from
// Font Config values to Qt would give surprising results. So, we do a piecewise linear
// mapping. This ensures that where there is a corresponding enum on both sides (for example
// FC_WEIGHT_DEMIBOLD and QFont::DemiBold) we map one to the other but other values map
// to intermediate Qt weights.
if (fcweight <= FC_WEIGHT_THIN)
return QFont::Thin;
if (fcweight <= FC_WEIGHT_ULTRALIGHT)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_THIN, FC_WEIGHT_ULTRALIGHT, QFont::Thin, QFont::ExtraLight);
if (fcweight <= FC_WEIGHT_LIGHT)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRALIGHT, FC_WEIGHT_LIGHT, QFont::ExtraLight, QFont::Light);
if (fcweight <= FC_WEIGHT_NORMAL)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_LIGHT, FC_WEIGHT_NORMAL, QFont::Light, QFont::Normal);
if (fcweight <= FC_WEIGHT_MEDIUM)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_NORMAL, FC_WEIGHT_MEDIUM, QFont::Normal, QFont::Medium);
if (fcweight <= FC_WEIGHT_DEMIBOLD)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_MEDIUM, FC_WEIGHT_DEMIBOLD, QFont::Medium, QFont::DemiBold);
if (fcweight <= FC_WEIGHT_BOLD)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_DEMIBOLD, FC_WEIGHT_BOLD, QFont::DemiBold, QFont::Bold);
if (fcweight <= FC_WEIGHT_ULTRABOLD)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_BOLD, FC_WEIGHT_ULTRABOLD, QFont::Bold, QFont::ExtraBold);
if (fcweight <= FC_WEIGHT_BLACK)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRABOLD, FC_WEIGHT_BLACK, QFont::ExtraBold, QFont::Black);
if (fcweight <= FC_WEIGHT_ULTRABLACK)
return mapToQtWeightForRange(fcweight, FC_WEIGHT_BLACK, FC_WEIGHT_ULTRABLACK, QFont::Black, maxWeight);
return maxWeight;
}
static inline int stretchFromFcWidth(int fcwidth)
{
// Font Config enums for width match pretty closely with those used by Qt so just use
// Font Config values directly while enforcing the same limits imposed by QFont.
const int maxStretch = 4000;
int qtstretch;
if (fcwidth < 1)
qtstretch = 1;
else if (fcwidth > maxStretch)
qtstretch = maxStretch;
else
qtstretch = fcwidth;
return qtstretch;
}
static const char *specialLanguages[] = {
"", // Unknown
"", // Inherited
"", // Common
"en", // Latin
"el", // Greek
"ru", // Cyrillic
"hy", // Armenian
"he", // Hebrew
"ar", // Arabic
"syr", // Syriac
"dv", // Thaana
"hi", // Devanagari
"bn", // Bengali
"pa", // Gurmukhi
"gu", // Gujarati
"or", // Oriya
"ta", // Tamil
"te", // Telugu
"kn", // Kannada
"ml", // Malayalam
"si", // Sinhala
"th", // Thai
"lo", // Lao
"bo", // Tibetan
"my", // Myanmar
"ka", // Georgian
"ko", // Hangul
"am", // Ethiopic
"chr", // Cherokee
"cr", // CanadianAboriginal
"sga", // Ogham
"non", // Runic
"km", // Khmer
"mn", // Mongolian
"ja", // Hiragana
"ja", // Katakana
"zh-TW", // Bopomofo
"", // Han
"ii", // Yi
"ett", // OldItalic
"got", // Gothic
"en", // Deseret
"fil", // Tagalog
"hnn", // Hanunoo
"bku", // Buhid
"tbw", // Tagbanwa
"cop", // Coptic
"lif", // Limbu
"tdd", // TaiLe
"grc", // LinearB
"uga", // Ugaritic
"en", // Shavian
"so", // Osmanya
"grc", // Cypriot
"", // Braille
"bug", // Buginese
"khb", // NewTaiLue
"cu", // Glagolitic
"shi", // Tifinagh
"syl", // SylotiNagri
"peo", // OldPersian
"pra", // Kharoshthi
"ban", // Balinese
"akk", // Cuneiform
"phn", // Phoenician
"lzh", // PhagsPa
"man", // Nko
"su", // Sundanese
"lep", // Lepcha
"sat", // OlChiki
"vai", // Vai
"saz", // Saurashtra
"eky", // KayahLi
"rej", // Rejang
"xlc", // Lycian
"xcr", // Carian
"xld", // Lydian
"cjm", // Cham
"nod", // TaiTham
"blt", // TaiViet
"ae", // Avestan
"egy", // EgyptianHieroglyphs
"smp", // Samaritan
"lis", // Lisu
"bax", // Bamum
"jv", // Javanese
"mni", // MeeteiMayek
"arc", // ImperialAramaic
"xsa", // OldSouthArabian
"xpr", // InscriptionalParthian
"pal", // InscriptionalPahlavi
"otk", // OldTurkic
"bh", // Kaithi
"bbc", // Batak
"pra", // Brahmi
"myz", // Mandaic
"ccp", // Chakma
"xmr", // MeroiticCursive
"xmr", // MeroiticHieroglyphs
"hmd", // Miao
"sa", // Sharada
"srb", // SoraSompeng
"doi", // Takri
"lez", // CaucasianAlbanian
"bsq", // BassaVah
"fr", // Duployan
"sq", // Elbasan
"sa", // Grantha
"hnj", // PahawhHmong
"sd", // Khojki
"lab", // LinearA
"hi", // Mahajani
"xmn", // Manichaean
"men", // MendeKikakui
"mr", // Modi
"mru", // Mro
"xna", // OldNorthArabian
"arc", // Nabataean
"arc", // Palmyrene
"ctd", // PauCinHau
"kv", // OldPermic
"pal", // PsalterPahlavi
"sa", // Siddham
"sd", // Khudawadi
"mai", // Tirhuta
"hoc" // WarangCiti
};
Q_STATIC_ASSERT(sizeof(specialLanguages) / sizeof(const char *) == QChar::ScriptCount);
// this could become a list of all languages used for each writing
// system, instead of using the single most common language.
static const char *languageForWritingSystem[] = {
0, // Any
"en", // Latin
"el", // Greek
"ru", // Cyrillic
"hy", // Armenian
"he", // Hebrew
"ar", // Arabic
"syr", // Syriac
"div", // Thaana
"hi", // Devanagari
"bn", // Bengali
"pa", // Gurmukhi
"gu", // Gujarati
"or", // Oriya
"ta", // Tamil
"te", // Telugu
"kn", // Kannada
"ml", // Malayalam
"si", // Sinhala
"th", // Thai
"lo", // Lao
"bo", // Tibetan
"my", // Myanmar
"ka", // Georgian
"km", // Khmer
"zh-cn", // SimplifiedChinese
"zh-tw", // TraditionalChinese
"ja", // Japanese
"ko", // Korean
"vi", // Vietnamese
0, // Symbol
"sga", // Ogham
"non", // Runic
"man" // N'Ko
};
Q_STATIC_ASSERT(sizeof(languageForWritingSystem) / sizeof(const char *) == QFontDatabase::WritingSystemsCount);
#if FC_VERSION >= 20297
// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no
// open type tables for is directly. Do this so we don't pick some strange
// pseudo unicode font
static const char *openType[] = {
0, // Any
0, // Latin
0, // Greek
0, // Cyrillic
0, // Armenian
0, // Hebrew
0, // Arabic
"syrc", // Syriac
"thaa", // Thaana
"deva", // Devanagari
"beng", // Bengali
"guru", // Gurmukhi
"gujr", // Gujarati
"orya", // Oriya
"taml", // Tamil
"telu", // Telugu
"knda", // Kannada
"mlym", // Malayalam
"sinh", // Sinhala
0, // Thai
0, // Lao
"tibt", // Tibetan
"mymr", // Myanmar
0, // Georgian
"khmr", // Khmer
0, // SimplifiedChinese
0, // TraditionalChinese
0, // Japanese
0, // Korean
0, // Vietnamese
0, // Symbol
0, // Ogham
0, // Runic
"nko " // N'Ko
};
Q_STATIC_ASSERT(sizeof(openType) / sizeof(const char *) == QFontDatabase::WritingSystemsCount);
#endif
static const char *getFcFamilyForStyleHint(const QFont::StyleHint style)
{
const char *stylehint = 0;
switch (style) {
case QFont::SansSerif:
stylehint = "sans-serif";
break;
case QFont::Serif:
stylehint = "serif";
break;
case QFont::TypeWriter:
case QFont::Monospace:
stylehint = "monospace";
break;
case QFont::Cursive:
stylehint = "cursive";
break;
case QFont::Fantasy:
stylehint = "fantasy";
break;
default:
break;
}
return stylehint;
}
static void populateFromPattern(FcPattern *pattern)
{
QString familyName;
FcChar8 *value = 0;
int weight_value;
int slant_value;
int spacing_value;
int width_value;
FcChar8 *file_value;
int indexValue;
FcChar8 *foundry_value;
FcChar8 *style_value;
FcBool scalable;
FcBool antialias;
if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
return;
familyName = QString::fromUtf8((const char *)value);
if (familyName == QLatin1String("Open Sans")) {
FcChar8 *styl = 0;
if (FcPatternGetString(pattern, FC_STYLE, 0, &styl) == FcResultMatch) {
QString style = QString::fromUtf8(reinterpret_cast<const char *>(styl));
if (style == QLatin1String("Semibold")) {
familyName.append(QChar(QChar::Space)).append(style);
}
}
}
slant_value = FC_SLANT_ROMAN;
weight_value = FC_WEIGHT_REGULAR;
spacing_value = FC_PROPORTIONAL;
file_value = 0;
indexValue = 0;
scalable = FcTrue;
if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
slant_value = FC_SLANT_ROMAN;
if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
weight_value = FC_WEIGHT_REGULAR;
if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
width_value = FC_WIDTH_NORMAL;
if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
spacing_value = FC_PROPORTIONAL;
if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
file_value = 0;
if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
indexValue = 0;
if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
scalable = FcTrue;
if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
foundry_value = 0;
if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
style_value = 0;
if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
antialias = true;
QSupportedWritingSystems writingSystems;
FcLangSet *langset = 0;
FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
if (res == FcResultMatch) {
bool hasLang = false;
for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
if (lang) {
FcLangResult langRes = FcLangSetHasLang(langset, lang);
if (langRes != FcLangDifferentLang) {
writingSystems.setSupported(QFontDatabase::WritingSystem(j));
hasLang = true;
}
}
}
if (!hasLang)
// none of our known languages, add it to the other set
writingSystems.setSupported(QFontDatabase::Other);
} else {
// we set Other to supported for symbol fonts. It makes no
// sense to merge these with other ones, as they are
// special in a way.
writingSystems.setSupported(QFontDatabase::Other);
}
#if FC_VERSION >= 20297
for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
if (writingSystems.supported(QFontDatabase::WritingSystem(j))
&& requiresOpenType(j) && openType[j]) {
FcChar8 *cap;
res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap);
if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
writingSystems.setSupported(QFontDatabase::WritingSystem(j),false);
}
}
#endif
FontFile *fontFile = new FontFile;
fontFile->fileName = QString::fromLocal8Bit((const char *)file_value);
fontFile->indexValue = indexValue;
QFont::Style style = (slant_value == FC_SLANT_ITALIC)
? QFont::StyleItalic
: ((slant_value == FC_SLANT_OBLIQUE)
? QFont::StyleOblique
: QFont::StyleNormal);
// Note: weight should really be an int but registerFont incorrectly uses an enum
QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
double pixel_size = 0;
if (!scalable)
FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
bool fixedPitch = spacing_value >= FC_MONO;
// Note: stretch should really be an int but registerFont incorrectly uses an enum
QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k)
QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));
}
void QFontconfigDatabase::populateFontDatabase()
{
FcInitReinitialize();
FcFontSet *fonts;
{
FcObjectSet *os = FcObjectSetCreate();
FcPattern *pattern = FcPatternCreate();
const char *properties [] = {
FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
FC_SPACING, FC_FILE, FC_INDEX,
FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
FC_WIDTH,
#if FC_VERSION >= 20297
FC_CAPABILITY,
#endif
(const char *)0
};
const char **p = properties;
while (*p) {
FcObjectSetAdd(os, *p);
++p;
}
fonts = FcFontList(0, pattern, os);
FcObjectSetDestroy(os);
FcPatternDestroy(pattern);
}
for (int i = 0; i < fonts->nfont; i++)
populateFromPattern(fonts->fonts[i]);
FcFontSetDestroy (fonts);
struct FcDefaultFont {
const char *qtname;
const char *rawname;
bool fixed;
};
const FcDefaultFont defaults[] = {
{ "Serif", "serif", false },
{ "Sans Serif", "sans-serif", false },
{ "Monospace", "monospace", true },
{ 0, 0, false }
};
const FcDefaultFont *f = defaults;
// aliases only make sense for 'common', not for any of the specials
QSupportedWritingSystems ws;
ws.setSupported(QFontDatabase::Latin);
while (f->qtname) {
QString familyQtName = QString::fromLatin1(f->qtname);
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,0);
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,0);
registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,0);
++f;
}
//Lighthouse has very lazy population of the font db. We want it to be initialized when
//QApplication is constructed, so that the population procedure can do something like this to
//set the default font
// const FcDefaultFont *s = defaults;
// QFont font("Sans Serif");
// font.setPointSize(9);
// QApplication::setFont(font);
}
QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
{
return new QFontEngineMultiFontConfig(fontEngine, script);
}
namespace {
QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool useXftConf)
{
switch (hintingPreference) {
case QFont::PreferNoHinting:
return QFontEngine::HintNone;
case QFont::PreferVerticalHinting:
return QFontEngine::HintLight;
case QFont::PreferFullHinting:
return QFontEngine::HintFull;
case QFont::PreferDefaultHinting:
break;
}
if (QGuiApplication::platformNativeInterface()->nativeResourceForScreen("nofonthinting",
QGuiApplication::primaryScreen())) {
return QFontEngine::HintNone;
}
int hint_style = 0;
if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
switch (hint_style) {
case FC_HINT_NONE:
return QFontEngine::HintNone;
case FC_HINT_SLIGHT:
return QFontEngine::HintLight;
case FC_HINT_MEDIUM:
return QFontEngine::HintMedium;
case FC_HINT_FULL:
return QFontEngine::HintFull;
default:
Q_UNREACHABLE();
break;
}
}
if (useXftConf) {
void *hintStyleResource =
QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
QGuiApplication::primaryScreen());
int hintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
if (hintStyle > 0)
return QFontEngine::HintStyle(hintStyle - 1);
}
return QFontEngine::HintFull;
}
QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool useXftConf)
{
int subpixel = FC_RGBA_UNKNOWN;
if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
switch (subpixel) {
case FC_RGBA_UNKNOWN:
case FC_RGBA_NONE:
return QFontEngine::Subpixel_None;
case FC_RGBA_RGB:
return QFontEngine::Subpixel_RGB;
case FC_RGBA_BGR:
return QFontEngine::Subpixel_BGR;
case FC_RGBA_VRGB:
return QFontEngine::Subpixel_VRGB;
case FC_RGBA_VBGR:
return QFontEngine::Subpixel_VBGR;
default:
Q_UNREACHABLE();
break;
}
}
if (useXftConf) {
void *subpixelTypeResource =
QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
QGuiApplication::primaryScreen());
int subpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
if (subpixelType > 0)
return QFontEngine::SubpixelAntialiasingType(subpixelType - 1);
}
return QFontEngine::Subpixel_None;
}
} // namespace
QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
if (!usrPtr)
return 0;
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
QFontEngineFT *engine = new QFontEngineFT(f);
engine->face_id = fid;
setupFontEngine(engine, f);
if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) {
delete engine;
engine = 0;
}
return engine;
}
QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
QFontEngineFT *engine = static_cast<QFontEngineFT*>(QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference));
if (engine == 0)
return 0;
setupFontEngine(engine, engine->fontDef);
return engine;
}
QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
QStringList fallbackFamilies;
FcPattern *pattern = FcPatternCreate();
if (!pattern)
return fallbackFamilies;
FcValue value;
value.type = FcTypeString;
QByteArray cs = family.toUtf8();
value.u.s = (const FcChar8 *)cs.data();
FcPatternAdd(pattern,FC_FAMILY,value,true);
int slant_value = FC_SLANT_ROMAN;
if (style == QFont::StyleItalic)
slant_value = FC_SLANT_ITALIC;
else if (style == QFont::StyleOblique)
slant_value = FC_SLANT_OBLIQUE;
FcPatternAddInteger(pattern, FC_SLANT, slant_value);
Q_ASSERT(uint(script) < QChar::ScriptCount);
if (*specialLanguages[script] != '\0') {
FcLangSet *ls = FcLangSetCreate();
FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
FcPatternAddLangSet(pattern, FC_LANG, ls);
FcLangSetDestroy(ls);
} else if (!family.isEmpty()) {
// If script is Common or Han, then it may include languages like CJK,
// we should attach system default language set to the pattern
// to obtain correct font fallback list (i.e. if LANG=zh_CN
// then we normally want to use a Chinese font for CJK text;
// while a Japanese font should be used for that if LANG=ja)
FcPattern *dummy = FcPatternCreate();
FcDefaultSubstitute(dummy);
FcChar8 *lang = 0;
FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
if (res == FcResultMatch)
FcPatternAddString(pattern, FC_LANG, lang);
FcPatternDestroy(dummy);
}
const char *stylehint = getFcFamilyForStyleHint(styleHint);
if (stylehint) {
value.u.s = (const FcChar8 *)stylehint;
FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
}
FcConfigSubstitute(0, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
FcResult result = FcResultMatch;
FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result);
FcPatternDestroy(pattern);
if (fontSet) {
for (int i = 0; i < fontSet->nfont; i++) {
FcChar8 *value = 0;
if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
continue;
// capitalize(value);
QString familyName = QString::fromUtf8((const char *)value);
if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) &&
familyName.compare(family, Qt::CaseInsensitive)) {
fallbackFamilies << familyName;
}
}
FcFontSetDestroy(fontSet);
}
// qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies;
return fallbackFamilies;
}
static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count)
{
#if FC_VERSION < 20402
Q_UNUSED(data)
return FcFreeTypeQuery(file, id, blanks, count);
#else
if (data.isEmpty())
return FcFreeTypeQuery(file, id, blanks, count);
FT_Library lib = qt_getFreetype();
FcPattern *pattern = 0;
FT_Face face;
if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) {
*count = face->num_faces;
pattern = FcFreeTypeQueryFace(face, file, id, blanks);
FT_Done_Face(face);
}
return pattern;
#endif
}
QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
{
QStringList families;
FcFontSet *set = FcConfigGetFonts(0, FcSetApplication);
if (!set) {
FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent");
set = FcConfigGetFonts(0, FcSetApplication); // try again
if (!set)
return families;
}
int id = 0;
FcBlanks *blanks = FcConfigGetBlanks(0);
int count = 0;
FcPattern *pattern;
do {
pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(),
fontData, id, blanks, &count);
if (!pattern)
return families;
FcChar8 *fam = 0;
if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
if (family == QLatin1String("Open Sans")) {
FcChar8 *styl = 0;
if (FcPatternGetString(pattern, FC_STYLE, 0, &styl) == FcResultMatch) {
QString style = QString::fromUtf8(reinterpret_cast<const char *>(styl));
if (style == QLatin1String("Semibold")) {
family.append(QChar(QChar::Space)).append(style);
}
}
}
families << family;
}
populateFromPattern(pattern);
FcFontSetAdd(set, pattern);
++id;
} while (id < count);
return families;
}
QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const
{
QString resolved = QBasicFontDatabase::resolveFontFamilyAlias(family);
if (!resolved.isEmpty() && resolved != family)
return resolved;
FcPattern *pattern = FcPatternCreate();
if (!pattern)
return family;
if (!family.isEmpty()) {
QByteArray cs = family.toUtf8();
FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData());
}
FcConfigSubstitute(0, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
FcChar8 *familyAfterSubstitution = 0;
FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
resolved = QString::fromUtf8((const char *) familyAfterSubstitution);
FcPatternDestroy(pattern);
return resolved;
}
QFont QFontconfigDatabase::defaultFont() const
{
// Hack to get system default language until FcGetDefaultLangs()
// is exported (https://bugs.freedesktop.org/show_bug.cgi?id=32853)
// or https://bugs.freedesktop.org/show_bug.cgi?id=35482 is fixed
FcPattern *dummy = FcPatternCreate();
FcDefaultSubstitute(dummy);
FcChar8 *lang = 0;
FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
FcPattern *pattern = FcPatternCreate();
if (res == FcResultMatch) {
// Make defaultFont pattern matching locale language aware, because
// certain FC_LANG based custom rules may happen in FcConfigSubstitute()
FcPatternAddString(pattern, FC_LANG, lang);
}
FcConfigSubstitute(0, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
FcChar8 *familyAfterSubstitution = 0;
FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution);
FcPatternDestroy(pattern);
FcPatternDestroy(dummy);
return QFont(resolved);
}
void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const
{
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
bool forcedAntialiasSetting = !antialias;
const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY"));
if (useXftConf) {
void *antialiasResource =
QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
QGuiApplication::primaryScreen());
int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource));
if (antialiasingEnabled > 0)
antialias = antialiasingEnabled - 1;
}
QFontEngine::GlyphFormat format;
// try and get the pattern
FcPattern *pattern = FcPatternCreate();
FcValue value;
value.type = FcTypeString;
QByteArray cs = fontDef.family.toUtf8();
value.u.s = (const FcChar8 *)cs.data();
FcPatternAdd(pattern,FC_FAMILY,value,true);
QFontEngine::FaceId fid = engine->faceId();
if (!fid.filename.isEmpty()) {
value.u.s = (const FcChar8 *)fid.filename.data();
FcPatternAdd(pattern,FC_FILE,value,true);
value.type = FcTypeInteger;
value.u.i = fid.index;
FcPatternAdd(pattern,FC_INDEX,value,true);
}
if (fontDef.pixelSize > 0.1)
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
FcResult result;
FcConfigSubstitute(0, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
FcPattern *match = FcFontMatch(0, pattern, &result);
if (match) {
engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf));
FcBool fc_autohint;
if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
engine->forceAutoHint = fc_autohint;
#if defined(FT_LCD_FILTER_H)
int lcdFilter;
if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
engine->lcdFilterType = lcdFilter;
#endif
if (!forcedAntialiasSetting) {
FcBool fc_antialias;
if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
antialias = fc_antialias;
}
if (antialias) {
QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
subpixelType = subpixelTypeFromMatch(match, useXftConf);
engine->subpixelType = subpixelType;
format = (subpixelType == QFontEngine::Subpixel_None)
? QFontEngine::Format_A8
: QFontEngine::Format_A32;
} else
format = QFontEngine::Format_Mono;
FcPatternDestroy(match);
} else
format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono;
FcPatternDestroy(pattern);
engine->antialias = antialias;
engine->defaultFormat = format;
engine->glyphFormat = format;
}
QT_END_NAMESPACE

View file

@ -1,900 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qglobal.h"
#if defined(Q_OS_MACX)
#import <Cocoa/Cocoa.h>
#import <IOKit/graphics/IOGraphicsLib.h>
#elif defined(Q_OS_IOS)
#import <UIKit/UIFont.h>
#endif
#include "qcoretextfontdatabase_p.h"
#include "qfontengine_coretext_p.h"
#include <QtCore/QSettings>
#include <QtGui/QGuiApplication>
#include <QtCore/QtEndian>
QT_BEGIN_NAMESPACE
namespace {
class AutoReleasePool
{
public:
AutoReleasePool(): pool([[NSAutoreleasePool alloc] init]) {}
~AutoReleasePool() { [pool release]; }
private:
NSAutoreleasePool *pool;
};
}
// this could become a list of all languages used for each writing
// system, instead of using the single most common language.
static const char *languageForWritingSystem[] = {
0, // Any
"en", // Latin
"el", // Greek
"ru", // Cyrillic
"hy", // Armenian
"he", // Hebrew
"ar", // Arabic
"syr", // Syriac
"div", // Thaana
"hi", // Devanagari
"bn", // Bengali
"pa", // Gurmukhi
"gu", // Gujarati
"or", // Oriya
"ta", // Tamil
"te", // Telugu
"kn", // Kannada
"ml", // Malayalam
"si", // Sinhala
"th", // Thai
"lo", // Lao
"bo", // Tibetan
"my", // Myanmar
"ka", // Georgian
"km", // Khmer
"zh-Hans", // SimplifiedChinese
"zh-Hant", // TraditionalChinese
"ja", // Japanese
"ko", // Korean
"vi", // Vietnamese
0, // Symbol
"sga", // Ogham
"non", // Runic
"man" // N'Ko
};
enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) };
#ifdef Q_OS_OSX
static NSInteger languageMapSort(id obj1, id obj2, void *context)
{
NSArray *map1 = (NSArray *) obj1;
NSArray *map2 = (NSArray *) obj2;
NSArray *languages = (NSArray *) context;
NSString *lang1 = [map1 objectAtIndex: 0];
NSString *lang2 = [map2 objectAtIndex: 0];
return [languages indexOfObject: lang1] - [languages indexOfObject: lang2];
}
#endif
QCoreTextFontDatabase::QCoreTextFontDatabase()
{
#ifdef Q_OS_MACX
QSettings appleSettings(QLatin1String("apple.com"));
QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
if (appleValue.isValid())
QCoreTextFontEngine::antialiasingThreshold = appleValue.toInt();
/*
font_smoothing = 0 means no smoothing, while 1-3 means subpixel
antialiasing with different hinting styles (but we don't care about the
exact value, only if subpixel rendering is available or not)
*/
int font_smoothing = 0;
appleValue = appleSettings.value(QLatin1String("AppleFontSmoothing"));
if (appleValue.isValid()) {
font_smoothing = appleValue.toInt();
} else {
// non-Apple displays do not provide enough information about subpixel rendering so
// draw text with cocoa and compare pixel colors to see if subpixel rendering is enabled
int w = 10;
int h = 10;
NSRect rect = NSMakeRect(0.0, 0.0, w, h);
NSImage *fontImage = [[NSImage alloc] initWithSize:NSMakeSize(w, h)];
[fontImage lockFocus];
[[NSColor whiteColor] setFill];
NSRectFill(rect);
NSString *str = @"X\\";
NSFont *font = [NSFont fontWithName:@"Helvetica" size:10.0];
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
[attrs setObject:font forKey:NSFontAttributeName];
[attrs setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
[str drawInRect:rect withAttributes:attrs];
NSBitmapImageRep *nsBitmapImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect:rect];
[fontImage unlockFocus];
float red, green, blue;
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
NSColor *pixelColor = [nsBitmapImage colorAtX:x y:y];
red = [pixelColor redComponent];
green = [pixelColor greenComponent];
blue = [pixelColor blueComponent];
if (red != green || red != blue)
font_smoothing = 1;
}
}
[nsBitmapImage release];
[fontImage release];
}
QCoreTextFontEngine::defaultGlyphFormat = (font_smoothing > 0
? QFontEngine::Format_A32
: QFontEngine::Format_A8);
#else
QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A8;
#endif
}
QCoreTextFontDatabase::~QCoreTextFontDatabase()
{
foreach (CTFontDescriptorRef ref, m_systemFontDescriptors)
CFRelease(ref);
}
static CFArrayRef availableFamilyNames()
{
#if defined(Q_OS_OSX)
return CTFontManagerCopyAvailableFontFamilyNames();
#elif defined(Q_OS_IOS)
return (CFArrayRef) [[UIFont familyNames] retain];
#endif
}
void QCoreTextFontDatabase::populateFontDatabase()
{
// The caller (QFontDB) expects the db to be populate only with system fonts, so we need
// to make sure that any previously registered app fonts become invisible.
removeApplicationFonts();
QCFType<CFArrayRef> familyNames = availableFamilyNames();
const int numberOfFamilies = CFArrayGetCount(familyNames);
for (int i = 0; i < numberOfFamilies; ++i) {
CFStringRef familyNameRef = (CFStringRef) CFArrayGetValueAtIndex(familyNames, i);
QString familyName = QCFString::toQString(familyNameRef);
// Don't populate internal fonts
if (familyName.startsWith(QLatin1Char('.')) || familyName == QLatin1String("LastResort"))
continue;
QPlatformFontDatabase::registerFontFamily(familyName);
#if defined(Q_OS_OSX)
QString localizedFamilyName = QString::fromNSString([[NSFontManager sharedFontManager] localizedNameForFamily:(NSString*)familyNameRef face:nil]);
if (familyName != localizedFamilyName)
QPlatformFontDatabase::registerAliasToFontFamily(familyName, localizedFamilyName);
#endif
}
// Force creating the theme fonts to get the descriptors in m_systemFontDescriptors
if (m_themeFonts.isEmpty())
(void)themeFonts();
Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors)
populateFromDescriptor(fontDesc);
}
void QCoreTextFontDatabase::populateFamily(const QString &familyName)
{
QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(familyName));
QCFType<CTFontDescriptorRef> nameOnlyDescriptor = CTFontDescriptorCreateWithAttributes(attributes);
// A single family might match several different fonts with different styles eg.
QCFType<CFArrayRef> matchingFonts = (CFArrayRef) CTFontDescriptorCreateMatchingFontDescriptors(nameOnlyDescriptor, 0);
if (!matchingFonts) {
qWarning() << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName;
return;
}
const int numFonts = CFArrayGetCount(matchingFonts);
for (int i = 0; i < numFonts; ++i)
populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)));
}
struct FontDescription {
QCFString familyName;
QCFString styleName;
QString foundryName;
QFont::Weight weight;
QFont::Style style;
QFont::Stretch stretch;
int pixelSize;
bool fixedPitch;
QSupportedWritingSystems writingSystems;
};
static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
{
QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
fd->foundryName = QStringLiteral("CoreText");
fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
QCFString _displayName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute);
if (_displayName == QStringLiteral("Open Sans Semibold")) {
fd->familyName = _displayName;
}
fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute);
fd->weight = QFont::Normal;
fd->style = QFont::StyleNormal;
fd->stretch = QFont::Unstretched;
fd->fixedPitch = false;
if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
uint tag = MAKE_TAG('O', 'S', '/', '2');
CTFontRef tempFontRef = tempFont;
void *userData = reinterpret_cast<void *>(&tempFontRef);
uint length = 128;
QVarLengthArray<uchar, 128> os2Table(length);
if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length) && length >= 86) {
if (length > uint(os2Table.length())) {
os2Table.resize(length);
if (!QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length))
Q_UNREACHABLE();
Q_ASSERT(length >= 86);
}
quint32 unicodeRange[4] = {
qFromBigEndian<quint32>(os2Table.data() + 42),
qFromBigEndian<quint32>(os2Table.data() + 46),
qFromBigEndian<quint32>(os2Table.data() + 50),
qFromBigEndian<quint32>(os2Table.data() + 54)
};
quint32 codePageRange[2] = {
qFromBigEndian<quint32>(os2Table.data() + 78),
qFromBigEndian<quint32>(os2Table.data() + 82)
};
fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
}
}
if (styles) {
if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
float normalizedWeight;
if (CFNumberGetValue(weightValue, kCFNumberFloatType, &normalizedWeight))
fd->weight = QCoreTextFontEngine::qtWeightFromCFWeight(normalizedWeight);
}
if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
double d;
if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
if (d > 0.0)
fd->style = QFont::StyleItalic;
}
}
if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
int d;
if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
if (d & kCTFontMonoSpaceTrait)
fd->fixedPitch = true;
if (d & kCTFontExpandedTrait)
fd->stretch = QFont::Expanded;
else if (d & kCTFontCondensedTrait)
fd->stretch = QFont::Condensed;
}
}
}
if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
if (CFNumberIsFloatType(size)) {
double d;
CFNumberGetValue(size, kCFNumberDoubleType, &d);
fd->pixelSize = d;
} else {
CFNumberGetValue(size, kCFNumberIntType, &fd->pixelSize);
}
}
if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
CFIndex length = CFArrayGetCount(languages);
for (int i = 1; i < LanguageCount; ++i) {
if (!languageForWritingSystem[i])
continue;
QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
fd->writingSystems.setSupported(QFontDatabase::WritingSystem(i));
}
}
}
void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
{
FontDescription fd;
getFontDescription(font, &fd);
CFRetain(font);
QPlatformFontDatabase::registerFont(fd.familyName, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
true /* antialiased */, true /* scalable */,
fd.pixelSize, fd.fixedPitch, fd.writingSystems, (void *) font);
}
void QCoreTextFontDatabase::releaseHandle(void *handle)
{
CFRelease(CTFontDescriptorRef(handle));
}
extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
qreal scaledPointSize = f.pixelSize;
// When 96 DPI is forced, the Mac plugin will use DPI 72 for some
// fonts (hardcoded in qcocoaintegration.mm) and 96 for others. This
// discrepancy makes it impossible to find the correct point size
// here without having the DPI used for the font. Until a proper
// solution (requiring API change) can be made, we simply fall back
// to passing in the point size to retain old behavior.
if (QGuiApplication::testAttribute(Qt::AA_Use96Dpi))
scaledPointSize = f.pointSize;
CTFontDescriptorRef descriptor = (CTFontDescriptorRef) usrPtr;
CGAffineTransform matrix = qt_transform_from_fontdef(f);
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix);
if (font) {
QFontEngine *engine = new QCoreTextFontEngine(font, f);
engine->fontDef = f;
CFRelease(font);
return engine;
}
return NULL;
}
static void releaseFontData(void* info, const void* data, size_t size)
{
Q_UNUSED(data);
Q_UNUSED(size);
delete (QByteArray*)info;
}
QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
Q_UNUSED(hintingPreference);
QByteArray* fontDataCopy = new QByteArray(fontData);
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy,
fontDataCopy->constData(), fontDataCopy->size(), releaseFontData);
CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider);
QFontEngine *fontEngine = NULL;
if (cgFont == NULL) {
qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed");
} else {
QFontDef def;
def.pixelSize = pixelSize;
def.pointSize = pixelSize * 72.0 / qt_defaultDpi();
fontEngine = new QCoreTextFontEngine(cgFont, def);
CFRelease(cgFont);
}
return fontEngine;
}
QFont::StyleHint styleHintFromNSString(NSString *style)
{
if ([style isEqual: @"sans-serif"])
return QFont::SansSerif;
else if ([style isEqual: @"monospace"])
return QFont::Monospace;
else if ([style isEqual: @"cursive"])
return QFont::Cursive;
else if ([style isEqual: @"serif"])
return QFont::Serif;
else if ([style isEqual: @"fantasy"])
return QFont::Fantasy;
else // if ([style isEqual: @"default"])
return QFont::AnyStyle;
}
#ifdef Q_OS_OSX
static QString familyNameFromPostScriptName(NSString *psName)
{
QCFType<CTFontDescriptorRef> fontDescriptor = (CTFontDescriptorRef) CTFontDescriptorCreateWithNameAndSize((CFStringRef)psName, 12.0);
QCFString familyName = (CFStringRef) CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute);
QString name = QCFString::toQString(familyName);
if (name.isEmpty())
qWarning() << "QCoreTextFontDatabase: Failed to resolve family name for PostScript name " << QCFString::toQString((CFStringRef)psName);
return name;
}
#endif
QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
Q_UNUSED(style);
Q_UNUSED(script);
AutoReleasePool pool;
static QHash<QString, QStringList> fallbackLists;
if (!family.isEmpty()) {
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_6_0)
// CTFontCopyDefaultCascadeListForLanguages is available in the SDK
#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_8, __IPHONE_6_0)
// But we have to feature check at runtime
if (&CTFontCopyDefaultCascadeListForLanguages)
#endif
{
if (fallbackLists.contains(family))
return fallbackLists.value(family);
QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(family));
if (QCFType<CTFontDescriptorRef> fontDescriptor = CTFontDescriptorCreateWithAttributes(attributes)) {
if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(fontDescriptor, 12.0, 0)) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"];
QCFType<CFArrayRef> cascadeList = (CFArrayRef) CTFontCopyDefaultCascadeListForLanguages(font, (CFArrayRef) languages);
if (cascadeList) {
QStringList fallbackList;
const int numCascades = CFArrayGetCount(cascadeList);
for (int i = 0; i < numCascades; ++i) {
CTFontDescriptorRef fontFallback = (CTFontDescriptorRef) CFArrayGetValueAtIndex(cascadeList, i);
QCFString fallbackFamilyName = (CFStringRef) CTFontDescriptorCopyAttribute(fontFallback, kCTFontFamilyNameAttribute);
fallbackList.append(QCFString::toQString(fallbackFamilyName));
}
#if defined(Q_OS_OSX)
// Since we are only returning a list of default fonts for the current language, we do not
// cover all unicode completely. This was especially an issue for some of the common script
// symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk
// of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most
// of Unicode 2.1.
if (!fallbackList.contains(QStringLiteral("Arial Unicode MS")))
fallbackList.append(QStringLiteral("Arial Unicode MS"));
#endif
fallbackLists[family] = fallbackList;
}
}
if (fallbackLists.contains(family))
return fallbackLists.value(family);
}
}
#endif
}
// We were not able to find a fallback for the specific family,
// so we fall back to the stylehint.
static const QString styleLookupKey = QString::fromLatin1(".QFontStyleHint_%1");
static bool didPopulateStyleFallbacks = false;
if (!didPopulateStyleFallbacks) {
#if defined(Q_OS_MACX)
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"];
NSDictionary *fallbackDict = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist"];
for (NSString *style in [fallbackDict allKeys]) {
NSArray *list = [fallbackDict valueForKey: style];
QFont::StyleHint fallbackStyleHint = styleHintFromNSString(style);
QStringList fallbackList;
for (id item in list) {
// sort the array based on system language preferences
if ([item isKindOfClass: [NSArray class]]) {
NSArray *langs = [(NSArray *) item sortedArrayUsingFunction: languageMapSort
context: languages];
for (NSArray *map in langs)
fallbackList.append(familyNameFromPostScriptName([map objectAtIndex: 1]));
}
else if ([item isKindOfClass: [NSString class]])
fallbackList.append(familyNameFromPostScriptName(item));
}
if (QCoreTextFontEngine::supportsColorGlyphs())
fallbackList.append(QLatin1String("Apple Color Emoji"));
// Since we are only returning a list of default fonts for the current language, we do not
// cover all unicode completely. This was especially an issue for some of the common script
// symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk
// of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most
// of Unicode 2.1.
if (!fallbackList.contains(QStringLiteral("Arial Unicode MS")))
fallbackList.append(QStringLiteral("Arial Unicode MS"));
fallbackLists[styleLookupKey.arg(fallbackStyleHint)] = fallbackList;
}
#else
QStringList staticFallbackList;
staticFallbackList << QString::fromLatin1("Helvetica,Apple Color Emoji,Geeza Pro,Arial Hebrew,Thonburi,Kailasa"
"Hiragino Kaku Gothic ProN,.Heiti J,Apple SD Gothic Neo,.Heiti K,Heiti SC,Heiti TC"
"Bangla Sangam MN,Devanagari Sangam MN,Gujarati Sangam MN,Gurmukhi MN,Kannada Sangam MN"
"Malayalam Sangam MN,Oriya Sangam MN,Sinhala Sangam MN,Tamil Sangam MN,Telugu Sangam MN"
"Euphemia UCAS,.PhoneFallback").split(QLatin1String(","));
for (int i = QFont::Helvetica; i <= QFont::Fantasy; ++i)
fallbackLists[styleLookupKey.arg(i)] = staticFallbackList;
#endif
didPopulateStyleFallbacks = true;
}
Q_ASSERT(!fallbackLists.isEmpty());
return fallbackLists[styleLookupKey.arg(styleHint)];
}
#if HAVE_CORETEXT
static CFArrayRef createDescriptorArrayForFont(CTFontRef font)
{
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(array, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font)));
return array;
}
#endif
QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
{
QCFType<CFArrayRef> fonts;
QStringList families;
#if HAVE_CORETEXT
if (&CTFontManagerRegisterGraphicsFont) {
CFErrorRef error = 0;
if (!fontData.isEmpty()) {
QByteArray* fontDataCopy = new QByteArray(fontData);
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy,
fontDataCopy->constData(), fontDataCopy->size(), releaseFontData);
QCFType<CGFontRef> cgFont = CGFontCreateWithDataProvider(dataProvider);
if (cgFont) {
if (CTFontManagerRegisterGraphicsFont(cgFont, &error)) {
QCFType<CTFontRef> font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL);
fonts = createDescriptorArrayForFont(font);
m_applicationFonts.append(QVariant::fromValue(QCFType<CGFontRef>::constructFromGet(cgFont)));
}
}
} else {
QCFType<CFURLRef> fontURL = CFURLCreateWithFileSystemPath(NULL, QCFString(fileName), kCFURLPOSIXPathStyle, false);
if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error)) {
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_6, __IPHONE_7_0)
if (&CTFontManagerCreateFontDescriptorsFromURL)
fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL);
else
#endif
{
// We're limited to a single font per file, unless we dive into the font tables
QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL);
QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes);
QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL);
fonts = createDescriptorArrayForFont(font);
}
m_applicationFonts.append(QVariant::fromValue(QCFType<CFURLRef>::constructFromGet(fontURL)));
}
}
if (error) {
NSLog(@"Unable to register font: %@", error);
CFRelease(error);
}
}
#endif
#if HAVE_CORETEXT && HAVE_ATS
else
#endif
#if HAVE_ATS
{
ATSFontContainerRef fontContainer;
OSStatus e;
if (!fontData.isEmpty()) {
e = ATSFontActivateFromMemory((void *) fontData.constData(), fontData.size(),
kATSFontContextLocal, kATSFontFormatUnspecified, NULL,
kATSOptionFlagsDefault, &fontContainer);
} else {
FSRef ref;
OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref);
if (qt_mac_create_fsref(fileName, &ref) != noErr)
return QStringList();
e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0,
kATSOptionFlagsDefault, &fontContainer);
}
if (e == noErr) {
ItemCount fontCount = 0;
e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, 0, 0, &fontCount);
if (e != noErr)
return QStringList();
QVarLengthArray<ATSFontRef> containedFonts(fontCount);
e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount);
if (e != noErr)
return QStringList();
CFMutableArrayRef fontsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
for (int i = 0; i < containedFonts.size(); ++i) {
QCFType<CTFontRef> font = CTFontCreateWithPlatformFont(containedFonts[i], 12.0, NULL, NULL);
CFArrayAppendValue(fontsArray, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font)));
}
fonts = fontsArray;
m_applicationFonts.append(QVariant::fromValue(fontContainer));
}
}
#endif
if (fonts) {
const int numFonts = CFArrayGetCount(fonts);
for (int i = 0; i < numFonts; ++i) {
CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i));
populateFromDescriptor(fontDescriptor);
QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute));
families.append(QCFString(familyName));
}
}
return families;
}
bool QCoreTextFontDatabase::isPrivateFontFamily(const QString &family) const
{
if (family.startsWith(QLatin1Char('.')))
return true;
return QPlatformFontDatabase::isPrivateFontFamily(family);
}
static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
{
switch (f) {
case QPlatformTheme::SystemFont:
return kCTFontSystemFontType;
case QPlatformTheme::MenuFont:
case QPlatformTheme::MenuBarFont:
case QPlatformTheme::MenuItemFont:
return kCTFontMenuItemFontType;
case QPlatformTheme::MessageBoxFont:
return kCTFontEmphasizedSystemFontType;
case QPlatformTheme::LabelFont:
return kCTFontSystemFontType;
case QPlatformTheme::TipLabelFont:
return kCTFontToolTipFontType;
case QPlatformTheme::StatusBarFont:
return kCTFontSystemFontType;
case QPlatformTheme::TitleBarFont:
return kCTFontWindowTitleFontType;
case QPlatformTheme::MdiSubWindowTitleFont:
case QPlatformTheme::DockWidgetTitleFont:
return kCTFontSystemFontType;
case QPlatformTheme::PushButtonFont:
return kCTFontPushButtonFontType;
case QPlatformTheme::CheckBoxFont:
case QPlatformTheme::RadioButtonFont:
return kCTFontSystemFontType;
case QPlatformTheme::ToolButtonFont:
return kCTFontSmallToolbarFontType;
case QPlatformTheme::ItemViewFont:
return kCTFontSystemFontType;
case QPlatformTheme::ListViewFont:
return kCTFontViewsFontType;
case QPlatformTheme::HeaderViewFont:
return kCTFontSmallSystemFontType;
case QPlatformTheme::ListBoxFont:
return kCTFontViewsFontType;
case QPlatformTheme::ComboMenuItemFont:
return kCTFontSystemFontType;
case QPlatformTheme::ComboLineEditFont:
return kCTFontViewsFontType;
case QPlatformTheme::SmallFont:
return kCTFontSmallSystemFontType;
case QPlatformTheme::MiniFont:
return kCTFontMiniSystemFontType;
case QPlatformTheme::FixedFont:
return kCTFontUserFixedPitchFontType;
default:
return kCTFontSystemFontType;
}
}
static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f)
{
#ifdef Q_OS_IOS
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
// Use Dynamic Type to resolve theme fonts if possible, to get
// correct font sizes and style based on user configuration.
NSString *textStyle = 0;
switch (f) {
case QPlatformTheme::TitleBarFont:
case QPlatformTheme::HeaderViewFont:
textStyle = UIFontTextStyleHeadline;
break;
case QPlatformTheme::MdiSubWindowTitleFont:
textStyle = UIFontTextStyleSubheadline;
break;
case QPlatformTheme::TipLabelFont:
case QPlatformTheme::SmallFont:
textStyle = UIFontTextStyleFootnote;
break;
case QPlatformTheme::MiniFont:
textStyle = UIFontTextStyleCaption2;
break;
case QPlatformTheme::FixedFont:
// Fall back to regular code path, as iOS doesn't provide
// an appropriate text style for this theme font.
break;
default:
textStyle = UIFontTextStyleBody;
break;
}
if (textStyle) {
UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc));
}
}
#endif // Q_OS_IOS
// OSX default case and iOS fallback case
CTFontUIFontType fontType = fontTypeFromTheme(f);
QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL);
return CTFontCopyFontDescriptor(ctFont);
}
const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const
{
if (m_themeFonts.isEmpty()) {
for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) {
QPlatformTheme::Font ft = static_cast<QPlatformTheme::Font>(f);
m_themeFonts.insert(ft, themeFont(ft));
}
}
return m_themeFonts;
}
QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
{
CTFontDescriptorRef fontDesc = fontDescriptorFromTheme(f);
FontDescription fd;
getFontDescription(fontDesc, &fd);
if (!m_systemFontDescriptors.contains(fontDesc))
m_systemFontDescriptors.insert(fontDesc);
else
CFRelease(fontDesc);
QFont *font = new QFont(fd.familyName, fd.pixelSize, fd.weight, fd.style == QFont::StyleItalic);
return font;
}
QFont QCoreTextFontDatabase::defaultFont() const
{
if (defaultFontName.isEmpty()) {
QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 12.0, NULL);
defaultFontName = (QString) QCFString(CTFontCopyFullName(font));
}
return QFont(defaultFontName);
}
bool QCoreTextFontDatabase::fontsAlwaysScalable() const
{
return true;
}
QList<int> QCoreTextFontDatabase::standardSizes() const
{
QList<int> ret;
static const unsigned short standard[] =
{ 9, 10, 11, 12, 13, 14, 18, 24, 36, 48, 64, 72, 96, 144, 288, 0 };
ret.reserve(int(sizeof(standard) / sizeof(standard[0])));
const unsigned short *sizes = standard;
while (*sizes) ret << *sizes++;
return ret;
}
void QCoreTextFontDatabase::removeApplicationFonts()
{
if (m_applicationFonts.isEmpty())
return;
foreach (const QVariant &font, m_applicationFonts) {
#if HAVE_CORETEXT
if (&CTFontManagerUnregisterGraphicsFont && &CTFontManagerUnregisterFontsForURL) {
CFErrorRef error;
if (font.canConvert(qMetaTypeId<QCFType<CGFontRef> >())) {
CTFontManagerUnregisterGraphicsFont(font.value<QCFType<CGFontRef> >(), &error);
} else if (font.canConvert(qMetaTypeId<QCFType<CFURLRef> >())) {
CTFontManagerUnregisterFontsForURL(font.value<QCFType<CFURLRef> >(), kCTFontManagerScopeProcess, &error);
}
}
#endif
#if HAVE_CORETEXT && HAVE_ATS
else
#endif
#if HAVE_ATS
if (font.canConvert(qMetaTypeId<ATSFontContainerRef>())) {
ATSFontDeactivate(font.value<ATSFontContainerRef>(), 0, kATSOptionFlagsDoNotNotify);
}
#endif
}
m_applicationFonts.clear();
#if HAVE_ATS
ATSFontNotify(kATSFontNotifyActionFontsChanged, 0);
#endif
}
QT_END_NAMESPACE

View file

@ -1,29 +0,0 @@
TARGET = composeplatforminputcontextplugin
PLUGIN_TYPE = platforminputcontexts
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QComposePlatformInputContextPlugin
load(qt_plugin)
QT += gui-private
DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"'
SOURCES += $$PWD/qcomposeplatforminputcontextmain.cpp \
$$PWD/qcomposeplatforminputcontext.cpp \
$$PWD/generator/qtablegenerator.cpp \
HEADERS += $$PWD/qcomposeplatforminputcontext.h \
$$PWD/generator/qtablegenerator.h \
# libxkbcommon
contains(QT_CONFIG, xkbcommon-qt): {
# dont't need x11 dependency for compose key plugin
QT_CONFIG -= use-xkbcommon-x11support
# include(../../../3rdparty/xkbcommon.pri)
} else {
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
}
OTHER_FILES += $$PWD/compose.json

View file

@ -1,38 +0,0 @@
TARGET = fcitxplatforminputcontextplugin
PLUGIN_TYPE = platforminputcontexts
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QFcitxPlatformInputContextPlugin
load(qt_plugin)
QT += dbus gui-private
SOURCES += $$PWD/fcitxqtconnection.cpp \
$$PWD/fcitxqtformattedpreedit.cpp \
$$PWD/fcitxqtinputcontextproxy.cpp \
$$PWD/fcitxqtinputmethoditem.cpp \
$$PWD/fcitxqtinputmethodproxy.cpp \
$$PWD/fcitxqtkeyboardlayout.cpp \
$$PWD/fcitxqtkeyboardproxy.cpp \
$$PWD/keyuni.cpp \
$$PWD/main.cpp \
$$PWD/qfcitxplatforminputcontext.cpp \
$$PWD/utils.cpp
HEADERS += $$PWD/fcitxqtconnection.h \
$$PWD/fcitxqtconnection_p.h \
$$PWD/fcitxqtdbusaddons_export.h \
$$PWD/fcitxqtdbusaddons_version.h \
$$PWD/fcitxqtformattedpreedit.h \
$$PWD/fcitxqtinputcontextproxy.h \
$$PWD/fcitxqtinputmethoditem.h \
$$PWD/fcitxqtinputmethodproxy.h \
$$PWD/fcitxqtkeyboardlayout.h \
$$PWD/fcitxqtkeyboardproxy.h \
$$PWD/keydata.h \
$$PWD/keyserver_x11.h \
$$PWD/keyuni.h \
$$PWD/main.h \
$$PWD/qfcitxplatforminputcontext.h \
$$PWD/utils.h
OTHER_FILES += $$PWD/fcitx.json

View file

@ -1,369 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "fcitxqtconnection_p.h"
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QDBusReply>
#include <QDBusConnectionInterface>
#include <QDebug>
#include <QFile>
#include <QTimer>
#include <QDir>
#include <signal.h>
#include <errno.h>
// utils function in fcitx-utils and fcitx-config
bool _pid_exists(pid_t pid) {
if (pid <= 0)
return 0;
return !(kill(pid, 0) && (errno == ESRCH));
}
FcitxQtConnection::FcitxQtConnection(QObject* parent): QObject(parent)
,d_ptr(new FcitxQtConnectionPrivate(this))
{
}
void FcitxQtConnection::startConnection()
{
Q_D(FcitxQtConnection);
if (!d->m_initialized) {
d->initialize();
d->createConnection();
}
}
void FcitxQtConnection::endConnection()
{
Q_D(FcitxQtConnection);
d->cleanUp();
d->finalize();
d->m_connectedOnce = false;
}
bool FcitxQtConnection::autoReconnect()
{
Q_D(FcitxQtConnection);
return d->m_autoReconnect;
}
void FcitxQtConnection::setAutoReconnect(bool a)
{
Q_D(FcitxQtConnection);
d->m_autoReconnect = a;
}
QDBusConnection* FcitxQtConnection::connection()
{
Q_D(FcitxQtConnection);
return d->m_connection;
}
const QString& FcitxQtConnection::serviceName()
{
Q_D(FcitxQtConnection);
return d->m_serviceName;
}
bool FcitxQtConnection::isConnected()
{
Q_D(FcitxQtConnection);
return d->isConnected();
}
FcitxQtConnection::~FcitxQtConnection()
{
}
FcitxQtConnectionPrivate::FcitxQtConnectionPrivate(FcitxQtConnection* conn) : QObject(conn)
,q_ptr(conn)
,m_displayNumber(-1)
,m_serviceName(QString("%1-%2").arg("org.fcitx.Fcitx").arg(displayNumber()))
,m_connection(0)
,m_serviceWatcher(new QDBusServiceWatcher(conn))
,m_watcher(new QFileSystemWatcher(this))
,m_autoReconnect(true)
,m_connectedOnce(false)
,m_initialized(false)
{
}
FcitxQtConnectionPrivate::~FcitxQtConnectionPrivate()
{
if (m_connection)
delete m_connection;
}
void FcitxQtConnectionPrivate::initialize() {
m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
m_serviceWatcher->addWatchedService(m_serviceName);
QFileInfo info(socketFile());
QDir dir(info.path());
if (!dir.exists()) {
QDir rt(QDir::root());
rt.mkpath(info.path());
}
m_watcher->addPath(info.path());
if (info.exists()) {
m_watcher->addPath(info.filePath());
}
connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(socketFileChanged()));
connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(socketFileChanged()));
m_initialized = true;
}
void FcitxQtConnectionPrivate::finalize() {
m_serviceWatcher->removeWatchedService(m_serviceName);
m_watcher->removePaths(m_watcher->files());
m_watcher->removePaths(m_watcher->directories());
m_watcher->disconnect(SIGNAL(fileChanged(QString)));
m_watcher->disconnect(SIGNAL(directoryChanged(QString)));
m_initialized = false;
}
void FcitxQtConnectionPrivate::socketFileChanged() {
QFileInfo info(socketFile());
if (info.exists()) {
if (m_watcher->files().indexOf(info.filePath()) == -1)
m_watcher->addPath(info.filePath());
}
QString addr = address();
if (addr.isNull())
return;
cleanUp();
createConnection();
}
QByteArray FcitxQtConnectionPrivate::localMachineId()
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
return QDBusConnection::localMachineId();
#else
QFile file1("/var/lib/dbus/machine-id");
QFile file2("/etc/machine-id");
QFile* fileToRead = NULL;
if (file1.open(QIODevice::ReadOnly)) {
fileToRead = &file1;
}
else if (file2.open(QIODevice::ReadOnly)) {
fileToRead = &file2;
}
if (fileToRead) {
QByteArray result = fileToRead->readLine(1024);
fileToRead->close();
result = result.trimmed();
if (!result.isEmpty())
return result;
}
return "machine-id";
#endif
}
int FcitxQtConnectionPrivate::displayNumber() {
if (m_displayNumber < 0) {
QByteArray displayNumber("0");
QByteArray display(qgetenv("DISPLAY"));
int pos = display.indexOf(':');
if (pos >= 0) {
++pos;
int pos2 = display.indexOf('.', pos);
if (pos2 > 0) {
displayNumber = display.mid(pos, pos2 - pos);
} else {
displayNumber = display.mid(pos);
}
}
bool ok;
int d = displayNumber.toInt(&ok);
if (ok) {
m_displayNumber = d;
} else {
m_displayNumber = 0;
}
}
return m_displayNumber;
}
const QString& FcitxQtConnectionPrivate::socketFile()
{
if (!m_socketFile.isEmpty())
return m_socketFile;
QString filename = QString("%1-%2").arg(QString::fromLatin1(QDBusConnection::localMachineId())).arg(displayNumber());
QString home = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME"));
if (home.isEmpty()) {
home = QDir::homePath().append(QLatin1Literal("/.config"));
}
m_socketFile = QString("%1/fcitx/dbus/%2").arg(home).arg(filename);
return m_socketFile;
}
QString FcitxQtConnectionPrivate::address()
{
QString addr;
QByteArray addrVar = qgetenv("FCITX_DBUS_ADDRESS");
if (!addrVar.isNull())
return QString::fromLocal8Bit(addrVar);
QFile file(socketFile());
if (!file.open(QIODevice::ReadOnly))
return QString();
const int BUFSIZE = 1024;
char buffer[BUFSIZE];
size_t sz = file.read(buffer, BUFSIZE);
file.close();
if (sz == 0)
return QString();
char* p = buffer;
while(*p)
p++;
size_t addrlen = p - buffer;
if (sz != addrlen + 2 * sizeof(pid_t) + 1)
return QString();
/* skip '\0' */
p++;
pid_t *ppid = (pid_t*) p;
pid_t daemonpid = ppid[0];
pid_t fcitxpid = ppid[1];
if (!_pid_exists(daemonpid)
|| !_pid_exists(fcitxpid))
return QString();
addr = QLatin1String(buffer);
return addr;
}
void FcitxQtConnectionPrivate::createConnection() {
if (m_connectedOnce && !m_autoReconnect) {
return;
}
m_serviceWatcher->disconnect(SIGNAL(serviceOwnerChanged(QString,QString,QString)));
QString addr = address();
if (!addr.isNull()) {
QDBusConnection connection(QDBusConnection::connectToBus(addr, "fcitx"));
if (connection.isConnected()) {
// qDebug() << "create private";
m_connection = new QDBusConnection(connection);
}
else
QDBusConnection::disconnectFromBus("fcitx");
}
if (!m_connection) {
QDBusConnection* connection = new QDBusConnection(QDBusConnection::sessionBus());
connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(imChanged(QString,QString,QString)));
QDBusReply<bool> registered = connection->interface()->isServiceRegistered(m_serviceName);
if (!registered.isValid() || !registered.value()) {
delete connection;
}
else {
m_connection = connection;
}
}
Q_Q(FcitxQtConnection);
if (m_connection) {
m_connection->connect ("org.freedesktop.DBus.Local",
"/org/freedesktop/DBus/Local",
"org.freedesktop.DBus.Local",
"Disconnected",
this,
SLOT (dbusDisconnected ()));
m_connectedOnce = true;
emit q->connected();
}
}
void FcitxQtConnectionPrivate::dbusDisconnected()
{
cleanUp();
createConnection();
}
void FcitxQtConnectionPrivate::imChanged(const QString& service, const QString& oldowner, const QString& newowner)
{
if (service == m_serviceName) {
/* old die */
if (oldowner.length() > 0 || newowner.length() > 0)
cleanUp();
/* new rise */
if (newowner.length() > 0) {
QTimer::singleShot(100, this, SLOT(newServiceAppear()));
}
}
}
void FcitxQtConnectionPrivate::cleanUp()
{
Q_Q(FcitxQtConnection);
bool doemit = false;
QDBusConnection::disconnectFromBus("fcitx");
if (m_connection) {
delete m_connection;
m_connection = 0;
doemit = true;
}
if (!m_autoReconnect && m_connectedOnce)
finalize();
/* we want m_connection and finalize being called before the signal
* thus isConnected will return false in slot
* and startConnection can be called in slot
*/
if (doemit)
emit q->disconnected();
}
bool FcitxQtConnectionPrivate::isConnected()
{
return m_connection && m_connection->isConnected();
}
void FcitxQtConnectionPrivate::newServiceAppear() {
if (!isConnected()) {
cleanUp();
createConnection();
}
}

View file

@ -1,111 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITXQTCONNECTION_H
#define FCITXQTCONNECTION_H
#include "fcitxqtdbusaddons_export.h"
#include <QtCore/QObject>
class QDBusConnection;
class FcitxQtConnectionPrivate;
/**
* dbus connection to fcitx
**/
class FCITXQTDBUSADDONS_EXPORT FcitxQtConnection : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
Q_PROPERTY(bool connected READ isConnected)
Q_PROPERTY(QDBusConnection* connection READ connection)
Q_PROPERTY(QString serviceName READ serviceName)
public:
/**
* create a new connection
*
* @param parent
**/
explicit FcitxQtConnection(QObject* parent = 0);
/**
* destroy the connection
**/
virtual ~FcitxQtConnection();
/**
* the connection will not start to work until you call this function
* you may want to connect to the signal before you call this function
**/
void startConnection();
void endConnection();
/**
* automatically reconnect if fcitx disappeared
*
* @param a ...
* @return void
**/
void setAutoReconnect(bool a);
/**
* check this connection is doing automatical reconnect or not
*
* default value is true
**/
bool autoReconnect();
/**
* return the current dbus connection to fcitx, notice, the object return
* by this function might be deteled if fcitx disappear, or might return 0
* if fcitx is not running
*
* @return QDBusConnection*
**/
QDBusConnection* connection();
/**
* current fcitx dbus service name, can be used for create DBus proxy
*
* @return service name
**/
const QString& serviceName();
/**
* check its connected or not
**/
bool isConnected();
Q_SIGNALS:
/**
* this signal will be emitted upon fcitx appears
**/
void connected();
/**
* this signal will be emitted upon fcitx disappears
*
* it will come with connected in pair
**/
void disconnected();
private:
FcitxQtConnectionPrivate * const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtConnection);
};
#endif // FCITXCONNECTION_H

View file

@ -1,68 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITXQTCONNECTION_P_H
#define FCITXQTCONNECTION_P_H
#include "fcitxqtconnection.h"
#include <QtCore/QWeakPointer>
#include <QtCore/QFileSystemWatcher>
class QDBusConnection;
class QDBusServiceWatcher;
class FcitxQtConnectionPrivate : public QObject {
Q_OBJECT
public:
FcitxQtConnectionPrivate(FcitxQtConnection* conn);
virtual ~FcitxQtConnectionPrivate();
FcitxQtConnection * const q_ptr;
Q_DECLARE_PUBLIC(FcitxQtConnection);
private Q_SLOTS:
void imChanged(const QString& service, const QString& oldowner, const QString& newowner);
void dbusDisconnected();
void cleanUp();
void newServiceAppear();
void socketFileChanged();
private:
bool isConnected();
static QByteArray localMachineId();
const QString& socketFile();
void createConnection();
QString address();
int displayNumber();
void initialize();
void finalize();
int m_displayNumber;
QString m_serviceName;
QDBusConnection* m_connection;
QDBusServiceWatcher* m_serviceWatcher;
QFileSystemWatcher* m_watcher;
QString m_socketFile;
bool m_autoReconnect;
bool m_connectedOnce;
bool m_initialized;
};
#endif // FCITXCONNECTION_P_H

View file

@ -1,41 +0,0 @@
#ifndef FCITXQTDBUSADDONS_EXPORT_H
#define FCITXQTDBUSADDONS_EXPORT_H
#ifdef FCITXQTDBUSADDONS_STATIC_DEFINE
# define FCITXQTDBUSADDONS_EXPORT
# define FCITXQTDBUSADDONS_NO_EXPORT
#else
# ifndef FCITXQTDBUSADDONS_EXPORT
# ifdef FcitxQt5DBusAddons_EXPORTS
/* We are building this library */
# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default")))
# else
/* We are using this library */
# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default")))
# endif
# endif
# ifndef FCITXQTDBUSADDONS_NO_EXPORT
# define FCITXQTDBUSADDONS_NO_EXPORT __attribute__((visibility("hidden")))
# endif
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED
# define FCITXQTDBUSADDONS_DEPRECATED __attribute__ ((__deprecated__))
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED_EXPORT
# define FCITXQTDBUSADDONS_DEPRECATED_EXPORT FCITXQTDBUSADDONS_EXPORT FCITXQTDBUSADDONS_DEPRECATED
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT
# define FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT FCITXQTDBUSADDONS_NO_EXPORT FCITXQTDBUSADDONS_DEPRECATED
#endif
#define DEFINE_NO_DEPRECATED 0
#if DEFINE_NO_DEPRECATED
# define FCITXQTDBUSADDONS_NO_DEPRECATED
#endif
#endif

View file

@ -1,11 +0,0 @@
#ifndef FCITXQT5DBUSADDONS_VERSION_H
#define FCITXQT5DBUSADDONS_VERSION_H
#define FCITXQT5DBUSADDONS_VERSION_STRING "1.0.0"
#define FCITXQT5DBUSADDONS_VERSION_MAJOR 1
#define FCITXQT5DBUSADDONS_VERSION_MINOR 0
#define FCITXQT5DBUSADDONS_VERSION_PATCH 0
#define FCITXQT5DBUSADDONS_VERSION ((1<<16)|(0<<8)|(0))
#endif

View file

@ -1,78 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <QDBusMetaType>
#include "fcitxqtformattedpreedit.h"
void FcitxQtFormattedPreedit::registerMetaType()
{
qRegisterMetaType<FcitxQtFormattedPreedit>("FcitxQtFormattedPreedit");
qDBusRegisterMetaType<FcitxQtFormattedPreedit>();
qRegisterMetaType<FcitxQtFormattedPreeditList>("FcitxQtFormattedPreeditList");
qDBusRegisterMetaType<FcitxQtFormattedPreeditList>();
}
qint32 FcitxQtFormattedPreedit::format() const
{
return m_format;
}
const QString& FcitxQtFormattedPreedit::string() const
{
return m_string;
}
void FcitxQtFormattedPreedit::setFormat(qint32 format)
{
m_format = format;
}
void FcitxQtFormattedPreedit::setString(const QString& str)
{
m_string = str;
}
bool FcitxQtFormattedPreedit::operator==(const FcitxQtFormattedPreedit& preedit) const
{
return (preedit.m_format == m_format) && (preedit.m_string == m_string);
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtFormattedPreedit& preedit)
{
argument.beginStructure();
argument << preedit.string();
argument << preedit.format();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtFormattedPreedit& preedit)
{
QString str;
qint32 format;
argument.beginStructure();
argument >> str >> format;
argument.endStructure();
preedit.setString(str);
preedit.setFormat(format);
return argument;
}

View file

@ -1,51 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_FORMATTED_PREEDIT_H
#define FCITX_QT_FORMATTED_PREEDIT_H
#include "fcitxqtdbusaddons_export.h"
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtFormattedPreedit {
public:
const QString& string() const;
qint32 format() const;
void setString(const QString& str);
void setFormat(qint32 format);
static void registerMetaType();
bool operator ==(const FcitxQtFormattedPreedit& preedit) const;
private:
QString m_string;
qint32 m_format;
};
typedef QList<FcitxQtFormattedPreedit> FcitxQtFormattedPreeditList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtFormattedPreedit& im);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtFormattedPreedit& im);
Q_DECLARE_METATYPE(FcitxQtFormattedPreedit)
Q_DECLARE_METATYPE(FcitxQtFormattedPreeditList)
#endif

View file

@ -1,26 +0,0 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext.xml -i fcitxqtformattedpreedit.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtinputcontextproxy.h"
/*
* Implementation of interface class FcitxQtInputContextProxy
*/
FcitxQtInputContextProxy::FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtInputContextProxy::~FcitxQtInputContextProxy()
{
}

View file

@ -1,136 +0,0 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext.xml -i fcitxqtformattedpreedit.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTCONTEXTPROXY_H_1409252990
#define FCITXQTINPUTCONTEXTPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtformattedpreedit.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputContextProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputContext"; }
public:
FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtInputContextProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> CloseIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("CloseIC"), argumentList);
}
inline QDBusPendingReply<> DestroyIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("DestroyIC"), argumentList);
}
inline QDBusPendingReply<> EnableIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("EnableIC"), argumentList);
}
inline QDBusPendingReply<> FocusIn()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusIn"), argumentList);
}
inline QDBusPendingReply<> FocusOut()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusOut"), argumentList);
}
inline QDBusPendingReply<> MouseEvent(int x)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x);
return asyncCallWithArgumentList(QLatin1String("MouseEvent"), argumentList);
}
inline QDBusPendingReply<int> ProcessKeyEvent(uint keyval, uint keycode, uint state, int type, uint time)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval) << QVariant::fromValue(keycode) << QVariant::fromValue(state) << QVariant::fromValue(type) << QVariant::fromValue(time);
return asyncCallWithArgumentList(QLatin1String("ProcessKeyEvent"), argumentList);
}
inline QDBusPendingReply<> Reset()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapacity(uint caps)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QLatin1String("SetCapacity"), argumentList);
}
inline QDBusPendingReply<> SetCursorLocation(int x, int y)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y);
return asyncCallWithArgumentList(QLatin1String("SetCursorLocation"), argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y) << QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QLatin1String("SetCursorRect"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text, uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CloseIM();
void CommitString(const QString &str);
void DeleteSurroundingText(int offset, uint nchar);
void EnableIM();
void ForwardKey(uint keyval, uint state, int type);
void UpdateClientSideUI(const QString &auxup, const QString &auxdown, const QString &preedit, const QString &candidateword, const QString &imname, int cursorpos);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
};
#endif

View file

@ -1,95 +0,0 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
// Qt
#include <QDBusArgument>
#include <QDBusMetaType>
// self
#include "fcitxqtinputmethoditem.h"
bool FcitxQtInputMethodItem::enabled() const
{
return m_enabled;
}
const QString& FcitxQtInputMethodItem::langCode() const
{
return m_langCode;
}
const QString& FcitxQtInputMethodItem::name() const
{
return m_name;
}
const QString& FcitxQtInputMethodItem::uniqueName() const
{
return m_uniqueName;
}
void FcitxQtInputMethodItem::setEnabled(bool enable)
{
m_enabled = enable;
}
void FcitxQtInputMethodItem::setLangCode(const QString& lang)
{
m_langCode = lang;
}
void FcitxQtInputMethodItem::setName(const QString& name)
{
m_name = name;
}
void FcitxQtInputMethodItem::setUniqueName(const QString& name)
{
m_uniqueName = name;
}
void FcitxQtInputMethodItem::registerMetaType()
{
qRegisterMetaType<FcitxQtInputMethodItem>("FcitxQtInputMethodItem");
qDBusRegisterMetaType<FcitxQtInputMethodItem>();
qRegisterMetaType<FcitxQtInputMethodItemList>("FcitxQtInputMethodItemList");
qDBusRegisterMetaType<FcitxQtInputMethodItemList>();
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im)
{
argument.beginStructure();
argument << im.name();
argument << im.uniqueName();
argument << im.langCode();
argument << im.enabled();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im)
{
QString name;
QString uniqueName;
QString langCode;
bool enabled;
argument.beginStructure();
argument >> name >> uniqueName >> langCode >> enabled;
argument.endStructure();
im.setName(name);
im.setUniqueName(uniqueName);
im.setLangCode(langCode);
im.setEnabled(enabled);
return argument;
}

View file

@ -1,64 +0,0 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_INPUT_METHOD_ITEM_H
#define FCITX_QT_INPUT_METHOD_ITEM_H
#include "fcitxqtdbusaddons_export.h"
// Qt
#include <QtCore/QString>
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodItem
{
public:
const QString& name() const;
const QString& uniqueName() const;
const QString& langCode() const;
bool enabled() const;
void setName(const QString& name);
void setUniqueName(const QString& name);
void setLangCode(const QString& name);
void setEnabled(bool name);
static void registerMetaType();
inline bool operator < (const FcitxQtInputMethodItem& im) const {
if (m_enabled == true && im.m_enabled == false)
return true;
return false;
}
private:
QString m_name;
QString m_uniqueName;
QString m_langCode;
bool m_enabled;
};
typedef QList<FcitxQtInputMethodItem> FcitxQtInputMethodItemList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im);
Q_DECLARE_METATYPE(FcitxQtInputMethodItem)
Q_DECLARE_METATYPE(FcitxQtInputMethodItemList)
#endif

View file

@ -1,26 +0,0 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtinputmethodproxy.h"
/*
* Implementation of interface class FcitxQtInputMethodProxy
*/
FcitxQtInputMethodProxy::FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtInputMethodProxy::~FcitxQtInputMethodProxy()
{
}

View file

@ -1,217 +0,0 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTMETHODPROXY_H_1409252990
#define FCITXQTINPUTMETHODPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtinputmethoditem.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.InputMethod
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputMethod"; }
public:
FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtInputMethodProxy();
Q_PROPERTY(QString CurrentIM READ currentIM WRITE setCurrentIM)
inline QString currentIM() const
{ return qvariant_cast< QString >(property("CurrentIM")); }
inline void setCurrentIM(const QString &value)
{ setProperty("CurrentIM", QVariant::fromValue(value)); }
Q_PROPERTY(FcitxQtInputMethodItemList IMList READ iMList WRITE setIMList)
inline FcitxQtInputMethodItemList iMList() const
{ return qvariant_cast< FcitxQtInputMethodItemList >(property("IMList")); }
inline void setIMList(FcitxQtInputMethodItemList value)
{ setProperty("IMList", QVariant::fromValue(value)); }
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> ActivateIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ActivateIM"), argumentList);
}
inline QDBusPendingReply<> Configure()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Configure"), argumentList);
}
inline QDBusPendingReply<> ConfigureAddon(const QString &addon)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(addon);
return asyncCallWithArgumentList(QLatin1String("ConfigureAddon"), argumentList);
}
inline QDBusPendingReply<> ConfigureIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("ConfigureIM"), argumentList);
}
inline QDBusPendingReply<int, uint, uint, uint, uint> CreateIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("CreateIC"), argumentList);
}
inline QDBusReply<int> CreateIC(uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateIC"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 5) {
keyval1 = qdbus_cast<uint>(reply.arguments().at(1));
state1 = qdbus_cast<uint>(reply.arguments().at(2));
keyval2 = qdbus_cast<uint>(reply.arguments().at(3));
state2 = qdbus_cast<uint>(reply.arguments().at(4));
}
return reply;
}
inline QDBusPendingReply<int, bool, uint, uint, uint, uint> CreateICv2(const QString &appname)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname);
return asyncCallWithArgumentList(QLatin1String("CreateICv2"), argumentList);
}
inline QDBusReply<int> CreateICv2(const QString &appname, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateICv2"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) {
enable = qdbus_cast<bool>(reply.arguments().at(1));
keyval1 = qdbus_cast<uint>(reply.arguments().at(2));
state1 = qdbus_cast<uint>(reply.arguments().at(3));
keyval2 = qdbus_cast<uint>(reply.arguments().at(4));
state2 = qdbus_cast<uint>(reply.arguments().at(5));
}
return reply;
}
inline QDBusPendingReply<int, bool, uint, uint, uint, uint> CreateICv3(const QString &appname, int pid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid);
return asyncCallWithArgumentList(QLatin1String("CreateICv3"), argumentList);
}
inline QDBusReply<int> CreateICv3(const QString &appname, int pid, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateICv3"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) {
enable = qdbus_cast<bool>(reply.arguments().at(1));
keyval1 = qdbus_cast<uint>(reply.arguments().at(2));
state1 = qdbus_cast<uint>(reply.arguments().at(3));
keyval2 = qdbus_cast<uint>(reply.arguments().at(4));
state2 = qdbus_cast<uint>(reply.arguments().at(5));
}
return reply;
}
inline QDBusPendingReply<> Exit()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Exit"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentIM"), argumentList);
}
inline QDBusPendingReply<int> GetCurrentState()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentState"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentUI()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentUI"), argumentList);
}
inline QDBusPendingReply<QString> GetIMAddon(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("GetIMAddon"), argumentList);
}
inline QDBusPendingReply<> InactivateIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("InactivateIM"), argumentList);
}
inline QDBusPendingReply<> ReloadAddonConfig(const QString &addon)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(addon);
return asyncCallWithArgumentList(QLatin1String("ReloadAddonConfig"), argumentList);
}
inline QDBusPendingReply<> ReloadConfig()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ReloadConfig"), argumentList);
}
inline QDBusPendingReply<> ResetIMList()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ResetIMList"), argumentList);
}
inline QDBusPendingReply<> Restart()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Restart"), argumentList);
}
inline QDBusPendingReply<> SetCurrentIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("SetCurrentIM"), argumentList);
}
inline QDBusPendingReply<> ToggleIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ToggleIM"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View file

@ -1,100 +0,0 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
// Qt
#include <QDBusArgument>
#include <QDBusMetaType>
// self
#include "fcitxqtkeyboardlayout.h"
const QString& FcitxQtKeyboardLayout::layout() const
{
return m_layout;
}
const QString& FcitxQtKeyboardLayout::langCode() const
{
return m_langCode;
}
const QString& FcitxQtKeyboardLayout::name() const
{
return m_name;
}
const QString& FcitxQtKeyboardLayout::variant() const
{
return m_variant;
}
void FcitxQtKeyboardLayout::setLayout(const QString& layout)
{
m_layout = layout;
}
void FcitxQtKeyboardLayout::setLangCode(const QString& lang)
{
m_langCode = lang;
}
void FcitxQtKeyboardLayout::setName(const QString& name)
{
m_name = name;
}
void FcitxQtKeyboardLayout::setVariant(const QString& variant)
{
m_variant = variant;
}
void FcitxQtKeyboardLayout::registerMetaType()
{
qRegisterMetaType<FcitxQtKeyboardLayout>("FcitxQtKeyboardLayout");
qDBusRegisterMetaType<FcitxQtKeyboardLayout>();
qRegisterMetaType<FcitxQtKeyboardLayoutList>("FcitxQtKeyboardLayoutList");
qDBusRegisterMetaType<FcitxQtKeyboardLayoutList>();
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtKeyboardLayout& layout)
{
argument.beginStructure();
argument << layout.layout();
argument << layout.variant();
argument << layout.name();
argument << layout.langCode();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtKeyboardLayout& layout)
{
QString l;
QString variant;
QString name;
QString langCode;
argument.beginStructure();
argument >> l >> variant >> name >> langCode;
argument.endStructure();
layout.setLayout(l);
layout.setVariant(variant);
layout.setName(name);
layout.setLangCode(langCode);
return argument;
}

View file

@ -1,58 +0,0 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_KEYBOARD_LAYOUT_H
#define FCITX_QT_KEYBOARD_LAYOUT_H
#include "fcitxqtdbusaddons_export.h"
// Qt
#include <QtCore/QString>
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtKeyboardLayout
{
public:
const QString& layout() const;
const QString& variant() const;
const QString& name() const;
const QString& langCode() const;
void setLayout(const QString& layout);
void setLangCode(const QString& lang);
void setName(const QString& name);
void setVariant(const QString& variant);
static void registerMetaType();
private:
QString m_layout;
QString m_variant;
QString m_name;
QString m_langCode;
};
typedef QList<FcitxQtKeyboardLayout> FcitxQtKeyboardLayoutList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtKeyboardLayout& l);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtKeyboardLayout& l);
Q_DECLARE_METATYPE(FcitxQtKeyboardLayout)
Q_DECLARE_METATYPE(FcitxQtKeyboardLayoutList)
#endif

View file

@ -1,26 +0,0 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtkeyboardproxy -c FcitxQtKeyboardProxy interfaces/org.fcitx.Fcitx.Keyboard.xml -i fcitxqtkeyboardlayout.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtkeyboardproxy.h"
/*
* Implementation of interface class FcitxQtKeyboardProxy
*/
FcitxQtKeyboardProxy::FcitxQtKeyboardProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtKeyboardProxy::~FcitxQtKeyboardProxy()
{
}

View file

@ -1,74 +0,0 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtkeyboardproxy -c FcitxQtKeyboardProxy interfaces/org.fcitx.Fcitx.Keyboard.xml -i fcitxqtkeyboardlayout.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTKEYBOARDPROXY_H_1409252990
#define FCITXQTKEYBOARDPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtkeyboardlayout.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.Keyboard
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtKeyboardProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.Keyboard"; }
public:
FcitxQtKeyboardProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtKeyboardProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<QString, QString> GetLayoutForIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("GetLayoutForIM"), argumentList);
}
inline QDBusReply<QString> GetLayoutForIM(const QString &im, QString &variant)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("GetLayoutForIM"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
variant = qdbus_cast<QString>(reply.arguments().at(1));
}
return reply;
}
inline QDBusPendingReply<FcitxQtKeyboardLayoutList> GetLayouts()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetLayouts"), argumentList);
}
inline QDBusPendingReply<> SetLayoutForIM(const QString &im, const QString &layout, const QString &variant)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im) << QVariant::fromValue(layout) << QVariant::fromValue(variant);
return asyncCallWithArgumentList(QLatin1String("SetLayoutForIM"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View file

@ -1,81 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.InputContext">
<method name="EnableIC">
</method>
<method name="CloseIC">
</method>
<method name="FocusIn">
</method>
<method name="FocusOut">
</method>
<method name="Reset">
</method>
<method name="MouseEvent">
<arg name="x" direction="in" type="i" />
</method>
<method name="SetCursorLocation">
<arg name="x" direction="in" type="i"/>
<arg name="y" direction="in" type="i"/>
</method>
<method name="SetCursorRect">
<arg name="x" direction="in" type="i"/>
<arg name="y" direction="in" type="i"/>
<arg name="w" direction="in" type="i"/>
<arg name="h" direction="in" type="i"/>
</method>
<method name="SetCapacity">
<arg name="caps" direction="in" type="u"/>
</method>
<method name="SetSurroundingText">
<arg name="text" direction="in" type="s"/>
<arg name="cursor" direction="in" type="u"/>
<arg name="anchor" direction="in" type="u"/>
</method>
<method name="SetSurroundingTextPosition">
<arg name="cursor" direction="in" type="u"/>
<arg name="anchor" direction="in" type="u"/>
</method>
<method name="DestroyIC">
</method>
<method name="ProcessKeyEvent">
<arg name="keyval" direction="in" type="u"/>
<arg name="keycode" direction="in" type="u"/>
<arg name="state" direction="in" type="u"/>
<arg name="type" direction="in" type="i"/>
<arg name="time" direction="in" type="u"/>
<arg name="ret" direction="out" type="i"/>
</method>
<signal name="EnableIM">
</signal>
<signal name="CloseIM">
</signal>
<signal name="CommitString">
<arg name="str" type="s"/>
</signal>
<signal name="UpdateFormattedPreedit">
<arg name="str" type="a(si)" />
<arg name="cursorpos" type="i"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="FcitxQtFormattedPreeditList" />
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="FcitxQtFormattedPreeditList" />
</signal>
<signal name="UpdateClientSideUI">
<arg name="auxup" type="s"/>
<arg name="auxdown" type="s"/>
<arg name="preedit" type="s"/>
<arg name="candidateword" type="s"/>
<arg name="imname" type="s"/>
<arg name="cursorpos" type="i"/>
</signal>
<signal name="ForwardKey">
<arg name="keyval" type="u"/>
<arg name="state" type="u"/>
<arg name="type" type="i"/>
</signal>
<signal name="DeleteSurroundingText">
<arg name="offset" type="i"/>
<arg name="nchar" type="u"/>
</signal>
</interface>
</node>

View file

@ -1,81 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.InputMethod">
<method name="CreateIC">
<arg name="icid" direction="out" type="i"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="CreateICv2">
<arg name="appname" direction="in" type="s"/>
<arg name="icid" direction="out" type="i"/>
<arg name="enable" direction="out" type="b"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="CreateICv3">
<arg name="appname" direction="in" type="s"/>
<arg name="pid" direction="in" type="i"/>
<arg name="icid" direction="out" type="i"/>
<arg name="enable" direction="out" type="b"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="Exit">
</method>
<method name="GetCurrentIM">
<arg name="im" direction="out" type="s"/>
</method>
<method name="SetCurrentIM">
<arg name="im" direction="in" type="s"/>
</method>
<method name="ReloadConfig">
</method>
<method name="ReloadAddonConfig">
<arg name="addon" direction="in" type="s"/>
</method>
<method name="Restart">
</method>
<method name="Configure">
</method>
<method name="ConfigureAddon">
<arg name="addon" direction="in" type="s"/>
</method>
<method name="ConfigureIM">
<arg name="im" direction="in" type="s"/>
</method>
<method name="GetCurrentUI">
<arg name="addon" direction="out" type="s"/>
</method>
<method name="GetIMAddon">
<arg name="im" direction="in" type="s"/>
<arg name="addon" direction="out" type="s"/>
</method>
<method name="ActivateIM">
</method>
<method name="InactivateIM">
</method>
<method name="ToggleIM">
</method>
<method name="ResetIMList">
</method>
<method name="GetCurrentState">
<arg name="state" direction="out" type="i"/>
</method>
<property access="readwrite" type="a(sssb)" name="IMList">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
<annotation name="com.trolltech.QtDBus.QtTypeName" value="FcitxQtInputMethodItemList" />
<annotation name="org.qtproject.QtDBus.QtTypeName" value="FcitxQtInputMethodItemList" />
</property>
<property access="readwrite" type="s" name="CurrentIM">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
</property>
</interface>
</node>

View file

@ -1,20 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.Keyboard">
<method name="GetLayouts">
<arg name="layouts" direction="out" type="a(ssss)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="FcitxQtKeyboardLayoutList" />
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="FcitxQtKeyboardLayoutList" />
</method>
<method name="GetLayoutForIM">
<arg name="im" direction="in" type="s"/>
<arg name="layout" direction="out" type="s"/>
<arg name="variant" direction="out" type="s"/>
</method>
<method name="SetLayoutForIM">
<arg name="im" direction="in" type="s"/>
<arg name="layout" direction="in" type="s"/>
<arg name="variant" direction="in" type="s"/>
</method>
</interface>
</node>

View file

@ -1,173 +0,0 @@
/*
Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
Win32 port:
Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KEYSERVER_X11_H
#define KEYSERVER_X11_H
#include <X11/keysym.h>
struct TransKey {
int keySymQt;
uint keySymX;
};
static const TransKey g_rgQtToSymX[] = {
{ Qt::Key_Escape, XK_Escape },
{ Qt::Key_Tab, XK_Tab },
{ Qt::Key_Backtab, XK_ISO_Left_Tab },
{ Qt::Key_Backspace, XK_BackSpace },
{ Qt::Key_Return, XK_Return },
{ Qt::Key_Enter, XK_KP_Enter },
{ Qt::Key_Insert, XK_Insert },
{ Qt::Key_Delete, XK_Delete },
{ Qt::Key_Pause, XK_Pause },
#ifdef sun
{ Qt::Key_Print, XK_F22 },
#else
{ Qt::Key_Print, XK_Print },
#endif
{ Qt::Key_SysReq, XK_Sys_Req },
{ Qt::Key_Home, XK_Home },
{ Qt::Key_End, XK_End },
{ Qt::Key_Left, XK_Left },
{ Qt::Key_Up, XK_Up },
{ Qt::Key_Right, XK_Right },
{ Qt::Key_Down, XK_Down },
//{ Qt::Key_Shift, 0 },
//{ Qt::Key_Control, 0 },
//{ Qt::Key_Meta, 0 },
//{ Qt::Key_Alt, 0 },
{ Qt::Key_CapsLock, XK_Caps_Lock },
{ Qt::Key_NumLock, XK_Num_Lock },
{ Qt::Key_ScrollLock, XK_Scroll_Lock },
{ Qt::Key_F1, XK_F1 },
{ Qt::Key_F2, XK_F2 },
{ Qt::Key_F3, XK_F3 },
{ Qt::Key_F4, XK_F4 },
{ Qt::Key_F5, XK_F5 },
{ Qt::Key_F6, XK_F6 },
{ Qt::Key_F7, XK_F7 },
{ Qt::Key_F8, XK_F8 },
{ Qt::Key_F9, XK_F9 },
{ Qt::Key_F10, XK_F10 },
{ Qt::Key_F11, XK_F11 },
{ Qt::Key_F12, XK_F12 },
{ Qt::Key_F13, XK_F13 },
{ Qt::Key_F14, XK_F14 },
{ Qt::Key_F15, XK_F15 },
{ Qt::Key_F16, XK_F16 },
{ Qt::Key_F17, XK_F17 },
{ Qt::Key_F18, XK_F18 },
{ Qt::Key_F19, XK_F19 },
{ Qt::Key_F20, XK_F20 },
{ Qt::Key_F21, XK_F21 },
{ Qt::Key_F22, XK_F22 },
{ Qt::Key_F23, XK_F23 },
{ Qt::Key_F24, XK_F24 },
{ Qt::Key_F25, XK_F25 },
{ Qt::Key_F26, XK_F26 },
{ Qt::Key_F27, XK_F27 },
{ Qt::Key_F28, XK_F28 },
{ Qt::Key_F29, XK_F29 },
{ Qt::Key_F30, XK_F30 },
{ Qt::Key_F31, XK_F31 },
{ Qt::Key_F32, XK_F32 },
{ Qt::Key_F33, XK_F33 },
{ Qt::Key_F34, XK_F34 },
{ Qt::Key_F35, XK_F35 },
{ Qt::Key_Super_L, XK_Super_L },
{ Qt::Key_Super_R, XK_Super_R },
{ Qt::Key_Menu, XK_Menu },
{ Qt::Key_Hyper_L, XK_Hyper_L },
{ Qt::Key_Hyper_R, XK_Hyper_R },
{ Qt::Key_Help, XK_Help },
{ '/', XK_KP_Divide },
{ '*', XK_KP_Multiply },
{ '-', XK_KP_Subtract },
{ '+', XK_KP_Add },
{ Qt::Key_Return, XK_KP_Enter },
{Qt::Key_Multi_key, XK_Multi_key},
{Qt::Key_Codeinput, XK_Codeinput},
{Qt::Key_SingleCandidate, XK_SingleCandidate},
{Qt::Key_MultipleCandidate, XK_MultipleCandidate},
{Qt::Key_PreviousCandidate, XK_PreviousCandidate},
{Qt::Key_Mode_switch, XK_Mode_switch},
{Qt::Key_Kanji, XK_Kanji},
{Qt::Key_Muhenkan, XK_Muhenkan},
{Qt::Key_Henkan, XK_Henkan},
{Qt::Key_Romaji, XK_Romaji},
{Qt::Key_Hiragana, XK_Hiragana},
{Qt::Key_Katakana, XK_Katakana},
{Qt::Key_Hiragana_Katakana, XK_Hiragana_Katakana},
{Qt::Key_Zenkaku, XK_Zenkaku},
{Qt::Key_Hankaku, XK_Hankaku},
{Qt::Key_Zenkaku_Hankaku, XK_Zenkaku_Hankaku},
{Qt::Key_Touroku, XK_Touroku},
{Qt::Key_Massyo, XK_Massyo},
{Qt::Key_Kana_Lock, XK_Kana_Lock},
{Qt::Key_Kana_Shift, XK_Kana_Shift},
{Qt::Key_Eisu_Shift, XK_Eisu_Shift},
{Qt::Key_Eisu_toggle, XK_Eisu_toggle},
{Qt::Key_Hangul, XK_Hangul},
{Qt::Key_Hangul_Start, XK_Hangul_Start},
{Qt::Key_Hangul_End, XK_Hangul_End},
{Qt::Key_Hangul_Hanja, XK_Hangul_Hanja},
{Qt::Key_Hangul_Jamo, XK_Hangul_Jamo},
{Qt::Key_Hangul_Romaja, XK_Hangul_Romaja},
{Qt::Key_Hangul_Jeonja, XK_Hangul_Jeonja},
{Qt::Key_Hangul_Banja, XK_Hangul_Banja},
{Qt::Key_Hangul_PreHanja, XK_Hangul_PreHanja},
{Qt::Key_Hangul_PostHanja, XK_Hangul_PostHanja},
{Qt::Key_Hangul_Special, XK_Hangul_Special},
};
#include <qstring.h>
inline int map_sym_to_qt(uint keySym)
{
if (keySym < 0x1000) {
if (keySym >= 'a' && keySym <= 'z')
return QChar(keySym).toUpper().unicode();
return keySym;
}
#ifdef Q_WS_WIN
if (keySym < 0x3000)
return keySym;
#else
if (keySym < 0x3000)
return keySym | Qt::UNICODE_ACCEL;
for (uint i = 0; i < sizeof(g_rgQtToSymX) / sizeof(TransKey); i++)
if (g_rgQtToSymX[i].keySymX == keySym)
return g_rgQtToSymX[i].keySymQt;
#endif
return Qt::Key_unknown;
}
static bool symToKeyQt(uint keySym, int& keyQt)
{
keyQt = map_sym_to_qt(keySym);
return (keyQt != Qt::Key_unknown);
}
#endif

View file

@ -1,56 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <stdint.h>
#include "keyuni.h"
#include "keydata.h"
uint32_t
FcitxKeySymToUnicode (uint32_t keyval)
{
int min = 0;
int max = sizeof (gdk_keysym_to_unicode_tab) / sizeof(gdk_keysym_to_unicode_tab[0]) - 1;
int mid;
/* First check for Latin-1 characters (1:1 mapping) */
if ((keyval >= 0x0020 && keyval <= 0x007e) ||
(keyval >= 0x00a0 && keyval <= 0x00ff))
return keyval;
/* Also check for directly encoded 24-bit UCS characters:
*/
if ((keyval & 0xff000000) == 0x01000000)
return keyval & 0x00ffffff;
/* binary search in table */
while (max >= min) {
mid = (min + max) / 2;
if (gdk_keysym_to_unicode_tab[mid].keysym < keyval)
min = mid + 1;
else if (gdk_keysym_to_unicode_tab[mid].keysym > keyval)
max = mid - 1;
else {
/* found it */
return gdk_keysym_to_unicode_tab[mid].ucs;
}
}
/* No matching Unicode value found */
return 0;
}

View file

@ -1,29 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef KEYUNI_H
#define KEYUNI_H
#include <qglobal.h>
quint32
FcitxKeySymToUnicode (quint32 keyval);
#endif // KEYUNI_H

View file

@ -1,35 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "main.h"
QStringList QFcitxPlatformInputContextPlugin::keys() const
{
return QStringList(QStringLiteral("fcitx"));
}
QFcitxPlatformInputContext *QFcitxPlatformInputContextPlugin::create(const QString& system, const QStringList& paramList)
{
Q_UNUSED(paramList);
if (system.compare(system, QStringLiteral("fcitx"), Qt::CaseInsensitive) == 0)
return new QFcitxPlatformInputContext;
return 0;
}

View file

@ -1,37 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef MAIN_H
#define MAIN_H
#include <qpa/qplatforminputcontextplugin_p.h>
#include <QtCore/QStringList>
#include "qfcitxplatforminputcontext.h"
class QFcitxPlatformInputContextPlugin : public QPlatformInputContextPlugin
{
Q_OBJECT
public:
Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "fcitx.json")
QStringList keys() const;
QFcitxPlatformInputContext *create(const QString& system, const QStringList& paramList);
};
#endif // MAIN_H

View file

@ -1,770 +0,0 @@
/***************************************************************************
* Copyright (C) 2011~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <QKeyEvent>
#include <QDBusConnection>
#include <QGuiApplication>
#include <QInputMethod>
#include <QTextCharFormat>
#include <QPalette>
#include <QWindow>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformcursor.h>
#include <qpa/qwindowsysteminterface.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include "keyserver_x11.h"
#include "qfcitxplatforminputcontext.h"
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputmethodproxy.h"
#include "fcitxqtconnection.h"
#include "keyuni.h"
#include "utils.h"
static bool key_filtered = false;
static bool
get_boolean_env(const char *name,
bool defval)
{
const char *value = getenv(name);
if (value == NULL)
return defval;
if (strcmp(value, "") == 0 ||
strcmp(value, "0") == 0 ||
strcmp(value, "false") == 0 ||
strcmp(value, "False") == 0 ||
strcmp(value, "FALSE") == 0)
return false;
return true;
}
static inline const char*
get_locale()
{
const char* locale = getenv("LC_ALL");
if (!locale)
locale = getenv("LC_CTYPE");
if (!locale)
locale = getenv("LANG");
if (!locale)
locale = "C";
return locale;
}
struct xkb_context* _xkb_context_new_helper()
{
struct xkb_context* context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (context) {
xkb_context_set_log_level(context, XKB_LOG_LEVEL_CRITICAL);
}
return context;
}
QFcitxPlatformInputContext::QFcitxPlatformInputContext() :
m_connection(new FcitxQtConnection(this)),
m_improxy(0),
m_n_compose(0),
m_cursorPos(0),
m_useSurroundingText(false),
m_syncMode(true),
m_lastWId(0),
m_destroy(false),
m_xkbContext(_xkb_context_new_helper()),
m_xkbComposeTable(m_xkbContext ? xkb_compose_table_new_from_locale(m_xkbContext.data(), get_locale(), XKB_COMPOSE_COMPILE_NO_FLAGS) : 0),
m_xkbComposeState(m_xkbComposeTable ? xkb_compose_state_new(m_xkbComposeTable.data(), XKB_COMPOSE_STATE_NO_FLAGS) : 0)
{
FcitxQtFormattedPreedit::registerMetaType();
memset(m_compose_buffer, 0, sizeof(uint) * (MAX_COMPOSE_LEN + 1));
connect(m_connection, SIGNAL(connected()), this, SLOT(connected()));
connect(m_connection, SIGNAL(disconnected()), this, SLOT(cleanUp()));
m_connection->startConnection();
}
QFcitxPlatformInputContext::~QFcitxPlatformInputContext()
{
m_destroy = true;
cleanUp();
}
void QFcitxPlatformInputContext::connected()
{
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->name();
if (m_improxy) {
delete m_improxy;
m_improxy = 0;
}
m_improxy = new FcitxQtInputMethodProxy(m_connection->serviceName(), QLatin1String("/inputmethod"), *m_connection->connection(), this);
QWindow* w = qApp->focusWindow();
if (w)
createICData(w);
}
void QFcitxPlatformInputContext::cleanUp()
{
for(QHash<WId, FcitxQtICData *>::const_iterator i = m_icMap.constBegin(),
e = m_icMap.constEnd(); i != e; ++i) {
FcitxQtICData* data = i.value();
if (data->proxy)
delete data->proxy;
}
m_icMap.clear();
if (m_improxy) {
delete m_improxy;
m_improxy = 0;
}
if (!m_destroy) {
commitPreedit();
}
}
bool QFcitxPlatformInputContext::isValid() const
{
return true;
}
void QFcitxPlatformInputContext::invokeAction(QInputMethod::Action action, int cursorPosition)
{
if (action == QInputMethod::Click
&& (cursorPosition <= 0 || cursorPosition >= m_preedit.length())
)
{
// qDebug() << action << cursorPosition;
commitPreedit();
}
}
void QFcitxPlatformInputContext::commitPreedit()
{
QObject *input = qApp->focusObject();
if (!input)
return;
if (m_commitPreedit.length() <= 0)
return;
QInputMethodEvent e;
e.setCommitString(m_commitPreedit);
QCoreApplication::sendEvent(input, &e);
m_commitPreedit.clear();
}
void QFcitxPlatformInputContext::reset()
{
commitPreedit();
FcitxQtInputContextProxy* proxy = validIC();
if (proxy)
proxy->Reset();
if (m_xkbComposeState) {
xkb_compose_state_reset(m_xkbComposeState.data());
}
QPlatformInputContext::reset();
}
void QFcitxPlatformInputContext::update(Qt::InputMethodQueries queries )
{
QWindow* window = qApp->focusWindow();
FcitxQtInputContextProxy* proxy = validICByWindow(window);
if (!proxy)
return;
FcitxQtICData* data = m_icMap.value(window->winId());
QInputMethod *method = qApp->inputMethod();
QObject *input = qApp->focusObject();
if (!input)
return;
QInputMethodQueryEvent query(queries);
QGuiApplication::sendEvent(input, &query);
if (queries & Qt::ImCursorRectangle) {
cursorRectChanged();
}
if (queries & Qt::ImHints) {
Qt::InputMethodHints hints = Qt::InputMethodHints(query.value(Qt::ImHints).toUInt());
#define CHECK_HINTS(_HINTS, _CAPACITY) \
if (hints & _HINTS) \
addCapacity(data, _CAPACITY); \
else \
removeCapacity(data, _CAPACITY);
CHECK_HINTS(Qt::ImhNoAutoUppercase, CAPACITY_NOAUTOUPPERCASE)
CHECK_HINTS(Qt::ImhPreferNumbers, CAPACITY_NUMBER)
CHECK_HINTS(Qt::ImhPreferUppercase, CAPACITY_UPPERCASE)
CHECK_HINTS(Qt::ImhPreferLowercase, CAPACITY_LOWERCASE)
CHECK_HINTS(Qt::ImhNoPredictiveText, CAPACITY_NO_SPELLCHECK)
CHECK_HINTS(Qt::ImhDigitsOnly, CAPACITY_DIGIT)
CHECK_HINTS(Qt::ImhFormattedNumbersOnly, CAPACITY_NUMBER)
CHECK_HINTS(Qt::ImhUppercaseOnly, CAPACITY_UPPERCASE)
CHECK_HINTS(Qt::ImhLowercaseOnly, CAPACITY_LOWERCASE)
CHECK_HINTS(Qt::ImhDialableCharactersOnly, CAPACITY_DIALABLE)
CHECK_HINTS(Qt::ImhEmailCharactersOnly, CAPACITY_EMAIL)
}
bool setSurrounding = false;
do {
if (!m_useSurroundingText)
break;
if (!((queries & Qt::ImSurroundingText) && (queries & Qt::ImCursorPosition)))
break;
if (data->capacity.testFlag(CAPACITY_PASSWORD))
break;
QVariant var = query.value(Qt::ImSurroundingText);
QVariant var1 = query.value(Qt::ImCursorPosition);
QVariant var2 = query.value(Qt::ImAnchorPosition);
if (!var.isValid() || !var1.isValid())
break;
QString text = var.toString();
/* we don't want to waste too much memory here */
#define SURROUNDING_THRESHOLD 4096
if (text.length() < SURROUNDING_THRESHOLD) {
if (_utf8_check_string(text.toUtf8().data())) {
addCapacity(data, CAPACITY_SURROUNDING_TEXT);
int cursor = var1.toInt();
int anchor;
if (var2.isValid())
anchor = var2.toInt();
else
anchor = cursor;
if (data->surroundingText != text) {
data->surroundingText = text;
proxy->SetSurroundingText(text, cursor, anchor);
}
else {
if (data->surroundingAnchor != anchor ||
data->surroundingCursor != cursor)
proxy->SetSurroundingTextPosition(cursor, anchor);
}
data->surroundingCursor = cursor;
data->surroundingAnchor = anchor;
setSurrounding = true;
}
}
if (!setSurrounding) {
data->surroundingAnchor = -1;
data->surroundingCursor = -1;
data->surroundingText = QString::null;
removeCapacity(data, CAPACITY_SURROUNDING_TEXT);
}
} while(0);
}
void QFcitxPlatformInputContext::commit()
{
QPlatformInputContext::commit();
}
void QFcitxPlatformInputContext::setFocusObject(QObject* object)
{
FcitxQtInputContextProxy* proxy = validICByWId(m_lastWId);
if (proxy) {
proxy->FocusOut();
}
QWindow *window = qApp->focusWindow();
if (window) {
m_lastWId = window->winId();
} else {
m_lastWId = 0;
return;
}
proxy = validICByWindow(window);
if (proxy)
proxy->FocusIn();
else {
FcitxQtICData* data = m_icMap.value(window->winId());
if (!data) {
createICData(window);
return;
}
}
}
void QFcitxPlatformInputContext::windowDestroyed(QObject* object)
{
/* access QWindow is not possible here, so we use our own map to do so */
WId wid = m_windowToWidMap.take(object);
if (!wid)
return;
FcitxQtICData* data = m_icMap.take(wid);
if (!data)
return;
delete data;
// qDebug() << "Window Destroyed and we destroy IC correctly, horray!";
}
void QFcitxPlatformInputContext::cursorRectChanged()
{
QWindow *inputWindow = qApp->focusWindow();
if (!inputWindow)
return;
FcitxQtInputContextProxy* proxy = validICByWindow(inputWindow);
if (!proxy)
return;
FcitxQtICData* data = m_icMap.value(inputWindow->winId());
QRect r = qApp->inputMethod()->cursorRectangle().toRect();
if(!r.isValid())
return;
r.moveTopLeft(inputWindow->mapToGlobal(r.topLeft()));
qreal scale = inputWindow->devicePixelRatio();
if (data->rect != r) {
data->rect = r;
proxy->SetCursorRect(r.x() * scale, r.y() * scale,
r.width() * scale, r.height() * scale);
}
}
void QFcitxPlatformInputContext::createInputContext(WId w)
{
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->connection()->name();
if (m_improxy) {
delete m_improxy;
m_improxy = NULL;
}
m_improxy = new FcitxQtInputMethodProxy(m_connection->serviceName(), QLatin1String("/inputmethod"), *m_connection->connection(), this);
if (!m_improxy->isValid())
return;
QFileInfo info(QCoreApplication::applicationFilePath());
QDBusPendingReply< int, bool, uint, uint, uint, uint > result = m_improxy->CreateICv3(info.fileName(), QCoreApplication::applicationPid());
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(result);
watcher->setProperty("wid", (qulonglong) w);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(createInputContextFinished(QDBusPendingCallWatcher*)));
}
void QFcitxPlatformInputContext::createInputContextFinished(QDBusPendingCallWatcher* watcher)
{
WId w = watcher->property("wid").toULongLong();
FcitxQtICData* data = m_icMap.value(w);
if (!data)
return;
QDBusPendingReply< int, bool, uint, uint, uint, uint > result = *watcher;
do {
if (result.isError()) {
break;
}
if (!m_connection->isConnected())
break;
int id = qdbus_cast<int>(result.argumentAt(0));
QString path = QString("/inputcontext_%1").arg(id);
if (data->proxy) {
delete data->proxy;
}
data->proxy = new FcitxQtInputContextProxy(m_connection->serviceName(), path, *m_connection->connection(), this);
connect(data->proxy, SIGNAL(CommitString(QString)), this, SLOT(commitString(QString)));
connect(data->proxy, SIGNAL(ForwardKey(uint, uint, int)), this, SLOT(forwardKey(uint, uint, int)));
connect(data->proxy, SIGNAL(UpdateFormattedPreedit(FcitxQtFormattedPreeditList,int)), this, SLOT(updateFormattedPreedit(FcitxQtFormattedPreeditList,int)));
connect(data->proxy, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
if (data->proxy->isValid()) {
QWindow* window = qApp->focusWindow();
if (window && window->winId() == w)
data->proxy->FocusIn();
}
QFlags<FcitxCapacityFlags> flag;
flag |= CAPACITY_PREEDIT;
flag |= CAPACITY_FORMATTED_PREEDIT;
flag |= CAPACITY_CLIENT_UNFOCUS_COMMIT;
m_useSurroundingText = get_boolean_env("FCITX_QT_ENABLE_SURROUNDING_TEXT", true);
if (m_useSurroundingText)
flag |= CAPACITY_SURROUNDING_TEXT;
/*
* event loop will cause some problem, so we tries to use async way.
*/
m_syncMode = get_boolean_env("FCITX_QT_USE_SYNC", false);
addCapacity(data, flag, true);
} while(0);
delete watcher;
}
void QFcitxPlatformInputContext::updateCapacity(FcitxQtICData* data)
{
if (!data->proxy || !data->proxy->isValid())
return;
QDBusPendingReply< void > result = data->proxy->SetCapacity((uint) data->capacity);
}
void QFcitxPlatformInputContext::commitString(const QString& str)
{
m_cursorPos = 0;
m_preeditList.clear();
m_commitPreedit.clear();
QObject *input = qApp->focusObject();
if (!input)
return;
QInputMethodEvent event;
event.setCommitString(str);
QCoreApplication::sendEvent(input, &event);
}
void QFcitxPlatformInputContext::updateFormattedPreedit(const FcitxQtFormattedPreeditList& preeditList, int cursorPos)
{
QObject *input = qApp->focusObject();
if (!input)
return;
if (cursorPos == m_cursorPos && preeditList == m_preeditList)
return;
m_preeditList = preeditList;
m_cursorPos = cursorPos;
QString str, commitStr;
int pos = 0;
QList<QInputMethodEvent::Attribute> attrList;
Q_FOREACH(const FcitxQtFormattedPreedit& preedit, preeditList)
{
str += preedit.string();
if (!(preedit.format() & MSG_DONOT_COMMIT_WHEN_UNFOCUS))
commitStr += preedit.string();
QTextCharFormat format;
if ((preedit.format() & MSG_NOUNDERLINE) == 0) {
format.setUnderlineStyle(QTextCharFormat::DashUnderline);
}
if (preedit.format() & MSG_HIGHLIGHT) {
QBrush brush;
QPalette palette;
palette = QGuiApplication::palette();
format.setBackground(QBrush(QColor(palette.color(QPalette::Active, QPalette::Highlight))));
format.setForeground(QBrush(QColor(palette.color(QPalette::Active, QPalette::HighlightedText))));
}
attrList.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, pos, preedit.string().length(), format));
pos += preedit.string().length();
}
QByteArray array = str.toUtf8();
array.truncate(cursorPos);
cursorPos = QString::fromUtf8(array).length();
attrList.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPos, 1, 0));
m_preedit = str;
m_commitPreedit = commitStr;
QInputMethodEvent event(str, attrList);
QCoreApplication::sendEvent(input, &event);
update(Qt::ImCursorRectangle);
}
void QFcitxPlatformInputContext::deleteSurroundingText(int offset, uint nchar)
{
QObject *input = qApp->focusObject();
if (!input)
return;
QInputMethodEvent event;
event.setCommitString("", offset, nchar);
QCoreApplication::sendEvent(input, &event);
}
void QFcitxPlatformInputContext::forwardKey(uint keyval, uint state, int type)
{
QObject *input = qApp->focusObject();
if (input != NULL) {
key_filtered = true;
QKeyEvent *keyevent = createKeyEvent(keyval, state, type);
QCoreApplication::sendEvent(input, keyevent);
delete keyevent;
key_filtered = false;
}
}
void QFcitxPlatformInputContext::createICData(QWindow* w)
{
FcitxQtICData* data = m_icMap.value(w->winId());
if (!data) {
data = new FcitxQtICData;
m_icMap[w->winId()] = data;
m_windowToWidMap[w] = w->winId();
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*)));
}
createInputContext(w->winId());
}
QKeyEvent* QFcitxPlatformInputContext::createKeyEvent(uint keyval, uint state, int type)
{
Qt::KeyboardModifiers qstate = Qt::NoModifier;
int count = 1;
if (state & FcitxKeyState_Alt) {
qstate |= Qt::AltModifier;
count ++;
}
if (state & FcitxKeyState_Shift) {
qstate |= Qt::ShiftModifier;
count ++;
}
if (state & FcitxKeyState_Ctrl) {
qstate |= Qt::ControlModifier;
count ++;
}
int key;
symToKeyQt(keyval, key);
QKeyEvent* keyevent = new QKeyEvent(
(type == FCITX_PRESS_KEY) ? (QEvent::KeyPress) : (QEvent::KeyRelease),
key,
qstate,
QString(),
false,
count
);
return keyevent;
}
bool QFcitxPlatformInputContext::filterEvent(const QEvent* event)
{
do {
if (event->type() != QEvent::KeyPress && event->type() != QEvent::KeyRelease) {
break;
}
const QKeyEvent* keyEvent = static_cast<const QKeyEvent*>(event);
quint32 keyval = keyEvent->nativeVirtualKey();
quint32 keycode = keyEvent->nativeScanCode();
quint32 state = keyEvent->nativeModifiers();
bool press = keyEvent->type() == QEvent::KeyPress;
if (key_filtered) {
break;
}
if (!inputMethodAccepted())
break;
QObject *input = qApp->focusObject();
if (!input) {
break;
}
FcitxQtInputContextProxy* proxy = validICByWindow(qApp->focusWindow());
if (!proxy) {
if (filterEventFallback(keyval, keycode, state, press)) {
return true;
} else {
break;
}
}
proxy->FocusIn();
QDBusPendingReply< int > reply = proxy->ProcessKeyEvent(keyval,
keycode,
state,
(press) ? FCITX_PRESS_KEY : FCITX_RELEASE_KEY,
QDateTime::currentDateTime().toTime_t());
if (Q_UNLIKELY(m_syncMode)) {
reply.waitForFinished();
if (!m_connection->isConnected() || !reply.isFinished() || reply.isError() || reply.value() <= 0) {
if (filterEventFallback(keyval, keycode, state, press)) {
return true;
} else {
break;
}
} else {
update(Qt::ImCursorRectangle);
return true;
}
}
else {
ProcessKeyWatcher* watcher = new ProcessKeyWatcher(*keyEvent, qApp->focusWindow(), reply, this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
this, SLOT(processKeyEventFinished(QDBusPendingCallWatcher*)));
return true;
}
} while(0);
return QPlatformInputContext::filterEvent(event);
}
void QFcitxPlatformInputContext::processKeyEventFinished(QDBusPendingCallWatcher* w)
{
ProcessKeyWatcher* watcher = static_cast<ProcessKeyWatcher*>(w);
QDBusPendingReply< int > result(*watcher);
bool filtered = false;
QWindow* window = watcher->window();
// if window is already destroyed, we can only throw this event away.
if (!window) {
return;
}
const QKeyEvent& keyEvent = watcher->event();
// use same variable name as in QXcbKeyboard::handleKeyEvent
QEvent::Type type = keyEvent.type();
int qtcode = keyEvent.key();
Qt::KeyboardModifiers modifiers = keyEvent.modifiers();
quint32 code = keyEvent.nativeScanCode();
quint32 sym = keyEvent.nativeVirtualKey();
quint32 state = keyEvent.nativeModifiers();
QString string = keyEvent.text();
bool isAutoRepeat = keyEvent.isAutoRepeat();
ulong time = keyEvent.timestamp();
if (result.isError() || result.value() <= 0) {
filtered = filterEventFallback(sym, code, state, type == QEvent::KeyPress);
} else {
filtered = true;
}
if (!result.isError()) {
update(Qt::ImCursorRectangle);
}
if (!filtered) {
// copied from QXcbKeyboard::handleKeyEvent()
if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) {
const QPoint globalPos = window->screen()->handle()->cursor()->pos();
const QPoint pos = window->mapFromGlobal(globalPos); QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers);
}
QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
code, sym, state, string, isAutoRepeat);
}
delete watcher;
}
bool QFcitxPlatformInputContext::filterEventFallback(uint keyval, uint keycode, uint state, bool press)
{
Q_UNUSED(keycode);
if (processCompose(keyval, state, (press) ? FCITX_PRESS_KEY : FCITX_RELEASE_KEY)) {
return true;
}
return false;
}
FcitxQtInputContextProxy* QFcitxPlatformInputContext::validIC()
{
if (m_icMap.isEmpty()) {
return 0;
}
QWindow* window = qApp->focusWindow();
return validICByWindow(window);
}
FcitxQtInputContextProxy* QFcitxPlatformInputContext::validICByWId(WId wid)
{
if (m_icMap.isEmpty()) {
return 0;
}
FcitxQtICData* icData = m_icMap.value(wid);
if (!icData)
return 0;
if (icData->proxy.isNull()) {
return 0;
} else if (icData->proxy->isValid()) {
return icData->proxy.data();
}
return 0;
}
FcitxQtInputContextProxy* QFcitxPlatformInputContext::validICByWindow(QWindow* w)
{
if (!w) {
return 0;
}
if (m_icMap.isEmpty()) {
return 0;
}
return validICByWId(w->winId());
}
bool QFcitxPlatformInputContext::processCompose(uint keyval, uint state, FcitxKeyEventType event)
{
Q_UNUSED(state);
if (!m_xkbComposeTable || event == FCITX_RELEASE_KEY)
return false;
struct xkb_compose_state* xkbComposeState = m_xkbComposeState.data();
enum xkb_compose_feed_result result = xkb_compose_state_feed(xkbComposeState, keyval);
if (result == XKB_COMPOSE_FEED_IGNORED) {
return false;
}
enum xkb_compose_status status = xkb_compose_state_get_status(xkbComposeState);
if (status == XKB_COMPOSE_NOTHING) {
return 0;
} else if (status == XKB_COMPOSE_COMPOSED) {
char buffer[] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0'};
int length = xkb_compose_state_get_utf8(xkbComposeState, buffer, sizeof(buffer));
xkb_compose_state_reset(xkbComposeState);
if (length != 0) {
commitString(QString::fromUtf8(buffer));
}
} else if (status == XKB_COMPOSE_CANCELLED) {
xkb_compose_state_reset(xkbComposeState);
}
return true;
}
// kate: indent-mode cstyle; space-indent on; indent-width 0;

View file

@ -1,269 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef QFCITXPLATFORMINPUTCONTEXT_H
#define QFCITXPLATFORMINPUTCONTEXT_H
#include <qpa/qplatforminputcontext.h>
#include <QWindow>
#include <QKeyEvent>
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QPointer>
#include <QFileSystemWatcher>
#include <QRect>
#include <xkbcommon/xkbcommon-compose.h>
#include "fcitxqtformattedpreedit.h"
#include "fcitxqtinputcontextproxy.h"
#define MAX_COMPOSE_LEN 7
class FcitxQtConnection;
class QFileSystemWatcher;
enum FcitxKeyEventType {
FCITX_PRESS_KEY,
FCITX_RELEASE_KEY
};
enum FcitxCapacityFlags {
CAPACITY_NONE = 0,
CAPACITY_CLIENT_SIDE_UI = (1 << 0),
CAPACITY_PREEDIT = (1 << 1),
CAPACITY_CLIENT_SIDE_CONTROL_STATE = (1 << 2),
CAPACITY_PASSWORD = (1 << 3),
CAPACITY_FORMATTED_PREEDIT = (1 << 4),
CAPACITY_CLIENT_UNFOCUS_COMMIT = (1 << 5),
CAPACITY_SURROUNDING_TEXT = (1 << 6),
CAPACITY_EMAIL = (1 << 7),
CAPACITY_DIGIT = (1 << 8),
CAPACITY_UPPERCASE = (1 << 9),
CAPACITY_LOWERCASE = (1 << 10),
CAPACITY_NOAUTOUPPERCASE = (1 << 11),
CAPACITY_URL = (1 << 12),
CAPACITY_DIALABLE = (1 << 13),
CAPACITY_NUMBER = (1 << 14),
CAPACITY_NO_ON_SCREEN_KEYBOARD = (1 << 15),
CAPACITY_SPELLCHECK = (1 << 16),
CAPACITY_NO_SPELLCHECK = (1 << 17),
CAPACITY_WORD_COMPLETION = (1 << 18),
CAPACITY_UPPERCASE_WORDS = (1 << 19),
CAPACITY_UPPERCASE_SENTENCES = (1 << 20),
CAPACITY_ALPHA = (1 << 21),
CAPACITY_NAME = (1 << 22)
} ;
/** message type and flags */
enum FcitxMessageType {
MSG_TYPE_FIRST = 0,
MSG_TYPE_LAST = 6,
MSG_TIPS = 0, /**< Hint Text */
MSG_INPUT = 1, /**< User Input */
MSG_INDEX = 2, /**< Index Number */
MSG_FIRSTCAND = 3, /**< First candidate */
MSG_USERPHR = 4, /**< User Phrase */
MSG_CODE = 5, /**< Typed character */
MSG_OTHER = 6, /**< Other Text */
MSG_NOUNDERLINE = (1 << 3), /**< backward compatible, no underline is a flag */
MSG_HIGHLIGHT = (1 << 4), /**< highlight the preedit */
MSG_DONOT_COMMIT_WHEN_UNFOCUS = (1 << 5), /**< backward compatible */
MSG_REGULAR_MASK = 0x7 /**< regular color type mask */
};
enum FcitxKeyState {
FcitxKeyState_None = 0,
FcitxKeyState_Shift = 1 << 0,
FcitxKeyState_CapsLock = 1 << 1,
FcitxKeyState_Ctrl = 1 << 2,
FcitxKeyState_Alt = 1 << 3,
FcitxKeyState_Alt_Shift = FcitxKeyState_Alt | FcitxKeyState_Shift,
FcitxKeyState_Ctrl_Shift = FcitxKeyState_Ctrl | FcitxKeyState_Shift,
FcitxKeyState_Ctrl_Alt = FcitxKeyState_Ctrl | FcitxKeyState_Alt,
FcitxKeyState_Ctrl_Alt_Shift = FcitxKeyState_Ctrl | FcitxKeyState_Alt | FcitxKeyState_Shift,
FcitxKeyState_NumLock = 1 << 4,
FcitxKeyState_Super = 1 << 6,
FcitxKeyState_ScrollLock = 1 << 7,
FcitxKeyState_MousePressed = 1 << 8,
FcitxKeyState_HandledMask = 1 << 24,
FcitxKeyState_IgnoredMask = 1 << 25,
FcitxKeyState_Super2 = 1 << 26,
FcitxKeyState_Hyper = 1 << 27,
FcitxKeyState_Meta = 1 << 28,
FcitxKeyState_UsedMask = 0x5c001fff
};
struct FcitxQtICData {
FcitxQtICData() : capacity(0), proxy(0), surroundingAnchor(-1), surroundingCursor(-1) {}
~FcitxQtICData() {
if (proxy && proxy->isValid()) {
proxy->DestroyIC();
delete proxy;
}
}
QFlags<FcitxCapacityFlags> capacity;
QPointer<FcitxQtInputContextProxy> proxy;
QRect rect;
QString surroundingText;
int surroundingAnchor;
int surroundingCursor;
};
class ProcessKeyWatcher : public QDBusPendingCallWatcher
{
Q_OBJECT
public:
ProcessKeyWatcher(const QKeyEvent& event, QWindow* window, const QDBusPendingCall &call, QObject *parent = 0) :
QDBusPendingCallWatcher(call, parent)
,m_event(event.type(), event.key(), event.modifiers(),
event.nativeScanCode(), event.nativeVirtualKey(), event.nativeModifiers(),
event.text(), event.isAutoRepeat(), event.count())
,m_window(window)
{
}
virtual ~ProcessKeyWatcher() {
}
const QKeyEvent& event() {
return m_event;
}
QWindow* window() {
return m_window.data();
}
private:
QKeyEvent m_event;
QPointer<QWindow> m_window;
};
struct XkbContextDeleter
{
static inline void cleanup(struct xkb_context* pointer)
{
if (pointer) xkb_context_unref(pointer);
}
};
struct XkbComposeTableDeleter
{
static inline void cleanup(struct xkb_compose_table* pointer)
{
if (pointer) xkb_compose_table_unref(pointer);
}
};
struct XkbComposeStateDeleter
{
static inline void cleanup(struct xkb_compose_state* pointer)
{
if (pointer) xkb_compose_state_unref(pointer);
}
};
class FcitxQtInputMethodProxy;
class QFcitxPlatformInputContext : public QPlatformInputContext
{
Q_OBJECT
public:
QFcitxPlatformInputContext();
virtual ~QFcitxPlatformInputContext();
virtual bool filterEvent(const QEvent* event);
virtual bool isValid() const;
virtual void invokeAction(QInputMethod::Action , int cursorPosition);
virtual void reset();
virtual void commit();
virtual void update(Qt::InputMethodQueries quries );
virtual void setFocusObject(QObject* object);
public Q_SLOTS:
void cursorRectChanged();
void commitString(const QString& str);
void updateFormattedPreedit(const FcitxQtFormattedPreeditList& preeditList, int cursorPos);
void deleteSurroundingText(int offset, uint nchar);
void forwardKey(uint keyval, uint state, int type);
void createInputContextFinished(QDBusPendingCallWatcher* watcher);
void connected();
void cleanUp();
void windowDestroyed(QObject* object);
private:
void createInputContext(WId w);
bool processCompose(uint keyval, uint state, FcitxKeyEventType event);
bool checkAlgorithmically();
bool checkCompactTable(const struct _FcitxComposeTableCompact *table);
QKeyEvent* createKeyEvent(uint keyval, uint state, int type);
void addCapacity(FcitxQtICData* data, QFlags<FcitxCapacityFlags> capacity, bool forceUpdate = false)
{
QFlags< FcitxCapacityFlags > newcaps = data->capacity | capacity;
if (data->capacity != newcaps || forceUpdate) {
data->capacity = newcaps;
updateCapacity(data);
}
}
void removeCapacity(FcitxQtICData* data, QFlags<FcitxCapacityFlags> capacity, bool forceUpdate = false)
{
QFlags< FcitxCapacityFlags > newcaps = data->capacity & (~capacity);
if (data->capacity != newcaps || forceUpdate) {
data->capacity = newcaps;
updateCapacity(data);
}
}
void updateCapacity(FcitxQtICData* data);
void commitPreedit();
void createICData(QWindow* w);
FcitxQtInputContextProxy* validIC();
FcitxQtInputContextProxy* validICByWindow(QWindow* window);
FcitxQtInputContextProxy* validICByWId(WId wid);
bool filterEventFallback(uint keyval, uint keycode, uint state, bool press);
FcitxQtInputMethodProxy* m_improxy;
uint m_compose_buffer[MAX_COMPOSE_LEN + 1];
int m_n_compose;
QString m_preedit;
QString m_commitPreedit;
FcitxQtFormattedPreeditList m_preeditList;
int m_cursorPos;
bool m_useSurroundingText;
bool m_syncMode;
FcitxQtConnection* m_connection;
QString m_lastSurroundingText;
int m_lastSurroundingAnchor;
int m_lastSurroundingCursor;
QHash<WId, FcitxQtICData*> m_icMap;
QHash<QObject*, WId> m_windowToWidMap;
WId m_lastWId;
bool m_destroy;
QScopedPointer<struct xkb_context, XkbContextDeleter> m_xkbContext;
QScopedPointer<struct xkb_compose_table, XkbComposeTableDeleter> m_xkbComposeTable;
QScopedPointer<struct xkb_compose_state, XkbComposeStateDeleter> m_xkbComposeState;
private slots:
void processKeyEventFinished(QDBusPendingCallWatcher*);
};
#endif // QFCITXPLATFORMINPUTCONTEXT_H

View file

@ -1,177 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "utils.h"
/** check utf8 character */
#define ISUTF8_CB(c) (((c)&0xc0) == 0x80)
#define CONT(i) ISUTF8_CB(in[i])
#define VAL(i, s) ((in[i]&0x3f) << s)
#define UTF8_LENGTH(Char) \
((Char) < 0x80 ? 1 : \
((Char) < 0x800 ? 2 : \
((Char) < 0x10000 ? 3 : \
((Char) < 0x200000 ? 4 : \
((Char) < 0x4000000 ? 5 : 6)))))
#define UNICODE_VALID(Char) \
((Char) < 0x110000 && \
(((Char) & 0xFFFFF800) != 0xD800) && \
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFE) != 0xFFFE)
int
_utf8_get_char_extended(const char *s,
int max_len)
{
const unsigned char*p = (const unsigned char*)s;
int i, len;
unsigned int wc = (unsigned char) * p;
if (wc < 0x80) {
return wc;
} else if (wc < 0xc0) {
return (unsigned int) - 1;
} else if (wc < 0xe0) {
len = 2;
wc &= 0x1f;
} else if (wc < 0xf0) {
len = 3;
wc &= 0x0f;
} else if (wc < 0xf8) {
len = 4;
wc &= 0x07;
} else if (wc < 0xfc) {
len = 5;
wc &= 0x03;
} else if (wc < 0xfe) {
len = 6;
wc &= 0x01;
} else {
return (unsigned int) - 1;
}
if (max_len >= 0 && len > max_len) {
for (i = 1; i < max_len; i++) {
if ((((unsigned char *)p)[i] & 0xc0) != 0x80)
return (unsigned int) - 1;
}
return (unsigned int) - 2;
}
for (i = 1; i < len; ++i) {
unsigned int ch = ((unsigned char *)p)[i];
if ((ch & 0xc0) != 0x80) {
if (ch)
return (unsigned int) - 1;
else
return (unsigned int) - 2;
}
wc <<= 6;
wc |= (ch & 0x3f);
}
if (UTF8_LENGTH(wc) != len)
return (unsigned int) - 1;
return wc;
}
int _utf8_get_char_validated(const char *p,
int max_len)
{
int result;
if (max_len == 0)
return -2;
result = _utf8_get_char_extended(p, max_len);
if (result & 0x80000000)
return result;
else if (!UNICODE_VALID(result))
return -1;
else
return result;
}
char *
_utf8_get_char(const char *i, uint32_t *chr)
{
const unsigned char* in = (const unsigned char *)i;
if (!(in[0] & 0x80)) {
*(chr) = *(in);
return (char *)in + 1;
}
/* 2-byte, 0x80-0x7ff */
if ((in[0] & 0xe0) == 0xc0 && CONT(1)) {
*chr = ((in[0] & 0x1f) << 6) | VAL(1, 0);
return (char *)in + 2;
}
/* 3-byte, 0x800-0xffff */
if ((in[0] & 0xf0) == 0xe0 && CONT(1) && CONT(2)) {
*chr = ((in[0] & 0xf) << 12) | VAL(1, 6) | VAL(2, 0);
return (char *)in + 3;
}
/* 4-byte, 0x10000-0x1FFFFF */
if ((in[0] & 0xf8) == 0xf0 && CONT(1) && CONT(2) && CONT(3)) {
*chr = ((in[0] & 0x7) << 18) | VAL(1, 12) | VAL(2, 6) | VAL(3, 0);
return (char *)in + 4;
}
/* 5-byte, 0x200000-0x3FFFFFF */
if ((in[0] & 0xfc) == 0xf8 && CONT(1) && CONT(2) && CONT(3) && CONT(4)) {
*chr = ((in[0] & 0x3) << 24) | VAL(1, 18) | VAL(2, 12) | VAL(3, 6) | VAL(4, 0);
return (char *)in + 5;
}
/* 6-byte, 0x400000-0x7FFFFFF */
if ((in[0] & 0xfe) == 0xfc && CONT(1) && CONT(2) && CONT(3) && CONT(4) && CONT(5)) {
*chr = ((in[0] & 0x1) << 30) | VAL(1, 24) | VAL(2, 18) | VAL(3, 12) | VAL(4, 6) | VAL(5, 0);
return (char *)in + 6;
}
*chr = *in;
return (char *)in + 1;
}
int _utf8_check_string(const char *s)
{
while (*s) {
uint32_t chr;
if (_utf8_get_char_validated(s, 6) < 0)
return 0;
s = _utf8_get_char(s, &chr);
}
return 1;
}

View file

@ -1,35 +0,0 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef UTILS_H
#define UTILS_H
#include <stdint.h>
int
_utf8_get_char_extended(const char *s,
int max_len);
int _utf8_get_char_validated(const char *p,
int max_len);
char *
_utf8_get_char(const char *i, uint32_t *chr);
int _utf8_check_string(const char *s);
#endif // UTILS_H

View file

@ -1,98 +0,0 @@
/*
* Copyright © 2012 Daniel Stone
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#ifndef _XKBCOMMON_COMPAT_H
#define _XKBCOMMON_COMPAT_H
/**
* Renamed keymap API.
*/
#define xkb_group_index_t xkb_layout_index_t
#define xkb_group_mask_t xkb_layout_mask_t
#define xkb_map_compile_flags xkb_keymap_compile_flags
#define XKB_GROUP_INVALID XKB_LAYOUT_INVALID
#define XKB_STATE_DEPRESSED \
(XKB_STATE_MODS_DEPRESSED | XKB_STATE_LAYOUT_DEPRESSED)
#define XKB_STATE_LATCHED \
(XKB_STATE_MODS_LATCHED | XKB_STATE_LAYOUT_LATCHED)
#define XKB_STATE_LOCKED \
(XKB_STATE_MODS_LOCKED | XKB_STATE_LAYOUT_LOCKED)
#define XKB_STATE_EFFECTIVE \
(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED | XKB_STATE_LOCKED | \
XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LAYOUT_EFFECTIVE)
#define xkb_map_new_from_names(context, names, flags) \
xkb_keymap_new_from_names(context, names, flags)
#define xkb_map_new_from_file(context, file, format, flags) \
xkb_keymap_new_from_file(context, file, format, flags)
#define xkb_map_new_from_string(context, string, format, flags) \
xkb_keymap_new_from_string(context, string, format, flags)
#define xkb_map_get_as_string(keymap) \
xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1)
#define xkb_map_ref(keymap) xkb_keymap_ref(keymap)
#define xkb_map_unref(keymap) xkb_keymap_unref(keymap)
#define xkb_map_num_mods(keymap) xkb_keymap_num_mods(keymap)
#define xkb_map_mod_get_name(keymap, idx) xkb_keymap_mod_get_name(keymap, idx)
#define xkb_map_mod_get_index(keymap, str) xkb_keymap_mod_get_index(keymap, str)
#define xkb_key_mod_index_is_consumed(state, key, mod) \
xkb_state_mod_index_is_consumed(state, key, mod)
#define xkb_key_mod_mask_remove_consumed(state, key, modmask) \
xkb_state_mod_mask_remove_consumed(state, key, modmask)
#define xkb_map_num_groups(keymap) xkb_keymap_num_layouts(keymap)
#define xkb_key_num_groups(keymap, key) \
xkb_keymap_num_layouts_for_key(keymap, key)
#define xkb_map_group_get_name(keymap, idx) \
xkb_keymap_layout_get_name(keymap, idx)
#define xkb_map_group_get_index(keymap, str) \
xkb_keymap_layout_get_index(keymap, str)
#define xkb_map_num_leds(keymap) xkb_keymap_num_leds(keymap)
#define xkb_map_led_get_name(keymap, idx) xkb_keymap_led_get_name(keymap, idx)
#define xkb_map_led_get_index(keymap, str) \
xkb_keymap_led_get_index(keymap, str)
#define xkb_key_repeats(keymap, key) xkb_keymap_key_repeats(keymap, key)
#define xkb_key_get_syms(state, key, syms_out) \
xkb_state_key_get_syms(state, key, syms_out)
#define xkb_state_group_name_is_active(state, name, type) \
xkb_state_layout_name_is_active(state, name, type)
#define xkb_state_group_index_is_active(state, idx, type) \
xkb_state_layout_index_is_active(state, idx, type)
#define xkb_state_serialize_group(state, component) \
xkb_state_serialize_layout(state, component)
#define xkb_state_get_map(state) xkb_state_get_keymap(state)
/* Not needed anymore, since there's NO_FLAGS. */
#define XKB_MAP_COMPILE_PLACEHOLDER XKB_KEYMAP_COMPILE_NO_FLAGS
#define XKB_MAP_COMPILE_NO_FLAGS XKB_KEYMAP_COMPILE_NO_FLAGS
#endif

View file

@ -1,488 +0,0 @@
/*
* Copyright © 2013 Ran Benita
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _XKBCOMMON_COMPOSE_H
#define _XKBCOMMON_COMPOSE_H
#include <xkbcommon/xkbcommon.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* libxkbcommon Compose API - support for Compose and dead-keys.
*/
/**
* @defgroup compose Compose and dead-keys support
* Support for Compose and dead-keys.
* @since 0.5.0
*
* @{
*/
/**
* @page compose-overview Overview
* @parblock
*
* Compose and dead-keys are a common feature of many keyboard input
* systems. They extend the range of the keysysm that can be produced
* directly from a keyboard by using a sequence of key strokes, instead
* of just one.
*
* Here are some example sequences, in the libX11 Compose file format:
*
* <dead_acute> <a> : "á" aacute # LATIN SMALL LETTER A WITH ACUTE
* <Multi_key> <A> <T> : "@" at # COMMERCIAL AT
*
* When the user presses a key which produces the `<dead_acute>` keysym,
* nothing initially happens (thus the key is dubbed a "dead-key"). But
* when the user enters `<a>`, "á" is "composed", in place of "a". If
* instead the user had entered a keysym which does not follow
* `<dead_acute>` in any compose sequence, the sequence is said to be
* "cancelled".
*
* Compose files define many such sequences. For a description of the
* common file format for Compose files, see the Compose(5) man page.
*
* A successfuly-composed sequence has two results: a keysym and a UTF-8
* string. At least one of the two is defined for each sequence. If only
* a keysym is given, the keysym's string representation is used for the
* result string (using xkb_keysym_to_utf8()).
*
* This library provides low-level support for Compose file parsing and
* processing. Higher-level APIs (such as libX11's `Xutf8LookupString`(3))
* may be built upon it, or it can be used directly.
*
* @endparblock
*/
/**
* @page compose-conflicting Conflicting Sequences
* @parblock
*
* To avoid ambiguity, a sequence is not allowed to be a prefix of another.
* In such a case, the conflict is resolved thus:
*
* 1. A longer sequence overrides a shorter one.
* 2. An equal sequence overrides an existing one.
* 3. A shorter sequence does not override a longer one.
*
* Sequences of length 1 are allowed.
*
* @endparblock
*/
/**
* @page compose-cancellation Cancellation Behavior
* @parblock
*
* What should happen when a sequence is cancelled? For example, consider
* there are only the above sequences, and the input keysyms are
* `<dead_acute> <b>`. There are a few approaches:
*
* 1. Swallow the cancelling keysym; that is, no keysym is produced.
* This is the approach taken by libX11.
* 2. Let the cancelling keysym through; that is, `<b>` is produced.
* 3. Replay the entire sequence; that is, `<dead_acute> <b>` is produced.
* This is the approach taken by Microsoft Windows (approximately;
* instead of `<dead_acute>`, the underlying key is used. This is
* difficult to simulate with XKB keymaps).
*
* You can program whichever approach best fits users' expectations.
*
* @endparblock
*/
/**
* @struct xkb_compose_table
* Opaque Compose table object.
*
* The compose table holds the definitions of the Compose sequences, as
* gathered from Compose files. It is immutable.
*/
struct xkb_compose_table;
/**
* @struct xkb_compose_state
* Opaque Compose state object.
*
* The compose state maintains state for compose sequence matching, such
* as which possible sequences are being matched, and the position within
* these sequences. It acts as a simple state machine wherein keysyms are
* the input, and composed keysyms and strings are the output.
*
* The compose state is usually associated with a keyboard device.
*/
struct xkb_compose_state;
/** Flags affecting Compose file compilation. */
enum xkb_compose_compile_flags {
/** Do not apply any flags. */
XKB_COMPOSE_COMPILE_NO_FLAGS = 0
};
/** The recognized Compose file formats. */
enum xkb_compose_format {
/** The classic libX11 Compose text format, described in Compose(5). */
XKB_COMPOSE_FORMAT_TEXT_V1 = 1
};
/**
* @page compose-locale Compose Locale
* @parblock
*
* Compose files are locale dependent:
* - Compose files are written for a locale, and the locale is used when
* searching for the appropriate file to use.
* - Compose files may reference the locale internally, with directives
* such as \%L.
*
* As such, functions like xkb_compose_table_new_from_locale() require
* a `locale` parameter. This will usually be the current locale (see
* locale(7) for more details). You may also want to allow the user to
* explicitly configure it, so he can use the Compose file of a given
* locale, but not use that locale for other things.
*
* You may query the current locale as follows:
* @code
* const char *locale;
* locale = setlocale(LC_CTYPE, NULL);
* @endcode
*
* This will only give useful results if the program had previously set
* the current locale using setlocale(3), with `LC_CTYPE` or `LC_ALL`
* and a non-NULL argument.
*
* If you prefer not to use the locale system of the C runtime library,
* you may nevertheless obtain the user's locale directly using
* environment variables, as described in locale(7). For example,
* @code
* locale = getenv("LC_ALL");
* if (!locale)
* locale = getenv("LC_CTYPE");
* if (!locale)
* locale = getenv("LANG");
* if (!locale)
* locale = "C";
* @endcode
*
* Note that some locales supported by the C standard library may not
* have a Compose file assigned.
*
* @endparblock
*/
/**
* Create a compose table for a given locale.
*
* The locale is used for searching the file-system for an appropriate
* Compose file. The search order is described in Compose(5). It is
* affected by the following environment variables:
*
* 1. `XCOMPOSEFILE` - see Compose(5).
* 2. `HOME` - see Compose(5).
* 3. `XLOCALEDIR` - if set, used as the base directory for the system's
* X locale files, e.g. `/usr/share/X11/locale`, instead of the
* preconfigured directory.
*
* @param context
* The library context in which to create the compose table.
* @param locale
* The current locale. See @ref compose-locale.
* @param flags
* Optional flags for the compose table, or 0.
*
* @returns A compose table for the given locale, or NULL if the
* compilation failed or a Compose file was not found.
*
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_new_from_locale(struct xkb_context *context,
const char *locale,
enum xkb_compose_compile_flags flags);
/**
* Create a new compose table from a Compose file.
*
* @param context
* The library context in which to create the compose table.
* @param file
* The Compose file to compile.
* @param locale
* The current locale. See @ref compose-locale.
* @param format
* The text format of the Compose file to compile.
* @param flags
* Optional flags for the compose table, or 0.
*
* @returns A compose table compiled from the given file, or NULL if
* the compilation failed.
*
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_new_from_file(struct xkb_context *context,
FILE *file,
const char *locale,
enum xkb_compose_format format,
enum xkb_compose_compile_flags flags);
/**
* Create a new compose table from a memory buffer.
*
* This is just like xkb_compose_table_new_from_file(), but instead of
* a file, gets the table as one enormous string.
*
* @see xkb_compose_table_new_from_file()
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_new_from_buffer(struct xkb_context *context,
const char *buffer, size_t length,
const char *locale,
enum xkb_compose_format format,
enum xkb_compose_compile_flags flags);
/**
* Take a new reference on a compose table.
*
* @returns The passed in object.
*
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_ref(struct xkb_compose_table *table);
/**
* Release a reference on a compose table, and possibly free it.
*
* @param table The object. If it is NULL, this function does nothing.
*
* @memberof xkb_compose_table
*/
void
xkb_compose_table_unref(struct xkb_compose_table *table);
/** Flags for compose state creation. */
enum xkb_compose_state_flags {
/** Do not apply any flags. */
XKB_COMPOSE_STATE_NO_FLAGS = 0
};
/**
* Create a new compose state object.
*
* @param table
* The compose table the state will use.
* @param flags
* Optional flags for the compose state, or 0.
*
* @returns A new compose state, or NULL on failure.
*
* @memberof xkb_compose_state
*/
struct xkb_compose_state *
xkb_compose_state_new(struct xkb_compose_table *table,
enum xkb_compose_state_flags flags);
/**
* Take a new reference on a compose state object.
*
* @returns The passed in object.
*
* @memberof xkb_compose_state
*/
struct xkb_compose_state *
xkb_compose_state_ref(struct xkb_compose_state *state);
/**
* Release a reference on a compose state object, and possibly free it.
*
* @param state The object. If NULL, do nothing.
*
* @memberof xkb_compose_state
*/
void
xkb_compose_state_unref(struct xkb_compose_state *state);
/**
* Get the compose table which a compose state object is using.
*
* @returns The compose table which was passed to xkb_compose_state_new()
* when creating this state object.
*
* This function does not take a new reference on the compose table; you
* must explicitly reference it yourself if you plan to use it beyond the
* lifetime of the state.
*
* @memberof xkb_compose_state
*/
struct xkb_compose_table *
xkb_compose_state_get_compose_table(struct xkb_compose_state *state);
/** Status of the Compose sequence state machine. */
enum xkb_compose_status {
/** The initial state; no sequence has started yet. */
XKB_COMPOSE_NOTHING,
/** In the middle of a sequence. */
XKB_COMPOSE_COMPOSING,
/** A complete sequence has been matched. */
XKB_COMPOSE_COMPOSED,
/** The last sequence was cancelled due to an unmatched keysym. */
XKB_COMPOSE_CANCELLED
};
/** The effect of a keysym fed to xkb_compose_state_feed(). */
enum xkb_compose_feed_result {
/** The keysym had no effect - it did not affect the status. */
XKB_COMPOSE_FEED_IGNORED,
/** The keysym started, advanced or cancelled a sequence. */
XKB_COMPOSE_FEED_ACCEPTED
};
/**
* Feed one keysym to the Compose sequence state machine.
*
* This function can advance into a compose sequence, cancel a sequence,
* start a new sequence, or do nothing in particular. The resulting
* status may be observed with xkb_compose_state_get_status().
*
* Some keysyms, such as keysyms for modifier keys, are ignored - they
* have no effect on the status or otherwise.
*
* The following is a description of the possible status transitions, in
* the format CURRENT STATUS => NEXT STATUS, given a non-ignored input
* keysym `keysym`:
*
@verbatim
NOTHING or CANCELLED or COMPOSED =>
NOTHING if keysym does not start a sequence.
COMPOSING if keysym starts a sequence.
COMPOSED if keysym starts and terminates a single-keysym sequence.
COMPOSING =>
COMPOSING if keysym advances any of the currently possible
sequences but does not terminate any of them.
COMPOSED if keysym terminates one of the currently possible
sequences.
CANCELLED if keysym does not advance any of the currently
possible sequences.
@endverbatim
*
* The current Compose formats do not support multiple-keysyms.
* Therefore, if you are using a function such as xkb_state_key_get_syms()
* and it returns more than one keysym, consider feeding XKB_KEY_NoSymbol
* instead.
*
* @param state
* The compose state object.
* @param keysym
* A keysym, usually obtained after a key-press event, with a
* function such as xkb_state_key_get_one_sym().
*
* @returns Whether the keysym was ignored. This is useful, for example,
* if you want to keep a record of the sequence matched thus far.
*
* @memberof xkb_compose_state
*/
enum xkb_compose_feed_result
xkb_compose_state_feed(struct xkb_compose_state *state,
xkb_keysym_t keysym);
/**
* Reset the Compose sequence state machine.
*
* The status is set to XKB_COMPOSE_NOTHING, and the current sequence
* is discarded.
*
* @memberof xkb_compose_state
*/
void
xkb_compose_state_reset(struct xkb_compose_state *state);
/**
* Get the current status of the compose state machine.
*
* @see xkb_compose_status
* @memberof xkb_compose_state
**/
enum xkb_compose_status
xkb_compose_state_get_status(struct xkb_compose_state *state);
/**
* Get the result Unicode/UTF-8 string for a composed sequence.
*
* See @ref compose-overview for more details. This function is only
* useful when the status is XKB_COMPOSE_COMPOSED.
*
* @param[in] state
* The compose state.
* @param[out] buffer
* A buffer to write the string into.
* @param[in] size
* Size of the buffer.
*
* @warning If the buffer passed is too small, the string is truncated
* (though still NUL-terminated).
*
* @returns
* The number of bytes required for the string, excluding the NUL byte.
* If the sequence is not complete, or does not have a viable result
* string, returns 0, and sets `buffer` to the empty string (if possible).
* @returns
* You may check if truncation has occurred by comparing the return value
* with the size of `buffer`, similarly to the `snprintf`(3) function.
* You may safely pass NULL and 0 to `buffer` and `size` to find the
* required size (without the NUL-byte).
*
* @memberof xkb_compose_state
**/
int
xkb_compose_state_get_utf8(struct xkb_compose_state *state,
char *buffer, size_t size);
/**
* Get the result keysym for a composed sequence.
*
* See @ref compose-overview for more details. This function is only
* useful when the status is XKB_COMPOSE_COMPOSED.
*
* @returns The result keysym. If the sequence is not complete, or does
* not specify a result keysym, returns XKB_KEY_NoSymbol.
*
* @memberof xkb_compose_state
**/
xkb_keysym_t
xkb_compose_state_get_one_sym(struct xkb_compose_state *state);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _XKBCOMMON_COMPOSE_H */

View file

@ -1,45 +0,0 @@
/*
* Copyright © 2012 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#ifndef _XKBCOMMON_NAMES_H
#define _XKBCOMMON_NAMES_H
/**
* @file
* @brief Predefined names for common modifiers and LEDs.
*/
#define XKB_MOD_NAME_SHIFT "Shift"
#define XKB_MOD_NAME_CAPS "Lock"
#define XKB_MOD_NAME_CTRL "Control"
#define XKB_MOD_NAME_ALT "Mod1"
#define XKB_MOD_NAME_NUM "Mod2"
#define XKB_MOD_NAME_LOGO "Mod4"
#define XKB_LED_NAME_CAPS "Caps Lock"
#define XKB_LED_NAME_NUM "Num Lock"
#define XKB_LED_NAME_SCROLL "Scroll Lock"
#endif

View file

@ -1,244 +0,0 @@
/*
* Copyright © 2013 Ran Benita
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _XKBCOMMON_X11_H
#define _XKBCOMMON_X11_H
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* libxkbcommon-x11 API - Additional X11 support for xkbcommon.
*/
/**
* @defgroup x11 X11 support
* Additional X11 support for xkbcommon.
* @since 0.4.0
*
* @{
*/
/**
* @page x11-overview Overview
* @parblock
*
* The xkbcommon-x11 module provides a means for creating an xkb_keymap
* corresponding to the currently active keymap on the X server. To do
* so, it queries the XKB X11 extension using the xcb-xkb library. It
* can be used as a replacement for Xlib's keyboard handling.
*
* Following is an example workflow using xkbcommon-x11. A complete
* example may be found in the test/interactive-x11.c file in the
* xkbcommon source repository. On startup:
*
* 1. Connect to the X server using xcb_connect().
* 2. Setup the XKB X11 extension. You can do this either by using the
* xcb_xkb_use_extension() request directly, or by using the
* xkb_x11_setup_xkb_extension() helper function.
*
* The XKB extension supports using separate keymaps and states for
* different keyboard devices. The devices are identified by an integer
* device ID and are managed by another X11 extension, XInput (or its
* successor, XInput2). The original X11 protocol only had one keyboard
* device, called the "core keyboard", which is still supported as a
* "virtual device".
*
* 3. We will use the core keyboard as an example. To get its device ID,
* use either the xcb_xkb_get_device_info() request directly, or the
* xkb_x11_get_core_keyboard_device_id() helper function.
* 4. Create an initial xkb_keymap for this device, using the
* xkb_x11_keymap_new_from_device() function.
* 5. Create an initial xkb_state for this device, using the
* xkb_x11_state_new_from_device() function.
*
* @note At this point, you may consider setting various XKB controls and
* XKB per-client flags. For example, enabling detectable autorepeat: \n
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat
*
* Next, you need to react to state changes (e.g. a modifier was pressed,
* the layout was changed) and to keymap changes (e.g. a tool like xkbcomp,
* setxkbmap or xmodmap was used):
*
* 6. Select to listen to at least the following XKB events:
* NewKeyboardNotify, MapNotify, StateNotify; using the
* xcb_xkb_select_events_aux() request.
* 7. When NewKeyboardNotify or MapNotify are received, recreate the
* xkb_keymap and xkb_state as described above.
* 8. When StateNotify is received, update the xkb_state accordingly
* using the xkb_state_update_mask() function.
*
* @note It is also possible to use the KeyPress/KeyRelease @p state
* field to find the effective modifier and layout state, instead of
* using XkbStateNotify: \n
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State
* \n However, XkbStateNotify is more accurate.
*
* @note There is no need to call xkb_state_update_key(); the state is
* already synchronized.
*
* Finally, when a key event is received, you can use ordinary xkbcommon
* functions, like xkb_state_key_get_one_sym() and xkb_state_key_get_utf8(),
* as you normally would.
*
* @endparblock
*/
/**
* The minimal compatible major version of the XKB X11 extension which
* this library can use.
*/
#define XKB_X11_MIN_MAJOR_XKB_VERSION 1
/**
* The minimal compatible minor version of the XKB X11 extension which
* this library can use (for the minimal major version).
*/
#define XKB_X11_MIN_MINOR_XKB_VERSION 0
/** Flags for the xkb_x11_setup_xkb_extension() function. */
enum xkb_x11_setup_xkb_extension_flags {
/** Do not apply any flags. */
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS = 0
};
/**
* Setup the XKB X11 extension for this X client.
*
* The xkbcommon-x11 library uses various XKB requests. Before doing so,
* an X client must notify the server that it will be using the extension.
* This function (or an XCB equivalent) must be called before any other
* function in this library is used.
*
* Some X servers may not support or disable the XKB extension. If you
* want to support such servers, you need to use a different fallback.
*
* You may call this function several times; it is idempotent.
*
* @param connection
* An XCB connection to the X server.
* @param major_xkb_version
* See @p minor_xkb_version.
* @param minor_xkb_version
* The XKB extension version to request. To operate correctly, you
* must have (major_xkb_version, minor_xkb_version) >=
* (XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION),
* though this is not enforced.
* @param flags
* Optional flags, or 0.
* @param[out] major_xkb_version_out
* See @p minor_xkb_version_out.
* @param[out] minor_xkb_version_out
* Backfilled with the compatible XKB extension version numbers picked
* by the server. Can be NULL.
* @param[out] base_event_out
* Backfilled with the XKB base (also known as first) event code, needed
* to distinguish XKB events. Can be NULL.
* @param[out] base_error_out
* Backfilled with the XKB base (also known as first) error code, needed
* to distinguish XKB errors. Can be NULL.
*
* @returns 1 on success, or 0 on failure.
*/
int
xkb_x11_setup_xkb_extension(xcb_connection_t *connection,
uint16_t major_xkb_version,
uint16_t minor_xkb_version,
enum xkb_x11_setup_xkb_extension_flags flags,
uint16_t *major_xkb_version_out,
uint16_t *minor_xkb_version_out,
uint8_t *base_event_out,
uint8_t *base_error_out);
/**
* Get the keyboard device ID of the core X11 keyboard.
*
* @param connection An XCB connection to the X server.
*
* @returns A device ID which may be used with other xkb_x11_* functions,
* or -1 on failure.
*/
int32_t
xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection);
/**
* Create a keymap from an X11 keyboard device.
*
* This function queries the X server with various requests, fetches the
* details of the active keymap on a keyboard device, and creates an
* xkb_keymap from these details.
*
* @param context
* The context in which to create the keymap.
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
* @param flags
* Optional flags for the keymap, or 0.
*
* @returns A keymap retrieved from the X server, or NULL on failure.
*
* @memberof xkb_keymap
*/
struct xkb_keymap *
xkb_x11_keymap_new_from_device(struct xkb_context *context,
xcb_connection_t *connection,
int32_t device_id,
enum xkb_keymap_compile_flags flags);
/**
* Create a new keyboard state object from an X11 keyboard device.
*
* This function is the same as xkb_state_new(), only pre-initialized
* with the state of the device at the time this function is called.
*
* @param keymap
* The keymap for which to create the state.
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
*
* @returns A new keyboard state object, or NULL on failure.
*
* @memberof xkb_state
*/
struct xkb_state *
xkb_x11_state_new_from_device(struct xkb_keymap *keymap,
xcb_connection_t *connection,
int32_t device_id);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _XKBCOMMON_X11_H */

View file

@ -1,10 +0,0 @@
TEMPLATE = subdirs
qtHaveModule(dbus) {
!mac:!win32:SUBDIRS += fcitx
!mac:!win32:SUBDIRS += ibus
}
contains(QT_CONFIG, xcb-plugin): SUBDIRS += compose

View file

@ -1,449 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/****************************************************************************
**
** Copyright (c) 2007-2008, Apple, Inc.
**
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
**
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
**
** * Neither the name of Apple, Inc. nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
#import "qcocoaapplicationdelegate.h"
#import "qnswindowdelegate.h"
#import "qcocoamenuloader.h"
#include "qcocoaintegration.h"
#include <qevent.h>
#include <qurl.h>
#include <qdebug.h>
#include <qguiapplication.h>
#include <private/qguiapplication_p.h>
#include "qt_mac_p.h"
#include <qpa/qwindowsysteminterface.h>
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
static QCocoaApplicationDelegate *sharedCocoaApplicationDelegate = nil;
static void cleanupCocoaApplicationDelegate()
{
[sharedCocoaApplicationDelegate release];
}
QT_END_NAMESPACE
@implementation QCocoaApplicationDelegate
- (id)init
{
self = [super init];
if (self) {
inLaunch = true;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(updateScreens:)
name:NSApplicationDidChangeScreenParametersNotification
object:NSApp];
}
return self;
}
- (void)updateScreens:(NSNotification *)notification
{
Q_UNUSED(notification);
if (QCocoaIntegration *ci = QCocoaIntegration::instance())
ci->updateScreens();
}
- (void)dealloc
{
sharedCocoaApplicationDelegate = nil;
[dockMenu release];
[qtMenuLoader release];
if (reflectionDelegate) {
[[NSApplication sharedApplication] setDelegate:reflectionDelegate];
[reflectionDelegate release];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (sharedCocoaApplicationDelegate == nil) {
sharedCocoaApplicationDelegate = [super allocWithZone:zone];
return sharedCocoaApplicationDelegate;
qAddPostRoutine(cleanupCocoaApplicationDelegate);
}
}
return nil;
}
+ (QCocoaApplicationDelegate *)sharedDelegate
{
@synchronized(self) {
if (sharedCocoaApplicationDelegate == nil)
[[self alloc] init];
}
return [[sharedCocoaApplicationDelegate retain] autorelease];
}
- (void)setDockMenu:(NSMenu*)newMenu
{
[newMenu retain];
[dockMenu release];
dockMenu = newMenu;
}
- (NSMenu *)applicationDockMenu:(NSApplication *)sender
{
Q_UNUSED(sender);
// Manually invoke the delegate's -menuWillOpen: method.
// See QTBUG-39604 (and its fix) for details.
[[dockMenu delegate] menuWillOpen:dockMenu];
return [[dockMenu retain] autorelease];
}
- (void)setMenuLoader:(QCocoaMenuLoader *)menuLoader
{
[menuLoader retain];
[qtMenuLoader release];
qtMenuLoader = menuLoader;
}
- (QCocoaMenuLoader *)menuLoader
{
return [[qtMenuLoader retain] autorelease];
}
- (BOOL) canQuit
{
[[NSApp mainMenu] cancelTracking];
bool handle_quit = true;
NSMenuItem *quitMenuItem = [[[QCocoaApplicationDelegate sharedDelegate] menuLoader] quitMenuItem];
if (!QGuiApplicationPrivate::instance()->modalWindowList.isEmpty()
&& [quitMenuItem isEnabled]) {
int visible = 0;
const QWindowList tlws = QGuiApplication::topLevelWindows();
for (int i = 0; i < tlws.size(); ++i) {
if (tlws.at(i)->isVisible())
++visible;
}
handle_quit = (visible <= 1);
}
if (handle_quit) {
QCloseEvent ev;
QGuiApplication::sendEvent(qGuiApp, &ev);
if (ev.isAccepted()) {
return YES;
}
}
return NO;
}
// This function will only be called when NSApp is actually running.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
// The reflection delegate gets precedence
if (reflectionDelegate) {
if ([reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)])
return [reflectionDelegate applicationShouldTerminate:sender];
//return NSTerminateNow;
}
if ([self canQuit]) {
if (!startedQuit) {
startedQuit = true;
// Close open windows. This is done in order to deliver de-expose
// events while the event loop is still running.
const QWindowList topLevels = QGuiApplication::topLevelWindows();
for (int i = 0; i < topLevels.size(); ++i) {
QWindow *topLevelWindow = topLevels.at(i);
// Widgets have alreay received a CloseEvent from the QApplication
// QCloseEvent handler. (see canQuit above). Prevent running the
// CloseEvent logic twice, call close() directly.
if (topLevelWindow->inherits("QWidgetWindow"))
topLevelWindow->close();
else
QWindowSystemInterface::handleCloseEvent(topLevelWindow);
}
QWindowSystemInterface::flushWindowSystemEvents();
QGuiApplication::exit(0);
startedQuit = false;
}
}
if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) {
// INVARIANT: No event loop is executing. This probably
// means that Qt is used as a plugin, or as a part of a native
// Cocoa application. In any case it should be fine to
// terminate now:
return NSTerminateNow;
}
return NSTerminateCancel;
}
- (void) applicationWillFinishLaunching:(NSNotification *)notification
{
Q_UNUSED(notification);
/*
From the Cocoa documentation: "A good place to install event handlers
is in the applicationWillFinishLaunching: method of the application
delegate. At that point, the Application Kit has installed its default
event handlers, so if you install a handler for one of the same events,
it will replace the Application Kit version."
*/
/*
If Qt is used as a plugin, we let the 3rd party application handle
events like quit and open file events. Otherwise, if we install our own
handlers, we easily end up breaking functionality the 3rd party
application depends on.
*/
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager setEventHandler:self
andSelector:@selector(appleEventQuit:withReplyEvent:)
forEventClass:kCoreEventClass
andEventID:kAEQuitApplication];
[eventManager setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
}
// called by QCocoaIntegration's destructor before resetting the application delegate to nil
- (void) removeAppleEventHandlers
{
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication];
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Q_UNUSED(aNotification);
inLaunch = false;
// qt_release_apple_event_handler();
// Insert code here to initialize your application
}
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
{
Q_UNUSED(filenames);
Q_UNUSED(sender);
for (NSString *fileName in filenames) {
QString qtFileName = QCFString::toQString(fileName);
if (inLaunch) {
// We need to be careful because Cocoa will be nice enough to take
// command line arguments and send them to us as events. Given the history
// of Qt Applications, this will result in behavior people don't want, as
// they might be doing the opening themselves with the command line parsing.
if (qApp->arguments().contains(qtFileName))
continue;
}
QWindowSystemInterface::handleFileOpenEvent(qtFileName);
}
if (reflectionDelegate &&
[reflectionDelegate respondsToSelector:@selector(application:openFiles:)])
[reflectionDelegate application:sender openFiles:filenames];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
// If we have a reflection delegate, that will get to call the shots.
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:
@selector(applicationShouldTerminateAfterLastWindowClosed:)])
return [reflectionDelegate applicationShouldTerminateAfterLastWindowClosed:sender];
return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together.
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
[reflectionDelegate applicationDidBecomeActive:notification];
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
/*
onApplicationChangedActivation(true);
if (!QWidget::mouseGrabber()){
// Update enter/leave immidiatly, don't wait for a move event. But only
// if no grab exists (even if the grab points to this widget, it seems, ref X11)
QPoint qlocal, qglobal;
QWidget *widgetUnderMouse = 0;
qt_mac_getTargetForMouseEvent(0, QEvent::Enter, qlocal, qglobal, 0, &widgetUnderMouse);
QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, 0);
qt_last_mouse_receiver = widgetUnderMouse;
qt_last_native_mouse_receiver = widgetUnderMouse ?
(widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0;
}
*/
}
- (void)applicationDidResignActive:(NSNotification *)notification
{
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
[reflectionDelegate applicationDidResignActive:notification];
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
/*
onApplicationChangedActivation(false);
if (!QWidget::mouseGrabber())
QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver);
qt_last_mouse_receiver = 0;
qt_last_native_mouse_receiver = 0;
qt_button_down = 0;
*/
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
Q_UNUSED(theApplication);
Q_UNUSED(flag);
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationShouldHandleReopen:hasVisibleWindows:)])
return [reflectionDelegate applicationShouldHandleReopen:theApplication hasVisibleWindows:flag];
/*
true to force delivery of the event even if the application state is already active,
because rapp (handle reopen) events are sent each time the dock icon is clicked regardless
of the active state of the application or number of visible windows. For example, a browser
app that has no windows opened would need the event be to delivered even if it was already
active in order to create a new window as per OS X conventions.
*/
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
return YES;
}
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
{
[oldDelegate retain];
[reflectionDelegate release];
reflectionDelegate = oldDelegate;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *result = [super methodSignatureForSelector:aSelector];
if (!result && reflectionDelegate) {
result = [reflectionDelegate methodSignatureForSelector:aSelector];
}
return result;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
BOOL result = [super respondsToSelector:aSelector];
if (!result && reflectionDelegate)
result = [reflectionDelegate respondsToSelector:aSelector];
return result;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
SEL invocationSelector = [invocation selector];
if (reflectionDelegate && [reflectionDelegate respondsToSelector:invocationSelector])
[invocation invokeWithTarget:reflectionDelegate];
else
[self doesNotRecognizeSelector:invocationSelector];
}
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
Q_UNUSED(replyEvent);
NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
QWindowSystemInterface::handleFileOpenEvent(QUrl(QCFString::toQString(urlString)));
}
- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
Q_UNUSED(event);
Q_UNUSED(replyEvent);
[NSApp terminate:self];
}
- (void)qtDispatcherToQAction:(id)sender
{
Q_UNUSED(sender);
[qtMenuLoader qtDispatcherToQPAMenuItem:sender];
}
@end

View file

@ -1,70 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QBACKINGSTORE_COCOA_H
#define QBACKINGSTORE_COCOA_H
#include <Cocoa/Cocoa.h>
#include "qcocoawindow.h"
#include "qnsview.h"
#include <qpa/qplatformbackingstore.h>
QT_BEGIN_NAMESPACE
class QCocoaBackingStore : public QPlatformBackingStore
{
public:
QCocoaBackingStore(QWindow *window);
~QCocoaBackingStore();
QPaintDevice *paintDevice();
void flush(QWindow *widget, const QRegion &region, const QPoint &offset);
QImage toImage() const;
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &region);
void beforeBeginPaint(QWindow *widget);
void afterEndPaint(QWindow *widget);
qreal getBackingStoreDevicePixelRatio();
private:
QImage m_qImage;
QSize m_requestedSize;
bool m_qImageNeedsClear, m_imageWasEqual;
};
QT_END_NAMESPACE
#endif

View file

@ -1,137 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcocoabackingstore.h"
#include <QtGui/QPainter>
#include "qcocoahelpers.h"
QT_BEGIN_NAMESPACE
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
: QPlatformBackingStore(window), m_qImageNeedsClear(false), m_imageWasEqual(false)
{
}
QCocoaBackingStore::~QCocoaBackingStore()
{
}
QPaintDevice *QCocoaBackingStore::paintDevice()
{
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
int windowDevicePixelRatio = int(cocoaWindow->devicePixelRatio());
// Receate the backing store buffer if the effective buffer size has changed,
// either due to a window resize or devicePixelRatio change.
QSize effectiveBufferSize = m_requestedSize * windowDevicePixelRatio;
if (m_qImage.size() != effectiveBufferSize) {
QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient)
? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
m_qImageNeedsClear = window()->requestedFormat().hasAlpha() || cocoaWindow->m_drawContentBorderGradient;
m_qImage = QImage(effectiveBufferSize, format);
m_qImage.setDevicePixelRatio(windowDevicePixelRatio);
if (m_qImageNeedsClear)
m_qImage.fill(Qt::transparent);
}
return &m_qImage;
}
void QCocoaBackingStore::flush(QWindow *win, const QRegion &region, const QPoint &offset)
{
if (!m_qImage.isNull()) {
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(win->handle()))
[cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset];
}
}
QImage QCocoaBackingStore::toImage() const
{
return m_qImage;
}
void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
{
m_requestedSize = size;
}
bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
{
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
const qreal devicePixelRatio = m_qImage.devicePixelRatio();
QPoint qpoint(dx * devicePixelRatio, dy * devicePixelRatio);
const QVector<QRect> qrects = area.rects();
for (int i = 0; i < qrects.count(); ++i) {
const QRect &qrect = QRect(qrects.at(i).topLeft() * devicePixelRatio, qrects.at(i).size() * devicePixelRatio);
qt_scrollRectInImage(m_qImage, qrect, qpoint);
}
return true;
}
void QCocoaBackingStore::beginPaint(const QRegion &region)
{
if (m_qImageNeedsClear && m_qImage.hasAlphaChannel()) {
QPainter p(&m_qImage);
p.setCompositionMode(QPainter::CompositionMode_Source);
const QVector<QRect> rects = region.rects();
const QColor blank = Qt::transparent;
for (QVector<QRect>::const_iterator it = rects.begin(), end = rects.end(); it != end; ++it)
p.fillRect(*it, blank);
}
}
void QCocoaBackingStore::beforeBeginPaint(QWindow *win) {
m_imageWasEqual = false;
if (!m_qImage.isNull()) {
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(win->handle())) {
if ([cocoaWindow->m_qtView beforeBeginPaint:this])
m_imageWasEqual = true;
}
}
}
void QCocoaBackingStore::afterEndPaint(QWindow *win) {
if (!m_qImage.isNull()) {
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(win->handle())) {
if (m_imageWasEqual)
[cocoaWindow->m_qtView afterEndPaint:this];
}
}
m_imageWasEqual = false;
}
qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio()
{
return m_qImage.devicePixelRatio();
}
QT_END_NAMESPACE

View file

@ -1,323 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcocoacursor.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include "qcocoaautoreleasepool.h"
#include <QtGui/QBitmap>
QT_BEGIN_NAMESPACE
QCocoaCursor::QCocoaCursor()
{
}
QCocoaCursor::~QCocoaCursor()
{
// release cursors
QHash<Qt::CursorShape, NSCursor *>::const_iterator i = m_cursors.constBegin();
while (i != m_cursors.constEnd()) {
[*i release];
++i;
}
}
void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window)
{
NSCursor * cocoaCursor = convertCursor(cursor);
if (QPlatformWindow * platformWindow = window->handle())
static_cast<QCocoaWindow *>(platformWindow)->setWindowCursor(cocoaCursor);
}
QPoint QCocoaCursor::pos() const
{
return qt_mac_flipPoint([NSEvent mouseLocation]).toPoint();
}
void QCocoaCursor::setPos(const QPoint &position)
{
CGPoint pos;
pos.x = position.x();
pos.y = position.y();
CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, e);
CFRelease(e);
}
NSCursor *QCocoaCursor::convertCursor(QCursor * cursor)
{
const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
NSCursor *cocoaCursor;
// Check for a suitable built-in NSCursor first:
switch (newShape) {
case Qt::ArrowCursor:
cocoaCursor= [NSCursor arrowCursor];
break;
case Qt::CrossCursor:
cocoaCursor = [NSCursor crosshairCursor];
break;
case Qt::IBeamCursor:
cocoaCursor = [NSCursor IBeamCursor];
break;
case Qt::WhatsThisCursor: //for now just use the pointing hand
case Qt::PointingHandCursor:
cocoaCursor = [NSCursor pointingHandCursor];
break;
case Qt::SplitVCursor:
cocoaCursor = [NSCursor resizeUpDownCursor];
break;
case Qt::SplitHCursor:
cocoaCursor = [NSCursor resizeLeftRightCursor];
break;
case Qt::OpenHandCursor:
cocoaCursor = [NSCursor openHandCursor];
break;
case Qt::ClosedHandCursor:
cocoaCursor = [NSCursor closedHandCursor];
break;
case Qt::DragMoveCursor:
cocoaCursor = [NSCursor crosshairCursor];
break;
case Qt::DragCopyCursor:
cocoaCursor = [NSCursor crosshairCursor];
break;
case Qt::DragLinkCursor:
cocoaCursor = [NSCursor dragLinkCursor];
break;
default : {
// No suitable OS cursor exist, use cursors provided
// by Qt for the rest. Check for a cached cursor:
cocoaCursor = m_cursors.value(newShape);
if (cocoaCursor && cursor->shape() == Qt::BitmapCursor) {
[cocoaCursor release];
cocoaCursor = 0;
}
if (cocoaCursor == 0) {
cocoaCursor = createCursorData(cursor);
if (cocoaCursor == 0)
return [NSCursor arrowCursor];
m_cursors.insert(newShape, cocoaCursor);
}
break; }
}
return cocoaCursor;
}
// Creates an NSCursor for the given QCursor.
NSCursor *QCocoaCursor::createCursorData(QCursor *cursor)
{
/* Note to self... ***
* mask x data
* 0xFF x 0x00 == fully opaque white
* 0x00 x 0xFF == xor'd black
* 0xFF x 0xFF == fully opaque black
* 0x00 x 0x00 == fully transparent
*/
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
static const uchar cur_ver_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0f, 0xf0,
0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00 };
static const uchar mcur_ver_bits[] = {
0x00, 0x00, 0x03, 0x80, 0x07, 0xc0, 0x0f, 0xe0, 0x1f, 0xf0, 0x3f, 0xf8,
0x7f, 0xfc, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x7f, 0xfc, 0x3f, 0xf8,
0x1f, 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80 };
static const uchar cur_hor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x18, 0x30,
0x38, 0x38, 0x7f, 0xfc, 0x7f, 0xfc, 0x38, 0x38, 0x18, 0x30, 0x08, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const uchar mcur_hor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x0c, 0x60, 0x1c, 0x70, 0x3c, 0x78,
0x7f, 0xfc, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfc, 0x3c, 0x78,
0x1c, 0x70, 0x0c, 0x60, 0x04, 0x40, 0x00, 0x00 };
static const uchar cur_fdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0xf8, 0x00, 0x78,
0x00, 0xf8, 0x01, 0xd8, 0x23, 0x88, 0x37, 0x00, 0x3e, 0x00, 0x3c, 0x00,
0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const uchar mcur_fdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0xfc,
0x41, 0xfc, 0x63, 0xfc, 0x77, 0xdc, 0x7f, 0x8c, 0x7f, 0x04, 0x7e, 0x00,
0x7f, 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x00, 0x00 };
static const uchar cur_bdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e, 0x00,
0x37, 0x00, 0x23, 0x88, 0x01, 0xd8, 0x00, 0xf8, 0x00, 0x78, 0x00, 0xf8,
0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const uchar mcur_bdiag_bits[] = {
0x00, 0x00, 0x7f, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7e, 0x00, 0x7f, 0x04,
0x7f, 0x8c, 0x77, 0xdc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01, 0xfc,
0x03, 0xfc, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00 };
static const unsigned char cur_up_arrow_bits[] = {
0x00, 0x80, 0x01, 0x40, 0x01, 0x40, 0x02, 0x20, 0x02, 0x20, 0x04, 0x10,
0x04, 0x10, 0x08, 0x08, 0x0f, 0x78, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,
0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0xc0 };
static const unsigned char mcur_up_arrow_bits[] = {
0x00, 0x80, 0x01, 0xc0, 0x01, 0xc0, 0x03, 0xe0, 0x03, 0xe0, 0x07, 0xf0,
0x07, 0xf0, 0x0f, 0xf8, 0x0f, 0xf8, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0 };
#endif
const uchar *cursorData = 0;
const uchar *cursorMaskData = 0;
QPoint hotspot = cursor->hotSpot();
switch (cursor->shape()) {
case Qt::BitmapCursor: {
if (cursor->pixmap().isNull())
return createCursorFromBitmap(cursor->bitmap(), cursor->mask(), hotspot);
else
return createCursorFromPixmap(cursor->pixmap(), hotspot);
break; }
case Qt::BlankCursor: {
QPixmap pixmap = QPixmap(16, 16);
pixmap.fill(Qt::transparent);
return createCursorFromPixmap(pixmap);
break; }
case Qt::WaitCursor: {
QPixmap pixmap = QPixmap(QLatin1String(":/qt-project.org/mac/cursors/images/spincursor.png"));
return createCursorFromPixmap(pixmap, hotspot);
break; }
case Qt::SizeAllCursor: {
QPixmap pixmap = QPixmap(QLatin1String(":/qt-project.org/mac/cursors/images/sizeallcursor.png"));
return createCursorFromPixmap(pixmap, QPoint(8, 8));
break; }
case Qt::BusyCursor: {
QPixmap pixmap = QPixmap(QLatin1String(":/qt-project.org/mac/cursors/images/waitcursor.png"));
return createCursorFromPixmap(pixmap, hotspot);
break; }
case Qt::ForbiddenCursor: {
QPixmap pixmap = QPixmap(QLatin1String(":/qt-project.org/mac/cursors/images/forbiddencursor.png"));
return createCursorFromPixmap(pixmap, hotspot);
break; }
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
cursorData = cur_ver_bits;
cursorMaskData = mcur_ver_bits;
hotspot = QPoint(8, 8);
break;
case Qt::SizeHorCursor:
cursorData = cur_hor_bits;
cursorMaskData = mcur_hor_bits;
hotspot = QPoint(8, 8);
break;
case Qt::SizeBDiagCursor:
cursorData = cur_fdiag_bits;
cursorMaskData = mcur_fdiag_bits;
hotspot = QPoint(8, 8);
break;
case Qt::SizeFDiagCursor:
cursorData = cur_bdiag_bits;
cursorMaskData = mcur_bdiag_bits;
hotspot = QPoint(8, 8);
break;
case Qt::UpArrowCursor:
cursorData = cur_up_arrow_bits;
cursorMaskData = mcur_up_arrow_bits;
hotspot = QPoint(8, 0);
break;
#endif
default:
qWarning("Qt: QCursor::update: Invalid cursor shape %d", cursor->shape());
return 0;
}
// Create an NSCursor from image data if this a self-provided cursor.
if (cursorData) {
QBitmap bitmap(QBitmap::fromData(QSize(16, 16), cursorData, QImage::Format_Mono));
QBitmap mask(QBitmap::fromData(QSize(16, 16), cursorMaskData, QImage::Format_Mono));
return (createCursorFromBitmap(&bitmap, &mask, hotspot));
}
return 0; // should not happen, all cases covered above
}
NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap *bitmap, const QBitmap *mask, const QPoint hotspot)
{
QImage finalCursor(bitmap->size(), QImage::Format_ARGB32);
QImage bmi = bitmap->toImage().convertToFormat(QImage::Format_RGB32);
QImage bmmi = mask->toImage().convertToFormat(QImage::Format_RGB32);
for (int row = 0; row < finalCursor.height(); ++row) {
QRgb *bmData = reinterpret_cast<QRgb *>(bmi.scanLine(row));
QRgb *bmmData = reinterpret_cast<QRgb *>(bmmi.scanLine(row));
QRgb *finalData = reinterpret_cast<QRgb *>(finalCursor.scanLine(row));
for (int col = 0; col < finalCursor.width(); ++col) {
if (bmmData[col] == 0xff000000 && bmData[col] == 0xffffffff) {
finalData[col] = 0xffffffff;
} else if (bmmData[col] == 0xff000000 && bmData[col] == 0xffffffff) {
finalData[col] = 0x7f000000;
} else if (bmmData[col] == 0xffffffff && bmData[col] == 0xffffffff) {
finalData[col] = 0x00000000;
} else {
finalData[col] = 0xff000000;
}
}
}
return createCursorFromPixmap(QPixmap::fromImage(finalCursor), hotspot);
}
NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoint hotspot)
{
NSPoint hotSpot = NSMakePoint(hotspot.x(), hotspot.y());
NSImage *nsimage;
if (pixmap.devicePixelRatio() > 1.0) {
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio();
QPixmap scaledPixmap = pixmap.scaled(layoutSize);
nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap));
CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage());
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
[nsimage addRepresentation:imageRep];
[imageRep release];
CGImageRelease(cgImage);
} else {
nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
}
NSCursor *nsCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot];
[nsimage release];
return nsCursor;
}
QT_END_NAMESPACE

View file

@ -1,550 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/****************************************************************************
**
** Copyright (c) 2007-2008, Apple, Inc.
**
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
**
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
**
** * Neither the name of Apple, Inc. nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
#define QT_MAC_SYSTEMTRAY_USE_GROWL
#include "qcocoasystemtrayicon.h"
#include <qtemporaryfile.h>
#include <qimagewriter.h>
#include <qdebug.h>
#include "qcocoamenu.h"
#include "qt_mac_p.h"
#include "qcocoahelpers.h"
#import <AppKit/AppKit.h>
QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QNSMenu);
@class QT_MANGLE_NAMESPACE(QNSImageView);
@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
<NSUserNotificationCenterDelegate>
#endif
{
@public
QCocoaSystemTrayIcon *systray;
NSStatusItem *item;
QCocoaMenu *menu;
bool menuVisible, iconSelected;
QIcon icon;
QT_MANGLE_NAMESPACE(QNSImageView) *imageCell;
}
-(id)initWithSysTray:(QCocoaSystemTrayIcon *)systray;
-(void)dealloc;
-(NSStatusItem*)item;
-(QRectF)geometry;
- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton;
- (void)doubleClickSelector:(id)sender;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification;
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification;
#endif
@end
@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView {
BOOL down;
QT_MANGLE_NAMESPACE(QNSStatusItem) *parent;
}
-(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent;
-(void)menuTrackingDone:(NSNotification*)notification;
-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
@end
@interface QT_MANGLE_NAMESPACE(QNSMenu) : NSMenu <NSMenuDelegate> {
QPlatformMenu *qmenu;
}
-(QPlatformMenu*)menu;
-(id)initWithQMenu:(QPlatformMenu*)qmenu;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSStatusItem);
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSImageView);
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSMenu);
QT_BEGIN_NAMESPACE
class QSystemTrayIconSys
{
public:
QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) {
item = [[QNSStatusItem alloc] initWithSysTray:sys];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item];
}
#endif
}
~QSystemTrayIconSys() {
[[[item item] view] setHidden: YES];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
}
#endif
[item release];
}
QNSStatusItem *item;
};
void QCocoaSystemTrayIcon::init()
{
if (!m_sys)
m_sys = new QSystemTrayIconSys(this);
}
QRect QCocoaSystemTrayIcon::geometry() const
{
if (!m_sys)
return QRect();
const QRectF geom = [m_sys->item geometry];
if (!geom.isNull())
return geom.toRect();
else
return QRect();
}
void QCocoaSystemTrayIcon::cleanup()
{
delete m_sys;
m_sys = 0;
}
static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); }
static QList<QSize> sortByHeight(const QList<QSize> &sizes)
{
QList<QSize> sorted = sizes;
std::sort(sorted.begin(), sorted.end(), heightCompareFunction);
return sorted;
}
void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
{
if (!m_sys)
return;
m_sys->item->icon = icon;
// The reccomended maximum title bar icon height is 18 points
// (device independent pixels). The menu height on past and
// current OS X versions is 22 points. Provide some future-proofing
// by deriving the icon height from the menu height.
const int padding = 0;
const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
const int maxImageHeight = menuHeight - padding;
// Select pixmap based on the device pixel height. Ideally we would use
// the devicePixelRatio of the target screen, but that value is not
// known until draw time. Use qApp->devicePixelRatio, which returns the
// devicePixelRatio for the "best" screen on the system.
qreal devicePixelRatio = qApp->devicePixelRatio();
const int maxPixmapHeight = maxImageHeight * devicePixelRatio;
const QIcon::Mode mode = m_sys->item->iconSelected ? QIcon::Selected : QIcon::Normal;
QSize selectedSize;
Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) {
// Select a pixmap based on the height. We want the largest pixmap
// with a height smaller or equal to maxPixmapHeight. The pixmap
// may rectangular; assume it has a reasonable size. If there is
// not suitable pixmap use the smallest one the icon can provide.
if (size.height() <= maxPixmapHeight) {
selectedSize = size;
} else {
if (!selectedSize.isValid())
selectedSize = size;
break;
}
}
// Handle SVG icons, which do not return anything for availableSizes().
if (!selectedSize.isValid())
selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode);
QPixmap pixmap = icon.pixmap(selectedSize, mode);
// Draw a low-resolution icon if there is not enough pixels for a retina
// icon. This prevents showing a small icon on retina displays.
if (devicePixelRatio > 1.0 && selectedSize.height() < maxPixmapHeight / 2)
devicePixelRatio = 1.0;
// Scale large pixmaps to fit the available menu bar area.
if (pixmap.height() > maxPixmapHeight)
pixmap = pixmap.scaledToHeight(maxPixmapHeight, Qt::SmoothTransformation);
// The icon will be stretched over the full height of the menu bar
// therefore we create a second pixmap which has the full height
QSize fullHeightSize(!pixmap.isNull() ? pixmap.width():
menuHeight * devicePixelRatio,
menuHeight * devicePixelRatio);
QPixmap fullHeightPixmap(fullHeightSize);
fullHeightPixmap.fill(Qt::transparent);
if (!pixmap.isNull()) {
QPainter p(&fullHeightPixmap);
QRect r = pixmap.rect();
r.moveCenter(fullHeightPixmap.rect().center());
p.drawPixmap(r, pixmap);
}
NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap));
[(NSImageView*)[[m_sys->item item] view] setImage: nsimage];
[nsimage release];
}
void QCocoaSystemTrayIcon::updateMenu(QPlatformMenu *menu)
{
if (!m_sys)
return;
m_sys->item->menu = static_cast<QCocoaMenu *>(menu);
if (menu && [m_sys->item->menu->nsMenu() numberOfItems] > 0) {
[[m_sys->item item] setHighlightMode:YES];
} else {
[[m_sys->item item] setHighlightMode:NO];
}
}
void QCocoaSystemTrayIcon::updateToolTip(const QString &toolTip)
{
if (!m_sys)
return;
[[[m_sys->item item] view] setToolTip:QCFString::toNSString(toolTip)];
}
bool QCocoaSystemTrayIcon::isSystemTrayAvailable() const
{
return true;
}
bool QCocoaSystemTrayIcon::supportsMessages() const
{
return true;
}
void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &message,
const QIcon& icon, MessageIcon, int)
{
if (!m_sys)
return;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
NSUserNotification *notification = [[NSUserNotification alloc] init];
notification.title = [NSString stringWithUTF8String:title.toUtf8().data()];
notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
return;
}
#endif
#ifdef QT_MAC_SYSTEMTRAY_USE_GROWL
// Make sure that we have Growl installed on the machine we are running on.
QCFType<CFURLRef> cfurl;
OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator,
CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
if (status == kLSApplicationNotFoundErr)
return;
QCFType<CFBundleRef> bundle = CFBundleCreate(0, cfurl);
if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"),
kCFCompareCaseInsensitive | kCFCompareBackwards) != kCFCompareEqualTo)
return;
QPixmap notificationIconPixmap = icon.pixmap(32, 32);
QTemporaryFile notificationIconFile;
QString notificationType(QLatin1String("Notification")), notificationIcon, notificationApp(qt_mac_applicationName());
if (notificationApp.isEmpty())
notificationApp = QLatin1String("Application");
if (!notificationIconPixmap.isNull() && notificationIconFile.open()) {
QImageWriter writer(&notificationIconFile, "PNG");
if (writer.write(notificationIconPixmap.toImage()))
notificationIcon = QLatin1String("image from location \"file://") + notificationIconFile.fileName() + QLatin1String("\"");
}
const QString script(QLatin1String(
"tell application \"System Events\"\n"
"set isRunning to (count of (every process whose bundle identifier is \"com.Growl.GrowlHelperApp\")) > 0\n"
"end tell\n"
"if isRunning\n"
"tell application id \"com.Growl.GrowlHelperApp\"\n"
"-- Make a list of all the notification types (all)\n"
"set the allNotificationsList to {\"") + notificationType + QLatin1String("\"}\n"
"-- Make a list of the notifications (enabled)\n"
"set the enabledNotificationsList to {\"") + notificationType + QLatin1String("\"}\n"
"-- Register our script with growl.\n"
"register as application \"") + notificationApp + QLatin1String("\" all notifications allNotificationsList default notifications enabledNotificationsList\n"
"-- Send a Notification...\n") +
QLatin1String("notify with name \"") + notificationType +
QLatin1String("\" title \"") + title +
QLatin1String("\" description \"") + message +
QLatin1String("\" application name \"") + notificationApp +
QLatin1String("\" ") + notificationIcon +
QLatin1String("\nend tell\nend if"));
qt_mac_execute_apple_script(script, 0);
#else
Q_UNUSED(icon);
Q_UNUSED(title);
Q_UNUSED(message);
#endif
}
QT_END_NAMESPACE
@implementation NSStatusItem (Qt)
@end
@implementation QNSImageView
-(id)initWithParent:(QNSStatusItem*)myParent {
self = [super init];
parent = myParent;
down = NO;
return self;
}
-(void)menuTrackingDone:(NSNotification*)notification
{
Q_UNUSED(notification);
down = NO;
parent->iconSelected = false;
parent->systray->updateIcon(parent->icon);
parent->menuVisible = false;
[self setNeedsDisplay:YES];
}
-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton
{
down = YES;
int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
parent->iconSelected = (clickCount != 2) && parent->menu;
parent->systray->updateIcon(parent->icon);
if (clickCount == 2) {
[self menuTrackingDone:nil];
[parent doubleClickSelector:self];
} else {
[parent triggerSelector:self button:mouseButton];
}
}
-(void)mouseDown:(NSEvent *)mouseEvent
{
[self mousePressed:mouseEvent button:Qt::LeftButton];
}
-(void)mouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
parent->iconSelected = false;
parent->systray->updateIcon(parent->icon);
[self menuTrackingDone:nil];
}
- (void)rightMouseDown:(NSEvent *)mouseEvent
{
[self mousePressed:mouseEvent button:Qt::RightButton];
}
-(void)rightMouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
parent->iconSelected = false;
parent->systray->updateIcon(parent->icon);
[self menuTrackingDone:nil];
}
- (void)otherMouseDown:(NSEvent *)mouseEvent
{
[self mousePressed:mouseEvent button:cocoaButton2QtButton([mouseEvent buttonNumber])];
}
-(void)otherMouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
[self menuTrackingDone:nil];
}
-(void)drawRect:(NSRect)rect {
[[parent item] drawStatusBarBackgroundInRect:rect withHighlight:parent->menu ? down : NO];
[super drawRect:rect];
}
@end
@implementation QNSStatusItem
-(id)initWithSysTray:(QCocoaSystemTrayIcon *)sys
{
self = [super init];
if (self) {
item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
menu = 0;
menuVisible = false;
systray = sys;
imageCell = [[QNSImageView alloc] initWithParent:self];
[item setView: imageCell];
}
return self;
}
-(void)dealloc {
[[NSStatusBar systemStatusBar] removeStatusItem:item];
[[NSNotificationCenter defaultCenter] removeObserver:imageCell];
[imageCell release];
[item release];
[super dealloc];
}
-(NSStatusItem*)item {
return item;
}
-(QRectF)geometry {
if (NSWindow *window = [[item view] window]) {
NSRect screenRect = [[window screen] frame];
NSRect windowRect = [window frame];
return QRectF(windowRect.origin.x, screenRect.size.height-windowRect.origin.y-windowRect.size.height, windowRect.size.width, windowRect.size.height);
}
return QRectF();
}
- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton {
Q_UNUSED(sender);
if (!systray)
return;
if (mouseButton == Qt::MidButton)
emit systray->activated(QPlatformSystemTrayIcon::MiddleClick);
else
emit systray->activated(QPlatformSystemTrayIcon::Trigger);
if (menu) {
NSMenu *m = menu->nsMenu();
[[NSNotificationCenter defaultCenter] addObserver:imageCell
selector:@selector(menuTrackingDone:)
name:NSMenuDidEndTrackingNotification
object:m];
menuVisible = true;
[item popUpStatusItemMenu: m];
}
}
- (void)doubleClickSelector:(id)sender {
Q_UNUSED(sender);
if (!systray)
return;
emit systray->activated(QPlatformSystemTrayIcon::DoubleClick);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
Q_UNUSED(center);
Q_UNUSED(notification);
return YES;
}
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
Q_UNUSED(center);
Q_UNUSED(notification);
emit systray->messageClicked();
}
#endif
@end
class QSystemTrayIconQMenu : public QPlatformMenu
{
public:
void doAboutToShow() { emit aboutToShow(); }
private:
QSystemTrayIconQMenu();
};
@implementation QNSMenu
-(id)initWithQMenu:(QPlatformMenu*)qm {
self = [super init];
if (self) {
self->qmenu = qm;
[self setDelegate:self];
}
return self;
}
-(QPlatformMenu*)menu {
return qmenu;
}
@end

View file

@ -1,145 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QNSVIEW_H
#define QNSVIEW_H
#include <Cocoa/Cocoa.h>
#include <QtCore/QPointer>
#include <QtGui/QImage>
#include <QtGui/QAccessible>
#include "private/qcore_mac_p.h"
QT_BEGIN_NAMESPACE
class QCocoaWindow;
class QCocoaBackingStore;
class QCocoaGLContext;
QT_END_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
QImage m_backingStore;
qreal m_pixelRatio;
QPoint m_backingStoreOffset;
CGImageRef m_maskImage;
uchar *m_maskData;
bool m_shouldInvalidateWindowShadow;
QWindow *m_window;
QCocoaWindow *m_platformWindow;
NSTrackingArea *m_trackingArea;
Qt::MouseButtons m_buttons;
Qt::MouseButtons m_frameStrutButtons;
QString m_composingText;
bool m_sendKeyEvent;
QStringList *currentCustomDragTypes;
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers currentWheelModifiers;
bool m_subscribesForGlobalFrameNotifications;
#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
bool m_shouldSetGLContextinDrawRect;
#endif
NSString *m_inputSource;
QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
bool m_resendKeyEvent;
bool m_scrolling;
bool m_exposedOnMoveToWindow;
}
- (id)init;
- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow;
- (void) clearQWindowPointers;
#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
- (BOOL)beforeBeginPaint:(QCocoaBackingStore *)backingStore;
- (void)afterEndPaint:(QCocoaBackingStore *)backingStore;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
- (void)drawRect:(NSRect)dirtyRect;
- (void)updateGeometry;
- (void)notifyWindowStateChanged:(Qt::WindowState)newState;
- (void)windowNotification : (NSNotification *) windowNotification;
- (void)notifyWindowWillZoom:(BOOL)willZoom;
- (void)viewDidHide;
- (void)viewDidUnhide;
- (BOOL)isFlipped;
- (BOOL)acceptsFirstResponder;
- (BOOL)becomeFirstResponder;
- (BOOL)hasMask;
- (BOOL)isOpaque;
- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint;
- (void)resetMouseButtons;
- (void)handleMouseEvent:(NSEvent *)theEvent;
- (void)mouseDown:(NSEvent *)theEvent;
- (void)mouseDragged:(NSEvent *)theEvent;
- (void)mouseUp:(NSEvent *)theEvent;
- (void)mouseMovedImpl:(NSEvent *)theEvent;
- (void)mouseEnteredImpl:(NSEvent *)theEvent;
- (void)mouseExitedImpl:(NSEvent *)theEvent;
- (void)cursorUpdateImpl:(NSEvent *)theEvent;
- (void)rightMouseDown:(NSEvent *)theEvent;
- (void)rightMouseDragged:(NSEvent *)theEvent;
- (void)rightMouseUp:(NSEvent *)theEvent;
- (void)otherMouseDown:(NSEvent *)theEvent;
- (void)otherMouseDragged:(NSEvent *)theEvent;
- (void)otherMouseUp:(NSEvent *)theEvent;
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent;
- (void)handleTabletEvent: (NSEvent *)theEvent;
- (void)tabletPoint: (NSEvent *)theEvent;
- (void)tabletProximity: (NSEvent *)theEvent;
- (int) convertKeyCode : (QChar)keyCode;
+ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags;
- (void)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType;
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
- (void)registerDragTypes;
- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSView);
#endif //QNSVIEW_H

View file

@ -1,160 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#define QT_NO_URL_CAST_FROM_STRING
#include "qwindowsservices.h"
#include "qtwindows_additional.h"
#include <QtCore/QUrl>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <shlobj.h>
#ifndef Q_OS_WINCE
# include <intshcut.h>
#endif
QT_BEGIN_NAMESPACE
enum { debug = 0 };
static inline bool shellExecute(const QUrl &url)
{
#ifndef Q_OS_WINCE
const QString nativeFilePath =
url.isLocalFile() ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString(QUrl::FullyEncoded);
const quintptr result = (quintptr)ShellExecute(0, 0, (wchar_t*)nativeFilePath.utf16(), 0, 0, SW_SHOWNORMAL);
// ShellExecute returns a value greater than 32 if successful
if (result <= 32) {
qWarning("ShellExecute '%s' failed (error %s).", qPrintable(url.toString()), qPrintable(QString::number(result)));
return false;
}
return true;
#else
Q_UNUSED(url);
return false;
#endif
}
// Retrieve the commandline for the default mail client. It contains a
// placeholder %1 for the URL. The default key used below is the
// command line for the mailto: shell command.
static inline QString mailCommand()
{
enum { BufferSize = sizeof(wchar_t) * MAX_PATH };
const wchar_t mailUserKey[] = L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice";
wchar_t command[MAX_PATH] = {0};
// Check if user has set preference, otherwise use default.
HKEY handle;
QString keyName;
if (!RegOpenKeyEx(HKEY_CURRENT_USER, mailUserKey, 0, KEY_READ, &handle)) {
DWORD bufferSize = BufferSize;
if (!RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast<unsigned char*>(command), &bufferSize))
keyName = QString::fromWCharArray(command);
RegCloseKey(handle);
}
if (keyName.isEmpty())
keyName = QStringLiteral("mailto");
keyName += QStringLiteral("\\Shell\\Open\\Command");
if (debug)
qDebug() << __FUNCTION__ << "keyName=" << keyName;
command[0] = 0;
if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle)) {
DWORD bufferSize = BufferSize;
RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(command), &bufferSize);
RegCloseKey(handle);
}
if (!command[0])
return QString();
#ifndef Q_OS_WINCE
wchar_t expandedCommand[MAX_PATH] = {0};
return ExpandEnvironmentStrings(command, expandedCommand, MAX_PATH) ?
QString::fromWCharArray(expandedCommand) : QString::fromWCharArray(command);
#else
return QString();
#endif
}
static inline bool launchMail(const QUrl &url)
{
QString command = mailCommand();
if (command.isEmpty()) {
qWarning("Cannot launch '%s': There is no mail program installed.", qPrintable(url.toString()));
return false;
}
//Make sure the path for the process is in quotes
const QChar doubleQuote = QLatin1Char('"');
if (!command.startsWith(doubleQuote)) {
const int exeIndex = command.indexOf(QStringLiteral(".exe "), 0, Qt::CaseInsensitive);
if (exeIndex != -1) {
command.insert(exeIndex + 4, doubleQuote);
command.prepend(doubleQuote);
}
}
// Pass the url as the parameter. Should use QProcess::startDetached(),
// but that cannot handle a Windows command line [yet].
if (command.indexOf(QStringLiteral("%1")) < 0) return false;
command.replace(QStringLiteral("%1"), url.toString(QUrl::FullyEncoded));
if (debug)
qDebug() << __FUNCTION__ << "Launching" << command;
//start the process
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
qErrnoWarning("Unable to launch '%s'", qPrintable(command));
return false;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
}
bool QWindowsServices::openUrl(const QUrl &url)
{
const QString scheme = url.scheme();
if (scheme == QLatin1String("mailto") && launchMail(url))
return true;
return shellExecute(url);
}
bool QWindowsServices::openDocument(const QUrl &url)
{
return shellExecute(url);
}
QT_END_NAMESPACE

View file

@ -1,387 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINDOWSWINDOW_H
#define QWINDOWSWINDOW_H
#include "qtwindows_additional.h"
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
#endif
#include "qwindowsscaling.h"
#include "qwindowscursor.h"
#include <qpa/qplatformwindow.h>
#include <QtPlatformHeaders/qwindowswindowfunctions.h>
QT_BEGIN_NAMESPACE
class QWindowsOleDropTarget;
class QDebug;
struct QWindowsGeometryHint
{
QWindowsGeometryHint() {}
explicit QWindowsGeometryHint(const QWindow *w, const QMargins &customMargins);
static QMargins frame(DWORD style, DWORD exStyle);
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result);
#ifndef Q_OS_WINCE //MinMax maybe define struct if not available
void applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const;
void applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const;
#endif
bool validSize(const QSize &s) const;
static inline QPoint mapToGlobal(HWND hwnd, const QPoint &);
static inline QPoint mapToGlobal(const QWindow *w, const QPoint &);
static inline QPoint mapFromGlobal(const HWND hwnd, const QPoint &);
static inline QPoint mapFromGlobal(const QWindow *w, const QPoint &);
static bool positionIncludesFrame(const QWindow *w);
QSize minimumSize;
QSize maximumSize;
QMargins customMargins;
};
struct QWindowCreationContext
{
QWindowCreationContext(const QWindow *w, const QRect &r,
const QMargins &customMargins,
DWORD style, DWORD exStyle);
#ifndef Q_OS_WINCE //MinMax maybe define struct if not available
void applyToMinMaxInfo(MINMAXINFO *mmi) const
{ geometryHint.applyToMinMaxInfo(style, exStyle, mmi); }
#endif
QWindowsGeometryHint geometryHint;
const QWindow *window;
DWORD style;
DWORD exStyle;
QRect requestedGeometry;
QRect obtainedGeometry;
QMargins margins;
QMargins customMargins; // User-defined, additional frame for WM_NCCALCSIZE
int frameX; // Passed on to CreateWindowEx(), including frame.
int frameY;
int frameWidth;
int frameHeight;
};
struct QWindowsWindowData
{
QWindowsWindowData() : hwnd(0), embedded(false) {}
Qt::WindowFlags flags;
QRect geometry;
QMargins frame; // Do not use directly for windows, see FrameDirty.
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd;
bool embedded;
static QWindowsWindowData create(const QWindow *w,
const QWindowsWindowData &parameters,
const QString &title);
};
class QWindowsWindow : public QPlatformWindow
{
public:
enum Flags
{
AutoMouseCapture = 0x1, //! Automatic mouse capture on button press.
WithinSetParent = 0x2,
FrameDirty = 0x4, //! Frame outdated by setStyle, recalculate in next query.
OpenGLSurface = 0x10,
OpenGL_ES2 = 0x20,
OpenGLDoubleBuffered = 0x40,
OpenGlPixelFormatInitialized = 0x80,
BlockedByModal = 0x100,
SizeGripOperation = 0x200,
FrameStrutEventsEnabled = 0x400,
SynchronousGeometryChangeEvent = 0x800,
WithinSetStyle = 0x1000,
WithinDestroy = 0x2000,
TouchRegistered = 0x4000,
AlertState = 0x8000,
Exposed = 0x10000,
WithinCreate = 0x20000,
WithinMaximize = 0x40000,
MaximizeToFullScreen = 0x80000,
InputMethodDisabled = 0x100000,
Compositing = 0x200000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsWindow();
QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
void setGeometryDp(const QRect &rectIn);
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE
{ setGeometryDp(QWindowsScaling::mapToNative(rect)); }
QRect geometryDp() const { return m_data.geometry; }
QRect geometry() const Q_DECL_OVERRIDE
{ return QWindowsScaling::mapFromNative(geometryDp()); }
QRect normalGeometryDp() const;
QRect normalGeometry() const Q_DECL_OVERRIDE
{ return QWindowsScaling::mapFromNative(normalGeometryDp()); }
qreal devicePixelRatio() const Q_DECL_OVERRIDE
{ return qreal(QWindowsScaling::factor()); }
void setVisible(bool visible) Q_DECL_OVERRIDE;
bool isVisible() const;
bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); }
bool isActive() const Q_DECL_OVERRIDE;
bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE;
QPoint mapToGlobalDp(const QPoint &pos) const;
QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE
{ return mapToGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); }
QPoint mapFromGlobalDp(const QPoint &pos) const;
QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE
{ return mapFromGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); }
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
HWND handle() const { return m_data.hwnd; }
WId winId() const Q_DECL_OVERRIDE { return WId(m_data.hwnd); }
void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
void raise() Q_DECL_OVERRIDE;
void lower() Q_DECL_OVERRIDE;
void windowEvent(QEvent *event);
void propagateSizeHints() Q_DECL_OVERRIDE;
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp);
bool handleGeometryChanging(MSG *message) const;
QMargins frameMarginsDp() const;
QMargins frameMargins() const Q_DECL_OVERRIDE { return frameMarginsDp() / QWindowsScaling::factor(); }
void setOpacity(qreal level) Q_DECL_OVERRIDE;
void setMask(const QRegion &region) Q_DECL_OVERRIDE;
qreal opacity() const { return m_opacity; }
void requestActivateWindow() Q_DECL_OVERRIDE;
bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
bool startSystemResize(const QPoint &, Qt::Corner corner) Q_DECL_OVERRIDE;
void setFrameStrutEventsEnabled(bool enabled);
bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
QMargins customMargins() const { return m_data.customMargins; }
void setCustomMargins(const QMargins &m);
inline unsigned style() const
{ return GetWindowLongPtr(m_data.hwnd, GWL_STYLE); }
void setStyle(unsigned s) const;
inline unsigned exStyle() const
{ return GetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE); }
void setExStyle(unsigned s) const;
bool handleWmPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void handleMoved();
void handleResized(int wParam);
void handleHidden();
void handleCompositionSettingsChanged();
static inline HWND handleOf(const QWindow *w);
static inline QWindowsWindow *baseWindowOf(const QWindow *w);
static QWindow *topLevelOf(QWindow *w);
static inline void *userDataOf(HWND hwnd);
static inline void setUserDataOf(HWND hwnd, void *ud);
static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity);
bool isLayered() const;
HDC getDC();
void releaseDC();
#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
void getSizeHints(MINMAXINFO *mmi) const;
bool handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const;
#endif // !Q_OS_WINCE
#ifndef QT_NO_CURSOR
QWindowsWindowCursor cursor() const { return m_cursor; }
#endif
void setCursor(const QWindowsWindowCursor &c);
void applyCursor();
inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; }
inline void setFlag(unsigned f) const { m_flags |= f; }
inline void clearFlag(unsigned f) const { m_flags &= ~f; }
void setEnabled(bool enabled);
bool isEnabled() const;
void setWindowIcon(const QIcon &icon);
void *surface(void *nativeConfig, int *err);
void invalidateSurface() Q_DECL_OVERRIDE;
void aboutToMakeCurrent();
#ifndef Q_OS_WINCE
void setAlertState(bool enabled);
bool isAlertState() const { return testFlag(AlertState); }
void alertWindow(int durationMs = 0);
void stopAlertWindow();
#endif
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
private:
inline void show_sys() const;
inline void hide_sys() const;
inline void setGeometry_sys(const QRect &rect) const;
inline QRect frameGeometry_sys() const;
inline QRect geometry_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
inline bool isFullScreen_sys() const;
inline void setWindowState_sys(Qt::WindowState newState);
inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
inline void clearTransientParent() const;
void destroyWindow();
inline bool isDropSiteEnabled() const { return m_dropTarget != 0; }
void setDropSiteEnabled(bool enabled);
void updateDropSite(bool topLevel);
void handleGeometryChange();
void handleWindowStateChange(Qt::WindowState state);
inline void destroyIcon();
void fireExpose(const QRegion &region, bool force=false);
mutable QWindowsWindowData m_data;
mutable unsigned m_flags;
HDC m_hdc;
Qt::WindowState m_windowState;
qreal m_opacity;
#ifndef QT_NO_CURSOR
QWindowsWindowCursor m_cursor;
#endif
QWindowsOleDropTarget *m_dropTarget;
unsigned m_savedStyle;
QRect m_savedFrameGeometry;
const QSurfaceFormat m_format;
#ifdef Q_OS_WINCE
bool m_previouslyHidden;
#endif
HICON m_iconSmall;
HICON m_iconBig;
void *m_surface;
};
// Debug
QDebug operator<<(QDebug d, const RECT &r);
#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO/WM_NCCALCSIZE
QDebug operator<<(QDebug d, const MINMAXINFO &i);
QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p);
#endif
// ---------- QWindowsGeometryHint inline functions.
QPoint QWindowsGeometryHint::mapToGlobal(HWND hwnd, const QPoint &qp)
{
POINT p = { qp.x(), qp.y() };
ClientToScreen(hwnd, &p);
return QPoint(p.x, p.y);
}
QPoint QWindowsGeometryHint::mapFromGlobal(const HWND hwnd, const QPoint &qp)
{
POINT p = { qp.x(), qp.y() };
ScreenToClient(hwnd, &p);
return QPoint(p.x, p.y);
}
QPoint QWindowsGeometryHint::mapToGlobal(const QWindow *w, const QPoint &p)
{ return QWindowsGeometryHint::mapToGlobal(QWindowsWindow::handleOf(w), p); }
QPoint QWindowsGeometryHint::mapFromGlobal(const QWindow *w, const QPoint &p)
{ return QWindowsGeometryHint::mapFromGlobal(QWindowsWindow::handleOf(w), p); }
// ---------- QWindowsBaseWindow inline functions.
QWindowsWindow *QWindowsWindow::baseWindowOf(const QWindow *w)
{
if (w)
if (QPlatformWindow *pw = w->handle())
return static_cast<QWindowsWindow *>(pw);
return 0;
}
HWND QWindowsWindow::handleOf(const QWindow *w)
{
if (const QWindowsWindow *bw = QWindowsWindow::baseWindowOf(w))
return bw->handle();
return 0;
}
void *QWindowsWindow::userDataOf(HWND hwnd)
{
return (void *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
void QWindowsWindow::setUserDataOf(HWND hwnd, void *ud)
{
SetWindowLongPtr(hwnd, GWLP_USERDATA, LONG_PTR(ud));
}
inline void QWindowsWindow::destroyIcon()
{
if (m_iconBig) {
DestroyIcon(m_iconBig);
m_iconBig = 0;
}
if (m_iconSmall) {
DestroyIcon(m_iconSmall);
m_iconSmall = 0;
}
}
inline bool QWindowsWindow::isLayered() const
{
#ifndef Q_OS_WINCE
return GetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE) & WS_EX_LAYERED;
#else
return false;
#endif
}
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QMargins)
#endif // QWINDOWSWINDOW_H

View file

@ -1,773 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the utils of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "lalr.h"
#include <limits.h>
#include <algorithm>
#define QLALR_NO_DEBUG_NULLABLES
#define QLALR_NO_DEBUG_LOOKBACKS
#define QLALR_NO_DEBUG_DIRECT_READS
#define QLALR_NO_DEBUG_READS
#define QLALR_NO_DEBUG_INCLUDES
#define QLALR_NO_DEBUG_LOOKAHEADS
QT_BEGIN_NAMESPACE
QTextStream qerr (stderr, QIODevice::WriteOnly);
QTextStream qout (stdout, QIODevice::WriteOnly);
bool operator < (Name a, Name b)
{
return *a < *b;
}
bool operator < (ItemPointer a, ItemPointer b)
{
return &*a < &*b;
}
bool operator < (StatePointer a, StatePointer b)
{
return &*a < &*b;
}
QT_END_NAMESPACE
bool Read::operator < (const Read &other) const
{
if (state == other.state)
return nt < other.nt;
return state < other.state;
}
bool Include::operator < (const Include &other) const
{
if (state == other.state)
return nt < other.nt;
return state < other.state;
}
bool Lookback::operator < (const Lookback &other) const
{
if (state == other.state)
return nt < other.nt;
return state < other.state;
}
QTextStream &operator << (QTextStream &out, const Name &n)
{
return out << *n;
}
QTextStream &operator << (QTextStream &out, const Rule &r)
{
out << *r.lhs << " ::=";
for (NameList::const_iterator name = r.rhs.begin (); name != r.rhs.end (); ++name)
out << " " << **name;
return out;
}
QTextStream &operator << (QTextStream &out, const NameSet &ns)
{
out << "{";
for (NameSet::const_iterator n = ns.begin (); n != ns.end (); ++n)
{
if (n != ns.begin ())
out << ", ";
out << *n;
}
return out << "}";
}
Item Item::next () const
{
Q_ASSERT (! isReduceItem ());
Item n;
n.rule = rule;
n.dot = dot;
++n.dot;
return n;
}
QTextStream &operator << (QTextStream &out, const Item &item)
{
RulePointer r = item.rule;
out << *r->lhs << ":";
for (NameList::iterator name = r->rhs.begin (); name != r->rhs.end (); ++name)
{
out << " ";
if (item.dot == name)
out << ". ";
out << **name;
}
if (item.isReduceItem ())
out << " .";
return out;
}
State::State (Grammar *g):
defaultReduce (g->rules.end ())
{
}
QPair<ItemPointer, bool> State::insert (const Item &item)
{
ItemPointer it = std::find (kernel.begin (), kernel.end (), item);
if (it != kernel.end ())
return qMakePair (it, false);
return qMakePair (kernel.insert (it, item), true);
}
QPair<ItemPointer, bool> State::insertClosure (const Item &item)
{
ItemPointer it = std::find (closure.begin (), closure.end (), item);
if (it != closure.end ())
return qMakePair (it, false);
return qMakePair (closure.insert (it, item), true);
}
/////////////////////////////////////////////////////////////
// Grammar
/////////////////////////////////////////////////////////////
Grammar::Grammar ():
start (names.end ())
{
expected_shift_reduce = 0;
expected_reduce_reduce = 0;
current_prec = 0;
current_assoc = NonAssoc;
table_name = QLatin1String ("parser_table");
tk_end = intern ("$end");
terminals.insert (tk_end);
spells.insert (tk_end, "end of file");
/*tk_error= terminals.insert (intern ("error"))*/;
}
Name Grammar::intern (const QString &id)
{
Name name = std::find (names.begin (), names.end (), id);
if (name == names.end ())
name = names.insert (names.end (), id);
return name;
}
void Grammar::buildRuleMap ()
{
NameSet undefined;
for (RulePointer rule = rules.begin (); rule != rules.end (); ++rule)
{
for (NameList::iterator it = rule->rhs.begin (); it != rule->rhs.end (); ++it)
{
Name name = *it;
if (isTerminal (name) || declared_lhs.find (name) != declared_lhs.end ()
|| undefined.find (name) != undefined.end ())
continue;
undefined.insert(name);
fprintf (stderr, "*** Warning. Symbol `%s' is not defined\n", qPrintable (*name));
}
rule_map.insert (rule->lhs, rule);
}
}
void Grammar::buildExtendedGrammar ()
{
accept_symbol = intern ("$accept");
goal = rules.insert (rules.end (), Rule ());
goal->lhs = accept_symbol;
goal->rhs.push_back (start);
goal->rhs.push_back (tk_end);
non_terminals.insert (accept_symbol);
}
struct __Nullable: public std::unary_function<Name, bool>
{
Automaton *_M_automaton;
__Nullable (Automaton *aut):
_M_automaton (aut) {}
bool operator () (Name name) const
{ return _M_automaton->nullables.find (name) != _M_automaton->nullables.end (); }
};
Automaton::Automaton (Grammar *g):
_M_grammar (g),
start (states.end ())
{
}
int Automaton::id (RulePointer rule)
{
return 1 + std::distance (_M_grammar->rules.begin (), rule);
}
int Automaton::id (Name name)
{
return std::distance (_M_grammar->names.begin (), name);
}
int Automaton::id (StatePointer state)
{
return std::distance (states.begin (), state);
}
void Automaton::build ()
{
Item item;
item.rule = _M_grammar->goal;
item.dot = _M_grammar->goal->rhs.begin ();
State tmp (_M_grammar);
tmp.insert (item);
start = internState (tmp).first;
closure (start);
buildNullables ();
buildLookbackSets ();
buildReads ();
buildIncludesAndFollows ();
buildLookaheads ();
buildDefaultReduceActions ();
}
void Automaton::buildNullables ()
{
bool changed = true;
while (changed)
{
changed = false;
for (RulePointer rule = _M_grammar->rules.begin (); rule != _M_grammar->rules.end (); ++rule)
{
NameList::iterator nn = std::find_if (rule->rhs.begin (), rule->rhs.end (), std::not1 (__Nullable (this)));
if (nn == rule->rhs.end ())
changed |= nullables.insert (rule->lhs).second;
}
}
#ifndef QLALR_NO_DEBUG_NULLABLES
qerr << "nullables = {" << nullables << endl;
#endif
}
QPair<StatePointer, bool> Automaton::internState (const State &state)
{
StatePointer it = std::find (states.begin (), states.end (), state);
if (it != states.end ())
return qMakePair (it, false);
return qMakePair (states.insert (it, state), true);
}
struct _Bucket
{
QLinkedList<ItemPointer> items;
void insert (ItemPointer item)
{ items.push_back (item); }
State toState (Automaton *aut)
{
State st (aut->_M_grammar);
for (QLinkedList<ItemPointer>::iterator item = items.begin (); item != items.end (); ++item)
st.insert ((*item)->next ());
return st;
}
};
void Automaton::closure (StatePointer state)
{
if (! state->closure.empty ()) // ### not true.
return;
typedef QMap<Name, _Bucket> bucket_map_type;
bucket_map_type buckets;
QStack<ItemPointer> working_list;
for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item)
working_list.push (item);
state->closure = state->kernel;
while (! working_list.empty ())
{
ItemPointer item = working_list.top ();
working_list.pop ();
if (item->isReduceItem ())
continue;
buckets [*item->dot].insert (item);
if (_M_grammar->isNonTerminal (*item->dot))
{
foreach (RulePointer rule, _M_grammar->rule_map.values (*item->dot))
{
Item ii;
ii.rule = rule;
ii.dot = rule->rhs.begin ();
QPair<ItemPointer, bool> r = state->insertClosure (ii);
if (r.second)
working_list.push (r.first);
}
}
}
QList<StatePointer> todo;
for (bucket_map_type::iterator bucket = buckets.begin (); bucket != buckets.end (); ++bucket)
{
QPair<StatePointer, bool> r = internState (bucket->toState (this));
StatePointer target = r.first;
if (r.second)
todo.push_back (target);
state->bundle.insert (bucket.key(), target);
}
while (! todo.empty ())
{
closure (todo.front ());
todo.pop_front ();
}
}
void Automaton::buildLookbackSets ()
{
for (StatePointer p = states.begin (); p != states.end (); ++p)
{
for (Bundle::iterator a = p->bundle.begin (); a != p->bundle.end (); ++a)
{
Name A = a.key ();
if (! _M_grammar->isNonTerminal (A))
continue;
foreach (RulePointer rule, _M_grammar->rule_map.values (A))
{
StatePointer q = p;
for (NameList::iterator dot = rule->rhs.begin (); dot != rule->rhs.end (); ++dot)
q = q->bundle.value (*dot, states.end ());
Q_ASSERT (q != states.end ());
ItemPointer item = q->closure.begin ();
for (; item != q->closure.end (); ++item)
{
if (item->rule == rule && item->dot == item->end_rhs ())
break;
}
if (item == q->closure.end ())
{
Q_ASSERT (q == p);
Q_ASSERT (rule->rhs.begin () == rule->rhs.end ());
for (item = q->closure.begin (); item != q->closure.end (); ++item)
{
if (item->rule == rule && item->dot == item->end_rhs ())
break;
}
}
Q_ASSERT (item != q->closure.end ());
lookbacks.insert (item, Lookback (p, A));
#ifndef QLALR_NO_DEBUG_LOOKBACKS
qerr << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl;
#endif
}
}
}
}
void Automaton::buildDirectReads ()
{
for (StatePointer q = states.begin (); q != states.end (); ++q)
{
for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a)
{
if (! _M_grammar->isNonTerminal (a.key ()))
continue;
StatePointer r = a.value ();
for (Bundle::iterator z = r->bundle.begin (); z != r->bundle.end (); ++z)
{
Name sym = z.key ();
if (! _M_grammar->isTerminal (sym))
continue;
q->reads [a.key ()].insert (sym);
}
}
#ifndef QLALR_NO_DEBUG_DIRECT_READS
for (QMap<Name, NameSet>::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr)
qerr << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl;
#endif
}
}
void Automaton::buildReadsDigraph ()
{
for (StatePointer q = states.begin (); q != states.end (); ++q)
{
for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a)
{
if (! _M_grammar->isNonTerminal (a.key ()))
continue;
StatePointer r = a.value ();
for (Bundle::iterator z = r->bundle.begin (); z != r->bundle.end (); ++z)
{
Name sym = z.key ();
if (! _M_grammar->isNonTerminal(sym) || nullables.find (sym) == nullables.end ())
continue;
ReadsGraph::iterator source = ReadsGraph::get (Read (q, a.key ()));
ReadsGraph::iterator target = ReadsGraph::get (Read (r, sym));
source->insertEdge (target);
#ifndef QLALR_NO_DEBUG_READS
qerr << "*** ";
dump (qerr, source);
qerr << " reads ";
dump (qerr, target);
qerr << endl;
#endif
}
}
}
}
void Automaton::buildReads ()
{
buildDirectReads ();
buildReadsDigraph ();
_M_reads_dfn = 0;
for (ReadsGraph::iterator node = ReadsGraph::begin_nodes (); node != ReadsGraph::end_nodes (); ++node)
{
if (! node->root)
continue;
visitReadNode (node);
}
for (ReadsGraph::iterator node = ReadsGraph::begin_nodes (); node != ReadsGraph::end_nodes (); ++node)
visitReadNode (node);
}
void Automaton::visitReadNode (ReadNode node)
{
if (node->dfn != 0)
return; // nothing to do
int N = node->dfn = ++_M_reads_dfn;
_M_reads_stack.push (node);
#ifndef QLALR_NO_DEBUG_INCLUDES
// qerr << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl;
#endif
for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge)
{
ReadsGraph::iterator r = *edge;
visitReadNode (r);
node->dfn = qMin (N, r->dfn);
NameSet &dst = node->data.state->reads [node->data.nt];
NameSet &src = r->data.state->reads [r->data.nt];
dst.insert (src.begin (), src.end ());
}
if (node->dfn == N)
{
ReadsGraph::iterator tos = _M_reads_stack.top ();
do {
tos = _M_reads_stack.top ();
_M_reads_stack.pop ();
tos->dfn = INT_MAX;
} while (tos != node);
}
}
void Automaton::buildIncludesAndFollows ()
{
for (StatePointer p = states.begin (); p != states.end (); ++p)
p->follows = p->reads;
buildIncludesDigraph ();
_M_includes_dfn = 0;
for (IncludesGraph::iterator node = IncludesGraph::begin_nodes (); node != IncludesGraph::end_nodes (); ++node)
{
if (! node->root)
continue;
visitIncludeNode (node);
}
for (IncludesGraph::iterator node = IncludesGraph::begin_nodes (); node != IncludesGraph::end_nodes (); ++node)
visitIncludeNode (node);
}
void Automaton::buildIncludesDigraph ()
{
for (StatePointer pp = states.begin (); pp != states.end (); ++pp)
{
for (Bundle::iterator a = pp->bundle.begin (); a != pp->bundle.end (); ++a)
{
Name name = a.key ();
if (! _M_grammar->isNonTerminal (name))
continue;
foreach (RulePointer rule, _M_grammar->rule_map.values (name))
{
StatePointer p = pp;
for (NameList::iterator A = rule->rhs.begin (); A != rule->rhs.end (); ++A)
{
NameList::iterator dot = A;
++dot;
if (_M_grammar->isNonTerminal (*A) && dot == rule->rhs.end ())
{
// found an include edge.
IncludesGraph::iterator target = IncludesGraph::get (Include (pp, name));
IncludesGraph::iterator source = IncludesGraph::get (Include (p, *A));
source->insertEdge (target);
#ifndef QLALR_NO_DEBUG_INCLUDES
qerr << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl;
#endif // QLALR_NO_DEBUG_INCLUDES
continue;
}
p = p->bundle.value (*A);
if (! _M_grammar->isNonTerminal (*A))
continue;
NameList::iterator first_not_nullable = std::find_if (dot, rule->rhs.end (), std::not1 (__Nullable (this)));
if (first_not_nullable != rule->rhs.end ())
continue;
// found an include edge.
IncludesGraph::iterator target = IncludesGraph::get (Include (pp, name));
IncludesGraph::iterator source = IncludesGraph::get (Include (p, *A));
source->insertEdge (target);
#ifndef QLALR_NO_DEBUG_INCLUDES
qerr << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl;
#endif // QLALR_NO_DEBUG_INCLUDES
}
}
}
}
}
void Automaton::visitIncludeNode (IncludeNode node)
{
if (node->dfn != 0)
return; // nothing to do
int N = node->dfn = ++_M_includes_dfn;
_M_includes_stack.push (node);
#ifndef QLALR_NO_DEBUG_INCLUDES
// qerr << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl;
#endif
for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge)
{
IncludesGraph::iterator r = *edge;
visitIncludeNode (r);
node->dfn = qMin (N, r->dfn);
#ifndef QLALR_NO_DEBUG_INCLUDES
qerr << "*** Merge. follows";
dump (qerr, node);
qerr << " += follows";
dump (qerr, r);
qerr << endl;
#endif
NameSet &dst = node->data.state->follows [node->data.nt];
NameSet &src = r->data.state->follows [r->data.nt];
dst.insert (src.begin (), src.end ());
}
if (node->dfn == N)
{
IncludesGraph::iterator tos = _M_includes_stack.top ();
do {
tos = _M_includes_stack.top ();
_M_includes_stack.pop ();
tos->dfn = INT_MAX;
} while (tos != node);
}
}
void Automaton::buildLookaheads ()
{
for (StatePointer p = states.begin (); p != states.end (); ++p)
{
for (ItemPointer item = p->closure.begin (); item != p->closure.end (); ++item)
{
foreach (Lookback lookback, lookbacks.values (item))
{
StatePointer q = lookback.state;
#ifndef QLALR_NO_DEBUG_LOOKAHEADS
qerr << "(" << id (p) << ", " << *item->rule << ") lookbacks ";
dump (qerr, lookback);
qerr << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl;
#endif
lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ());
}
}
// propagate the lookahead in the kernel
ItemPointer k = p->kernel.begin ();
ItemPointer c = p->closure.begin ();
for (; k != p->kernel.end (); ++k, ++c)
lookaheads [k] = lookaheads [c];
}
}
void Automaton::buildDefaultReduceActions ()
{
for (StatePointer state = states.begin (); state != states.end (); ++state)
{
ItemPointer def = state->closure.end ();
int size = -1;
for (ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item)
{
if (item->dot != item->end_rhs ())
continue;
int la = lookaheads.value (item).size ();
if (def == state->closure.end () || la > size)
{
def = item;
size = la;
}
}
if (def != state->closure.end ())
{
Q_ASSERT (size >= 0);
state->defaultReduce = def->rule;
}
}
}
void Automaton::dump (QTextStream &out, IncludeNode incl)
{
out << "(" << id (incl->data.state) << ", " << incl->data.nt << ")";
}
void Automaton::dump (QTextStream &out, ReadNode rd)
{
out << "(" << id (rd->data.state) << ", " << rd->data.nt << ")";
}
void Automaton::dump (QTextStream &out, const Lookback &lp)
{
out << "(" << id (lp.state) << ", " << lp.nt << ")";
}

View file

@ -1,309 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILEDIALOG_H
#define QFILEDIALOG_H
#include <QtCore/qdir.h>
#include <QtCore/qstring.h>
#include <QtCore/qurl.h>
#include <QtWidgets/qdialog.h>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_FILEDIALOG
class QModelIndex;
class QItemSelection;
struct QFileDialogArgs;
class QFileIconProvider;
class QFileDialogPrivate;
class QAbstractItemDelegate;
class QAbstractProxyModel;
class Q_WIDGETS_EXPORT QFileDialog : public QDialog
{
Q_OBJECT
Q_FLAGS(Options)
Q_PROPERTY(ViewMode viewMode READ viewMode WRITE setViewMode)
Q_PROPERTY(FileMode fileMode READ fileMode WRITE setFileMode)
Q_PROPERTY(AcceptMode acceptMode READ acceptMode WRITE setAcceptMode)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE false)
Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks DESIGNABLE false)
Q_PROPERTY(bool confirmOverwrite READ confirmOverwrite WRITE setConfirmOverwrite DESIGNABLE false)
Q_PROPERTY(QString defaultSuffix READ defaultSuffix WRITE setDefaultSuffix)
Q_PROPERTY(bool nameFilterDetailsVisible READ isNameFilterDetailsVisible
WRITE setNameFilterDetailsVisible DESIGNABLE false)
Q_PROPERTY(Options options READ options WRITE setOptions)
public:
enum ViewMode { Detail, List };
Q_ENUM(ViewMode)
enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
Q_ENUM(FileMode)
enum AcceptMode { AcceptOpen, AcceptSave };
Q_ENUM(AcceptMode)
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject };
enum Option
{
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
DontUseSheet = 0x00000008,
DontUseNativeDialog = 0x00000010,
ReadOnly = 0x00000020,
HideNameFilterDetails = 0x00000040,
DontUseCustomDirectoryIcons = 0x00000080
};
Q_ENUM(Option)
Q_DECLARE_FLAGS(Options, Option)
QFileDialog(QWidget *parent, Qt::WindowFlags f);
explicit QFileDialog(QWidget *parent = 0,
const QString &caption = QString(),
const QString &directory = QString(),
const QString &filter = QString());
~QFileDialog();
void setDirectory(const QString &directory);
inline void setDirectory(const QDir &directory);
QDir directory() const;
void setDirectoryUrl(const QUrl &directory);
QUrl directoryUrl() const;
void selectFile(const QString &filename);
QStringList selectedFiles() const;
QByteArray selectedRemoteContent() const;
void selectUrl(const QUrl &url);
QList<QUrl> selectedUrls() const;
void setNameFilterDetailsVisible(bool enabled);
bool isNameFilterDetailsVisible() const;
void setNameFilter(const QString &filter);
void setNameFilters(const QStringList &filters);
QStringList nameFilters() const;
void selectNameFilter(const QString &filter);
QString selectedNameFilter() const;
#ifndef QT_NO_MIMETYPE
void setMimeTypeFilters(const QStringList &filters);
QStringList mimeTypeFilters() const;
void selectMimeTypeFilter(const QString &filter);
#endif
QDir::Filters filter() const;
void setFilter(QDir::Filters filters);
void setViewMode(ViewMode mode);
ViewMode viewMode() const;
void setFileMode(FileMode mode);
FileMode fileMode() const;
void setAcceptMode(AcceptMode mode);
AcceptMode acceptMode() const;
void setReadOnly(bool enabled);
bool isReadOnly() const;
void setResolveSymlinks(bool enabled);
bool resolveSymlinks() const;
void setSidebarUrls(const QList<QUrl> &urls);
QList<QUrl> sidebarUrls() const;
QByteArray saveState() const;
bool restoreState(const QByteArray &state);
void setConfirmOverwrite(bool enabled);
bool confirmOverwrite() const;
void setDefaultSuffix(const QString &suffix);
QString defaultSuffix() const;
void setHistory(const QStringList &paths);
QStringList history() const;
void setItemDelegate(QAbstractItemDelegate *delegate);
QAbstractItemDelegate *itemDelegate() const;
void setIconProvider(QFileIconProvider *provider);
QFileIconProvider *iconProvider() const;
void setLabelText(DialogLabel label, const QString &text);
QString labelText(DialogLabel label) const;
#ifndef QT_NO_PROXYMODEL
void setProxyModel(QAbstractProxyModel *model);
QAbstractProxyModel *proxyModel() const;
#endif
void setOption(Option option, bool on = true);
bool testOption(Option option) const;
void setOptions(Options options);
Options options() const;
using QDialog::open;
void open(QObject *receiver, const char *member);
void setVisible(bool visible) Q_DECL_OVERRIDE;
Q_SIGNALS:
void fileSelected(const QString &file);
void filesSelected(const QStringList &files);
void currentChanged(const QString &path);
void directoryEntered(const QString &directory);
void urlSelected(const QUrl &url);
void urlsSelected(const QList<QUrl> &urls);
void currentUrlChanged(const QUrl &url);
void directoryUrlEntered(const QUrl &directory);
void filterSelected(const QString &filter);
public:
static QString getOpenFileName(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = 0,
Options options = 0);
static QUrl getOpenFileUrl(QWidget *parent = 0,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
const QString &filter = QString(),
QString *selectedFilter = 0,
Options options = 0,
const QStringList &supportedSchemes = QStringList());
static QString getSaveFileName(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = 0,
Options options = 0);
static QUrl getSaveFileUrl(QWidget *parent = 0,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
const QString &filter = QString(),
QString *selectedFilter = 0,
Options options = 0,
const QStringList &supportedSchemes = QStringList());
static QString getExistingDirectory(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
Options options = ShowDirsOnly);
static QUrl getExistingDirectoryUrl(QWidget *parent = 0,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
Options options = ShowDirsOnly,
const QStringList &supportedSchemes = QStringList());
static QStringList getOpenFileNames(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = 0,
Options options = 0);
static QList<QUrl> getOpenFileUrls(QWidget *parent = 0,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
const QString &filter = QString(),
QString *selectedFilter = 0,
Options options = 0,
const QStringList &supportedSchemes = QStringList());
protected:
QFileDialog(const QFileDialogArgs &args);
void done(int result) Q_DECL_OVERRIDE;
void accept() Q_DECL_OVERRIDE;
void changeEvent(QEvent *e) Q_DECL_OVERRIDE;
private:
Q_DECLARE_PRIVATE(QFileDialog)
Q_DISABLE_COPY(QFileDialog)
Q_PRIVATE_SLOT(d_func(), void _q_pathChanged(const QString &))
Q_PRIVATE_SLOT(d_func(), void _q_navigateBackward())
Q_PRIVATE_SLOT(d_func(), void _q_navigateForward())
Q_PRIVATE_SLOT(d_func(), void _q_navigateToParent())
Q_PRIVATE_SLOT(d_func(), void _q_createDirectory())
Q_PRIVATE_SLOT(d_func(), void _q_showListView())
Q_PRIVATE_SLOT(d_func(), void _q_showDetailsView())
Q_PRIVATE_SLOT(d_func(), void _q_showContextMenu(const QPoint &))
Q_PRIVATE_SLOT(d_func(), void _q_renameCurrent())
Q_PRIVATE_SLOT(d_func(), void _q_deleteCurrent())
Q_PRIVATE_SLOT(d_func(), void _q_showHidden())
Q_PRIVATE_SLOT(d_func(), void _q_updateOkButton())
Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex &index))
Q_PRIVATE_SLOT(d_func(), void _q_enterDirectory(const QModelIndex &index))
Q_PRIVATE_SLOT(d_func(), void _q_emitUrlSelected(const QUrl &))
Q_PRIVATE_SLOT(d_func(), void _q_emitUrlsSelected(const QList<QUrl> &))
Q_PRIVATE_SLOT(d_func(), void _q_nativeCurrentChanged(const QUrl &))
Q_PRIVATE_SLOT(d_func(), void _q_nativeEnterDirectory(const QUrl&))
Q_PRIVATE_SLOT(d_func(), void _q_goToDirectory(const QString &path))
Q_PRIVATE_SLOT(d_func(), void _q_useNameFilter(int index))
Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
Q_PRIVATE_SLOT(d_func(), void _q_goToUrl(const QUrl &url))
Q_PRIVATE_SLOT(d_func(), void _q_goHome())
Q_PRIVATE_SLOT(d_func(), void _q_showHeader(QAction *))
Q_PRIVATE_SLOT(d_func(), void _q_autoCompleteFileName(const QString &text))
Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent))
Q_PRIVATE_SLOT(d_func(), void _q_fileRenamed(const QString &path,
const QString &oldName,
const QString &newName))
friend class QPlatformDialogHelper;
};
inline void QFileDialog::setDirectory(const QDir &adirectory)
{ setDirectory(adirectory.absolutePath()); }
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDialog::Options)
#endif // QT_NO_FILEDIALOG
QT_END_NAMESPACE
#endif // QFILEDIALOG_H

View file

@ -1,428 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILEDIALOG_P_H
#define QFILEDIALOG_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 <QtCore/qglobal.h>
#ifndef QT_NO_FILEDIALOG
#include "qfiledialog.h"
#include "private/qdialog_p.h"
#include "qplatformdefs.h"
#include "qfilesystemmodel_p.h"
#include <qlistview.h>
#include <qtreeview.h>
#include <qcombobox.h>
#include <qtoolbutton.h>
#include <qlabel.h>
#include <qevent.h>
#include <qlineedit.h>
#include <qurl.h>
#include <qstackedwidget.h>
#include <qdialogbuttonbox.h>
#include <qabstractproxymodel.h>
#include <qcompleter.h>
#include <qpointer.h>
#include <qdebug.h>
#include "qsidebar_p.h"
#include "qfscompleter_p.h"
#if defined (Q_OS_UNIX)
#include <unistd.h>
#endif
QT_BEGIN_NAMESPACE
class QFileDialogListView;
class QFileDialogTreeView;
class QFileDialogLineEdit;
class QGridLayout;
class QCompleter;
class QHBoxLayout;
class Ui_QFileDialog;
class QPlatformDialogHelper;
struct QFileDialogArgs
{
QFileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {}
QWidget *parent;
QString caption;
QUrl directory;
QString selection;
QString filter;
QFileDialog::FileMode mode;
QFileDialog::Options options;
};
#define UrlRole (Qt::UserRole + 1)
class Q_WIDGETS_EXPORT QFileDialogPrivate : public QDialogPrivate
{
Q_DECLARE_PUBLIC(QFileDialog)
public:
QFileDialogPrivate();
QPlatformFileDialogHelper *platformFileDialogHelper() const
{ return static_cast<QPlatformFileDialogHelper *>(platformHelper()); }
void createToolButtons();
void createMenuActions();
void createWidgets();
void init(const QUrl &directory = QUrl(), const QString &nameFilter = QString(),
const QString &caption = QString());
bool itemViewKeyboardEvent(QKeyEvent *event);
QString getEnvironmentVariable(const QString &string);
static QUrl workingDirectory(const QUrl &path);
static QString initialSelection(const QUrl &path);
QStringList typedFiles() const;
QList<QUrl> userSelectedFiles() const;
QByteArray userSelectedRemoteContent() const;
QStringList addDefaultSuffixToFiles(const QStringList &filesToFix) const;
QList<QUrl> addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const;
bool removeDirectory(const QString &path);
void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text);
inline void updateLookInLabel();
inline void updateFileNameLabel();
inline void updateFileTypeLabel();
void updateOkButtonText(bool saveAsOnFolder = false);
void updateCancelButtonText();
inline QModelIndex mapToSource(const QModelIndex &index) const;
inline QModelIndex mapFromSource(const QModelIndex &index) const;
inline QModelIndex rootIndex() const;
inline void setRootIndex(const QModelIndex &index) const;
inline QModelIndex select(const QModelIndex &index) const;
inline QString rootPath() const;
QLineEdit *lineEdit() const;
static int maxNameLength(const QString &path);
QString basename(const QString &path) const
{
int separator = QDir::toNativeSeparators(path).lastIndexOf(QDir::separator());
if (separator != -1)
return path.mid(separator + 1);
return path;
}
QDir::Filters filterForMode(QDir::Filters filters) const
{
const QFileDialog::FileMode fileMode = q_func()->fileMode();
if (fileMode == QFileDialog::DirectoryOnly) {
filters |= QDir::Drives | QDir::AllDirs | QDir::Dirs;
filters &= ~QDir::Files;
} else {
filters |= QDir::Drives | QDir::AllDirs | QDir::Files | QDir::Dirs;
}
return filters;
}
QAbstractItemView *currentView() const;
static inline QString toInternal(const QString &path)
{
#if defined(Q_OS_WIN)
QString n(path);
n.replace(QLatin1Char('\\'), QLatin1Char('/'));
#if defined(Q_OS_WINCE)
if ((n.size() > 1) && (n.startsWith(QLatin1String("//"))))
n = n.mid(1);
#endif
return n;
#else // the compile should optimize away this
return path;
#endif
}
#ifndef QT_NO_SETTINGS
void saveSettings();
bool restoreFromSettings();
#endif
bool restoreWidgetState(QStringList &history, int splitterPosition);
static void setLastVisitedDirectory(const QUrl &dir);
void retranslateWindowTitle();
void retranslateStrings();
void emitFilesSelected(const QStringList &files);
void _q_goHome();
void _q_pathChanged(const QString &);
void _q_navigateBackward();
void _q_navigateForward();
void _q_navigateToParent();
void _q_createDirectory();
void _q_showListView();
void _q_showDetailsView();
void _q_showContextMenu(const QPoint &position);
void _q_renameCurrent();
void _q_deleteCurrent();
void _q_showHidden();
void _q_showHeader(QAction *);
void _q_updateOkButton();
void _q_currentChanged(const QModelIndex &index);
void _q_enterDirectory(const QModelIndex &index);
void _q_emitUrlSelected(const QUrl &file);
void _q_emitUrlsSelected(const QList<QUrl> &files);
void _q_nativeCurrentChanged(const QUrl &file);
void _q_nativeEnterDirectory(const QUrl &directory);
void _q_goToDirectory(const QString &);
void _q_useNameFilter(int index);
void _q_selectionChanged();
void _q_goToUrl(const QUrl &url);
void _q_autoCompleteFileName(const QString &);
void _q_rowsInserted(const QModelIndex & parent);
void _q_fileRenamed(const QString &path, const QString &oldName, const QString &newName);
// layout
#ifndef QT_NO_PROXYMODEL
QAbstractProxyModel *proxyModel;
#endif
// data
QStringList watching;
QFileSystemModel *model;
#ifndef QT_NO_FSCOMPLETER
QFSCompleter *completer;
#endif //QT_NO_FSCOMPLETER
QString setWindowTitle;
QStringList currentHistory;
int currentHistoryLocation;
QAction *renameAction;
QAction *deleteAction;
QAction *showHiddenAction;
QAction *newFolderAction;
bool useDefaultCaption;
bool defaultFileTypes;
// setVisible_sys returns true if it ends up showing a native
// dialog. Returning false means that a non-native dialog must be
// used instead.
bool canBeNativeDialog() const Q_DECL_OVERRIDE;
inline bool usingWidgets() const;
void setDirectory_sys(const QUrl &directory);
QUrl directory_sys() const;
void selectFile_sys(const QUrl &filename);
QList<QUrl> selectedFiles_sys() const;
QByteArray selectedRemoteContent_sys() const;
void setFilter_sys();
void selectNameFilter_sys(const QString &filter);
QString selectedNameFilter_sys() const;
//////////////////////////////////////////////
QScopedPointer<Ui_QFileDialog> qFileDialogUi;
QString acceptLabel;
QPointer<QObject> receiverToDisconnectOnClose;
QByteArray memberToDisconnectOnClose;
QByteArray signalToDisconnectOnClose;
QSharedPointer<QFileDialogOptions> options;
// Memory of what was read from QSettings in restoreState() in case widgets are not used
QByteArray splitterState;
QByteArray headerData;
QList<QUrl> sidebarUrls;
~QFileDialogPrivate();
private:
virtual void initHelper(QPlatformDialogHelper *) Q_DECL_OVERRIDE;
virtual void helperPrepareShow(QPlatformDialogHelper *) Q_DECL_OVERRIDE;
virtual void helperDone(QDialog::DialogCode, QPlatformDialogHelper *) Q_DECL_OVERRIDE;
Q_DISABLE_COPY(QFileDialogPrivate)
};
class QFileDialogLineEdit : public QLineEdit
{
public:
QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), d_ptr(0){}
void setFileDialogPrivate(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; }
void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
bool hideOnEsc;
private:
QFileDialogPrivate *d_ptr;
};
class QFileDialogComboBox : public QComboBox
{
public:
QFileDialogComboBox(QWidget *parent = 0) : QComboBox(parent), urlModel(0) {}
void setFileDialogPrivate(QFileDialogPrivate *d_pointer);
void showPopup() Q_DECL_OVERRIDE;
void setHistory(const QStringList &paths);
QStringList history() const { return m_history; }
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
private:
QUrlModel *urlModel;
QFileDialogPrivate *d_ptr;
QStringList m_history;
};
class QFileDialogListView : public QListView
{
public:
QFileDialogListView(QWidget *parent = 0);
void setFileDialogPrivate(QFileDialogPrivate *d_pointer);
QSize sizeHint() const Q_DECL_OVERRIDE;
protected:
void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
private:
QFileDialogPrivate *d_ptr;
};
class QFileDialogTreeView : public QTreeView
{
public:
QFileDialogTreeView(QWidget *parent);
void setFileDialogPrivate(QFileDialogPrivate *d_pointer);
QSize sizeHint() const Q_DECL_OVERRIDE;
protected:
void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
private:
QFileDialogPrivate *d_ptr;
};
inline QModelIndex QFileDialogPrivate::mapToSource(const QModelIndex &index) const {
#ifdef QT_NO_PROXYMODEL
return index;
#else
return proxyModel ? proxyModel->mapToSource(index) : index;
#endif
}
inline QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) const {
#ifdef QT_NO_PROXYMODEL
return index;
#else
return proxyModel ? proxyModel->mapFromSource(index) : index;
#endif
}
inline QString QFileDialogPrivate::rootPath() const {
return (model ? model->rootPath() : QStringLiteral("/"));
}
inline void QFileDialogPrivate::setDirectory_sys(const QUrl &directory)
{
QPlatformFileDialogHelper *helper = platformFileDialogHelper();
if (!helper)
return;
if (helper->isSupportedUrl(directory))
helper->setDirectory(directory);
}
inline QUrl QFileDialogPrivate::directory_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->directory();
return QUrl();
}
inline void QFileDialogPrivate::selectFile_sys(const QUrl &filename)
{
QPlatformFileDialogHelper *helper = platformFileDialogHelper();
if (!helper)
return;
if (helper->isSupportedUrl(filename))
helper->selectFile(filename);
}
inline QList<QUrl> QFileDialogPrivate::selectedFiles_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->selectedFiles();
return QList<QUrl>();
}
inline QByteArray QFileDialogPrivate::selectedRemoteContent_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->selectedRemoteContent();
return QByteArray();
}
inline void QFileDialogPrivate::setFilter_sys()
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
helper->setFilter();
}
inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter)
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
helper->selectNameFilter(filter);
}
inline QString QFileDialogPrivate::selectedNameFilter_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->selectedNameFilter();
return QString();
}
QT_END_NAMESPACE
#endif // QT_NO_FILEDIALOG
#endif // QFILEDIALOG_P_H

File diff suppressed because it is too large Load diff

View file

@ -1,772 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsystemtrayicon.h"
#include "qsystemtrayicon_p.h"
#ifndef QT_NO_SYSTEMTRAYICON
#include "qmenu.h"
#include "qlist.h"
#include "qevent.h"
#include "qpoint.h"
#include "qlabel.h"
#include "qpushbutton.h"
#include "qpainterpath.h"
#include "qpainter.h"
#include "qstyle.h"
#include "qgridlayout.h"
#include "qapplication.h"
#include "qdesktopwidget.h"
#include "qbitmap.h"
#include "private/qlabel_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QSystemTrayIcon
\brief The QSystemTrayIcon class provides an icon for an application in the system tray.
\since 4.2
\ingroup desktop
\inmodule QtWidgets
Modern operating systems usually provide a special area on the desktop,
called the \e{system tray} or \e{notification area}, where long-running
applications can display icons and short messages.
\image system-tray.png The system tray on Windows XP.
The QSystemTrayIcon class can be used on the following platforms:
\list
\li All supported versions of Windows.
\li All window managers and independent tray implementations for X11 that implement the
\l{http://standards.freedesktop.org/systemtray-spec/systemtray-spec-0.2.html freedesktop.org}
XEmbed system tray specification.
\li All X11 desktop environments that implement the D-Bus
\l{http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ StatusNotifierItem}
specification, including recent versions of KDE and Unity.
\li All supported versions of Mac OS X. Note that the Growl
notification system must be installed for
QSystemTrayIcon::showMessage() to display messages on Mac OS X prior to 10.8 (Mountain Lion).
\endlist
To check whether a system tray is present on the user's desktop,
call the QSystemTrayIcon::isSystemTrayAvailable() static function.
To add a system tray entry, create a QSystemTrayIcon object, call setContextMenu()
to provide a context menu for the icon, and call show() to make it visible in the
system tray. Status notification messages ("balloon messages") can be displayed at
any time using showMessage().
If the system tray is unavailable when a system tray icon is constructed, but
becomes available later, QSystemTrayIcon will automatically add an entry for the
application in the system tray if the icon is \l visible.
The activated() signal is emitted when the user activates the icon.
Only on X11, when a tooltip is requested, the QSystemTrayIcon receives a QHelpEvent
of type QEvent::ToolTip. Additionally, the QSystemTrayIcon receives wheel events of
type QEvent::Wheel. These are not supported on any other platform.
\sa QDesktopServices, QDesktopWidget, {Desktop Integration}, {System Tray Icon Example}
*/
/*!
\enum QSystemTrayIcon::MessageIcon
This enum describes the icon that is shown when a balloon message is displayed.
\value NoIcon No icon is shown.
\value Information An information icon is shown.
\value Warning A standard warning icon is shown.
\value Critical A critical warning icon is shown.
\sa QMessageBox
*/
/*!
Constructs a QSystemTrayIcon object with the given \a parent.
The icon is initially invisible.
\sa visible
*/
QSystemTrayIcon::QSystemTrayIcon(QObject *parent)
: QObject(*new QSystemTrayIconPrivate(), parent)
{
}
/*!
Constructs a QSystemTrayIcon object with the given \a icon and \a parent.
The icon is initially invisible.
\sa visible
*/
QSystemTrayIcon::QSystemTrayIcon(const QIcon &icon, QObject *parent)
: QObject(*new QSystemTrayIconPrivate(), parent)
{
setIcon(icon);
}
/*!
Removes the icon from the system tray and frees all allocated resources.
*/
QSystemTrayIcon::~QSystemTrayIcon()
{
Q_D(QSystemTrayIcon);
d->remove_sys();
}
#ifndef QT_NO_MENU
/*!
Sets the specified \a menu to be the context menu for the system tray icon.
The menu will pop up when the user requests the context menu for the system
tray icon by clicking the mouse button.
On Mac OS X, this is currenly converted to a NSMenu, so the
aboutToHide() signal is not emitted.
\note The system tray icon does not take ownership of the menu. You must
ensure that it is deleted at the appropriate time by, for example, creating
the menu with a suitable parent object.
*/
void QSystemTrayIcon::setContextMenu(QMenu *menu)
{
Q_D(QSystemTrayIcon);
d->menu = menu;
d->updateMenu_sys();
}
/*!
Returns the current context menu for the system tray entry.
*/
QMenu* QSystemTrayIcon::contextMenu() const
{
Q_D(const QSystemTrayIcon);
return d->menu;
}
#endif // QT_NO_MENU
/*!
\property QSystemTrayIcon::icon
\brief the system tray icon
On Windows, the system tray icon size is 16x16; on X11, the preferred size is
22x22. The icon will be scaled to the appropriate size as necessary.
*/
void QSystemTrayIcon::setIcon(const QIcon &icon)
{
Q_D(QSystemTrayIcon);
d->icon = icon;
d->updateIcon_sys();
}
QIcon QSystemTrayIcon::icon() const
{
Q_D(const QSystemTrayIcon);
return d->icon;
}
/*!
\property QSystemTrayIcon::toolTip
\brief the tooltip for the system tray entry
On some systems, the tooltip's length is limited. The tooltip will be truncated
if necessary.
*/
void QSystemTrayIcon::setToolTip(const QString &tooltip)
{
Q_D(QSystemTrayIcon);
d->toolTip = tooltip;
d->updateToolTip_sys();
}
QString QSystemTrayIcon::toolTip() const
{
Q_D(const QSystemTrayIcon);
return d->toolTip;
}
/*!
\fn void QSystemTrayIcon::show()
Shows the icon in the system tray.
\sa hide(), visible
*/
/*!
\fn void QSystemTrayIcon::hide()
Hides the system tray entry.
\sa show(), visible
*/
/*!
\since 4.3
Returns the geometry of the system tray icon in screen coordinates.
\sa visible
*/
QRect QSystemTrayIcon::geometry() const
{
Q_D(const QSystemTrayIcon);
if (!d->visible)
return QRect();
return d->geometry_sys();
}
/*!
\property QSystemTrayIcon::visible
\brief whether the system tray entry is visible
Setting this property to true or calling show() makes the system tray icon
visible; setting this property to false or calling hide() hides it.
*/
void QSystemTrayIcon::setVisible(bool visible)
{
Q_D(QSystemTrayIcon);
if (visible == d->visible)
return;
if (d->icon.isNull() && visible)
qWarning("QSystemTrayIcon::setVisible: No Icon set");
d->visible = visible;
if (d->visible)
d->install_sys();
else
d->remove_sys();
}
bool QSystemTrayIcon::isVisible() const
{
Q_D(const QSystemTrayIcon);
return d->visible;
}
/*!
\reimp
*/
bool QSystemTrayIcon::event(QEvent *e)
{
#if defined(Q_DEAD_CODE_FROM_QT4_X11)
if (e->type() == QEvent::ToolTip) {
Q_D(QSystemTrayIcon);
return d->sys->deliverToolTipEvent(e);
}
#endif
return QObject::event(e);
}
/*!
\enum QSystemTrayIcon::ActivationReason
This enum describes the reason the system tray was activated.
\value Unknown Unknown reason
\value Context The context menu for the system tray entry was requested
\value DoubleClick The system tray entry was double clicked
\value Trigger The system tray entry was clicked
\value MiddleClick The system tray entry was clicked with the middle mouse button
\sa activated()
*/
/*!
\fn void QSystemTrayIcon::activated(QSystemTrayIcon::ActivationReason reason)
This signal is emitted when the user activates the system tray icon. \a reason
specifies the reason for activation. QSystemTrayIcon::ActivationReason enumerates
the various reasons.
\sa QSystemTrayIcon::ActivationReason
*/
/*!
\fn void QSystemTrayIcon::messageClicked()
This signal is emitted when the message displayed using showMessage()
was clicked by the user.
Currently this signal is not sent on Mac OS X.
\note We follow Microsoft Windows XP/Vista behavior, so the
signal is also emitted when the user clicks on a tray icon with
a balloon message displayed.
\sa activated()
*/
/*!
Returns \c true if the system tray is available; otherwise returns \c false.
If the system tray is currently unavailable but becomes available later,
QSystemTrayIcon will automatically add an entry in the system tray if it
is \l visible.
*/
bool QSystemTrayIcon::isSystemTrayAvailable()
{
return QSystemTrayIconPrivate::isSystemTrayAvailable_sys();
}
/*!
Returns \c true if the system tray supports balloon messages; otherwise returns \c false.
\sa showMessage()
*/
bool QSystemTrayIcon::supportsMessages()
{
return QSystemTrayIconPrivate::supportsMessages_sys();
}
/*!
\fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint)
\since 4.3
Shows a balloon message for the entry with the given \a title, \a message and
\a icon for the time specified in \a millisecondsTimeoutHint. \a title and \a message
must be plain text strings.
Message can be clicked by the user; the messageClicked() signal will emitted when
this occurs.
Note that display of messages are dependent on the system configuration and user
preferences, and that messages may not appear at all. Hence, it should not be
relied upon as the sole means for providing critical information.
On Windows, the \a millisecondsTimeoutHint is usually ignored by the system
when the application has focus.
On Mac OS X, the Growl notification system must be installed for this function to
display messages.
Has been turned into a slot in Qt 5.2.
\sa show(), supportsMessages()
*/
void QSystemTrayIcon::showMessage(const QString& title, const QString& msg,
QSystemTrayIcon::MessageIcon icon, int msecs)
{
Q_D(QSystemTrayIcon);
if (d->visible)
d->showMessage_sys(title, msg, icon, msecs);
}
void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason)
{
Q_Q(QSystemTrayIcon);
emit q->activated(static_cast<QSystemTrayIcon::ActivationReason>(reason));
}
//////////////////////////////////////////////////////////////////////
static QBalloonTip *theSolitaryBalloonTip = 0;
void QBalloonTip::showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title,
const QString& message, QSystemTrayIcon *trayIcon,
const QPoint& pos, int timeout, bool showArrow)
{
hideBalloon();
if (message.isEmpty() && title.isEmpty())
return;
theSolitaryBalloonTip = new QBalloonTip(icon, title, message, trayIcon);
if (timeout < 0)
timeout = 10000; //10 s default
theSolitaryBalloonTip->balloon(pos, timeout, showArrow);
}
void QBalloonTip::hideBalloon()
{
if (!theSolitaryBalloonTip)
return;
theSolitaryBalloonTip->hide();
delete theSolitaryBalloonTip;
theSolitaryBalloonTip = 0;
}
void QBalloonTip::updateBalloonPosition(const QPoint& pos)
{
if (!theSolitaryBalloonTip)
return;
theSolitaryBalloonTip->hide();
theSolitaryBalloonTip->balloon(pos, 0, theSolitaryBalloonTip->showArrow);
}
bool QBalloonTip::isBalloonVisible()
{
return theSolitaryBalloonTip;
}
QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title,
const QString& message, QSystemTrayIcon *ti)
: QWidget(0, Qt::ToolTip), trayIcon(ti), timerId(-1)
{
setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(ti, SIGNAL(destroyed()), this, SLOT(close()));
QLabel *titleLabel = new QLabel;
titleLabel->installEventFilter(this);
titleLabel->setText(title);
QFont f = titleLabel->font();
f.setBold(true);
#ifdef Q_OS_WINCE
f.setPointSize(f.pointSize() - 2);
#endif
titleLabel->setFont(f);
titleLabel->setTextFormat(Qt::PlainText); // to maintain compat with windows
#ifdef Q_OS_WINCE
const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
const int closeButtonSize = style()->pixelMetric(QStyle::PM_SmallIconSize) - 2;
#else
const int iconSize = 18;
const int closeButtonSize = 15;
#endif
QPushButton *closeButton = new QPushButton;
closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
closeButton->setIconSize(QSize(closeButtonSize, closeButtonSize));
closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
closeButton->setFixedSize(closeButtonSize, closeButtonSize);
QObject::connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
QLabel *msgLabel = new QLabel;
#ifdef Q_OS_WINCE
f.setBold(false);
msgLabel->setFont(f);
#endif
msgLabel->installEventFilter(this);
msgLabel->setText(message);
msgLabel->setTextFormat(Qt::PlainText);
msgLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
// smart size for the message label
#ifdef Q_OS_WINCE
int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 2;
#else
int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 3;
#endif
if (msgLabel->sizeHint().width() > limit) {
msgLabel->setWordWrap(true);
if (msgLabel->sizeHint().width() > limit) {
msgLabel->d_func()->ensureTextControl();
if (QWidgetTextControl *control = msgLabel->d_func()->control) {
QTextOption opt = control->document()->defaultTextOption();
opt.setWrapMode(QTextOption::WrapAnywhere);
control->document()->setDefaultTextOption(opt);
}
}
#ifdef Q_OS_WINCE
// Make sure that the text isn't wrapped "somewhere" in the balloon widget
// in the case that we have a long title label.
setMaximumWidth(limit);
#else
// Here we allow the text being much smaller than the balloon widget
// to emulate the weird standard windows behavior.
msgLabel->setFixedSize(limit, msgLabel->heightForWidth(limit));
#endif
}
QIcon si;
switch (icon) {
case QSystemTrayIcon::Warning:
si = style()->standardIcon(QStyle::SP_MessageBoxWarning);
break;
case QSystemTrayIcon::Critical:
si = style()->standardIcon(QStyle::SP_MessageBoxCritical);
break;
case QSystemTrayIcon::Information:
si = style()->standardIcon(QStyle::SP_MessageBoxInformation);
break;
case QSystemTrayIcon::NoIcon:
default:
break;
}
QGridLayout *layout = new QGridLayout;
if (!si.isNull()) {
QLabel *iconLabel = new QLabel;
iconLabel->setPixmap(si.pixmap(iconSize, iconSize));
iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
iconLabel->setMargin(2);
layout->addWidget(iconLabel, 0, 0);
layout->addWidget(titleLabel, 0, 1);
} else {
layout->addWidget(titleLabel, 0, 0, 1, 2);
}
layout->addWidget(closeButton, 0, 2);
layout->addWidget(msgLabel, 1, 0, 1, 3);
layout->setSizeConstraint(QLayout::SetFixedSize);
layout->setMargin(3);
setLayout(layout);
QPalette pal = palette();
pal.setColor(QPalette::Window, QColor(0xff, 0xff, 0xe1));
pal.setColor(QPalette::WindowText, Qt::black);
setPalette(pal);
}
QBalloonTip::~QBalloonTip()
{
theSolitaryBalloonTip = 0;
}
void QBalloonTip::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawPixmap(rect(), pixmap);
}
void QBalloonTip::resizeEvent(QResizeEvent *ev)
{
QWidget::resizeEvent(ev);
}
void QBalloonTip::balloon(const QPoint& pos, int msecs, bool showArrow)
{
this->showArrow = showArrow;
QRect scr = QApplication::desktop()->screenGeometry(pos);
QSize sh = sizeHint();
const int border = 1;
const int ah = 18, ao = 18, aw = 18, rc = 7;
bool arrowAtTop = (pos.y() + sh.height() + ah < scr.height());
bool arrowAtLeft = (pos.x() + sh.width() - ao < scr.width());
setContentsMargins(border + 3, border + (arrowAtTop ? ah : 0) + 2, border + 3, border + (arrowAtTop ? 0 : ah) + 2);
updateGeometry();
sh = sizeHint();
int ml, mr, mt, mb;
QSize sz = sizeHint();
if (!arrowAtTop) {
ml = mt = 0;
mr = sz.width() - 1;
mb = sz.height() - ah - 1;
} else {
ml = 0;
mt = ah;
mr = sz.width() - 1;
mb = sz.height() - 1;
}
QPainterPath path;
#if defined(QT_NO_XSHAPE) && defined(Q_DEAD_CODE_FROM_QT4_X11)
// XShape is required for setting the mask, so we just
// draw an ugly square when its not available
path.moveTo(0, 0);
path.lineTo(sz.width() - 1, 0);
path.lineTo(sz.width() - 1, sz.height() - 1);
path.lineTo(0, sz.height() - 1);
path.lineTo(0, 0);
move(qMax(pos.x() - sz.width(), scr.left()), pos.y());
#else
path.moveTo(ml + rc, mt);
if (arrowAtTop && arrowAtLeft) {
if (showArrow) {
path.lineTo(ml + ao, mt);
path.lineTo(ml + ao, mt - ah);
path.lineTo(ml + ao + aw, mt);
}
move(qMax(pos.x() - ao, scr.left() + 2), pos.y());
} else if (arrowAtTop && !arrowAtLeft) {
if (showArrow) {
path.lineTo(mr - ao - aw, mt);
path.lineTo(mr - ao, mt - ah);
path.lineTo(mr - ao, mt);
}
move(qMin(pos.x() - sh.width() + ao, scr.right() - sh.width() - 2), pos.y());
}
path.lineTo(mr - rc, mt);
path.arcTo(QRect(mr - rc*2, mt, rc*2, rc*2), 90, -90);
path.lineTo(mr, mb - rc);
path.arcTo(QRect(mr - rc*2, mb - rc*2, rc*2, rc*2), 0, -90);
if (!arrowAtTop && !arrowAtLeft) {
if (showArrow) {
path.lineTo(mr - ao, mb);
path.lineTo(mr - ao, mb + ah);
path.lineTo(mr - ao - aw, mb);
}
move(qMin(pos.x() - sh.width() + ao, scr.right() - sh.width() - 2),
pos.y() - sh.height());
} else if (!arrowAtTop && arrowAtLeft) {
if (showArrow) {
path.lineTo(ao + aw, mb);
path.lineTo(ao, mb + ah);
path.lineTo(ao, mb);
}
move(qMax(pos.x() - ao, scr.x() + 2), pos.y() - sh.height());
}
path.lineTo(ml + rc, mb);
path.arcTo(QRect(ml, mb - rc*2, rc*2, rc*2), -90, -90);
path.lineTo(ml, mt + rc);
path.arcTo(QRect(ml, mt, rc*2, rc*2), 180, -90);
// Set the mask
QBitmap bitmap = QBitmap(sizeHint());
bitmap.fill(Qt::color0);
QPainter painter1(&bitmap);
painter1.setPen(QPen(Qt::color1, border));
painter1.setBrush(QBrush(Qt::color1));
painter1.drawPath(path);
setMask(bitmap);
#endif
// Draw the border
pixmap = QPixmap(sz);
QPainter painter2(&pixmap);
painter2.setPen(QPen(palette().color(QPalette::Window).darker(160), border));
painter2.setBrush(palette().color(QPalette::Window));
painter2.drawPath(path);
if (msecs > 0)
timerId = startTimer(msecs);
show();
}
void QBalloonTip::mousePressEvent(QMouseEvent *e)
{
close();
if(e->button() == Qt::LeftButton)
emit trayIcon->messageClicked();
}
void QBalloonTip::timerEvent(QTimerEvent *e)
{
if (e->timerId() == timerId) {
killTimer(timerId);
if (!underMouse())
close();
return;
}
QWidget::timerEvent(e);
}
//////////////////////////////////////////////////////////////////////
void QSystemTrayIconPrivate::install_sys_qpa()
{
qpa_sys->init();
QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
QObject::connect(qpa_sys, &QPlatformSystemTrayIcon::messageClicked,
q_func(), &QSystemTrayIcon::messageClicked);
updateMenu_sys();
updateIcon_sys();
updateToolTip_sys();
}
void QSystemTrayIconPrivate::remove_sys_qpa()
{
qpa_sys->cleanup();
}
QRect QSystemTrayIconPrivate::geometry_sys_qpa() const
{
return qpa_sys->geometry();
}
void QSystemTrayIconPrivate::updateIcon_sys_qpa()
{
qpa_sys->updateIcon(icon);
}
void QSystemTrayIconPrivate::updateMenu_sys_qpa()
{
if (menu) {
addPlatformMenu(menu);
qpa_sys->updateMenu(menu->platformMenu());
} else {
qpa_sys->updateMenu(0);
}
}
void QSystemTrayIconPrivate::updateToolTip_sys_qpa()
{
qpa_sys->updateToolTip(toolTip);
}
void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &title,
const QString &message,
QSystemTrayIcon::MessageIcon icon,
int msecs)
{
QIcon notificationIcon;
switch (icon) {
case QSystemTrayIcon::Information:
notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
break;
case QSystemTrayIcon::Warning:
notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
break;
case QSystemTrayIcon::Critical:
notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
break;
default:
break;
}
qpa_sys->showMessage(title, message, notificationIcon,
static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
}
void QSystemTrayIconPrivate::addPlatformMenu(QMenu *menu) const
{
if (menu->platformMenu())
return; // The platform menu already exists.
// The recursion depth is the same as menu depth, so should not
// be higher than 3 levels.
QListIterator<QAction *> it(menu->actions());
while (it.hasNext()) {
QAction *action = it.next();
if (action->menu())
addPlatformMenu(action->menu());
}
// This menu should be processed *after* its children, otherwise
// setMenu() is not called on respective QPlatformMenuItems.
QPlatformMenu *platformMenu = qpa_sys->createMenu();
if (platformMenu)
menu->setPlatformMenu(platformMenu);
}
QT_END_NAMESPACE
#endif // QT_NO_SYSTEMTRAYICON
#include "moc_qsystemtrayicon.cpp"