From 6a915fd6c787020d7f858ea65394f79045a6b7bb Mon Sep 17 00:00:00 2001 From: kleuter Date: Fri, 13 Jul 2018 13:53:03 +0200 Subject: [PATCH] 5.6.2 no longer needed --- 5.6.2/compile_mac.sh | 68 - 5.6.2/compile_win.pl | 77 - 5.6.2/qtbase/configure.bat | 120 - 5.6.2/qtbase/mkspecs/common/msvc-desktop.conf | 104 - .../cocoa/qcocoaapplicationdelegate.mm | 450 ---- .../plugins/platforms/cocoa/qcocoawindow.mm | 1920 --------------- .../src/plugins/platforms/cocoa/qnsview.h | 149 -- .../src/plugins/platforms/cocoa/qnsview.mm | 2137 ----------------- 8 files changed, 5025 deletions(-) delete mode 100644 5.6.2/compile_mac.sh delete mode 100644 5.6.2/compile_win.pl delete mode 100644 5.6.2/qtbase/configure.bat delete mode 100644 5.6.2/qtbase/mkspecs/common/msvc-desktop.conf delete mode 100644 5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm delete mode 100644 5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoawindow.mm delete mode 100644 5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.h delete mode 100644 5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.mm diff --git a/5.6.2/compile_mac.sh b/5.6.2/compile_mac.sh deleted file mode 100644 index d5de7ab..0000000 --- a/5.6.2/compile_mac.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -export PATH=$PATH:/usr/local/Qt-5.6.2/bin - -cd qtbase - -if [[ $1 == openssl ]]; then - - # download openssl - curl -O https://www.openssl.org/source/old/1.0.2/openssl-1.0.2l.tar.gz - tar -xvzf openssl-1.0.2l.tar.gz - - # compile openssl - cd openssl-1.0.2l - ./Configure darwin64-x86_64-cc --prefix=$PWD/dist - make - # print arch info (optional) - lipo -info libssl.a - lipo -info libcrypto.a - make install - cd .. - - # continue - - OPENSSL_LIBS='-L$PWD/openssl-1.0.2l/dist/lib -lssl -lcrypto' ./configure -opensource -confirm-license -no-securetransport -nomake examples -nomake tests -openssl-linked -I $PWD/openssl-1.0.2l/dist/include -L $PWD/openssl-1.0.2l/dist/lib - -elif [[ $1 == securetransport ]]; then - - ./configure -opensource -confirm-license -nomake examples -nomake tests -no-openssl -securetransport - -else - - echo "Error: please specify which SSL layer to use (openssl or securetransport)" - exit 1 - -fi - -make -echo 12345 | sudo -S sudo make install - -cd ../qtdeclarative -qmake -make -echo 12345 | sudo -S sudo make install - -cd ../qttools -qmake -make -echo 12345 | sudo -S sudo make install - -cd ../qtmacextras -qmake -make -echo 12345 | sudo -S sudo make install - -# make docs - -cd ../qtbase -make docs -cd ../qttools -make docs -cd ../qtmacextras -make docs - -echo 12345 | sudo -S cp -f -r ../qtbase/doc /usr/local/Qt-5.6.2/ - -cd /usr/local -zip -r ~/Desktop/qt5.6.2_mac.zip Qt-5.6.2/* \ No newline at end of file diff --git a/5.6.2/compile_win.pl b/5.6.2/compile_win.pl deleted file mode 100644 index 07b22e2..0000000 --- a/5.6.2/compile_win.pl +++ /dev/null @@ -1,77 +0,0 @@ -use strict; - -my $arch = $ARGV[0]; -my $openssl_v_major = "1.0.2"; # The 1.0.2 series is Long Term Support (LTS) release, supported until 31st December 2019 -my $openssl_v_minor = "l"; -my $openssl_version = "$openssl_v_major$openssl_v_minor"; -my $openssl_dir = "openssl-$openssl_version"; -my $openssl_download = "https://www.openssl.org/source/old/$openssl_v_major/openssl-$openssl_version.tar.gz"; -my $openssl_arch = $arch eq "amd64" ? "WIN64A" : "WIN32"; -my $openssl_do_ms = $arch eq "amd64" ? "do_win64a" : "do_ms"; - -die "Please specify architecture (x86 or amd64)" if ($arch ne "x86" && $arch ne "amd64"); - -# will create a batch file - -my $batfile = 'compile_win.bat'; - -open BAT, '>', $batfile; - -printLineToBat ("CALL \"C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat\" $arch"); -printLineToBat ("cd qtbase"); -printLineToBat ("wget $openssl_download"); -printLineToBat ("tar -xvzf openssl-$openssl_version.tar.gz"); -printLineToBat ("rm openssl-$openssl_version.tar.gz"); -printLineToBat ("cd $openssl_dir"); -# build debug -printLineToBat ("perl Configure no-asm no-shared --prefix=%cd%\\Debug --openssldir=%cd%\\Debug debug-VC-$openssl_arch"); -printLineToBat ("call ms\\$openssl_do_ms"); -printLineToBat ("nmake -f ms\\nt.mak"); -printLineToBat ("nmake -f ms\\nt.mak install"); -printLineToBat ("xcopy tmp32.dbg\\lib.pdb Debug\\lib\\"); # Telegram does it. -printLineToBat ("nmake -f ms\\nt.mak clean"); -# now release -printLineToBat ("perl Configure no-asm no-shared --prefix=%cd%\\Release --openssldir=%cd%\\Release VC-$openssl_arch"); -printLineToBat ("call ms\\$openssl_do_ms"); -printLineToBat ("nmake -f ms\\nt.mak"); -printLineToBat ("nmake -f ms\\nt.mak install"); -printLineToBat ("xcopy tmp32\\lib.pdb Release\\lib\\"); # Telegram does it. -printLineToBat ("nmake -f ms\\nt.mak clean"); -# go back to qtbase -printLineToBat ("cd .."); -printLineToBat ("SET _ROOT=%cd%"); -printLineToBat ("SET PATH=%_ROOT%\\qtbase\\bin;%_ROOT%\\gnuwin32\\bin;%PATH%"); # http://doc.qt.io/qt-5/windows-building.html -printLineToBat ("configure -opensource -confirm-license -opengl desktop -mp -nomake tests -nomake examples -target xp -I \"%cd%\\$openssl_dir\\Release\\include\" -openssl-linked OPENSSL_LIBS_DEBUG=\"%cd%\\$openssl_dir\\Debug\\lib\\ssleay32.lib %cd%\\$openssl_dir\\Debug\\lib\\libeay32.lib\" OPENSSL_LIBS_RELEASE=\"%cd%\\$openssl_dir\\Release\\lib\\ssleay32.lib %cd%\\$openssl_dir\\Release\\lib\\libeay32.lib\""); -printLineToBat ("nmake"); -printLineToBat ("cd ..\\qttools"); -printLineToBat ("..\\qtbase\\bin\\qmake"); -printLineToBat ("nmake"); -printLineToBat ("cd ..\\qtwinextras"); -printLineToBat ("..\\qtbase\\bin\\qmake"); -printLineToBat ("nmake"); -printLineToBat ("cd ..\\qtbase"); -printLineToBat ("nmake docs"); -printLineToBat ("cd .."); # go up to qt dir -# openssl clean up -printLineToBat ("cd qtbase"); -printLineToBat ("cd $openssl_dir"); -printLineToBat ("del /s /f /q out32"); -printLineToBat ("del /s /f /q out32.dbg"); -printLineToBat ("cd .."); -printLineToBat ("cd .."); -# the rest -printLineToBat ("del *.obj /s /f"); -printLineToBat ("del *.ilk /s /f"); -printLineToBat ("del *.pch /s /f"); -printLineToBat ("del Makefile* /s /f"); - -close BAT; - -system ($batfile); -#system ("del $batfile"); -system ("pause"); - -sub printLineToBat -{ - print BAT "$_[0]\n"; -} \ No newline at end of file diff --git a/5.6.2/qtbase/configure.bat b/5.6.2/qtbase/configure.bat deleted file mode 100644 index 9cecf3b..0000000 --- a/5.6.2/qtbase/configure.bat +++ /dev/null @@ -1,120 +0,0 @@ -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:: -:: Copyright (C) 2015 The Qt Company Ltd. -:: Contact: http://www.qt.io/licensing/ -:: -:: This file is part of the tools applications 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$ -:: -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - -@echo off -set QTSRC=%~dp0 -set QTDIR=%CD% - -::if not exist %QTSRC%.gitignore goto sconf -echo Please wait while bootstrapping configure ... - -for %%C in (cl.exe icl.exe g++.exe perl.exe jom.exe) do set %%C=%%~$PATH:C - -if "%perl.exe%" == "" ( - echo Perl not found in PATH. Aborting. >&2 - exit /b 1 -) -if not exist mkspecs ( - md mkspecs - if errorlevel 1 goto exit -) - -rem Extract Qt's version from .qmake.conf -for /f "eol=# tokens=1,2,3,4 delims=.= " %%i in (%QTSRC%.qmake.conf) do ( - if %%i == MODULE_VERSION ( - set QTVERMAJ=%%j - set QTVERMIN=%%k - set QTVERPAT=%%l - ) -) -set QTVERSION=%QTVERMAJ%.%QTVERMIN%.%QTVERPAT% - -perl %QTSRC%bin\syncqt.pl -minimal -version %QTVERSION% -module QtCore -outdir "%QTDIR%" %QTSRC% -if errorlevel 1 goto exit - -if not exist tools\configure ( - md tools\configure - if errorlevel 1 goto exit -) -cd tools\configure -if errorlevel 1 goto exit - -set make=nmake -if not "%jom.exe%" == "" set make=jom - -echo #### Generated by configure.bat - DO NOT EDIT! ####> Makefile -echo/>> Makefile -echo QTVERSION = %QTVERSION%>> Makefile -rem These must have trailing spaces to avoid misinterpretation as 5>>, etc. -echo QT_VERSION_MAJOR = %QTVERMAJ% >> Makefile -echo QT_VERSION_MINOR = %QTVERMIN% >> Makefile -echo QT_VERSION_PATCH = %QTVERPAT% >> Makefile -if not "%icl.exe%" == "" ( - echo CXX = icl>>Makefile - echo EXTRA_CXXFLAGS = /Zc:forScope>>Makefile - rem This must have a trailing space. - echo QTSRC = %QTSRC% >> Makefile - set tmpl=win32 -) else if not "%cl.exe%" == "" ( - echo CXX = cl>>Makefile - echo EXTRA_CXXFLAGS =>>Makefile - rem This must have a trailing space. - echo QTSRC = %QTSRC% >> Makefile - set tmpl=win32 -) else if not "%g++.exe%" == "" ( - echo CXX = g++>>Makefile - echo EXTRA_CXXFLAGS =>>Makefile - rem This must NOT have a trailing space. - echo QTSRC = %QTSRC:\=/%>> Makefile - set tmpl=mingw - set make=mingw32-make -) else ( - echo No suitable compiler found in PATH. Aborting. >&2 - cd ..\.. - exit /b 1 -) -echo/>> Makefile -type %QTSRC%tools\configure\Makefile.%tmpl% >> Makefile - -%make% -if errorlevel 1 (cd ..\.. & exit /b 1) - -cd ..\.. - -:conf -configure.exe -srcdir %QTSRC% %* -goto exit - -:sconf -%QTSRC%configure.exe %* -:exit diff --git a/5.6.2/qtbase/mkspecs/common/msvc-desktop.conf b/5.6.2/qtbase/mkspecs/common/msvc-desktop.conf deleted file mode 100644 index f78cb13..0000000 --- a/5.6.2/qtbase/mkspecs/common/msvc-desktop.conf +++ /dev/null @@ -1,104 +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 -# - -include(angle.conf) - -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 = bison -y -QMAKE_YACCFLAGS = -d -QMAKE_CFLAGS = -nologo -Zc:wchar_t -QMAKE_CFLAGS_WARN_ON = -W3 -QMAKE_CFLAGS_WARN_OFF = -W0 -QMAKE_CFLAGS_RELEASE = -O2 -MD -Zi -QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MD -Zi -QMAKE_CFLAGS_DEBUG = -Zi -MDd -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_WITH_DEBUGINFO -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 /DEBUG /OPT:REF -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_PREFIX_SHLIB = -QMAKE_EXTENSION_SHLIB = dll -QMAKE_PREFIX_STATICLIB = -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 user32.lib gdi32.lib -QMAKE_LIBS_OPENGL = glu32.lib opengl32.lib gdi32.lib user32.lib -QMAKE_LIBS_OPENGL_ES2 = $${LIBEGL_NAME}.lib $${LIBGLESV2_NAME}.lib gdi32.lib user32.lib -QMAKE_LIBS_OPENGL_ES2_DEBUG = $${LIBEGL_NAME}d.lib $${LIBGLESV2_NAME}d.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 - -include(msvc-base.conf) - -unset(MSC_VER) diff --git a/5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm deleted file mode 100644 index e3d82e0..0000000 --- a/5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ /dev/null @@ -1,450 +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 -#include -#include -#include -#include -#include "qt_mac_p.h" -#include - -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]; - qAddPostRoutine(cleanupCocoaApplicationDelegate); - return sharedCocoaApplicationDelegate; - } - } - 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); - // Already closed windows will not have a platform window, skip those - if (topLevelWindow->handle()) - 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]; -} - -- (bool) inLaunch -{ - return inLaunch; -} - -- (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 *)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 diff --git a/5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoawindow.mm b/5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoawindow.mm deleted file mode 100644 index ee3ebf5..0000000 --- a/5.6.2/qtbase/src/plugins/platforms/cocoa/qcocoawindow.mm +++ /dev/null @@ -1,1920 +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 "qcocoawindow.h" -#include "qcocoaintegration.h" -#include "qnswindowdelegate.h" -#include "qcocoaeventdispatcher.h" -#ifndef QT_NO_OPENGL -#include "qcocoaglcontext.h" -#endif -#include "qcocoahelpers.h" -#include "qcocoanativeinterface.h" -#include "qnsview.h" -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -enum { - defaultWindowWidth = 160, - defaultWindowHeight = 160 -}; - -static bool isMouseEvent(NSEvent *ev) -{ - switch ([ev type]) { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - return true; - default: - return false; - } -} - -@implementation QNSWindowHelper - -@synthesize window = _window; -@synthesize platformWindow = _platformWindow; -@synthesize grabbingMouse = _grabbingMouse; -@synthesize releaseOnMouseUp = _releaseOnMouseUp; - -- (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow -{ - self = [super init]; - if (self) { - _window = window; - _platformWindow.assign(platformWindow); - - _window.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:_platformWindow]; - - // Prevent Cocoa from releasing the window on close. Qt - // handles the close event asynchronously and we want to - // make sure that m_nsWindow stays valid until the - // QCocoaWindow is deleted by Qt. - [_window setReleasedWhenClosed:NO]; - } - - return self; -} - -- (void)handleWindowEvent:(NSEvent *)theEvent -{ - QCocoaWindow *pw = self.platformWindow; - if (pw && pw->m_forwardWindow) { - if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) { - QNSView *forwardView = pw->m_qtView; - if (theEvent.type == NSLeftMouseUp) { - [forwardView mouseUp:theEvent]; - pw->m_forwardWindow.clear(); - } else { - [forwardView mouseDragged:theEvent]; - } - } - - if (!pw->m_isNSWindowChild && theEvent.type == NSLeftMouseDown) { - pw->m_forwardWindow.clear(); - } - } - - if (theEvent.type == NSLeftMouseDown) { - self.grabbingMouse = YES; - } else if (theEvent.type == NSLeftMouseUp) { - self.grabbingMouse = NO; - if (self.releaseOnMouseUp) { - [self detachFromPlatformWindow]; - [self.window release]; - return; - } - } - - // The call to -[NSWindow sendEvent] may result in the window being deleted - // (e.g., when closing the window by pressing the title bar close button). - [self retain]; - [self.window superSendEvent:theEvent]; - bool windowStillAlive = self.window != nil; // We need to read before releasing - [self release]; - if (!windowStillAlive) - return; - - if (!self.window.delegate) - return; // Already detached, pending NSAppKitDefined event - - if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { - NSPoint loc = [theEvent locationInWindow]; - NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; - NSRect contentFrame = [[self.window contentView] frame]; - if (NSMouseInRect(loc, windowFrame, NO) && - !NSMouseInRect(loc, contentFrame, NO)) - { - QNSView *contentView = pw->m_qtView; - [contentView handleFrameStrutMouseEvent: theEvent]; - } - } -} - -- (void)detachFromPlatformWindow -{ - self.platformWindow.clear(); - [self.window.delegate release]; - self.window.delegate = nil; -} - -- (void)clearWindow -{ - if (_window) { - QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); - if (cocoaEventDispatcher) { - QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast(QObjectPrivate::get(cocoaEventDispatcher)); - cocoaEventDispatcherPrivate->removeQueuedUserInputEvents([_window windowNumber]); - } - - _window = nil; - } -} - -- (void)dealloc -{ - _window = nil; - self.platformWindow.clear(); - [super dealloc]; -} - -@end - -@implementation QNSWindow - -@synthesize helper = _helper; - -- (id)initWithContentRect:(NSRect)contentRect - styleMask:(NSUInteger)windowStyle - qPlatformWindow:(QCocoaWindow *)qpw -{ - self = [super initWithContentRect:contentRect - styleMask:windowStyle - backing:NSBackingStoreBuffered - defer:NO]; // Deferring window creation breaks OpenGL (the GL context is - // set up before the window is shown and needs a proper window) - - if (self) { - _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw]; - } - return self; -} - -- (BOOL)canBecomeKeyWindow -{ - // Prevent child NSWindows from becoming the key window in - // order keep the active apperance of the top-level window. - QCocoaWindow *pw = self.helper.platformWindow; - if (!pw || pw->m_isNSWindowChild) - return NO; - - if (pw->shouldRefuseKeyWindowAndFirstResponder()) - return NO; - - // The default implementation returns NO for title-bar less windows, - // override and return yes here to make sure popup windows such as - // the combobox popup can become the key window. - return YES; -} - -- (BOOL)canBecomeMainWindow -{ - BOOL canBecomeMain = YES; // By default, windows can become the main window - - // Windows with a transient parent (such as combobox popup windows) - // cannot become the main window: - QCocoaWindow *pw = self.helper.platformWindow; - if (!pw || pw->m_isNSWindowChild || pw->window()->transientParent()) - canBecomeMain = NO; - - return canBecomeMain; -} - -- (void) sendEvent: (NSEvent*) theEvent -{ - [self.helper handleWindowEvent:theEvent]; -} - -- (void)superSendEvent:(NSEvent *)theEvent -{ - [super sendEvent:theEvent]; -} - -- (void)closeAndRelease -{ - [self close]; - - if (self.helper.grabbingMouse) { - self.helper.releaseOnMouseUp = YES; - } else { - [self.helper detachFromPlatformWindow]; - [self release]; - } -} - -- (void)dealloc -{ - [_helper clearWindow]; - [_helper release]; - _helper = nil; - [super dealloc]; -} - -@end - -@implementation QNSPanel - -@synthesize helper = _helper; - -- (id)initWithContentRect:(NSRect)contentRect - styleMask:(NSUInteger)windowStyle - qPlatformWindow:(QCocoaWindow *)qpw -{ - self = [super initWithContentRect:contentRect - styleMask:windowStyle - backing:NSBackingStoreBuffered - defer:NO]; // Deferring window creation breaks OpenGL (the GL context is - // set up before the window is shown and needs a proper window) - - if (self) { - _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw]; - } - return self; -} - -- (BOOL)canBecomeKeyWindow -{ - QCocoaWindow *pw = self.helper.platformWindow; - if (!pw) - return NO; - - if (pw->shouldRefuseKeyWindowAndFirstResponder()) - return NO; - - // Only tool or dialog windows should become key: - Qt::WindowType type = pw->window()->type(); - if (type == Qt::Tool || type == Qt::Dialog) - return YES; - - return NO; -} - -- (void) sendEvent: (NSEvent*) theEvent -{ - [self.helper handleWindowEvent:theEvent]; -} - -- (void)superSendEvent:(NSEvent *)theEvent -{ - [super sendEvent:theEvent]; -} - -- (void)closeAndRelease -{ - [self.helper detachFromPlatformWindow]; - [self close]; - [self release]; -} - -- (void)dealloc -{ - [_helper clearWindow]; - [_helper release]; - _helper = nil; - [super dealloc]; -} - -@end - -void QCocoaWindowPointer::assign(QCocoaWindow *w) -{ - window = w; - watcher = &w->sentinel; -} - -void QCocoaWindowPointer::clear() -{ - window = Q_NULLPTR; - watcher.clear(); -} - -const int QCocoaWindow::NoAlertRequest = -1; - -QCocoaWindow::QCocoaWindow(QWindow *tlw) - : QPlatformWindow(tlw) - , m_contentView(nil) - , m_qtView(nil) - , m_nsWindow(0) - , m_contentViewIsEmbedded(false) - , m_contentViewIsToBeEmbedded(false) - , m_parentCocoaWindow(0) - , m_isNSWindowChild(false) - , m_effectivelyMaximized(false) - , m_synchedWindowState(Qt::WindowActive) - , m_windowModality(Qt::NonModal) - , m_windowUnderMouse(false) - , m_inConstructor(true) - , m_inSetVisible(false) - , m_inSetGeometry(false) - , m_inSetStyleMask(false) -#ifndef QT_NO_OPENGL - , m_glContext(0) -#endif - , m_menubar(0) - , m_windowCursor(0) - , m_hasModalSession(false) - , m_frameStrutEventsEnabled(false) - , m_geometryUpdateExposeAllowed(false) - , m_isExposed(false) - , m_registerTouchCount(0) - , m_resizableTransientParent(false) - , m_hiddenByClipping(false) - , m_hiddenByAncestor(false) - , m_alertRequest(NoAlertRequest) - , monitor(nil) - , m_drawContentBorderGradient(false) - , m_topContentBorderThickness(0) - , m_bottomContentBorderThickness(0) - , m_normalGeometry(QRect(0,0,-1,-1)) -{ -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::QCocoaWindow" << this; -#endif - QMacAutoReleasePool pool; - - if (tlw->type() == Qt::ForeignWindow) { - NSView *foreignView = (NSView *)WId(tlw->property("_q_foreignWinId").value()); - setContentView(foreignView); - } else { - m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; - m_contentView = m_qtView; - // Enable high-dpi OpenGL for retina displays. Enabling has the side - // effect that Cocoa will start calling glViewport(0, 0, width, height), - // overriding any glViewport calls in application code. This is usually not a - // problem, except if the appilcation wants to have a "custom" viewport. - // (like the hellogl example) - if (tlw->supportsOpenGL()) { - BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface", - "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); - [m_contentView setWantsBestResolutionOpenGLSurface:enable]; - } - BOOL enable = qt_mac_resolveOption(NO, tlw, "_q_mac_wantsLayer", - "QT_MAC_WANTS_LAYER"); - [m_contentView setWantsLayer:enable]; - } - setGeometry(tlw->geometry()); - recreateWindow(parent()); - tlw->setGeometry(geometry()); - if (tlw->isTopLevel()) - setWindowIcon(tlw->icon()); - m_inConstructor = false; -} - -QCocoaWindow::~QCocoaWindow() -{ -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::~QCocoaWindow" << this; -#endif - - QMacAutoReleasePool pool; - [m_nsWindow makeFirstResponder:nil]; - [m_nsWindow setContentView:nil]; - [m_nsWindow.helper detachFromPlatformWindow]; - if (m_isNSWindowChild) { - if (m_parentCocoaWindow) - m_parentCocoaWindow->removeChildWindow(this); - } else if ([m_contentView superview]) { - [m_contentView removeFromSuperview]; - } - - removeMonitor(); - - // Make sure to disconnect observer in all case if view is valid - // to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute - if (m_qtView) { - [[NSNotificationCenter defaultCenter] removeObserver:m_qtView]; - } - - // The QNSView object may outlive the corresponding QCocoaWindow object, - // for example during app shutdown when the QNSView is embedded in a - // foregin NSView hiearchy. Clear the pointers to the QWindow/QCocoaWindow - // here to make sure QNSView does not dereference stale pointers. - if (m_qtView) { - [m_qtView clearQWindowPointers]; - } - - // While it is unlikely that this window will be in the popup stack - // during deletetion we clear any pointers here to make sure. - if (QCocoaIntegration::instance()) { - QCocoaIntegration::instance()->popupWindowStack()->removeAll(this); - } - - foreach (QCocoaWindow *child, m_childWindows) { - [m_nsWindow removeChildWindow:child->m_nsWindow]; - child->m_parentCocoaWindow = 0; - } - - [m_contentView release]; - [m_nsWindow release]; - [m_windowCursor release]; -} - -QSurfaceFormat QCocoaWindow::format() const -{ - QSurfaceFormat format = window()->requestedFormat(); - - // Upgrade the default surface format to include an alpha channel. The default RGB format - // causes Cocoa to spend an unreasonable amount of time converting it to RGBA internally. - if (format == QSurfaceFormat()) - format.setAlphaBufferSize(8); - return format; -} - -void QCocoaWindow::setGeometry(const QRect &rectIn) -{ - QBoolBlocker inSetGeometry(m_inSetGeometry, true); - - QRect rect = rectIn; - // This means it is a call from QWindow::setFramePosition() and - // the coordinates include the frame (size is still the contents rectangle). - if (qt_window_private(const_cast(window()))->positionPolicy - == QWindowPrivate::WindowFrameInclusive) { - const QMargins margins = frameMargins(); - rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top())); - } - if (geometry() == rect) - return; -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::setGeometry" << this << rect; -#endif - setCocoaGeometry(rect); -} - -QRect QCocoaWindow::geometry() const -{ - // QWindows that are embedded in a NSView hiearchy may be considered - // top-level from Qt's point of view but are not from Cocoa's point - // of view. Embedded QWindows get global (screen) geometry. - if (m_contentViewIsEmbedded) { - NSPoint windowPoint = [m_contentView convertPoint:NSMakePoint(0, 0) toView:nil]; - NSRect screenRect = [[m_contentView window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; - NSPoint screenPoint = screenRect.origin; - QPoint position = qt_mac_flipPoint(screenPoint).toPoint(); - QSize size = qt_mac_toQRect([m_contentView bounds]).size(); - return QRect(position, size); - } - - return QPlatformWindow::geometry(); -} - -void QCocoaWindow::setCocoaGeometry(const QRect &rect) -{ - QMacAutoReleasePool pool; - - if (m_contentViewIsEmbedded) { - if (m_qtView) { - [m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; - } else { - QPlatformWindow::setGeometry(rect); - } - return; - } - - if (m_isNSWindowChild) { - QPlatformWindow::setGeometry(rect); - NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow; - NSRect parentWindowFrame = [parentNSWindow contentRectForFrameRect:parentNSWindow.frame]; - clipWindow(parentWindowFrame); - - // call this here: updateGeometry in qnsview.mm is a no-op for this case - QWindowSystemInterface::handleGeometryChange(window(), rect); - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size())); - } else if (m_nsWindow) { - NSRect bounds = qt_mac_flipRect(rect); - [m_nsWindow setFrame:[m_nsWindow frameRectForContentRect:bounds] display:YES animate:NO]; - } else { - [m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; - } - - if (!m_qtView) - QPlatformWindow::setGeometry(rect); - - // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) -} - -void QCocoaWindow::clipChildWindows() -{ - foreach (QCocoaWindow *childWindow, m_childWindows) { - childWindow->clipWindow(m_nsWindow.frame); - } -} - -void QCocoaWindow::clipWindow(const NSRect &clipRect) -{ - if (!m_isNSWindowChild) - return; - - NSRect clippedWindowRect = NSZeroRect; - if (!NSIsEmptyRect(clipRect)) { - NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size())); - clippedWindowRect = NSIntersectionRect(windowFrame, clipRect); - // Clipping top/left offsets the content. Move it back. - NSPoint contentViewOffset = NSMakePoint(qMax(CGFloat(0), NSMinX(clippedWindowRect) - NSMinX(windowFrame)), - qMax(CGFloat(0), NSMaxY(windowFrame) - NSMaxY(clippedWindowRect))); - [m_contentView setBoundsOrigin:contentViewOffset]; - } - - if (NSIsEmptyRect(clippedWindowRect)) { - if (!m_hiddenByClipping) { - // We dont call hide() here as we will recurse further down - [m_nsWindow orderOut:nil]; - m_hiddenByClipping = true; - } - } else { - [m_nsWindow setFrame:clippedWindowRect display:YES animate:NO]; - if (m_hiddenByClipping) { - m_hiddenByClipping = false; - if (!m_hiddenByAncestor) { - [m_nsWindow orderFront:nil]; - m_parentCocoaWindow->reinsertChildWindow(this); - } - } - } - - // recurse - foreach (QCocoaWindow *childWindow, m_childWindows) { - childWindow->clipWindow(clippedWindowRect); - } -} - -void QCocoaWindow::hide(bool becauseOfAncestor) -{ - bool visible = [m_nsWindow isVisible]; - - if (!m_hiddenByAncestor && !visible) // Already explicitly hidden - return; - if (m_hiddenByAncestor && becauseOfAncestor) // Trying to hide some child again - return; - - m_hiddenByAncestor = becauseOfAncestor; - - if (!visible) // Could have been clipped before - return; - - foreach (QCocoaWindow *childWindow, m_childWindows) - childWindow->hide(true); - - [m_nsWindow orderOut:nil]; -} - -void QCocoaWindow::show(bool becauseOfAncestor) -{ - if ([m_nsWindow isVisible]) - return; - - if (m_parentCocoaWindow && ![m_parentCocoaWindow->m_nsWindow isVisible]) { - m_hiddenByAncestor = true; // Parent still hidden, don't show now - } else if ((becauseOfAncestor == m_hiddenByAncestor) // Was NEITHER explicitly hidden - && !m_hiddenByClipping) { // ... NOR clipped - if (m_isNSWindowChild) { - m_hiddenByAncestor = false; - setCocoaGeometry(windowGeometry()); - } - if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status - [m_nsWindow orderFront:nil]; - if (m_isNSWindowChild) - m_parentCocoaWindow->reinsertChildWindow(this); - foreach (QCocoaWindow *childWindow, m_childWindows) - childWindow->show(true); - } - } -} - -void QCocoaWindow::setVisible(bool visible) -{ - if (m_isNSWindowChild && m_hiddenByClipping) - return; - - m_inSetVisible = true; - - QMacAutoReleasePool pool; - QCocoaWindow *parentCocoaWindow = 0; - if (window()->transientParent()) - parentCocoaWindow = static_cast(window()->transientParent()->handle()); -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::setVisible" << window() << visible; -#endif - if (visible) { - // We need to recreate if the modality has changed as the style mask will need updating - if (m_windowModality != window()->modality()) - recreateWindow(parent()); - - // Register popup windows. The Cocoa platform plugin will forward mouse events - // to them and close them when needed. - if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) - QCocoaIntegration::instance()->pushPopupWindow(this); - - if (parentCocoaWindow) { - // The parent window might have moved while this window was hidden, - // update the window geometry if there is a parent. - setGeometry(windowGeometry()); - - if (window()->type() == Qt::Popup) { - // QTBUG-30266: a window should not be resizable while a transient popup is open - // Since this isn't a native popup, the window manager doesn't close the popup when you click outside - NSUInteger parentStyleMask = [parentCocoaWindow->m_nsWindow styleMask]; - if ((m_resizableTransientParent = (parentStyleMask & NSResizableWindowMask)) - && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask)) - [parentCocoaWindow->m_nsWindow setStyleMask:parentStyleMask & ~NSResizableWindowMask]; - } - - } - - // This call is here to handle initial window show correctly: - // - top-level windows need to have backing store content ready when the - // window is shown, sendin the expose event here makes that more likely. - // - QNSViews for child windows are initialy not hidden and won't get the - // viewDidUnhide message. - exposeWindow(); - - if (m_nsWindow) { - QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); - - // setWindowState might have been called while the window was hidden and - // will not change the NSWindow state in that case. Sync up here: - syncWindowState(window()->windowState()); - - if (window()->windowState() != Qt::WindowMinimized) { - if ((window()->modality() == Qt::WindowModal - || window()->type() == Qt::Sheet) - && parentCocoaWindow) { - // show the window as a sheet - [NSApp beginSheet:m_nsWindow modalForWindow:parentCocoaWindow->m_nsWindow modalDelegate:nil didEndSelector:nil contextInfo:nil]; - } else if (window()->modality() != Qt::NonModal) { - // show the window as application modal - QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); - Q_ASSERT(cocoaEventDispatcher != 0); - QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast(QObjectPrivate::get(cocoaEventDispatcher)); - cocoaEventDispatcherPrivate->beginModalSession(window()); - m_hasModalSession = true; - } else if ([m_nsWindow canBecomeKeyWindow]) { - [m_nsWindow makeKeyAndOrderFront:nil]; - foreach (QCocoaWindow *childWindow, m_childWindows) - childWindow->show(true); - } else { - show(); - } - - // We want the events to properly reach the popup, dialog, and tool - if ((window()->type() == Qt::Popup || window()->type() == Qt::Dialog || window()->type() == Qt::Tool) - && [m_nsWindow isKindOfClass:[NSPanel class]]) { - [(NSPanel *)m_nsWindow setWorksWhenModal:YES]; - if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) { - removeMonitor(); - monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) { - QPointF localPoint = qt_mac_flipPoint([NSEvent mouseLocation]); - QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint, - cocoaButton2QtButton([e buttonNumber])); - }]; - } - } - } - } - // In some cases, e.g. QDockWidget, the content view is hidden before moving to its own - // Cocoa window, and then shown again. Therefore, we test for the view being hidden even - // if it's attached to an NSWindow. - if ([m_contentView isHidden]) - [m_contentView setHidden:NO]; - } else { - // qDebug() << "close" << this; -#ifndef QT_NO_OPENGL - if (m_glContext) - m_glContext->windowWasHidden(); -#endif - QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); - QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0; - if (cocoaEventDispatcher) - cocoaEventDispatcherPrivate = static_cast(QObjectPrivate::get(cocoaEventDispatcher)); - if (m_nsWindow) { - if (m_hasModalSession) { - if (cocoaEventDispatcherPrivate) - cocoaEventDispatcherPrivate->endModalSession(window()); - m_hasModalSession = false; - } else { - if ([m_nsWindow isSheet]) - [NSApp endSheet:m_nsWindow]; - } - - hide(); - if (m_nsWindow == [NSApp keyWindow] - && !(cocoaEventDispatcherPrivate && cocoaEventDispatcherPrivate->currentModalSession())) { - // Probably because we call runModalSession: outside [NSApp run] in QCocoaEventDispatcher - // (e.g., when show()-ing a modal QDialog instead of exec()-ing it), it can happen that - // the current NSWindow is still key after being ordered out. Then, after checking we - // don't have any other modal session left, it's safe to make the main window key again. - NSWindow *mainWindow = [NSApp mainWindow]; - if (mainWindow && [mainWindow canBecomeKeyWindow]) - [mainWindow makeKeyWindow]; - } - } else { - [m_contentView setHidden:YES]; - } - removeMonitor(); - - if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) - QCocoaIntegration::instance()->popupWindowStack()->removeAll(this); - - if (parentCocoaWindow && window()->type() == Qt::Popup) { - if (m_resizableTransientParent - && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask)) - // QTBUG-30266: a window should not be resizable while a transient popup is open - [parentCocoaWindow->m_nsWindow setStyleMask:[parentCocoaWindow->m_nsWindow styleMask] | NSResizableWindowMask]; - } - } - - m_inSetVisible = false; -} - -NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags) -{ - Qt::WindowType type = static_cast(int(flags & Qt::WindowType_Mask)); - - NSInteger windowLevel = NSNormalWindowLevel; - - if (type == Qt::Tool) - windowLevel = NSFloatingWindowLevel; - else if ((type & Qt::Popup) == Qt::Popup) - windowLevel = NSPopUpMenuWindowLevel; - - // StayOnTop window should appear above Tool windows. - if (flags & Qt::WindowStaysOnTopHint) - windowLevel = NSModalPanelWindowLevel; - // Tooltips should appear above StayOnTop windows. - if (type == Qt::ToolTip) - windowLevel = NSScreenSaverWindowLevel; - - // Any "special" window should be in at least the same level as its parent. - if (type != Qt::Window) { - const QWindow * const transientParent = window()->transientParent(); - const QCocoaWindow * const transientParentWindow = transientParent ? static_cast(transientParent->handle()) : 0; - if (transientParentWindow) - windowLevel = qMax([transientParentWindow->m_nsWindow level], windowLevel); - } - - return windowLevel; -} - -NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) -{ - Qt::WindowType type = static_cast(int(flags & Qt::WindowType_Mask)); - NSInteger styleMask = NSBorderlessWindowMask; - if (flags & Qt::FramelessWindowHint) - return styleMask; - if ((type & Qt::Popup) == Qt::Popup) { - if (!windowIsPopupType(type)) { - styleMask = NSUtilityWindowMask | NSResizableWindowMask; - if (!(flags & Qt::CustomizeWindowHint)) { - styleMask |= NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask; - } else { - if (flags & Qt::WindowTitleHint) - styleMask |= NSTitledWindowMask; - if (flags & Qt::WindowCloseButtonHint) - styleMask |= NSClosableWindowMask; - if (flags & Qt::WindowMinimizeButtonHint) - styleMask |= NSMiniaturizableWindowMask; - } - } - } else { - if (type == Qt::Window && !(flags & Qt::CustomizeWindowHint)) { - styleMask = (NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask); - } else if (type == Qt::Dialog) { - if (flags & Qt::CustomizeWindowHint) { - if (flags & Qt::WindowMaximizeButtonHint) - styleMask = NSResizableWindowMask; - if (flags & Qt::WindowTitleHint) - styleMask |= NSTitledWindowMask; - if (flags & Qt::WindowCloseButtonHint) - styleMask |= NSClosableWindowMask; - if (flags & Qt::WindowMinimizeButtonHint) - styleMask |= NSMiniaturizableWindowMask; - } else { - styleMask = NSResizableWindowMask | NSClosableWindowMask | NSTitledWindowMask; - } - } else { - if (flags & Qt::WindowMaximizeButtonHint) - styleMask |= NSResizableWindowMask; - if (flags & Qt::WindowTitleHint) - styleMask |= NSTitledWindowMask; - if (flags & Qt::WindowCloseButtonHint) - styleMask |= NSClosableWindowMask; - if (flags & Qt::WindowMinimizeButtonHint) - styleMask |= NSMiniaturizableWindowMask; - } - } - - if (m_drawContentBorderGradient) - styleMask |= NSTexturedBackgroundWindowMask; - -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug("windowStyleMask of '%s': flags %X -> styleMask %lX", qPrintable(window()->title()), (int)flags, styleMask); -#endif - return styleMask; -} - -void QCocoaWindow::setWindowShadow(Qt::WindowFlags flags) -{ - bool keepShadow = !(flags & Qt::NoDropShadowWindowHint); - [m_nsWindow setHasShadow:(keepShadow ? YES : NO)]; -} - -void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags) -{ - // Disable the zoom (maximize) button for fixed-sized windows and customized - // no-WindowMaximizeButtonHint windows. From a Qt perspective it migth be expected - // that the button would be removed in the latter case, but disabling it is more - // in line with the platform style guidelines. - bool fixedSizeNoZoom = (windowMinimumSize().isValid() && windowMaximumSize().isValid() - && windowMinimumSize() == windowMaximumSize()); - bool customizeNoZoom = ((flags & Qt::CustomizeWindowHint) && !(flags & Qt::WindowMaximizeButtonHint)); - [[m_nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)]; -} - -void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) -{ - if (m_nsWindow && !m_isNSWindowChild) { - NSUInteger styleMask = windowStyleMask(flags); - NSInteger level = this->windowLevel(flags); - // While setting style mask we can have -updateGeometry calls on a content - // view with null geometry, reporting an invalid coordinates as a result. - m_inSetStyleMask = true; - [m_nsWindow setStyleMask:styleMask]; - m_inSetStyleMask = false; - [m_nsWindow setLevel:level]; - setWindowShadow(flags); - if (!(flags & Qt::FramelessWindowHint)) { - setWindowTitle(window()->title()); - } - - Qt::WindowType type = window()->type(); - if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) { - NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior]; - if (flags & Qt::WindowFullscreenButtonHint) { - behavior |= NSWindowCollectionBehaviorFullScreenPrimary; - behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary; - } else { - behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary; - behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; - } - [m_nsWindow setCollectionBehavior:behavior]; - } - setWindowZoomButton(flags); - } - - m_windowFlags = flags; -} - -void QCocoaWindow::setWindowState(Qt::WindowState state) -{ - if (window()->isVisible()) - syncWindowState(state); // Window state set for hidden windows take effect when show() is called. -} - -void QCocoaWindow::setWindowTitle(const QString &title) -{ - QMacAutoReleasePool pool; - if (!m_nsWindow) - return; - - CFStringRef windowTitle = QCFString::toCFStringRef(title); - [m_nsWindow setTitle: const_cast(reinterpret_cast(windowTitle))]; - CFRelease(windowTitle); -} - -void QCocoaWindow::setWindowFilePath(const QString &filePath) -{ - QMacAutoReleasePool pool; - if (!m_nsWindow) - return; - - QFileInfo fi(filePath); - [m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""]; -} - -void QCocoaWindow::setWindowIcon(const QIcon &icon) -{ - QMacAutoReleasePool pool; - - NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; - if (iconButton == nil) { - if (icon.isNull()) - return; - NSString *title = QCFString::toNSString(window()->title()); - [m_nsWindow setRepresentedURL:[NSURL fileURLWithPath:title]]; - iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; - } - if (icon.isNull()) { - [iconButton setImage:nil]; - } else { - QPixmap pixmap = icon.pixmap(QSize(22, 22)); - NSImage *image = static_cast(qt_mac_create_nsimage(pixmap)); - [iconButton setImage:image]; - [image release]; - } -} - -void QCocoaWindow::setAlertState(bool enabled) -{ - if (m_alertRequest == NoAlertRequest && enabled) { - m_alertRequest = [NSApp requestUserAttention:NSCriticalRequest]; - } else if (m_alertRequest != NoAlertRequest && !enabled) { - [NSApp cancelUserAttentionRequest:m_alertRequest]; - m_alertRequest = NoAlertRequest; - } -} - -bool QCocoaWindow::isAlertState() const -{ - return m_alertRequest != NoAlertRequest; -} - -void QCocoaWindow::raise() -{ - //qDebug() << "raise" << this; - // ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm) - if (!m_nsWindow) - return; - if (m_isNSWindowChild) { - QList &siblings = m_parentCocoaWindow->m_childWindows; - siblings.removeOne(this); - siblings.append(this); - if (m_hiddenByClipping) - return; - } - if ([m_nsWindow isVisible]) { - if (m_isNSWindowChild) { - // -[NSWindow orderFront:] doesn't work with attached windows. - // The only solution is to remove and add the child window. - // This will place it on top of all the other NSWindows. - NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow; - [parentNSWindow removeChildWindow:m_nsWindow]; - [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; - } else { - { - // Clean up autoreleased temp objects from orderFront immediately. - // Failure to do so has been observed to cause leaks also beyond any outer - // autorelease pool (for example around a complete QWindow - // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool - // behavior. - QMacAutoReleasePool pool; - [m_nsWindow orderFront: m_nsWindow]; - } - static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS"); - if (raiseProcess) { - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); - } - } - } -} - -void QCocoaWindow::lower() -{ - if (!m_nsWindow) - return; - if (m_isNSWindowChild) { - QList &siblings = m_parentCocoaWindow->m_childWindows; - siblings.removeOne(this); - siblings.prepend(this); - if (m_hiddenByClipping) - return; - } - if ([m_nsWindow isVisible]) { - if (m_isNSWindowChild) { - // -[NSWindow orderBack:] doesn't work with attached windows. - // The only solution is to remove and add all the child windows except this one. - // This will keep the current window at the bottom while adding the others on top of it, - // hopefully in the same order (this is not documented anywhere in the Cocoa documentation). - NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow; - NSArray *children = [parentNSWindow.childWindows copy]; - for (NSWindow *child in children) - if (m_nsWindow != child) { - [parentNSWindow removeChildWindow:child]; - [parentNSWindow addChildWindow:child ordered:NSWindowAbove]; - } - } else { - [m_nsWindow orderBack: m_nsWindow]; - } - } -} - -bool QCocoaWindow::isExposed() const -{ - return m_isExposed; -} - -bool QCocoaWindow::isOpaque() const -{ - // OpenGL surfaces can be ordered either above(default) or below the NSWindow. - // When ordering below the window must be tranclucent. - static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER"); - - bool translucent = (window()->format().alphaBufferSize() > 0 - || window()->opacity() < 1 - || (m_qtView && [m_qtView hasMask])) - || (surface()->supportsOpenGL() && openglSourfaceOrder == -1); - return !translucent; -} - -void QCocoaWindow::propagateSizeHints() -{ - QMacAutoReleasePool pool; - if (!m_nsWindow) - return; - -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::propagateSizeHints" << this; - qDebug() << " min/max" << windowMinimumSize() << windowMaximumSize(); - qDebug() << "size increment" << windowSizeIncrement(); - qDebug() << " basesize" << windowBaseSize(); - qDebug() << " geometry" << windowGeometry(); -#endif - - // Set the minimum content size. - const QSize minimumSize = windowMinimumSize(); - if (!minimumSize.isValid()) // minimumSize is (-1, -1) when not set. Make that (0, 0) for Cocoa. - [m_nsWindow setContentMinSize : NSMakeSize(0.0, 0.0)]; - [m_nsWindow setContentMinSize : NSMakeSize(minimumSize.width(), minimumSize.height())]; - - // Set the maximum content size. - const QSize maximumSize = windowMaximumSize(); - [m_nsWindow setContentMaxSize : NSMakeSize(maximumSize.width(), maximumSize.height())]; - - // The window may end up with a fixed size; in this case the zoom button should be disabled. - setWindowZoomButton(m_windowFlags); - - // sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be - // resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case. - const QSize sizeIncrement = windowSizeIncrement(); - if (!sizeIncrement.isEmpty()) - [m_nsWindow setResizeIncrements : qt_mac_toNSSize(sizeIncrement)]; - else - [m_nsWindow setResizeIncrements : NSMakeSize(1.0, 1.0)]; - - QRect rect = geometry(); - QSize baseSize = windowBaseSize(); - if (!baseSize.isNull() && baseSize.isValid()) { - [m_nsWindow setFrame:NSMakeRect(rect.x(), rect.y(), baseSize.width(), baseSize.height()) display:YES]; - } -} - -void QCocoaWindow::setOpacity(qreal level) -{ - if (m_nsWindow) { - [m_nsWindow setAlphaValue:level]; - [m_nsWindow setOpaque: isOpaque()]; - } -} - -void QCocoaWindow::setMask(const QRegion ®ion) -{ - if (m_nsWindow) - [m_nsWindow setBackgroundColor:[NSColor clearColor]]; - - [m_qtView setMaskRegion:®ion]; - [m_nsWindow setOpaque: isOpaque()]; -} - -bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) -{ - if (!m_nsWindow) - return false; - - if (grab && ![m_nsWindow isKeyWindow]) - [m_nsWindow makeKeyWindow]; - - return true; -} - -bool QCocoaWindow::setMouseGrabEnabled(bool grab) -{ - if (!m_nsWindow) - return false; - - if (grab && ![m_nsWindow isKeyWindow]) - [m_nsWindow makeKeyWindow]; - - return true; -} - -WId QCocoaWindow::winId() const -{ - return WId(m_contentView); -} - -void QCocoaWindow::setParent(const QPlatformWindow *parentWindow) -{ - // recreate the window for compatibility - bool unhideAfterRecreate = parentWindow && !m_contentViewIsToBeEmbedded && ![m_contentView isHidden]; - recreateWindow(parentWindow); - if (unhideAfterRecreate) - [m_contentView setHidden:NO]; - setCocoaGeometry(geometry()); -} - -NSView *QCocoaWindow::contentView() const -{ - return m_contentView; -} - -void QCocoaWindow::setContentView(NSView *contentView) -{ - // Remove and release the previous content view - if (m_nsWindow) - [m_nsWindow setContentView:nil]; - else - [m_contentView removeFromSuperview]; - - [m_contentView release]; - - // Insert and retain the new content view - [contentView retain]; - m_contentView = contentView; - m_qtView = 0; // The new content view is not a QNSView. - recreateWindow(parent()); // Adds the content view to parent NSView -} - -QNSView *QCocoaWindow::qtView() const -{ - return m_qtView; -} - -NSWindow *QCocoaWindow::nativeWindow() const -{ - return m_nsWindow; -} - -void QCocoaWindow::setEmbeddedInForeignView(bool embedded) -{ - m_contentViewIsToBeEmbedded = embedded; - // Release any previosly created NSWindow. - [m_nsWindow closeAndRelease]; - m_nsWindow = 0; -} - -void QCocoaWindow::windowWillMove() -{ - // Close any open popups on window move - while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) { - QWindowSystemInterface::handleCloseEvent(popup->window()); - QWindowSystemInterface::flushWindowSystemEvents(); - } -} - -void QCocoaWindow::windowDidMove() -{ - if (m_isNSWindowChild) - return; - - [m_qtView updateGeometry]; -} - -void QCocoaWindow::windowDidResize() -{ - if (!m_nsWindow) - return; - - if (m_isNSWindowChild) - return; - - clipChildWindows(); - [m_qtView updateGeometry]; -} - -void QCocoaWindow::windowDidEndLiveResize() -{ - if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) { - m_effectivelyMaximized = false; - [m_qtView notifyWindowStateChanged:Qt::WindowNoState]; - } -} - -bool QCocoaWindow::windowShouldClose() -{ - // This callback should technically only determine if the window - // should (be allowed to) close, but since our QPA API to determine - // that also involves actually closing the window we do both at the - // same time, instead of doing the latter in windowWillClose. - bool accepted = false; - QWindowSystemInterface::handleCloseEvent(window(), &accepted); - QWindowSystemInterface::flushWindowSystemEvents(); - return accepted; -} - -void QCocoaWindow::setSynchedWindowStateFromWindow() -{ - if (QWindow *w = window()) - m_synchedWindowState = w->windowState(); -} - -bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const -{ - if (type == Qt::Widget) - type = window()->type(); - if (type == Qt::Tool) - return false; // Qt::Tool has the Popup bit set but isn't, at least on Mac. - - return ((type & Qt::Popup) == Qt::Popup); -} - -#ifndef QT_NO_OPENGL -void QCocoaWindow::setCurrentContext(QCocoaGLContext *context) -{ - m_glContext = context; -} - -QCocoaGLContext *QCocoaWindow::currentContext() const -{ - return m_glContext; -} -#endif - -void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) -{ - bool wasNSWindowChild = m_isNSWindowChild; - BOOL requestNSWindowChild = qt_mac_resolveOption(NO, window(), "_q_platform_MacUseNSWindow", - "QT_MAC_USE_NSWINDOW"); - m_isNSWindowChild = parentWindow && requestNSWindowChild; - bool needsNSWindow = m_isNSWindowChild || !parentWindow; - - QCocoaWindow *oldParentCocoaWindow = m_parentCocoaWindow; - m_parentCocoaWindow = const_cast(static_cast(parentWindow)); - if (m_parentCocoaWindow && m_isNSWindowChild) { - QWindow *parentQWindow = m_parentCocoaWindow->window(); - if (!parentQWindow->property("_q_platform_MacUseNSWindow").toBool()) { - parentQWindow->setProperty("_q_platform_MacUseNSWindow", QVariant(true)); - m_parentCocoaWindow->recreateWindow(m_parentCocoaWindow->m_parentCocoaWindow); - } - } - - bool usesNSPanel = [m_nsWindow isKindOfClass:[QNSPanel class]]; - - // No child QNSWindow should notify its QNSView - if (m_nsWindow && m_qtView && m_parentCocoaWindow && !oldParentCocoaWindow) - [[NSNotificationCenter defaultCenter] removeObserver:m_qtView - name:nil object:m_nsWindow]; - - // Remove current window (if any) - if ((m_nsWindow && !needsNSWindow) || (usesNSPanel != shouldUseNSPanel())) { - [m_nsWindow closeAndRelease]; - if (wasNSWindowChild && oldParentCocoaWindow) - oldParentCocoaWindow->removeChildWindow(this); - m_nsWindow = 0; - } - - if (needsNSWindow) { - bool noPreviousWindow = m_nsWindow == 0; - if (noPreviousWindow) - m_nsWindow = createNSWindow(); - - // Only non-child QNSWindows should notify their QNSViews - // (but don't register more than once). - if (m_qtView && (noPreviousWindow || (wasNSWindowChild && !m_isNSWindowChild))) - [[NSNotificationCenter defaultCenter] addObserver:m_qtView - selector:@selector(windowNotification:) - name:nil // Get all notifications - object:m_nsWindow]; - - if (oldParentCocoaWindow) { - if (!m_isNSWindowChild || oldParentCocoaWindow != m_parentCocoaWindow) - oldParentCocoaWindow->removeChildWindow(this); - m_forwardWindow.assign(oldParentCocoaWindow); - } - - setNSWindow(m_nsWindow); - } - - if (m_contentViewIsToBeEmbedded) { - // An embedded window doesn't have its own NSWindow. - } else if (!parentWindow) { - // QPlatformWindow subclasses must sync up with QWindow on creation: - propagateSizeHints(); - setWindowFlags(window()->flags()); - setWindowTitle(window()->title()); - setWindowState(window()->windowState()); - } else if (m_isNSWindowChild) { - m_nsWindow.styleMask = NSBorderlessWindowMask; - m_nsWindow.hasShadow = NO; - m_nsWindow.level = NSNormalWindowLevel; - NSWindowCollectionBehavior collectionBehavior = - NSWindowCollectionBehaviorManaged | NSWindowCollectionBehaviorIgnoresCycle - | NSWindowCollectionBehaviorFullScreenAuxiliary; - m_nsWindow.animationBehavior = NSWindowAnimationBehaviorNone; - m_nsWindow.collectionBehavior = collectionBehavior; - setCocoaGeometry(windowGeometry()); - - QList &siblings = m_parentCocoaWindow->m_childWindows; - if (siblings.contains(this)) { - if (!m_hiddenByClipping) - m_parentCocoaWindow->reinsertChildWindow(this); - } else { - if (!m_hiddenByClipping) - [m_parentCocoaWindow->m_nsWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; - siblings.append(this); - } - } else { - // Child windows have no NSWindow, link the NSViews instead. - [m_parentCocoaWindow->m_contentView addSubview : m_contentView]; - QRect rect = windowGeometry(); - // Prevent setting a (0,0) window size; causes opengl context - // "Invalid Drawable" warnings. - if (rect.isNull()) - rect.setSize(QSize(1, 1)); - NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); - [m_contentView setFrame:frame]; - [m_contentView setHidden: YES]; - } - - m_nsWindow.ignoresMouseEvents = - (window()->flags() & Qt::WindowTransparentForInput) == Qt::WindowTransparentForInput; - - const qreal opacity = qt_window_private(window())->opacity; - if (!qFuzzyCompare(opacity, qreal(1.0))) - setOpacity(opacity); - - // top-level QWindows may have an attached NSToolBar, call - // update function which will attach to the NSWindow. - if (!parentWindow) - updateNSToolbar(); -} - -void QCocoaWindow::reinsertChildWindow(QCocoaWindow *child) -{ - int childIndex = m_childWindows.indexOf(child); - Q_ASSERT(childIndex != -1); - - for (int i = childIndex; i < m_childWindows.size(); i++) { - NSWindow *nsChild = m_childWindows[i]->m_nsWindow; - if (i != childIndex) - [m_nsWindow removeChildWindow:nsChild]; - [m_nsWindow addChildWindow:nsChild ordered:NSWindowAbove]; - } -} - -void QCocoaWindow::requestActivateWindow() -{ - NSWindow *window = [m_contentView window]; - [ window makeFirstResponder : m_contentView ]; - [ window makeKeyWindow ]; -} - -bool QCocoaWindow::shouldUseNSPanel() -{ - Qt::WindowType type = window()->type(); - - return !m_isNSWindowChild && - ((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog); -} - -QCocoaNSWindow * QCocoaWindow::createNSWindow() -{ - QMacAutoReleasePool pool; - - QRect rect = initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight); - NSRect frame = qt_mac_flipRect(rect); - - Qt::WindowType type = window()->type(); - Qt::WindowFlags flags = window()->flags(); - - NSUInteger styleMask; - if (m_isNSWindowChild) { - styleMask = NSBorderlessWindowMask; - } else { - styleMask = windowStyleMask(flags); - } - QCocoaNSWindow *createdWindow = 0; - - // Use NSPanel for popup-type windows. (Popup, Tool, ToolTip, SplashScreen) - // and dialogs - if (shouldUseNSPanel()) { - QNSPanel *window; - window = [[QNSPanel alloc] initWithContentRect:frame - styleMask: styleMask - qPlatformWindow:this]; - if ((type & Qt::Popup) == Qt::Popup) - [window setHasShadow:YES]; - - // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set. - QVariant showWithoutActivating = QPlatformWindow::window()->property("_q_macAlwaysShowToolWindow"); - bool shouldHideOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && - !(showWithoutActivating.isValid() && showWithoutActivating.toBool()); - [window setHidesOnDeactivate: shouldHideOnDeactivate]; - - // Make popup windows show on the same desktop as the parent full-screen window. - [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; - if ((type & Qt::Popup) == Qt::Popup) - [window setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow]; - - createdWindow = window; - } else { - QNSWindow *window; - window = [[QNSWindow alloc] initWithContentRect:frame - styleMask: styleMask - qPlatformWindow:this]; - createdWindow = window; - } - - if ([createdWindow respondsToSelector:@selector(setRestorable:)]) - [createdWindow setRestorable: NO]; - - NSInteger level = windowLevel(flags); - [createdWindow setLevel:level]; - - // OpenGL surfaces can be ordered either above(default) or below the NSWindow. - // When ordering below the window must be tranclucent and have a clear background color. - static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER"); - - bool isTranslucent = window()->format().alphaBufferSize() > 0 - || (surface()->supportsOpenGL() && openglSourfaceOrder == -1); - if (isTranslucent) { - [createdWindow setBackgroundColor:[NSColor clearColor]]; - [createdWindow setOpaque:NO]; - } - - m_windowModality = window()->modality(); - - applyContentBorderThickness(createdWindow); - - return createdWindow; -} - -void QCocoaWindow::setNSWindow(QCocoaNSWindow *window) -{ - if (window.contentView != m_contentView) { - [m_contentView setPostsFrameChangedNotifications: NO]; - [m_contentView retain]; - if (m_contentView.superview) // m_contentView comes from another NSWindow - [m_contentView removeFromSuperview]; - [window setContentView:m_contentView]; - [m_contentView release]; - [m_contentView setPostsFrameChangedNotifications: YES]; - } -} - -void QCocoaWindow::removeChildWindow(QCocoaWindow *child) -{ - m_childWindows.removeOne(child); - [m_nsWindow removeChildWindow:child->m_nsWindow]; -} - -void QCocoaWindow::removeMonitor() -{ - if (!monitor) - return; - [NSEvent removeMonitor:monitor]; - monitor = nil; -} - -// Returns the current global screen geometry for the nswindow associated with this window. -QRect QCocoaWindow::nativeWindowGeometry() const -{ - if (!m_nsWindow || m_isNSWindowChild) - return geometry(); - - NSRect rect = [m_nsWindow frame]; - QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window()); - int flippedY = onScreen->geometry().height() - rect.origin.y - rect.size.height; // account for nswindow inverted y. - QRect qRect = QRect(rect.origin.x, flippedY, rect.size.width, rect.size.height); - return qRect; -} - -// Returns a pointer to the parent QCocoaWindow for this window, or 0 if there is none. -QCocoaWindow *QCocoaWindow::parentCocoaWindow() const -{ - if (window() && window()->transientParent()) { - return static_cast(window()->transientParent()->handle()); - } - return 0; -} - -// Syncs the NSWindow minimize/maximize/fullscreen state with the current QWindow state -void QCocoaWindow::syncWindowState(Qt::WindowState newState) -{ - if (!m_nsWindow) - return; - // if content view width or height is 0 then the window animations will crash so - // do nothing except set the new state - NSRect contentRect = [contentView() frame]; - if (contentRect.size.width <= 0 || contentRect.size.height <= 0) { - qWarning("invalid window content view size, check your window geometry"); - m_synchedWindowState = newState; - return; - } - - Qt::WindowState predictedState = newState; - if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) { - const int styleMask = [m_nsWindow styleMask]; - const bool usePerform = styleMask & NSResizableWindowMask; - [m_nsWindow setStyleMask:styleMask | NSResizableWindowMask]; - if (usePerform) - [m_nsWindow performZoom : m_nsWindow]; // toggles - else - [m_nsWindow zoom : m_nsWindow]; // toggles - [m_nsWindow setStyleMask:styleMask]; - } - - if ((m_synchedWindowState & Qt::WindowMinimized) != (newState & Qt::WindowMinimized)) { - if (newState & Qt::WindowMinimized) { - if ([m_nsWindow styleMask] & NSMiniaturizableWindowMask) - [m_nsWindow performMiniaturize : m_nsWindow]; - else - [m_nsWindow miniaturize : m_nsWindow]; - } else { - [m_nsWindow deminiaturize : m_nsWindow]; - } - } - - const bool effMax = m_effectivelyMaximized; - if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized) || (m_effectivelyMaximized && newState == Qt::WindowNoState)) { - if ((m_synchedWindowState & Qt::WindowFullScreen) == (newState & Qt::WindowFullScreen)) { - [m_nsWindow zoom : m_nsWindow]; // toggles - m_effectivelyMaximized = !effMax; - } else if (!(newState & Qt::WindowMaximized)) { - // it would be nice to change the target geometry that toggleFullScreen will animate toward - // but there is no known way, so the maximized state is not possible at this time - predictedState = static_cast(static_cast(newState) | Qt::WindowMaximized); - m_effectivelyMaximized = true; - } - } - - if ((m_synchedWindowState & Qt::WindowFullScreen) != (newState & Qt::WindowFullScreen)) { - if (window()->flags() & Qt::WindowFullscreenButtonHint) { - if (m_effectivelyMaximized && m_synchedWindowState == Qt::WindowFullScreen) - predictedState = Qt::WindowMaximized; - [m_nsWindow toggleFullScreen : m_nsWindow]; - } else { - if (newState & Qt::WindowFullScreen) { - QScreen *screen = window()->screen(); - if (screen) { - if (m_normalGeometry.width() < 0) { - m_oldWindowFlags = m_windowFlags; - window()->setFlags(window()->flags() | Qt::FramelessWindowHint); - m_normalGeometry = nativeWindowGeometry(); - setGeometry(screen->geometry()); - m_presentationOptions = [NSApp presentationOptions]; - [NSApp setPresentationOptions : m_presentationOptions | NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock]; - } - } - } else { - window()->setFlags(m_oldWindowFlags); - setGeometry(m_normalGeometry); - m_normalGeometry.setRect(0, 0, -1, -1); - [NSApp setPresentationOptions : m_presentationOptions]; - } - } - } - -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::syncWindowState" << newState << "actual" << predictedState << "was" << m_synchedWindowState << "effectively maximized" << m_effectivelyMaximized; -#endif - - // New state is now the current synched state - m_synchedWindowState = predictedState; -} - -bool QCocoaWindow::setWindowModified(bool modified) -{ - if (!m_nsWindow) - return false; - [m_nsWindow setDocumentEdited:(modified?YES:NO)]; - return true; -} - -void QCocoaWindow::setMenubar(QCocoaMenuBar *mb) -{ - m_menubar = mb; -} - -QCocoaMenuBar *QCocoaWindow::menubar() const -{ - return m_menubar; -} - -void QCocoaWindow::setWindowCursor(NSCursor *cursor) -{ - // This function is called (via QCocoaCursor) by Qt to set - // the cursor for this window. It can be called for a window - // that is not currenly under the mouse pointer (for example - // for a popup window.) Qt expects the set cursor to "stick": - // it should be accociated with the window until a different - // cursor is set. - if (m_windowCursor != cursor) { - [m_windowCursor release]; - m_windowCursor = [cursor retain]; - } - - // Use the built in cursor rect API if the QCocoaWindow has a NSWindow. - // Othervise, set the cursor if this window is under the mouse. In - // this case QNSView::cursorUpdate will set the cursor as the pointer - // moves. - NSWindow *nsWindow = m_nsWindow; - if (!nsWindow) - nsWindow = [m_qtView nsWindow]; - - if (nsWindow && m_qtView) { - [nsWindow invalidateCursorRectsForView : m_qtView]; - } else { - if (m_windowUnderMouse) - [cursor set]; - } -} - -void QCocoaWindow::registerTouch(bool enable) -{ - m_registerTouchCount += enable ? 1 : -1; - if (enable && m_registerTouchCount == 1) - [m_contentView setAcceptsTouchEvents:YES]; - else if (m_registerTouchCount == 0) - [m_contentView setAcceptsTouchEvents:NO]; -} - -void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickness) -{ - m_topContentBorderThickness = topThickness; - m_bottomContentBorderThickness = bottomThickness; - bool enable = (topThickness > 0 || bottomThickness > 0); - m_drawContentBorderGradient = enable; - - applyContentBorderThickness(m_nsWindow); -} - -void QCocoaWindow::registerContentBorderArea(quintptr identifier, int upper, int lower) -{ - m_contentBorderAreas.insert(identifier, BorderRange(identifier, upper, lower)); - applyContentBorderThickness(m_nsWindow); -} - -void QCocoaWindow::setContentBorderAreaEnabled(quintptr identifier, bool enable) -{ - m_enabledContentBorderAreas.insert(identifier, enable); - applyContentBorderThickness(m_nsWindow); -} - -void QCocoaWindow::setContentBorderEnabled(bool enable) -{ - m_drawContentBorderGradient = enable; - applyContentBorderThickness(m_nsWindow); -} - -void QCocoaWindow::applyContentBorderThickness(NSWindow *window) -{ - if (!window) - return; - - if (!m_drawContentBorderGradient) { - [window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask]; - [[[window contentView] superview] setNeedsDisplay:YES]; - return; - } - - // Find consecutive registered border areas, starting from the top. - QList ranges = m_contentBorderAreas.values(); - std::sort(ranges.begin(), ranges.end()); - int effectiveTopContentBorderThickness = m_topContentBorderThickness; - foreach (BorderRange range, ranges) { - // Skip disiabled ranges (typically hidden tool bars) - if (!m_enabledContentBorderAreas.value(range.identifier, false)) - continue; - - // Is this sub-range adjacent to or overlaping the - // existing total border area range? If so merge - // it into the total range, - if (range.upper <= (effectiveTopContentBorderThickness + 1)) - effectiveTopContentBorderThickness = qMax(effectiveTopContentBorderThickness, range.lower); - else - break; - } - - int effectiveBottomContentBorderThickness = m_bottomContentBorderThickness; - - [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask]; - - [window setContentBorderThickness:effectiveTopContentBorderThickness forEdge:NSMaxYEdge]; - [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; - - [window setContentBorderThickness:effectiveBottomContentBorderThickness forEdge:NSMinYEdge]; - [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMinYEdge]; - - [[[window contentView] superview] setNeedsDisplay:YES]; -} - -void QCocoaWindow::updateNSToolbar() -{ - if (!m_nsWindow) - return; - - NSToolbar *toolbar = QCocoaIntegration::instance()->toolbar(window()); - - if ([m_nsWindow toolbar] == toolbar) - return; - - [m_nsWindow setToolbar: toolbar]; - [m_nsWindow setShowsToolbarButton:YES]; -} - -bool QCocoaWindow::testContentBorderAreaPosition(int position) const -{ - return m_nsWindow && m_drawContentBorderGradient && - 0 <= position && position < [m_nsWindow contentBorderThicknessForEdge: NSMaxYEdge]; -} - -qreal QCocoaWindow::devicePixelRatio() const -{ - // The documented way to observe the relationship between device-independent - // and device pixels is to use one for the convertToBacking functions. Other - // methods such as [NSWindow backingScaleFacor] might not give the correct - // result, for example if setWantsBestResolutionOpenGLSurface is not set or - // or ignored by the OpenGL driver. - NSSize backingSize = [m_contentView convertSizeToBacking:NSMakeSize(1.0, 1.0)]; - return backingSize.height; -} - -// Returns whether the window can be expose, which it can -// if it is on screen and has a valid geometry. -bool QCocoaWindow::isWindowExposable() -{ - QSize size = geometry().size(); - bool validGeometry = (size.width() > 0 && size.height() > 0); - bool validScreen = ([[m_contentView window] screen] != 0); - bool nonHiddenSuperView = ![[m_contentView superview] isHidden]; - return (validGeometry && validScreen && nonHiddenSuperView); -} - -// Exposes the window by posting an expose event to QWindowSystemInterface -void QCocoaWindow::exposeWindow() -{ - m_geometryUpdateExposeAllowed = true; - - if (!isWindowExposable()) - return; - - // Update the QWindow's screen property. This property is set - // to QGuiApplication::primaryScreen() at QWindow construciton - // time, and we won't get a NSWindowDidChangeScreenNotification - // on show. The case where the window is initially displayed - // on a non-primary screen needs special handling here. - NSUInteger screenIndex = [[NSScreen screens] indexOfObject:m_nsWindow.screen]; - if (screenIndex != NSNotFound) { - QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenAtIndex(screenIndex); - if (cocoaScreen) - window()->setScreen(cocoaScreen->screen()); - } - - if (!m_isExposed) { - m_isExposed = true; - m_exposedGeometry = geometry(); - m_exposedDevicePixelRatio = devicePixelRatio(); - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), m_exposedGeometry.size())); - } -} - -// Obscures the window by posting an empty expose event to QWindowSystemInterface -void QCocoaWindow::obscureWindow() -{ - if (m_isExposed) { - m_geometryUpdateExposeAllowed = false; - m_isExposed = false; - QWindowSystemInterface::handleExposeEvent(window(), QRegion()); - } -} - -// Updates window geometry by posting an expose event to QWindowSystemInterface -void QCocoaWindow::updateExposedGeometry() -{ - // updateExposedGeometry is not allowed to send the initial expose. If you want - // that call exposeWindow(); - if (!m_geometryUpdateExposeAllowed) - return; - - // Do not send incorrect exposes in case the window is not even visible yet. - // We might get here as a result of a resize() from QWidget's show(), for instance. - if (!window()->isVisible()) - return; - - if (!isWindowExposable()) - return; - - if (m_exposedGeometry.size() == geometry().size() && m_exposedDevicePixelRatio == devicePixelRatio()) - return; - - m_isExposed = true; - m_exposedGeometry = geometry(); - m_exposedDevicePixelRatio = devicePixelRatio(); - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), m_exposedGeometry.size())); -} - -QWindow *QCocoaWindow::childWindowAt(QPoint windowPoint) -{ - QWindow *targetWindow = window(); - foreach (QObject *child, targetWindow->children()) - if (QWindow *childWindow = qobject_cast(child)) - if (QPlatformWindow *handle = childWindow->handle()) - if (handle->isExposed() && childWindow->geometry().contains(windowPoint)) - targetWindow = static_cast(handle)->childWindowAt(windowPoint - childWindow->position()); - - return targetWindow; -} - -bool QCocoaWindow::shouldRefuseKeyWindowAndFirstResponder() -{ - // This function speaks up if there's any reason - // to refuse key window or first responder state. - - if (window()->flags() & Qt::WindowDoesNotAcceptFocus) - return true; - - if (m_inSetVisible) { - QVariant showWithoutActivating = window()->property("_q_showWithoutActivating"); - if (showWithoutActivating.isValid() && showWithoutActivating.toBool()) - return true; - } - - return false; -} - -QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffsetStatic(QWindow *window) -{ - if (window->handle()) - return static_cast(window->handle())->bottomLeftClippedByNSWindowOffset(); - return QPoint(); -} - -QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffset() const -{ - if (!m_contentView) - return QPoint(); - const NSPoint origin = [m_contentView isFlipped] ? NSMakePoint(0, [m_contentView frame].size.height) - : NSMakePoint(0, 0); - const NSRect visibleRect = [m_contentView visibleRect]; - - return QPoint(visibleRect.origin.x, -visibleRect.origin.y + (origin.y - visibleRect.size.height)); -} - -QMargins QCocoaWindow::frameMargins() const -{ - NSRect frameW = [m_nsWindow frame]; - NSRect frameC = [m_nsWindow contentRectForFrameRect:frameW]; - - return QMargins(frameW.origin.x - frameC.origin.x, - (frameW.origin.y + frameW.size.height) - (frameC.origin.y + frameC.size.height), - (frameW.origin.x + frameW.size.width) - (frameC.origin.x + frameC.size.width), - frameC.origin.y - frameW.origin.y); -} - -void QCocoaWindow::setFrameStrutEventsEnabled(bool enabled) -{ - m_frameStrutEventsEnabled = enabled; -} diff --git a/5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.h b/5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.h deleted file mode 100644 index 0df70f6..0000000 --- a/5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.h +++ /dev/null @@ -1,149 +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 - -#include -#include -#include - -#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 { - QCocoaBackingStore* m_backingStore; - QPoint m_backingStoreOffset; - CGImageRef m_maskImage; - uchar *m_maskData; - bool m_shouldInvalidateWindowShadow; - QPointer 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_updatingDrag; - bool m_exposedOnMoveToWindow; - NSEvent *m_currentlyInterpretedKeyEvent; - bool m_isMenuView; -} - -- (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; -- (void)clearBackingStore:(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)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification; -- (void)viewDidHide; -- (void)viewDidUnhide; -- (void)removeFromSuperview; - -- (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; - -- (bool)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; - -- (void)registerDragTypes; -- (NSDragOperation)handleDrag:(id )sender; - -- (NSWindow *)nsWindow; - -@end - -QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSView); - -#endif //QNSVIEW_H diff --git a/5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.mm b/5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.mm deleted file mode 100644 index 81f2111..0000000 --- a/5.6.2/qtbase/src/plugins/platforms/cocoa/qnsview.mm +++ /dev/null @@ -1,2137 +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 - -#include -#include - -#include "qnsview.h" -#include "qcocoawindow.h" -#include "qcocoahelpers.h" -#include "qmultitouch_mac_p.h" -#include "qcocoadrag.h" -#include "qcocoainputcontext.h" -#include - -#include -#include -#include -#include -#include -#include "qcocoabackingstore.h" -#ifndef QT_NO_OPENGL -#include "qcocoaglcontext.h" -#endif -#include "qcocoaintegration.h" - -#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR -#include -#endif - -Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") -#ifndef QT_NO_GESTURES -Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") -#endif -Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") - -static QTouchDevice *touchDevice = 0; - -// ### HACK Remove once 10.8 is unsupported -static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; - -static bool _q_dontOverrideCtrlLMB = false; - -@interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - - (CGFloat)deviceDeltaX; - - (CGFloat)deviceDeltaY; - - (CGFloat)deviceDeltaZ; -@end - -@interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject -{ - QNSView *view; -} - -- (id)initWithView:(QNSView *)theView; - -- (void)mouseMoved:(NSEvent *)theEvent; -- (void)mouseEntered:(NSEvent *)theEvent; -- (void)mouseExited:(NSEvent *)theEvent; -- (void)cursorUpdate:(NSEvent *)theEvent; - -@end - -@implementation QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) - -- (id)initWithView:(QNSView *)theView -{ - self = [super init]; - if (self) { - view = theView; - } - return self; -} - -- (void)mouseMoved:(NSEvent *)theEvent -{ - [view mouseMovedImpl:theEvent]; -} - -- (void)mouseEntered:(NSEvent *)theEvent -{ - [view mouseEnteredImpl:theEvent]; -} - -- (void)mouseExited:(NSEvent *)theEvent -{ - [view mouseExitedImpl:theEvent]; -} - -- (void)cursorUpdate:(NSEvent *)theEvent -{ - [view cursorUpdateImpl:theEvent]; -} - -@end - -@implementation QT_MANGLE_NAMESPACE(QNSView) - -+ (void)initialize -{ - NSString **notificationNameVar = (NSString **)dlsym(RTLD_NEXT, "NSWindowDidChangeOcclusionStateNotification"); - if (notificationNameVar) - _q_NSWindowDidChangeOcclusionStateNotification = *notificationNameVar; - - _q_dontOverrideCtrlLMB = qt_mac_resolveOption(false, "QT_MAC_DONT_OVERRIDE_CTRL_LMB"); -} - -- (id) init -{ - self = [super initWithFrame : NSMakeRect(0,0, 300,300)]; - if (self) { - m_backingStore = 0; - m_maskImage = 0; - m_shouldInvalidateWindowShadow = false; - m_window = 0; - m_buttons = Qt::NoButton; - m_frameStrutButtons = Qt::NoButton; - m_sendKeyEvent = false; - m_subscribesForGlobalFrameNotifications = false; -#ifndef QT_NO_OPENGL - m_glContext = 0; - m_shouldSetGLContextinDrawRect = false; -#endif - currentCustomDragTypes = 0; - m_sendUpAsRightButton = false; - m_inputSource = 0; - m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self]; - m_resendKeyEvent = false; - m_scrolling = false; - m_updatingDrag = false; - m_currentlyInterpretedKeyEvent = 0; - - if (!touchDevice) { - touchDevice = new QTouchDevice; - touchDevice->setType(QTouchDevice::TouchPad); - touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition | QTouchDevice::MouseEmulation); - QWindowSystemInterface::registerTouchDevice(touchDevice); - } - - m_isMenuView = false; - self.focusRingType = NSFocusRingTypeNone; - } - return self; -} - -- (void)dealloc -{ - CGImageRelease(m_maskImage); - [m_trackingArea release]; - m_maskImage = 0; - m_window = 0; - m_subscribesForGlobalFrameNotifications = false; - [m_inputSource release]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [m_mouseMoveHelper release]; - - delete currentCustomDragTypes; - - [super dealloc]; -} - -- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow -{ - self = [self init]; - if (!self) - return 0; - - m_window = window; - m_platformWindow = platformWindow; - m_sendKeyEvent = false; - m_trackingArea = nil; - -#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR - // prevent rift in space-time continuum, disable - // accessibility for the accessibility inspector's windows. - static bool skipAccessibilityForInspectorWindows = false; - if (!skipAccessibilityForInspectorWindows) { - - // m_accessibleRoot = window->accessibleRoot(); - - AccessibilityInspector *inspector = new AccessibilityInspector(window); - skipAccessibilityForInspectorWindows = true; - inspector->inspectWindow(window); - skipAccessibilityForInspectorWindows = false; - } -#endif - - [self registerDragTypes]; - [self setPostsFrameChangedNotifications : YES]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(updateGeometry) - name:NSViewFrameDidChangeNotification - object:self]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(textInputContextKeyboardSelectionDidChangeNotification:) - name:NSTextInputContextKeyboardSelectionDidChangeNotification - object:nil]; - - return self; -} - -- (void) clearQWindowPointers -{ - m_window = 0; - m_platformWindow = 0; -} - -#ifndef QT_NO_OPENGL -- (void) setQCocoaGLContext:(QCocoaGLContext *)context -{ - m_glContext = context; - [m_glContext->nsOpenGLContext() setView:self]; - if (![m_glContext->nsOpenGLContext() view]) { - //was unable to set view - m_shouldSetGLContextinDrawRect = true; - } - - if (!m_subscribesForGlobalFrameNotifications) { - // NSOpenGLContext expects us to repaint (or update) the view when - // it changes position on screen. Since this happens unnoticed for - // the view when the parent view moves, we need to register a special - // notification that lets us handle this case: - m_subscribesForGlobalFrameNotifications = true; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(globalFrameChanged:) - name:NSViewGlobalFrameDidChangeNotification - object:self]; - } -} -#endif - -- (void) globalFrameChanged:(NSNotification*)notification -{ - Q_UNUSED(notification); - m_platformWindow->updateExposedGeometry(); -} - -- (void)viewDidMoveToSuperview -{ - if (!(m_platformWindow->m_contentViewIsToBeEmbedded)) - return; - - if ([self superview]) { - m_platformWindow->m_contentViewIsEmbedded = true; - QWindowSystemInterface::handleGeometryChange(m_window, m_platformWindow->geometry()); - m_platformWindow->updateExposedGeometry(); - QWindowSystemInterface::flushWindowSystemEvents(); - } else { - m_platformWindow->m_contentViewIsEmbedded = false; - } -} - -- (void)viewDidMoveToWindow -{ - m_backingStore = Q_NULLPTR; - m_isMenuView = [self.window.className isEqualToString:@"NSCarbonMenuWindow"]; - if (self.window) { - // This is the case of QWidgetAction's generated QWidget inserted in an NSMenu. - // 10.9 and newer get the NSWindowDidChangeOcclusionStateNotification - if (!_q_NSWindowDidChangeOcclusionStateNotification && m_isMenuView) { - m_exposedOnMoveToWindow = true; - m_platformWindow->exposeWindow(); - } - } else if (m_exposedOnMoveToWindow) { - m_exposedOnMoveToWindow = false; - m_platformWindow->obscureWindow(); - } -} - -- (void)viewWillMoveToWindow:(NSWindow *)newWindow -{ - // ### Merge "normal" window code path with this one for 5.1. - if (!(m_window->type() & Qt::SubWindow)) - return; - - if (newWindow) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowNotification:) - name:nil // Get all notifications - object:newWindow]; - } - if ([self window]) - [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:[self window]]; -} - -- (QWindow *)topLevelWindow -{ - QWindow *focusWindow = m_window; - - // For widgets we need to do a bit of trickery as the window - // to activate is the window of the top-level widget. - if (qstrcmp(m_window->metaObject()->className(), "QWidgetWindow") == 0) { - while (focusWindow->parent()) { - focusWindow = focusWindow->parent(); - } - } - - return focusWindow; -} - -- (void)updateGeometry -{ - QRect geometry; - - if (m_platformWindow->m_isNSWindowChild) { - return; -#if 0 - //geometry = qt_mac_toQRect([self frame]); - qDebug() << "nsview updateGeometry" << m_platformWindow->window(); - QRect screenRect = qt_mac_toQRect([m_platformWindow->m_nsWindow convertRectToScreen:[self frame]]); - qDebug() << "screenRect" << screenRect; - - screenRect.moveTop(qt_mac_flipYCoordinate(screenRect.y() + screenRect.height())); - geometry = QRect(m_platformWindow->window()->parent()->mapFromGlobal(screenRect.topLeft()), screenRect.size()); - qDebug() << "geometry" << geometry; -#endif - //geometry = QRect(screenRect.origin.x, qt_mac_flipYCoordinate(screenRect.origin.y + screenRect.size.height), screenRect.size.width, screenRect.size.height); - } else if (m_platformWindow->m_nsWindow) { - // top level window, get window rect and flip y. - NSRect rect = [self frame]; - NSRect windowRect = [[self window] frame]; - geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height); - } else if (m_platformWindow->m_contentViewIsToBeEmbedded) { - // embedded child window, use the frame rect ### merge with case below - geometry = qt_mac_toQRect([self bounds]); - } else { - // child window, use the frame rect - geometry = qt_mac_toQRect([self frame]); - } - - if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry()) - return; - - const bool isResize = geometry.size() != m_platformWindow->geometry().size(); - - // It can happen that self.window is nil (if we are changing - // styleMask from/to borderless and content view is being re-parented) - // - this results in an invalid coordinates. - if (m_platformWindow->m_inSetStyleMask && !self.window) - return; - -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QNSView::udpateGeometry" << m_platformWindow << geometry; -#endif - - // Call setGeometry on QPlatformWindow. (not on QCocoaWindow, - // doing that will initiate a geometry change it and possibly create - // an infinite loop when this notification is triggered again.) - m_platformWindow->QPlatformWindow::setGeometry(geometry); - - // Don't send the geometry change if the QWindow is designated to be - // embedded in a foreign view hiearchy but has not actually been - // embedded yet - it's too early. - if (m_platformWindow->m_contentViewIsToBeEmbedded && !m_platformWindow->m_contentViewIsEmbedded) - return; - - // Send a geometry change event to Qt, if it's ready to handle events - if (!m_platformWindow->m_inConstructor) { - QWindowSystemInterface::handleGeometryChange(m_window, geometry); - m_platformWindow->updateExposedGeometry(); - // Guard against processing window system events during QWindow::setGeometry - // calles, which Qt and Qt applications do not excpect. - if (!m_platformWindow->m_inSetGeometry) - QWindowSystemInterface::flushWindowSystemEvents(); - else if (isResize) - m_backingStore = 0; - } -} - -- (void)notifyWindowStateChanged:(Qt::WindowState)newState -{ - // If the window was maximized, then fullscreen, then tried to go directly to "normal" state, - // this notification will say that it is "normal", but it will still look maximized, and - // if you called performZoom it would actually take it back to "normal". - // So we should say that it is maximized because it actually is. - if (newState == Qt::WindowNoState && m_platformWindow->m_effectivelyMaximized) - newState = Qt::WindowMaximized; - QWindowSystemInterface::handleWindowStateChanged(m_window, newState); - // We want to read the window state back from the window, - // but the event we just sent may be asynchronous. - QWindowSystemInterface::flushWindowSystemEvents(); - m_platformWindow->setSynchedWindowStateFromWindow(); -} - -- (void)windowNotification : (NSNotification *) windowNotification -{ - //qDebug() << "windowNotification" << QCFString::toQString([windowNotification name]); - - NSString *notificationName = [windowNotification name]; - if (notificationName == NSWindowDidBecomeKeyNotification) { - if (!m_platformWindow->windowIsPopupType() && !m_isMenuView) - QWindowSystemInterface::handleWindowActivated(m_window); - } else if (notificationName == NSWindowDidResignKeyNotification) { - // key window will be non-nil if another window became key... do not - // set the active window to zero here, the new key window's - // NSWindowDidBecomeKeyNotification hander will change the active window - NSWindow *keyWindow = [NSApp keyWindow]; - if (!keyWindow) { - // no new key window, go ahead and set the active window to zero - if (!m_platformWindow->windowIsPopupType() && !m_isMenuView) - QWindowSystemInterface::handleWindowActivated(0); - } - } else if (notificationName == NSWindowDidMiniaturizeNotification - || notificationName == NSWindowDidDeminiaturizeNotification) { - Qt::WindowState newState = notificationName == NSWindowDidMiniaturizeNotification ? - Qt::WindowMinimized : Qt::WindowNoState; - [self notifyWindowStateChanged:newState]; - } else if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) { - m_platformWindow->obscureWindow(); - } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { - m_platformWindow->exposeWindow(); - } else if (_q_NSWindowDidChangeOcclusionStateNotification - && [notificationName isEqualToString:_q_NSWindowDidChangeOcclusionStateNotification]) { -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 -// ### HACK Remove the enum declaration, the warning disabling and the cast further down once 10.8 is unsupported -QT_WARNING_PUSH -QT_WARNING_DISABLE_CLANG("-Wobjc-method-access") - enum { NSWindowOcclusionStateVisible = 1UL << 1 }; -#endif - // Several unit tests expect paint and/or expose events for windows that are - // sometimes (unpredictably) occluded and some unit tests depend on QWindow::isExposed - - // don't send Expose/Obscure events when running under QTestLib. - static const bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING"); - if (!onTestLib) { - if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) { - m_platformWindow->exposeWindow(); - } else { - // Send Obscure events on window occlusion to stop animations. - m_platformWindow->obscureWindow(); - } - } -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 -QT_WARNING_POP -#endif - } else if (notificationName == NSWindowDidChangeScreenNotification) { - if (m_window) { - NSUInteger screenIndex = [[NSScreen screens] indexOfObject:self.window.screen]; - if (screenIndex != NSNotFound) { - QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenAtIndex(screenIndex); - if (cocoaScreen) - QWindowSystemInterface::handleWindowScreenChanged(m_window, cocoaScreen->screen()); - m_platformWindow->updateExposedGeometry(); - } - } - } else if (notificationName == NSWindowDidEnterFullScreenNotification - || notificationName == NSWindowDidExitFullScreenNotification) { - Qt::WindowState newState = notificationName == NSWindowDidEnterFullScreenNotification ? - Qt::WindowFullScreen : Qt::WindowNoState; - [self notifyWindowStateChanged:newState]; - } -} - -- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification -{ - Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification) - if (([NSApp keyWindow] == [self window]) && [[self window] firstResponder] == self) { - QCocoaInputContext *ic = qobject_cast(QCocoaIntegration::instance()->inputContext()); - ic->updateLocale(); - } -} - -- (void)notifyWindowWillZoom:(BOOL)willZoom -{ - Qt::WindowState newState = willZoom ? Qt::WindowMaximized : Qt::WindowNoState; - if (!willZoom) - m_platformWindow->m_effectivelyMaximized = false; - [self notifyWindowStateChanged:newState]; -} - -- (void)viewDidHide -{ - m_platformWindow->obscureWindow(); -} - -- (void)viewDidUnhide -{ - m_platformWindow->exposeWindow(); -} - -- (void)removeFromSuperview -{ - QMacAutoReleasePool pool; - [super removeFromSuperview]; -} - -- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset -{ - m_backingStore = backingStore; - m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio(); - foreach (QRect rect, region.rects()) - [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; -} - -- (void)clearBackingStore:(QCocoaBackingStore *)backingStore -{ - if (backingStore == m_backingStore) - m_backingStore = 0; -} - -- (BOOL) hasMask -{ - return m_maskImage != 0; -} - -- (BOOL) isOpaque -{ - if (!m_platformWindow) - return true; - return m_platformWindow->isOpaque(); -} - -- (void) setMaskRegion:(const QRegion *)region -{ - m_shouldInvalidateWindowShadow = true; - if (m_maskImage) - CGImageRelease(m_maskImage); - if (region->isEmpty()) { - m_maskImage = 0; - return; - } - - const QRect &rect = region->boundingRect(); - QImage tmp(rect.size(), QImage::Format_RGB32); - tmp.fill(Qt::white); - QPainter p(&tmp); - p.setClipRegion(*region); - p.fillRect(rect, Qt::black); - p.end(); - QImage maskImage = QImage(rect.size(), QImage::Format_Indexed8); - for (int y=0; ym_nsWindow) { - [m_platformWindow->m_nsWindow invalidateShadow]; - m_shouldInvalidateWindowShadow = false; - } -} - -- (void) drawRect:(NSRect)dirtyRect -{ -#ifndef QT_NO_OPENGL - if (m_glContext && m_shouldSetGLContextinDrawRect) { - [m_glContext->nsOpenGLContext() setView:self]; - m_shouldSetGLContextinDrawRect = false; - } -#endif - - if (m_platformWindow->m_drawContentBorderGradient) - NSDrawWindowBackground(dirtyRect); - - if (!m_backingStore) - return; - - // Calculate source and target rects. The target rect is the dirtyRect: - CGRect dirtyWindowRect = NSRectToCGRect(dirtyRect); - - // The backing store source rect will be larger on retina displays. - // Scale dirtyRect by the device pixel ratio: - const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio(); - CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio, - dirtyRect.origin.y * devicePixelRatio, - dirtyRect.size.width * devicePixelRatio, - dirtyRect.size.height * devicePixelRatio); - - NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; - CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; - - // Translate coordiate system from CoreGraphics (bottom-left) to NSView (top-left): - CGContextSaveGState(cgContext); - int dy = dirtyWindowRect.origin.y + CGRectGetMaxY(dirtyWindowRect); - - CGContextTranslateCTM(cgContext, 0, dy); - CGContextScaleCTM(cgContext, 1, -1); - - // If a mask is set, modify the sub image accordingly: - CGImageRef subMask = 0; - if (m_maskImage) { - subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyWindowRect); - CGContextClipToMask(cgContext, dirtyWindowRect, subMask); - } - - // Clip out and draw the correct sub image from the (shared) backingstore: - CGRect backingStoreRect = CGRectMake( - dirtyBackingRect.origin.x + m_backingStoreOffset.x(), - dirtyBackingRect.origin.y + m_backingStoreOffset.y(), - dirtyBackingRect.size.width, - dirtyBackingRect.size.height - ); - CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage()); - CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect); - - // Optimization: Copy frame buffer content instead of blending for - // top-level windows where Qt fills the entire window content area. - // (But don't overpaint the title-bar gradient) - if (m_platformWindow->m_nsWindow && !m_platformWindow->m_drawContentBorderGradient) - CGContextSetBlendMode(cgContext, kCGBlendModeCopy); - - CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg); - - // Clean-up: - CGContextRestoreGState(cgContext); - CGImageRelease(cleanImg); - CGImageRelease(subMask); - CGImageRelease(bsCGImage); - - [self invalidateWindowShadowIfNeeded]; -} - -- (BOOL) isFlipped -{ - return YES; -} - -- (BOOL)becomeFirstResponder -{ - if (!m_window || !m_platformWindow) - return NO; - if (m_window->flags() & Qt::WindowTransparentForInput) - return NO; - if (!m_platformWindow->windowIsPopupType() && !m_isMenuView) - QWindowSystemInterface::handleWindowActivated([self topLevelWindow]); - return YES; -} - -- (BOOL)acceptsFirstResponder -{ - if (!m_window || !m_platformWindow) - return NO; - if (m_isMenuView) - return NO; - if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder()) - return NO; - if (m_window->flags() & Qt::WindowTransparentForInput) - return NO; - if ((m_window->flags() & Qt::ToolTip) == Qt::ToolTip) - return NO; - return YES; -} - -- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent) - if (!m_window || !m_platformWindow) - return NO; - if (m_window->flags() & Qt::WindowTransparentForInput) - return NO; - return YES; -} - -- (NSView *)hitTest:(NSPoint)aPoint -{ - NSView *candidate = [super hitTest:aPoint]; - if (candidate == self) { - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput)) - return nil; - } - return candidate; -} - -- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint -{ - // Calculate the mouse position in the QWindow and Qt screen coordinate system, - // starting from coordinates in the NSWindow coordinate system. - // - // This involves translating according to the window location on screen, - // as well as inverting the y coordinate due to the origin change. - // - // Coordinate system overview, outer to innermost: - // - // Name Origin - // - // OS X screen bottom-left - // Qt screen top-left - // NSWindow bottom-left - // NSView/QWindow top-left - // - // NSView and QWindow are equal coordinate systems: the QWindow covers the - // entire NSView, and we've set the NSView's isFlipped property to true. - - NSWindow *window = [self window]; - NSPoint nsWindowPoint; - NSRect windowRect = [window convertRectFromScreen:NSMakeRect(mouseLocation.x, mouseLocation.y, 1, 1)]; - nsWindowPoint = windowRect.origin; // NSWindow coordinates - NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil]; // NSView/QWindow coordinates - *qtWindowPoint = QPointF(nsViewPoint.x, nsViewPoint.y); // NSView/QWindow coordinates - - *qtScreenPoint = QPointF(mouseLocation.x, qt_mac_flipYCoordinate(mouseLocation.y)); // Qt screen coordinates -} - -- (void)resetMouseButtons -{ - m_buttons = Qt::NoButton; - m_frameStrutButtons = Qt::NoButton; -} - -- (NSPoint) screenMousePoint:(NSEvent *)theEvent -{ - NSPoint screenPoint; - if (theEvent) { - NSPoint windowPoint = [theEvent locationInWindow]; - NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; - screenPoint = screenRect.origin; - } else { - screenPoint = [NSEvent mouseLocation]; - } - return screenPoint; -} - -- (void)handleMouseEvent:(NSEvent *)theEvent -{ - bool isTabletEvent = [self handleTabletEvent: theEvent]; - - QPointF qtWindowPoint; - QPointF qtScreenPoint; - QNSView *targetView = self; - if (m_platformWindow && m_platformWindow->m_forwardWindow) { - if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp) - targetView = m_platformWindow->m_forwardWindow->m_qtView; - else - m_platformWindow->m_forwardWindow.clear(); - } - - // Popups implicitly grap mouse events; forward to the active popup if there is one - if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) { - // Tooltips must be transparent for mouse events - // The bug reference is QTBUG-46379 - if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) { - if (QNSView *popupView = popup->qtView()) - targetView = popupView; - } - } - - [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; - ulong timestamp = [theEvent timestamp] * 1000; - - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - nativeDrag->setLastMouseEvent(theEvent, self); - - Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - QWindowSystemInterface::handleMouseEvent(targetView->m_window, timestamp, qtWindowPoint, qtScreenPoint, m_buttons, keyboardModifiers, - isTabletEvent ? Qt::MouseEventSynthesizedByQt : Qt::MouseEventNotSynthesized); -} - -- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent -{ - // get m_buttons in sync - // Don't send frme strut events if we are in the middle of a mouse drag. - if (m_buttons != Qt::NoButton) - return; - - NSEventType ty = [theEvent type]; - switch (ty) { - case NSLeftMouseDown: - m_frameStrutButtons |= Qt::LeftButton; - break; - case NSLeftMouseUp: - m_frameStrutButtons &= ~Qt::LeftButton; - break; - case NSRightMouseDown: - m_frameStrutButtons |= Qt::RightButton; - break; - case NSLeftMouseDragged: - m_frameStrutButtons |= Qt::LeftButton; - break; - case NSRightMouseDragged: - m_frameStrutButtons |= Qt::RightButton; - break; - case NSRightMouseUp: - m_frameStrutButtons &= ~Qt::RightButton; - break; - case NSOtherMouseDown: - m_frameStrutButtons |= cocoaButton2QtButton([theEvent buttonNumber]); - break; - case NSOtherMouseUp: - m_frameStrutButtons &= ~cocoaButton2QtButton([theEvent buttonNumber]); - default: - break; - } - - NSWindow *window = [self window]; - NSPoint windowPoint = [theEvent locationInWindow]; - - int windowScreenY = [window frame].origin.y + [window frame].size.height; - NSPoint windowCoord = [self convertPoint:[self frame].origin toView:nil]; - int viewScreenY = [window convertRectToScreen:NSMakeRect(windowCoord.x, windowCoord.y, 0, 0)].origin.y; - int titleBarHeight = windowScreenY - viewScreenY; - - NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; - QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y); - NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 0, 0)].origin; - QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); - - ulong timestamp = [theEvent timestamp] * 1000; - QWindowSystemInterface::handleFrameStrutMouseEvent(m_window, timestamp, qtWindowPoint, qtScreenPoint, m_frameStrutButtons); -} - -- (void)mouseDown:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super mouseDown:theEvent]; - m_sendUpAsRightButton = false; - - // Handle any active poup windows; clicking outisde them should close them - // all. Don't do anything or clicks inside one of the menus, let Cocoa - // handle that case. Note that in practice many windows of the Qt::Popup type - // will actually close themselves in this case using logic implemented in - // that particular poup type (for example context menus). However, Qt expects - // that plain popup QWindows will also be closed, so we implement the logic - // here as well. - QList *popups = QCocoaIntegration::instance()->popupWindowStack(); - if (!popups->isEmpty()) { - // Check if the click is outside all popups. - bool inside = false; - QPointF qtScreenPoint = qt_mac_flipPoint([self screenMousePoint:theEvent]); - for (QList::const_iterator it = popups->begin(); it != popups->end(); ++it) { - if ((*it)->geometry().contains(qtScreenPoint.toPoint())) { - inside = true; - break; - } - } - // Close the popups if the click was outside. - if (!inside) { - Qt::WindowType type = QCocoaIntegration::instance()->activePopupWindow()->window()->type(); - while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) { - QWindowSystemInterface::handleCloseEvent(popup->window()); - QWindowSystemInterface::flushWindowSystemEvents(); - } - // Consume the mouse event when closing the popup, except for tool tips - // were it's expected that the event is processed normally. - if (type != Qt::ToolTip) - return; - } - } - - if ([self hasMarkedText]) { - [[NSTextInputContext currentInputContext] handleEvent:theEvent]; - } else { - if (!_q_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { - m_buttons |= Qt::RightButton; - m_sendUpAsRightButton = true; - } else { - m_buttons |= Qt::LeftButton; - } - [self handleMouseEvent:theEvent]; - } -} - -- (void)mouseDragged:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super mouseDragged:theEvent]; - if (!(m_buttons & (m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton))) - qCDebug(lcQpaCocoaWindow, "QNSView mouseDragged: Internal mouse button tracking invalid (missing Qt::LeftButton)"); - [self handleMouseEvent:theEvent]; -} - -- (void)mouseUp:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super mouseUp:theEvent]; - if (m_sendUpAsRightButton) { - m_buttons &= ~Qt::RightButton; - m_sendUpAsRightButton = false; - } else { - m_buttons &= ~Qt::LeftButton; - } - [self handleMouseEvent:theEvent]; -} - -- (void)updateTrackingAreas -{ - [super updateTrackingAreas]; - - QMacAutoReleasePool pool; - - // NSTrackingInVisibleRect keeps care of updating once the tracking is set up, so bail out early - if (m_trackingArea && [[self trackingAreas] containsObject:m_trackingArea]) - return; - - // Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should - // only be turned on if mouseTracking, hover is on or a tool tip is set. - // Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to - // turn it on in ALL case. That means EVERY QWindow gets to pay the cost of - // mouse moves delivered to it (Apple recommends keeping it OFF because there - // is a performance hit). So it goes. - NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp - | NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate; - [m_trackingArea release]; - m_trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame] - options:trackingOptions - owner:m_mouseMoveHelper - userInfo:nil]; - [self addTrackingArea:m_trackingArea]; -} - --(void)cursorUpdateImpl:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent) - // Set the cursor manually if there is no NSWindow. - if (![self nsWindow] && m_platformWindow->m_windowCursor) - [m_platformWindow->m_windowCursor set]; - else - [super cursorUpdate:theEvent]; -} - --(void)resetCursorRects -{ - // Use the cursor rect API if there is a NSWindow - if ([self nsWindow] && m_platformWindow->m_windowCursor) - [self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor]; -} - -- (void)mouseMovedImpl:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return; - - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindow *childWindow = m_platformWindow->childWindowAt(windowPoint.toPoint()); - - // Top-level windows generate enter-leave events for sub-windows. - // Qt wants to know which window (if any) will be entered at the - // the time of the leave. This is dificult to accomplish by - // handling mouseEnter and mouseLeave envents, since they are sent - // individually to different views. - if (m_platformWindow->m_nsWindow && childWindow) { - if (childWindow != m_platformWindow->m_enterLeaveTargetWindow) { - QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); - m_platformWindow->m_enterLeaveTargetWindow = childWindow; - } - } - - // Cocoa keeps firing mouse move events for obscured parent views. Qt should not - // send those events so filter them out here. - if (childWindow != m_window) - return; - - [self handleMouseEvent: theEvent]; -} - -- (void)mouseEnteredImpl:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent) - m_platformWindow->m_windowUnderMouse = true; - - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return; - - // Top-level windows generate enter events for sub-windows. - if (!m_platformWindow->m_nsWindow) - return; - - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - m_platformWindow->m_enterLeaveTargetWindow = m_platformWindow->childWindowAt(windowPoint.toPoint()); - QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); -} - -- (void)mouseExitedImpl:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent); - m_platformWindow->m_windowUnderMouse = false; - - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return; - - // Top-level windows generate leave events for sub-windows. - if (!m_platformWindow->m_nsWindow) - return; - - QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_enterLeaveTargetWindow); - m_platformWindow->m_enterLeaveTargetWindow = 0; -} - -- (void)rightMouseDown:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super rightMouseDown:theEvent]; - m_buttons |= Qt::RightButton; - m_sendUpAsRightButton = true; - [self handleMouseEvent:theEvent]; -} - -- (void)rightMouseDragged:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super rightMouseDragged:theEvent]; - if (!(m_buttons & Qt::RightButton)) - qCDebug(lcQpaCocoaWindow, "QNSView rightMouseDragged: Internal mouse button tracking invalid (missing Qt::RightButton)"); - [self handleMouseEvent:theEvent]; -} - -- (void)rightMouseUp:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super rightMouseUp:theEvent]; - m_buttons &= ~Qt::RightButton; - m_sendUpAsRightButton = false; - [self handleMouseEvent:theEvent]; -} - -- (void)otherMouseDown:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super otherMouseDown:theEvent]; - m_buttons |= cocoaButton2QtButton([theEvent buttonNumber]); - [self handleMouseEvent:theEvent]; -} - -- (void)otherMouseDragged:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super otherMouseDragged:theEvent]; - if (!(m_buttons & ~(Qt::LeftButton | Qt::RightButton))) - qCDebug(lcQpaCocoaWindow, "QNSView otherMouseDragged: Internal mouse button tracking invalid (missing Qt::MiddleButton or Qt::ExtraButton*)"); - [self handleMouseEvent:theEvent]; -} - -- (void)otherMouseUp:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super otherMouseUp:theEvent]; - m_buttons &= ~cocoaButton2QtButton([theEvent buttonNumber]); - [self handleMouseEvent:theEvent]; -} - -struct QCocoaTabletDeviceData -{ - QTabletEvent::TabletDevice device; - QTabletEvent::PointerType pointerType; - uint capabilityMask; - qint64 uid; -}; - -typedef QHash QCocoaTabletDeviceDataHash; -Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash) - -- (bool)handleTabletEvent: (NSEvent *)theEvent -{ - NSEventType eventType = [theEvent type]; - if (eventType != NSTabletPoint && [theEvent subtype] != NSTabletPointEventSubtype) - return false; // Not a tablet event. - - ulong timestamp = [theEvent timestamp] * 1000; - - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint: &windowPoint andScreenPoint: &screenPoint]; - - uint deviceId = [theEvent deviceID]; - if (!tabletDeviceDataHash->contains(deviceId)) { - // Error: Unknown tablet device. Qt also gets into this state - // when running on a VM. This appears to be harmless; don't - // print a warning. - return false; - } - const QCocoaTabletDeviceData &deviceData = tabletDeviceDataHash->value(deviceId); - - bool down = (eventType != NSMouseMoved); - - qreal pressure; - if (down) { - pressure = [theEvent pressure]; - } else { - pressure = 0.0; - } - - NSPoint tilt = [theEvent tilt]; - int xTilt = qRound(tilt.x * 60.0); - int yTilt = qRound(tilt.y * -60.0); - Qt::MouseButtons buttons = static_cast(static_cast([theEvent buttonMask])); - qreal tangentialPressure = 0; - qreal rotation = 0; - int z = 0; - if (deviceData.capabilityMask & 0x0200) - z = [theEvent absoluteZ]; - - if (deviceData.capabilityMask & 0x0800) - tangentialPressure = ([theEvent tangentialPressure] * 2.0) - 1.0; - - rotation = 360.0 - [theEvent rotation]; - if (rotation > 180.0) - rotation -= 360.0; - - Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - - qCDebug(lcQpaTablet, "event on tablet %d with tool %d type %d unique ID %lld pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf", - deviceId, deviceData.device, deviceData.pointerType, deviceData.uid, - windowPoint.x(), windowPoint.y(), screenPoint.x(), screenPoint.y(), - static_cast(buttons), pressure, xTilt, yTilt, rotation); - - QWindowSystemInterface::handleTabletEvent(m_window, timestamp, windowPoint, screenPoint, - deviceData.device, deviceData.pointerType, buttons, pressure, xTilt, yTilt, - tangentialPressure, rotation, z, deviceData.uid, - keyboardModifiers); - return true; -} - -- (void)tabletPoint: (NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super tabletPoint:theEvent]; - - [self handleTabletEvent: theEvent]; -} - -static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) -{ - qint64 uid = [theEvent uniqueID]; - uint bits = [theEvent vendorPointingDeviceType]; - if (bits == 0 && uid != 0) { - // Fallback. It seems that the driver doesn't always include all the information. - // High-End Wacom devices store their "type" in the uper bits of the Unique ID. - // I'm not sure how to handle it for consumer devices, but I'll test that in a bit. - bits = uid >> 32; - } - - QTabletEvent::TabletDevice device; - // Defined in the "EN0056-NxtGenImpGuideX" - // on Wacom's Developer Website (www.wacomeng.com) - if (((bits & 0x0006) == 0x0002) && ((bits & 0x0F06) != 0x0902)) { - device = QTabletEvent::Stylus; - } else { - switch (bits & 0x0F06) { - case 0x0802: - device = QTabletEvent::Stylus; - break; - case 0x0902: - device = QTabletEvent::Airbrush; - break; - case 0x0004: - device = QTabletEvent::FourDMouse; - break; - case 0x0006: - device = QTabletEvent::Puck; - break; - case 0x0804: - device = QTabletEvent::RotationStylus; - break; - default: - device = QTabletEvent::NoDevice; - } - } - return device; -} - -- (void)tabletProximity: (NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super tabletProximity:theEvent]; - - ulong timestamp = [theEvent timestamp] * 1000; - - QCocoaTabletDeviceData deviceData; - deviceData.uid = [theEvent uniqueID]; - deviceData.capabilityMask = [theEvent capabilityMask]; - - switch ([theEvent pointingDeviceType]) { - case NSUnknownPointingDevice: - default: - deviceData.pointerType = QTabletEvent::UnknownPointer; - break; - case NSPenPointingDevice: - deviceData.pointerType = QTabletEvent::Pen; - break; - case NSCursorPointingDevice: - deviceData.pointerType = QTabletEvent::Cursor; - break; - case NSEraserPointingDevice: - deviceData.pointerType = QTabletEvent::Eraser; - break; - } - - deviceData.device = wacomTabletDevice(theEvent); - - // The deviceID is "unique" while in the proximity, it's a key that we can use for - // linking up QCocoaTabletDeviceData to an event (especially if there are two devices in action). - bool entering = [theEvent isEnteringProximity]; - uint deviceId = [theEvent deviceID]; - if (entering) { - tabletDeviceDataHash->insert(deviceId, deviceData); - } else { - tabletDeviceDataHash->remove(deviceId); - } - - qCDebug(lcQpaTablet, "proximity change on tablet %d: current tool %d type %d unique ID %lld", - deviceId, deviceData.device, deviceData.pointerType, deviceData.uid); - - if (entering) { - QWindowSystemInterface::handleTabletEnterProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid); - } else { - QWindowSystemInterface::handleTabletLeaveProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid); - } -} - -- (bool) shouldSendSingleTouch -{ - // QtWidgets expects single-point touch events, QtDeclarative does not. - // Until there is an API we solve this by looking at the window class type. - return m_window->inherits("QWidgetWindow"); -} - -- (void)touchesBeganWithEvent:(NSEvent *)event -{ - const NSTimeInterval timestamp = [event timestamp]; - const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, touchDevice, points); -} - -- (void)touchesMovedWithEvent:(NSEvent *)event -{ - const NSTimeInterval timestamp = [event timestamp]; - const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, touchDevice, points); -} - -- (void)touchesEndedWithEvent:(NSEvent *)event -{ - const NSTimeInterval timestamp = [event timestamp]; - const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, touchDevice, points); -} - -- (void)touchesCancelledWithEvent:(NSEvent *)event -{ - const NSTimeInterval timestamp = [event timestamp]; - const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, touchDevice, points); -} - -#ifndef QT_NO_GESTURES - -- (bool)handleGestureAsBeginEnd:(NSEvent *)event -{ - if (QSysInfo::QSysInfo::MacintoshVersion < QSysInfo::MV_10_11) - return false; - - if ([event phase] == NSEventPhaseBegan) { - [self beginGestureWithEvent:event]; - return true; - } - - if ([event phase] == NSEventPhaseEnded) { - [self endGestureWithEvent:event]; - return true; - } - - return false; -} -- (void)magnifyWithEvent:(NSEvent *)event -{ - if ([self handleGestureAsBeginEnd:event]) - return; - - qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification]; - const NSTimeInterval timestamp = [event timestamp]; - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::ZoomNativeGesture, - [event magnification], windowPoint, screenPoint); -} - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 -- (void)smartMagnifyWithEvent:(NSEvent *)event -{ - static bool zoomIn = true; - qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn; - const NSTimeInterval timestamp = [event timestamp]; - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::SmartZoomNativeGesture, - zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint); - zoomIn = !zoomIn; -} -#endif - -- (void)rotateWithEvent:(NSEvent *)event -{ - if ([self handleGestureAsBeginEnd:event]) - return; - - const NSTimeInterval timestamp = [event timestamp]; - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::RotateNativeGesture, - -[event rotation], windowPoint, screenPoint); -} - -- (void)swipeWithEvent:(NSEvent *)event -{ - qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY]; - const NSTimeInterval timestamp = [event timestamp]; - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - - qreal angle = 0.0f; - if ([event deltaX] == 1) - angle = 180.0f; - else if ([event deltaX] == -1) - angle = 0.0f; - else if ([event deltaY] == 1) - angle = 90.0f; - else if ([event deltaY] == -1) - angle = 270.0f; - - QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::SwipeNativeGesture, - angle, windowPoint, screenPoint); -} - -- (void)beginGestureWithEvent:(NSEvent *)event -{ - const NSTimeInterval timestamp = [event timestamp]; - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint; - QWindowSystemInterface::handleGestureEvent(m_window, timestamp, Qt::BeginNativeGesture, - windowPoint, screenPoint); -} - -- (void)endGestureWithEvent:(NSEvent *)event -{ - qCDebug(lcQpaGestures) << "endGestureWithEvent"; - const NSTimeInterval timestamp = [event timestamp]; - QPointF windowPoint; - QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEvent(m_window, timestamp, Qt::EndNativeGesture, - windowPoint, screenPoint); -} -#endif // QT_NO_GESTURES - -#ifndef QT_NO_WHEELEVENT -- (void)scrollWheel:(NSEvent *)theEvent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super scrollWheel:theEvent]; - - QPoint angleDelta; - Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; - if ([theEvent hasPreciseScrollingDeltas]) { - // The mouse device contains pixel scroll wheel support (Mighty Mouse, Trackpad). - // Since deviceDelta is delivered as pixels rather than degrees, we need to - // convert from pixels to degrees in a sensible manner. - // It looks like 1/4 degrees per pixel behaves most native. - // (NB: Qt expects the unit for delta to be 8 per degree): - const int pixelsToDegrees = 2; // 8 * 1/4 - angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees); - angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees); - source = Qt::MouseEventSynthesizedBySystem; - } else { - // Remove acceleration, and use either -120 or 120 as delta: - angleDelta.setX(qBound(-120, int([theEvent deltaX] * 10000), 120)); - angleDelta.setY(qBound(-120, int([theEvent deltaY] * 10000), 120)); - } - - QPoint pixelDelta; - if ([theEvent hasPreciseScrollingDeltas]) { - pixelDelta.setX([theEvent scrollingDeltaX]); - pixelDelta.setY([theEvent scrollingDeltaY]); - } else { - // docs: "In the case of !hasPreciseScrollingDeltas, multiply the delta with the line width." - // scrollingDeltaX seems to return a minimum value of 0.1 in this case, map that to two pixels. - const CGFloat lineWithEstimate = 20.0; - pixelDelta.setX([theEvent scrollingDeltaX] * lineWithEstimate); - pixelDelta.setY([theEvent scrollingDeltaY] * lineWithEstimate); - } - - QPointF qt_windowPoint; - QPointF qt_screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qt_windowPoint andScreenPoint:&qt_screenPoint]; - NSTimeInterval timestamp = [theEvent timestamp]; - ulong qt_timestamp = timestamp * 1000; - - // Prevent keyboard modifier state from changing during scroll event streams. - // A two-finger trackpad flick generates a stream of scroll events. We want - // the keyboard modifier state to be the state at the beginning of the - // flick in order to avoid changing the interpretation of the events - // mid-stream. One example of this happening would be when pressing cmd - // after scrolling in Qt Creator: not taking the phase into account causes - // the end of the event stream to be interpreted as font size changes. - NSEventPhase momentumPhase = [theEvent momentumPhase]; - if (momentumPhase == NSEventPhaseNone) { - currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - } - - NSEventPhase phase = [theEvent phase]; - Qt::ScrollPhase ph = Qt::ScrollUpdate; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { - // On 10.8 and above, MayBegin is likely to happen. We treat it the same as an actual begin. - if (phase == NSEventPhaseMayBegin) { - m_scrolling = true; - ph = Qt::ScrollBegin; - } - } -#endif - if (phase == NSEventPhaseBegan) { - // If MayBegin did not happen, Began is the actual beginning. - if (!m_scrolling) - ph = Qt::ScrollBegin; - m_scrolling = true; - } else if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled || - momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) { - ph = Qt::ScrollEnd; - m_scrolling = false; - } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) { - ph = Qt::NoScrollPhase; - if (!QGuiApplicationPrivate::scrollNoPhaseAllowed) - ph = Qt::ScrollUpdate; - } - - QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source); -} -#endif //QT_NO_WHEELEVENT - -- (int) convertKeyCode : (QChar)keyChar -{ - return qt_mac_cocoaKey2QtKey(keyChar); -} - -+ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags -{ - Qt::KeyboardModifiers qtMods =Qt::NoModifier; - if (modifierFlags & NSShiftKeyMask) - qtMods |= Qt::ShiftModifier; - if (modifierFlags & NSControlKeyMask) - qtMods |= Qt::MetaModifier; - if (modifierFlags & NSAlternateKeyMask) - qtMods |= Qt::AltModifier; - if (modifierFlags & NSCommandKeyMask) - qtMods |= Qt::ControlModifier; - if (modifierFlags & NSNumericPadKeyMask) - qtMods |= Qt::KeypadModifier; - return qtMods; -} - -- (void)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType -{ - ulong timestamp = [nsevent timestamp] * 1000; - ulong nativeModifiers = [nsevent modifierFlags]; - Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers]; - NSString *charactersIgnoringModifiers = [nsevent charactersIgnoringModifiers]; - NSString *characters = [nsevent characters]; - if (m_inputSource != characters) { - [m_inputSource release]; - m_inputSource = [characters retain]; - } - - // There is no way to get the scan code from carbon/cocoa. But we cannot - // use the value 0, since it indicates that the event originates from somewhere - // else than the keyboard. - quint32 nativeScanCode = 1; - quint32 nativeVirtualKey = [nsevent keyCode]; - - QChar ch = QChar::ReplacementCharacter; - int keyCode = Qt::Key_unknown; - if ([characters length] != 0) { - if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0)) - ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); - else - ch = QChar([characters characterAtIndex:0]); - keyCode = [self convertKeyCode:ch]; - } - - // we will send a key event unless the input method sets m_sendKeyEvent to false - m_sendKeyEvent = true; - QString text; - // ignore text for the U+F700-U+F8FF range. This is used by Cocoa when - // delivering function keys (e.g. arrow keys, backspace, F1-F35, etc.) - if (!(modifiers & (Qt::ControlModifier | Qt::MetaModifier)) && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff)) - text = QCFString::toQString(characters); - - QWindow *window = [self topLevelWindow]; - - // Popups implicitly grab key events; forward to the active popup if there is one. - // This allows popups to e.g. intercept shortcuts and close the popup in response. - if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) { - if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) - window = popup->window(); - } - - if (eventType == QEvent::KeyPress) { - - if (m_composingText.isEmpty()) { - m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(window, timestamp, keyCode, - modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1); - } - - QObject *fo = QGuiApplication::focusObject(); - if (m_sendKeyEvent && fo) { - QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints); - if (QCoreApplication::sendEvent(fo, &queryEvent)) { - bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool(); - Qt::InputMethodHints hints = static_cast(queryEvent.value(Qt::ImHints).toUInt()); - if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) { - // pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call - m_currentlyInterpretedKeyEvent = nsevent; - [self interpretKeyEvents:[NSArray arrayWithObject:nsevent]]; - m_currentlyInterpretedKeyEvent = 0; - } - } - } - if (m_resendKeyEvent) - m_sendKeyEvent = true; - } - - if (m_sendKeyEvent && m_composingText.isEmpty()) - QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, QEvent::Type(eventType), keyCode, modifiers, - nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1, false); - - m_sendKeyEvent = false; - m_resendKeyEvent = false; -} - -- (void)keyDown:(NSEvent *)nsevent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super keyDown:nsevent]; - [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)]; -} - -- (void)keyUp:(NSEvent *)nsevent -{ - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) - return [super keyUp:nsevent]; - [self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)]; -} - -- (void)cancelOperation:(id)sender -{ - Q_UNUSED(sender); - - NSEvent *currentEvent = [NSApp currentEvent]; - if (!currentEvent || currentEvent.type != NSKeyDown) - return; - - // Handling the key event may recurse back here through interpretKeyEvents - // (when IM is enabled), so we need to guard against that. - if (currentEvent == m_currentlyInterpretedKeyEvent) - return; - - // Send Command+Key_Period and Escape as normal keypresses so that - // the key sequence is delivered through Qt. That way clients can - // intercept the shortcut and override its effect. - [self handleKeyEvent:currentEvent eventType:int(QEvent::KeyPress)]; -} - -- (void)flagsChanged:(NSEvent *)nsevent -{ - ulong timestamp = [nsevent timestamp] * 1000; - ulong modifiers = [nsevent modifierFlags]; - Qt::KeyboardModifiers qmodifiers = [QNSView convertKeyModifiers:modifiers]; - - // calculate the delta and remember the current modifiers for next time - static ulong m_lastKnownModifiers; - ulong lastKnownModifiers = m_lastKnownModifiers; - ulong delta = lastKnownModifiers ^ modifiers; - m_lastKnownModifiers = modifiers; - - struct qt_mac_enum_mapper - { - ulong mac_mask; - Qt::Key qt_code; - }; - static qt_mac_enum_mapper modifier_key_symbols[] = { - { NSShiftKeyMask, Qt::Key_Shift }, - { NSControlKeyMask, Qt::Key_Meta }, - { NSCommandKeyMask, Qt::Key_Control }, - { NSAlternateKeyMask, Qt::Key_Alt }, - { NSAlphaShiftKeyMask, Qt::Key_CapsLock }, - { 0ul, Qt::Key_unknown } }; - for (int i = 0; modifier_key_symbols[i].mac_mask != 0u; ++i) { - uint mac_mask = modifier_key_symbols[i].mac_mask; - if ((delta & mac_mask) == 0u) - continue; - - QWindowSystemInterface::handleKeyEvent(m_window, - timestamp, - (lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress, - modifier_key_symbols[i].qt_code, - qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]); - } -} - -- (void) insertNewline:(id)sender -{ - Q_UNUSED(sender); - m_resendKeyEvent = true; -} - -- (void) doCommandBySelector:(SEL)aSelector -{ - [self tryToPerform:aSelector with:self]; -} - -- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange -{ - Q_UNUSED(replacementRange) - - if (m_sendKeyEvent && m_composingText.isEmpty() && [aString isEqualToString:m_inputSource]) { - // don't send input method events for simple text input (let handleKeyEvent send key events instead) - return; - } - - QString commitString; - if ([aString length]) { - if ([aString isKindOfClass:[NSAttributedString class]]) { - commitString = QCFString::toQString(reinterpret_cast([aString string])); - } else { - commitString = QCFString::toQString(reinterpret_cast(aString)); - }; - } - QObject *fo = QGuiApplication::focusObject(); - if (fo) { - QInputMethodQueryEvent queryEvent(Qt::ImEnabled); - if (QCoreApplication::sendEvent(fo, &queryEvent)) { - if (queryEvent.value(Qt::ImEnabled).toBool()) { - QInputMethodEvent e; - e.setCommitString(commitString); - QCoreApplication::sendEvent(fo, &e); - // prevent handleKeyEvent from sending a key event - m_sendKeyEvent = false; - } - } - } - - m_composingText.clear(); -} - -- (void) setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange -{ - Q_UNUSED(replacementRange) - QString preeditString; - - QList attrs; - attrs<([aString string])); - int composingLength = preeditString.length(); - int index = 0; - // Create attributes for individual sections of preedit text - while (index < composingLength) { - NSRange effectiveRange; - NSRange range = NSMakeRange(index, composingLength-index); - NSDictionary *attributes = [aString attributesAtIndex:index - longestEffectiveRange:&effectiveRange - inRange:range]; - NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName]; - if (underlineStyle) { - QColor clr (Qt::black); - NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName]; - if (color) { - clr = qt_mac_toQColor(color); - } - QTextCharFormat format; - format.setFontUnderline(true); - format.setUnderlineColor(clr); - attrs<(aString)); - } - - if (attrs.isEmpty()) { - QTextCharFormat format; - format.setFontUnderline(true); - attrs<((CFStringRef)string); - return [[[NSAttributedString alloc] initWithString:const_cast(tmpString)] autorelease]; -} - -- (NSRange) markedRange -{ - NSRange range; - if (!m_composingText.isEmpty()) { - range.location = 0; - range.length = m_composingText.length(); - } else { - range.location = NSNotFound; - range.length = 0; - } - return range; -} - -- (NSRange) selectedRange -{ - NSRange selectedRange = {NSNotFound, 0}; - selectedRange.location = NSNotFound; - selectedRange.length = 0; - - QObject *fo = QGuiApplication::focusObject(); - if (!fo) - return selectedRange; - QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection); - if (!QCoreApplication::sendEvent(fo, &queryEvent)) - return selectedRange; - if (!queryEvent.value(Qt::ImEnabled).toBool()) - return selectedRange; - - QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString(); - - if (!selectedText.isEmpty()) { - selectedRange.location = 0; - selectedRange.length = selectedText.length(); - } - return selectedRange; -} - -- (NSRect) firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange -{ - Q_UNUSED(aRange) - Q_UNUSED(actualRange) - QObject *fo = QGuiApplication::focusObject(); - if (!fo) - return NSZeroRect; - - QInputMethodQueryEvent queryEvent(Qt::ImEnabled); - if (!QCoreApplication::sendEvent(fo, &queryEvent)) - return NSZeroRect; - if (!queryEvent.value(Qt::ImEnabled).toBool()) - return NSZeroRect; - - if (!m_window) - return NSZeroRect; - - // The returned rect is always based on the internal cursor. - QRect mr = qApp->inputMethod()->cursorRectangle().toRect(); - QPoint mp = m_window->mapToGlobal(mr.bottomLeft()); - - NSRect rect; - rect.origin.x = mp.x(); - rect.origin.y = qt_mac_flipYCoordinate(mp.y()); - rect.size.width = mr.width(); - rect.size.height = mr.height(); - return rect; -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint -{ - // We don't support cursor movements using mouse while composing. - Q_UNUSED(aPoint); - return NSNotFound; -} - -- (NSArray*) validAttributesForMarkedText -{ - if (m_window != QGuiApplication::focusWindow()) - return nil; - - QObject *fo = QGuiApplication::focusObject(); - if (!fo) - return nil; - - QInputMethodQueryEvent queryEvent(Qt::ImEnabled); - if (!QCoreApplication::sendEvent(fo, &queryEvent)) - return nil; - if (!queryEvent.value(Qt::ImEnabled).toBool()) - return nil; - - // Support only underline color/style. - return [NSArray arrayWithObjects:NSUnderlineColorAttributeName, - NSUnderlineStyleAttributeName, nil]; -} - --(void)registerDragTypes -{ - QMacAutoReleasePool pool; - QStringList customTypes = qt_mac_enabledDraggedTypes(); - if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) { - if (currentCustomDragTypes == 0) - currentCustomDragTypes = new QStringList(); - *currentCustomDragTypes = customTypes; - const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName"; - NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType, - NSFilenamesPboardType, NSStringPboardType, - NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType, - NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType, - NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType, - NSRTFDPboardType, NSHTMLPboardType, - NSURLPboardType, NSPDFPboardType, NSVCardPboardType, - NSFilesPromisePboardType, NSInkTextPboardType, - NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil]; - // Add custom types supported by the application. - for (int i = 0; i < customTypes.size(); i++) { - [supportedTypes addObject:QCFString::toNSString(customTypes[i])]; - } - [self registerForDraggedTypes:supportedTypes]; - } -} - -static QWindow *findEventTargetWindow(QWindow *candidate) -{ - while (candidate) { - if (!(candidate->flags() & Qt::WindowTransparentForInput)) - return candidate; - candidate = candidate->parent(); - } - return candidate; -} - -static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint point) -{ - return target->mapFromGlobal(source->mapToGlobal(point)); -} - -- (NSDragOperation)draggingSession:(NSDraggingSession *)session - sourceOperationMaskForDraggingContext:(NSDraggingContext)context -{ - Q_UNUSED(session); - Q_UNUSED(context); - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - return qt_mac_mapDropActions(nativeDrag->currentDrag()->supportedActions()); -} - -- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session -{ - Q_UNUSED(session); - // According to the "Dragging Sources" chapter on Cocoa DnD Programming - // (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DragandDrop/Concepts/dragsource.html), - // if the control, option, or command key is pressed, the source’s - // operation mask is filtered to only contain a reduced set of operations. - // - // Since Qt already takes care of tracking the keyboard modifiers, we - // don't need (or want) Cocoa to filter anything. Instead, we'll let - // the application do the actual filtering. - return YES; -} - -- (BOOL)wantsPeriodicDraggingUpdates -{ - // From the documentation: - // - // "If the destination returns NO, these messages are sent only when the mouse moves - // or a modifier flag changes. Otherwise the destination gets the default behavior, - // where it receives periodic dragging-updated messages even if nothing changes." - // - // We do not want these constant drag update events while mouse is stationary, - // since we do all animations (autoscroll) with timers. - return NO; -} - -- (void)updateCursorFromDragResponse:(QPlatformDragQtResponse)response drag:(QCocoaDrag *)drag -{ - const QPixmap pixmapCursor = drag->currentDrag()->dragCursor(response.acceptedAction()); - NSCursor *nativeCursor = nil; - - if (pixmapCursor.isNull()) { - switch (response.acceptedAction()) { - case Qt::CopyAction: - nativeCursor = [NSCursor dragCopyCursor]; - break; - case Qt::LinkAction: - nativeCursor = [NSCursor dragLinkCursor]; - break; - case Qt::IgnoreAction: - // Uncomment the next lines if forbiden cursor wanted on non droppable targets. - /*nativeCursor = [NSCursor operationNotAllowedCursor]; - break;*/ - case Qt::MoveAction: - default: - nativeCursor = [NSCursor arrowCursor]; - break; - } - } - else { - NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor); - nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint]; - [nsimage release]; - } - - // change the cursor - [nativeCursor set]; - - // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor - // by creating a fake move event - if (m_updatingDrag) - return; - - const QPoint mousePos(QCursor::pos()); - CGEventRef moveEvent(CGEventCreateMouseEvent( - NULL, kCGEventMouseMoved, - CGPointMake(mousePos.x(), mousePos.y()), - kCGMouseButtonLeft // ignored - )); - CGEventPost(kCGHIDEventTap, moveEvent); - CFRelease(moveEvent); -} - -- (NSDragOperation)draggingEntered:(id )sender -{ - return [self handleDrag : sender]; -} - -- (NSDragOperation)draggingUpdated:(id )sender -{ - m_updatingDrag = true; - const NSDragOperation ret([self handleDrag : sender]); - m_updatingDrag = false; - - return ret; -} - -// Sends drag update to Qt, return the action -- (NSDragOperation)handleDrag:(id )sender -{ - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); - - QWindow *target = findEventTargetWindow(m_window); - if (!target) - return NSDragOperationNone; - - // update these so selecting move/copy/link works - QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]]; - - QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect()); - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - if (nativeDrag->currentDrag()) { - // The drag was started from within the application - response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); - [self updateCursorFromDragResponse:response drag:nativeDrag]; - } else { - QCocoaDropData mimeData([sender draggingPasteboard]); - response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); - } - - return qt_mac_mapDropAction(response.acceptedAction()); -} - -- (void)draggingExited:(id )sender -{ - QWindow *target = findEventTargetWindow(m_window); - if (!target) - return; - - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); - - // Send 0 mime data to indicate drag exit - QWindowSystemInterface::handleDrag(target, 0, mapWindowCoordinates(m_window, target, qt_windowPoint), Qt::IgnoreAction); -} - -// called on drop, send the drop to Qt and return if it was accepted. -- (BOOL)performDragOperation:(id )sender -{ - QWindow *target = findEventTargetWindow(m_window); - if (!target) - return false; - - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); - - QPlatformDropQtResponse response(false, Qt::IgnoreAction); - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - if (nativeDrag->currentDrag()) { - // The drag was started from within the application - response = QWindowSystemInterface::handleDrop(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); - } else { - QCocoaDropData mimeData([sender draggingPasteboard]); - response = QWindowSystemInterface::handleDrop(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); - } - if (response.isAccepted()) { - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - nativeDrag->setAcceptedAction(response.acceptedAction()); - } - return response.isAccepted(); -} - -- (void)draggingSession:(NSDraggingSession *)session - endedAtPoint:(NSPoint)screenPoint - operation:(NSDragOperation)operation -{ - Q_UNUSED(session); - Q_UNUSED(operation); - QWindow *target = findEventTargetWindow(m_window); - if (!target) - return; - - // keep our state, and QGuiApplication state (buttons member) in-sync, - // or future mouse events will be processed incorrectly - NSUInteger pmb = [NSEvent pressedMouseButtons]; - for (int buttonNumber = 0; buttonNumber < 32; buttonNumber++) { // see cocoaButton2QtButton() for the 32 value - if (!(pmb & (1 << buttonNumber))) - m_buttons &= ~cocoaButton2QtButton(buttonNumber); - } - - NSPoint windowPoint = [self.window convertRectFromScreen:NSMakeRect(screenPoint.x, screenPoint.y, 1, 1)].origin; - QPoint qtWindowPoint(windowPoint.x, windowPoint.y); - - QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); - - QWindowSystemInterface::handleMouseEvent(target, mapWindowCoordinates(m_window, target, qtWindowPoint), qtScreenPoint, m_buttons); -} - -- (NSWindow *)nsWindow -{ - typedef QT_MANGLE_NAMESPACE(QNSView) QNSV; - - NSWindow *win = m_platformWindow->m_nsWindow; - NSView *parent = self.superview; - while (!win) { - if (![parent isKindOfClass:[QNSV class]]) - break; - - QCocoaWindow *platformWindow = static_cast(parent)->m_platformWindow; - if (platformWindow) - win = platformWindow->m_nsWindow; - - parent = parent.superview; - } - - return win; -} - -@end