/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "qnsview.h" #include "qcocoahelpers.h" #include "qmultitouch_mac_p.h" #include #include @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; - (CGFloat)deviceDeltaZ; @end @implementation QNSView - (id) init { self = [super init]; if (self) { m_cgImage = 0; m_window = 0; m_buttons = Qt::NoButton; } return self; } - (id)initWithQWindow:(QWindow *)widget { self = [self init]; if (self) { m_window = widget; } return self; } - (void) setImage:(QImage *)image { CGImageRelease(m_cgImage); const uchar *imageData = image->bits(); int bitDepth = image->depth(); int colorBufferSize = 8; int bytesPrLine = image->bytesPerLine(); int width = image->width(); int height = image->height(); CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB(); CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData( NULL, imageData, image->byteCount(), NULL); m_cgImage = CGImageCreate(width, height, colorBufferSize, bitDepth, bytesPrLine, cgColourSpaceRef, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, cgDataProviderRef, NULL, false, kCGRenderingIntentDefault); CGColorSpaceRelease(cgColourSpaceRef); } - (void) drawRect:(NSRect)dirtyRect { if (!m_cgImage) return; CGRect dirtyCGRect = NSRectToCGRect(dirtyRect); NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; CGContextSaveGState( cgContext ); int dy = dirtyCGRect.origin.y + CGRectGetMaxY(dirtyCGRect); CGContextTranslateCTM(cgContext, 0, dy); CGContextScaleCTM(cgContext, 1, -1); CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, dirtyCGRect); CGContextDrawImage(cgContext,dirtyCGRect,subImage); CGContextRestoreGState(cgContext); CGImageRelease(subImage); } - (BOOL) isFlipped { return YES; } - (BOOL)acceptsFirstResponder { return YES; } - (void)handleMouseEvent:(NSEvent *)theEvent; { NSPoint windowPoint = [self convertPoint: [theEvent locationInWindow] fromView: nil]; QPoint qt_windowPoint(windowPoint.x, windowPoint.y); NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; // ### Should the points be windowPoint and screenPoint? QWindowSystemInterface::handleMouseEvent(m_window, qt_timestamp, qt_windowPoint, qt_windowPoint, m_buttons); } - (void)mouseDown:(NSEvent *)theEvent { m_buttons |= Qt::LeftButton; [self handleMouseEvent:theEvent]; } - (void)mouseDragged:(NSEvent *)theEvent { if (!(m_buttons & Qt::LeftButton)) qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); [self handleMouseEvent:theEvent]; } - (void)mouseUp:(NSEvent *)theEvent { m_buttons &= QFlag(~int(Qt::LeftButton)); [self handleMouseEvent:theEvent]; } - (void)mouseMoved:(NSEvent *)theEvent { [self handleMouseEvent:theEvent]; } - (void)mouseEntered:(NSEvent *)theEvent { Q_UNUSED(theEvent); QWindowSystemInterface::handleEnterEvent(m_window); } - (void)mouseExited:(NSEvent *)theEvent { Q_UNUSED(theEvent); QWindowSystemInterface::handleLeaveEvent(m_window); } - (void)rightMouseDown:(NSEvent *)theEvent { m_buttons |= Qt::RightButton; [self handleMouseEvent:theEvent]; } - (void)rightMouseDragged:(NSEvent *)theEvent { if (!(m_buttons & Qt::LeftButton)) qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); [self handleMouseEvent:theEvent]; } - (void)rightMouseUp:(NSEvent *)theEvent { m_buttons &= QFlag(~int(Qt::RightButton)); [self handleMouseEvent:theEvent]; } - (void)otherMouseDown:(NSEvent *)theEvent { m_buttons |= Qt::RightButton; [self handleMouseEvent:theEvent]; } - (void)otherMouseDragged:(NSEvent *)theEvent { if (!(m_buttons & Qt::LeftButton)) qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); [self handleMouseEvent:theEvent]; } - (void)otherMouseUp:(NSEvent *)theEvent { m_buttons &= QFlag(~int(Qt::MiddleButton)); [self handleMouseEvent:theEvent]; } - (void)touchesBeganWithEvent:(NSEvent *)event; { const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, /*acceptSingleTouch= ### true or false?*/false); QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, QEvent::TouchBegin, QTouchEvent::TouchPad, points); } - (void)touchesMovedWithEvent:(NSEvent *)event; { const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, /*acceptSingleTouch= ### true or false?*/false); QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, QEvent::TouchUpdate, QTouchEvent::TouchPad, points); } - (void)touchesEndedWithEvent:(NSEvent *)event; { const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, /*acceptSingleTouch= ### true or false?*/false); QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, QEvent::TouchEnd, QTouchEvent::TouchPad, points); } - (void)touchesCancelledWithEvent:(NSEvent *)event; { const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, /*acceptSingleTouch= ### true or false?*/false); QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, QEvent::TouchEnd, QTouchEvent::TouchPad, points); } #ifndef QT_NO_WHEELEVENT - (void)scrollWheel:(NSEvent *)theEvent { int deltaX = 0; int deltaY = 0; int deltaZ = 0; const EventRef carbonEvent = (EventRef)[theEvent eventRef]; const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; const bool scrollEvent = carbonEventKind == kEventMouseScroll; if (scrollEvent) { // 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 deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees; } else { // carbonEventKind == kEventMouseWheelMoved // Remove acceleration, and use either -120 or 120 as delta: deltaX = qBound(-120, int([theEvent deltaX] * 10000), 120); deltaY = qBound(-120, int([theEvent deltaY] * 10000), 120); deltaZ = qBound(-120, int([theEvent deltaZ] * 10000), 120); } NSPoint windowPoint = [self convertPoint: [theEvent locationInWindow] fromView: nil]; QPoint qt_windowPoint(windowPoint.x, windowPoint.y); NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; if (deltaX != 0) QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_windowPoint, deltaX, Qt::Horizontal); if (deltaY != 0) QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_windowPoint, deltaY, Qt::Vertical); if (deltaZ != 0) // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to // try to be ahead of the pack, I'm adding this extra value. QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_windowPoint, deltaY, (Qt::Orientation)3); } #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 *)theEvent eventType:(int)eventType { NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; QString characters = QString::fromUtf8([[theEvent characters] UTF8String]); Qt::KeyboardModifiers modifiers = [self convertKeyModifiers : [theEvent modifierFlags]]; QChar ch([[theEvent charactersIgnoringModifiers] characterAtIndex:0]); int keyCode = [self convertKeyCode : ch]; QWindowSystemInterface::handleKeyEvent(m_window, qt_timestamp, QEvent::Type(eventType), keyCode, modifiers, characters); } - (void)keyDown:(NSEvent *)theEvent { [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; } - (void)keyUp:(NSEvent *)theEvent { [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; } @end