4#import <UIKit/UIGestureRecognizerSubclass.h>
5#import <UIKit/UITextView.h>
7#include <QtGui/QGuiApplication>
8#include <QtGui/QInputMethod>
9#include <QtGui/QStyleHints>
11#include <QtGui/private/qinputmethod_p.h>
12#include <QtCore/private/qobject_p.h>
13#include <QtCore/private/qcore_mac_p.h>
45 [CATransaction
begin];
46 [CATransaction
setValue:(
id)kCFBooleanTrue forKey:kCATransactionDisableActions];
57@property (nonatomic, assign) BOOL
visible;
67 if (self = [super
init]) {
68 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
70 [center addObserverForName:UIMenuControllerWillHideMenuNotification
71 object:nil queue:nil usingBlock:^(NSNotification *) {
75 [center addObserverForName:UIMenuControllerDidHideMenuNotification
76 object:nil queue:nil usingBlock:^(NSNotification *) {
79 if (self.reshowAfterHidden) {
82 self.reshowAfterHidden = NO;
83 dispatch_async(dispatch_get_main_queue (), ^{
self.visible = YES; });
86 [center addObserverForName:UIKeyboardDidHideNotification object:nil queue:nil
87 usingBlock:^(NSNotification *) {
98 [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:nil];
104 return [UIMenuController sharedMenuController].menuVisible;
107- (
void)setVisible:(BOOL)visible
122 CGRect targetRect = cr.
united(ar).toCGRect();
123 UIView *
focusView =
reinterpret_cast<UIView *
>(
qApp->focusWindow()->winId());
124 [[UIMenuController sharedMenuController] setTargetRect:targetRect inView:focusView];
125 [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
127 [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
136@property (nonatomic, retain) UIView *targetView;
138@property (nonatomic, assign) BOOL visible;
142 UIView *_snapshotView;
150- (instancetype)initWithSize:(CGSize)size cornerRadius:(
CGFloat)cornerRadius bottomOffset:(
CGFloat)bottomOffset
162 self.cornerRadius = cornerRadius;
163 self.shadowColor = [[UIColor grayColor] CGColor];
164 self.shadowOffset = CGSizeMake(0, 1);
165 self.shadowRadius = 2.0;
166 self.shadowOpacity = 0.75;
167 self.transform = CATransform3DMakeScale(0, 0, 0);
174 [
self addSublayer:_containerLayer];
178 CALayer *topShadeLayer = [[CALayer new] autorelease];
179 topShadeLayer.frame = CGRectOffset(CGRectInset(
self.bounds, -inset, -inset), 0, inset / 2);
180 topShadeLayer.borderWidth = inset / 2;
181 topShadeLayer.cornerRadius = cornerRadius;
182 topShadeLayer.borderColor = [[UIColor blackColor] CGColor];
183 topShadeLayer.shadowColor = [[UIColor blackColor] CGColor];
184 topShadeLayer.shadowOffset = CGSizeMake(0, 0);
185 topShadeLayer.shadowRadius = 15.0;
186 topShadeLayer.shadowOpacity = 0.6;
188 CALayer *
mask = [[CALayer new] autorelease];
189 mask.frame = CGRectOffset(
self.bounds, inset, inset / 2);
190 mask.backgroundColor = [[UIColor blackColor] CGColor];
191 mask.cornerRadius = cornerRadius;
192 topShadeLayer.mask =
mask;
193 [
self addSublayer:topShadeLayer];
198 CALayer *borderLayer = [[CALayer new] autorelease];
199 borderLayer.frame =
self.bounds;
200 borderLayer.borderWidth = 0.75;
201 borderLayer.cornerRadius = cornerRadius;
202 borderLayer.borderColor = [[UIColor lightGrayColor] CGColor];
203 [
self addSublayer:borderLayer];
215- (
void)setVisible:(BOOL)visible
217 if (_visible == visible)
222 dispatch_async(dispatch_get_main_queue (), ^{
225 self.transform = _visible ? CATransform3DMakeScale(1, 1, 1) : CATransform3DMakeScale(0.0, 0.0, 1);
229- (
void)updateSnapshot
232 [
self setNeedsDisplay];
235- (
void)setFocalPoint:(CGPoint)point
238 [
self updateSnapshot];
253 UIView *newSnapshot = [_targetView snapshotViewAfterScreenUpdates:NO];
254 [_snapshotView.layer removeFromSuperlayer];
255 [_snapshotView release];
256 _snapshotView = [newSnapshot retain];
257 [_containerLayer addSublayer:_snapshotView.layer];
263 const CGFloat loupeScale = 1.5;
267 CGFloat h = _targetView.frame.size.height * loupeScale;
268 _snapshotView.layer.frame = CGRectMake(
x,
y,
w,
h);
284 CALayer *_handleCursorLayer;
291- (instancetype)initWithKnobAtEdge:(
Qt::Edge)selectionEdge
294 CGColorRef bgColor = [UIColor colorWithRed:0.1 green:0.4 blue:0.9 alpha:1].CGColor;
296 self.handleScale = 0;
298 _handleCursorLayer = [[CALayer new] autorelease];
299 _handleCursorLayer.masksToBounds = YES;
300 _handleCursorLayer.backgroundColor = bgColor;
301 [
self addSublayer:_handleCursorLayer];
307 [
self addSublayer:_handleKnobLayer];
312+ (BOOL)needsDisplayForKey:(NSString *)key
314 if ([
key isEqualToString:
@"handleScale"])
316 return [
super needsDisplayForKey:key];
319- (
id<CAAction>)actionForKey:(NSString *)key
321 if ([
key isEqualToString:
@"handleScale"]) {
324 CAKeyframeAnimation *
animation = [CAKeyframeAnimation animationWithKeyPath:key];
325 [animation setDuration:0.5];
326 animation.values = @[@(0.0f), @(1.3f), @(1.3f), @(1.0f)];
327 animation.keyTimes = @[@(0.0f), @(0.3f), @(0.9f), @(1.0f)];
330 CABasicAnimation *
animation = [CABasicAnimation animationWithKeyPath:key];
331 [animation setDelegate:self];
332 animation.fromValue = [
self valueForKey:key];
333 [animation setDuration:0.2];
337 return [
super actionForKey:key];
340- (
void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
344 if (
self.onAnimationDidStop)
345 self.onAnimationDidStop();
348- (
void)setVisible:(BOOL)visible
350 if (visible == _visible)
355 self.handleScale = visible ? 1 : 0;
358- (
void)setCursorRectangle:(CGRect)cursorRect
360 if (CGRectEqualToRect(_cursorRectangle, cursorRect))
363 _cursorRectangle = cursorRect;
366 [
self setNeedsDisplay];
367 [
self displayIfNeeded];
374 CGPoint origin = _cursorRectangle.origin;
375 CGSize
size = _cursorRectangle.size;
384 _handleCursorLayer.frame = CGRectMake(cursorX, cursorY, cursorWidth,
size.height);
386 _handleCursorLayer.transform = CATransform3DMakeScale(1,
scale,
scale);
416 if (
self = [super initWithTarget:
self action:
@selector(gestureStateChanged)]) {
421 self.state = UIGestureRecognizerStateBegan;
428- (
void)setEnabled:(BOOL)enabled
433 [
super setEnabled:enabled];
436 _focusView = [reinterpret_cast<UIView *>(qApp->focusWindow()->winId()) retain];
437 _desktopView = [qt_apple_sharedApplication().keyWindow.rootViewController.view retain];
439 [_desktopView addGestureRecognizer:self];
441 [_desktopView removeGestureRecognizer:self];
442 [_desktopView release];
444 [_focusView release];
448 [_loupeLayer removeFromSuperlayer];
449 [_loupeLayer release];
455- (
void)gestureStateChanged
457 switch (
self.state) {
458 case UIGestureRecognizerStateBegan:
464 [
self updateFocalPoint:QPointF::fromCGPoint(_lastTouchPoint)];
465 _loupeLayer.visible = YES;
468 case UIGestureRecognizerStateChanged:
470 [
self updateFocalPoint:QPointF::fromCGPoint(_lastTouchPoint)];
472 case UIGestureRecognizerStateEnded:
476 _loupeLayer.visible = NO;
479 _loupeLayer.visible = NO;
488 _loupeLayer = [[
self createLoupeLayer] retain];
490 [_desktopView.superview.layer addSublayer:_loupeLayer];
495 return QPointF::fromCGPoint([_loupeLayer.targetView convertPoint:_loupeLayer.
focalPoint toView:
_focusView]);
500 _loupeLayer.focalPoint = [_loupeLayer.targetView convertPoint:point.toCGPoint() fromView:_focusView];
503- (
void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
505 [
super touchesBegan:touches withEvent:event];
508 self.state = UIGestureRecognizerStateFailed;
512 _firstTouchPoint = [static_cast<UITouch *>([touches anyObject]) locationInView:_focusView];
520 self.state = UIGestureRecognizerStateFailed;
523- (
void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
525 [
super touchesMoved:touches withEvent:event];
526 _lastTouchPoint = [static_cast<UITouch *>([touches anyObject]) locationInView:_focusView];
528 if (
self.state == UIGestureRecognizerStatePossible) {
534 if (dragDistance > startDragDistance) {
536 self.state =
self.dragTriggersGesture ? UIGestureRecognizerStateBegan : UIGestureRecognizerStateFailed;
539 self.state = UIGestureRecognizerStateChanged;
543- (
void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
545 [
super touchesEnded:touches withEvent:event];
547 _lastTouchPoint = [static_cast<UITouch *>([touches anyObject]) locationInView:_focusView];
548 self.state =
self.state == UIGestureRecognizerStatePossible ? UIGestureRecognizerStateFailed : UIGestureRecognizerStateEnded;
551- (
void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
553 [
super touchesCancelled:touches withEvent:event];
555 _lastTouchPoint = [static_cast<UITouch *>([touches anyObject]) locationInView:_focusView];
556 self.state = UIGestureRecognizerStateCancelled;
561- (BOOL)acceptTouchesBegan:(
QPointF)touchPoint
596 return [[[
QIOSLoupeLayer alloc] initWithSize:CGSizeMake(120, 120) cornerRadius:60 bottomOffset:4] autorelease];
599- (BOOL)acceptTouchesBegan:(
QPointF)touchPoint
607 self.focalPoint = touchPoint;
611 if (newCursorPos != currentCursorPos)
628 CALayer *_clipRectLayer;
644 self.delaysTouchesBegan = YES;
645 self.dragTriggersGesture = YES;
655- (
void)setEnabled:(BOOL)enabled
660 [
super setEnabled:enabled];
664 _clipRectLayer = [CALayer new];
665 _clipRectLayer.masksToBounds = YES;
666 [
self.focusView.layer addSublayer:_clipRectLayer];
674 [_clipRectLayer addSublayer:_cursorLayer];
675 [_clipRectLayer addSublayer:_anchorLayer];
688 [
self updateSelection];
696 __block CALayer *clipRectLayer = _clipRectLayer;
697 __block
int handleCount = 2;
699 if (--handleCount == 0) {
700 [clipRectLayer removeFromSuperlayer];
701 [clipRectLayer release];
726 CGSize loupeSize = CGSizeMake(123, 33);
727 CGSize arrowSize = CGSizeMake(25, 12);
728 CGFloat loupeOffset = arrowSize.height + 20;
732 CAShapeLayer *arrowLayer = [[[CAShapeLayer alloc] init] autorelease];
735 UIBezierPath *
path = [[UIBezierPath new] autorelease];
736 [path moveToPoint:CGPointMake(0, 0)];
737 [path addLineToPoint:CGPointMake(arrowSize.width / 2, arrowSize.height)];
738 [path addLineToPoint:CGPointMake(arrowSize.width, 0)];
740 arrowLayer.frame = CGRectMake((loupeSize.width - arrowSize.width) / 2, loupeSize.height - 1, arrowSize.width, arrowSize.height);
741 arrowLayer.path =
path.CGPath;
742 arrowLayer.backgroundColor = [[UIColor whiteColor] CGColor];
743 arrowLayer.strokeColor = [[UIColor lightGrayColor] CGColor];
744 arrowLayer.lineWidth = 0.75 * 2;
745 arrowLayer.fillColor = nil;
747 CAShapeLayer *
mask = [[CAShapeLayer new] autorelease];
748 mask.frame = arrowLayer.bounds;
750 arrowLayer.mask =
mask;
752 [loupeLayer addSublayer:arrowLayer];
757- (BOOL)acceptTouchesBegan:(
QPointF)touchPoint
763 const int handleRadius = 50;
766 QPointF cursorOffset =
QPointF(cursorCenter.
x() - touchPoint.
x(), cursorCenter.
y() - touchPoint.
y());
767 QPointF anchorOffset =
QPointF(anchorCenter.
x() - touchPoint.
x(), anchorCenter.
y() - touchPoint.
y());
768 double cursorDist = hypot(cursorOffset.
x(), cursorOffset.
y());
769 double anchorDist = hypot(anchorOffset.
x(), anchorOffset.
y());
771 if (cursorDist > handleRadius && anchorDist > handleRadius)
774 if (cursorDist < anchorDist) {
844 inputRect.
adjust(-margin / 2, -margin, margin / 2, margin);
867 int _cursorPosOnPress;
874 if (
self = [super initWithTarget:
self action:
@selector(gestureStateChanged)]) {
881- (
void)setEnabled:(BOOL)enabled
886 [
super setEnabled:enabled];
889 _focusView = [reinterpret_cast<UIView *>(qApp->focusWindow()->winId()) retain];
890 [_focusView addGestureRecognizer:self];
892 [_focusView removeGestureRecognizer:self];
893 [_focusView release];
898- (
void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
900 [
super touchesBegan:touches withEvent:event];
903 QPointF touchPos = QPointF::fromCGPoint([
static_cast<UITouch *
>([touches anyObject]) locationInView:
_focusView]);
904 const bool touchInsideInputArea = inputRect.
contains(touchPos);
912 self.state = UIGestureRecognizerStateFailed;
928 if (!touchInsideInputArea) {
931 self.state = UIGestureRecognizerStateFailed;
941- (
void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
946 QPointF touchPos = QPointF::fromCGPoint([
static_cast<UITouch *
>([touches anyObject]) locationInView:
_focusView]);
949 if (cursorPosOnRelease == _cursorPosOnPress) {
957 self.state = UIGestureRecognizerStateFailed;
958 dispatch_async(dispatch_get_main_queue(), ^{
965 self.state = UIGestureRecognizerStateFailed;
969 [
super touchesEnded:touches withEvent:event];
972- (
void)gestureStateChanged
974 if (
self.state != UIGestureRecognizerStateEnded)
990 , m_selectionRecognizer(
nullptr)
991 , m_openMenuOnTapRecognizer(
nullptr)
994 qWarning() <<
"text input overlays disabled in application extensions";
1007void QIOSTextInputOverlay::updateFocusObject()
1011 if (m_cursorRecognizer) {
1012 m_cursorRecognizer.enabled = NO;
1013 [m_cursorRecognizer release];
1014 m_cursorRecognizer =
nullptr;
1016 if (m_selectionRecognizer) {
1017 m_selectionRecognizer.enabled = NO;
1018 [m_selectionRecognizer release];
1019 m_selectionRecognizer =
nullptr;
1021 if (m_openMenuOnTapRecognizer) {
1022 m_openMenuOnTapRecognizer.enabled = NO;
1023 [m_openMenuOnTapRecognizer release];
1024 m_openMenuOnTapRecognizer =
nullptr;
1028 [s_editMenu release];
1033 const Qt::InputMethodHints hints = Qt::InputMethodHints(hintsVariant.
toUInt());
1052 if (inputAccepted || readOnly) {
1057 m_selectionRecognizer.enabled = YES;
1058 m_openMenuOnTapRecognizer.enabled = YES;
1061 if (inputAccepted) {
1063 m_cursorRecognizer.enabled = YES;
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
void focusObjectChanged(QObject *focusObject)
This signal is emitted when final receiver of events tied to focus is changed.
static QStyleHints * styleHints()
Returns the application's style hints.
static QInputMethod * inputMethod()
returns the input method.
static QIOSEditMenu * s_editMenu
void append(parameter_type t)
static QObjectPrivate * get(QObject *o)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
The QPlatformInputContext class abstracts the input method dependent data and composing state.
bool inputMethodAccepted() const
Returns true if current focus object supports input method events.
static QRectF anchorRectangle()
QPlatformInputContext::anchorRectangle.
static void setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos)
QPlatformInputContext::setSelectionOnFocusObject.
static QVariant queryFocusObject(Qt::InputMethodQuery query, QPointF position)
QPlatformInputContext::queryFocusObject.
static QRectF inputItemClipRectangle()
QPlatformInputContext::inputItemClipRectangle.
static QRectF cursorRectangle()
QPlatformInputContext::cursorRectangle.
static QRectF inputItemRectangle()
QPlatformInputContext::inputItemRectangle.
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
bool contains(const QRectF &r) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr QPointF center() const noexcept
Returns the center point of the rectangle.
constexpr void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
QRectF united(const QRectF &other) const noexcept
constexpr int width() const noexcept
Returns the width.
\macro QT_RESTRICTED_CAST_FROM_ASCII
int startDragTime
the time, in milliseconds, that a mouse button must be held down before a drag and drop operation wil...
int startDragDistance
the distance, in pixels, that the mouse must be moved with a button held down before a drag and drop ...
void setCursorFlashTime(int cursorFlashTime)
Sets the cursorFlashTime.
int cursorFlashTime
the text cursor's flash (blink) time in milliseconds.
void setSingleShot(bool singleShot)
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void setInterval(int msec)
void stop()
Stops the timer.
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
uint toUInt(bool *ok=nullptr) const
Returns the variant as an unsigned int if the variant has userType() \l QMetaType::UInt,...
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
struct wl_display * display
Combined button and popup list for selecting options.
static jboolean copy(JNIEnv *, jobject)
std::pair< T1, T2 > QPair
bool qt_apple_isApplicationExtension()
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static QUIView * focusView()
QTimer _triggerStateBeganTimer
static SelectionPair querySelection()
BOOL _pendingSnapshotUpdate
bool _menuShouldBeVisible
QMetaObject::Connection _clipRectConnection
int _originalCursorFlashTime
static const CGFloat kKnobWidth
CALayer * _containerLayer
CALayer * _handleKnobLayer
QMetaObject::Connection _anchorConnection
QIOSHandleLayer * _anchorLayer
QTimer _updateSelectionTimer
QIOSHandleLayer * _cursorLayer
static bool hasSelection()
static void executeBlockWithoutAnimation(Block block)
QMetaObject::Connection _cursorConnection
QPair< int, int > SelectionPair
static QPlatformInputContext * platformInputContext()
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLint GLint GLint GLint GLsizei GLsizei GLsizei GLboolean commit
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLfloat GLfloat GLfloat GLfloat h
GLsizei const GLchar *const * path
GLenum GLenum GLenum GLenum GLenum scale
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
settings setValue("DataPump/bgcolor", color)
myObject disconnect()
[26]
QItemSelection * selection
[0]