nss: upgrade to release 3.73
[LibreOffice.git] / vcl / osx / salframeview.mm
blob517998b188ead473ced8990c870ebbd55c0d9798
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
20 #include <sal/config.h>
22 #include <sal/macros.h>
23 #include <tools/helpers.hxx>
24 #include <tools/long.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/inputctx.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/window.hxx>
30 #include <vcl/commandevent.hxx>
32 #include <osx/a11yfactory.h>
33 #include <osx/salframe.h>
34 #include <osx/salframeview.h>
35 #include <osx/salinst.h>
36 #include <quartz/salgdi.h>
37 #include <quartz/utils.h>
39 #define WHEEL_EVENT_FACTOR 1.5
41 static sal_uInt16 ImplGetModifierMask( unsigned int nMask )
43     sal_uInt16 nRet = 0;
44 SAL_WNODEPRECATED_DECLARATIONS_PUSH
45         // 'NSAlternateKeyMask' is deprecated: first deprecated in macOS 10.12
46         // 'NSCommandKeyMask' is deprecated: first deprecated in macOS 10.12
47         // 'NSControlKeyMask' is deprecated: first deprecated in macOS 10.12
48         // 'NSShiftKeyMask' is deprecated: first deprecated in macOS 10.12
49     if( (nMask & NSShiftKeyMask) != 0 )
50         nRet |= KEY_SHIFT;
51     if( (nMask & NSControlKeyMask) != 0 )
52         nRet |= KEY_MOD3;
53     if( (nMask & NSAlternateKeyMask) != 0 )
54         nRet |= KEY_MOD2;
55     if( (nMask & NSCommandKeyMask) != 0 )
56         nRet |= KEY_MOD1;
57 SAL_WNODEPRECATED_DECLARATIONS_POP
58     return nRet;
61 static sal_uInt16 ImplMapCharCode( sal_Unicode aCode )
63     static sal_uInt16 aKeyCodeMap[ 128 ] =
64     {
65                     0,                0,                0,                0,                0,                0,                0,                0,
66         KEY_BACKSPACE,          KEY_TAB,       KEY_RETURN,                0,                0,       KEY_RETURN,                0,                0,
67                     0,                0,                0,                0,                0,                0,                0,                0,
68                     0,          KEY_TAB,                0,       KEY_ESCAPE,                0,                0,                0,                0,
69             KEY_SPACE,                0,                0,                0,                0,                0,                0,                0,
70                     0,                0,     KEY_MULTIPLY,          KEY_ADD,        KEY_COMMA,     KEY_SUBTRACT,        KEY_POINT,       KEY_DIVIDE,
71                 KEY_0,            KEY_1,            KEY_2,            KEY_3,            KEY_4,            KEY_5,            KEY_6,            KEY_7,
72                 KEY_8,            KEY_9,                0,                0,         KEY_LESS,        KEY_EQUAL,      KEY_GREATER,                0,
73                     0,            KEY_A,            KEY_B,            KEY_C,            KEY_D,            KEY_E,            KEY_F,            KEY_G,
74                 KEY_H,            KEY_I,            KEY_J,            KEY_K,            KEY_L,            KEY_M,            KEY_N,            KEY_O,
75                 KEY_P,            KEY_Q,            KEY_R,            KEY_S,            KEY_T,            KEY_U,            KEY_V,            KEY_W,
76                 KEY_X,            KEY_Y,            KEY_Z,                0,                0,                0,                0,                0,
77         KEY_QUOTELEFT,            KEY_A,            KEY_B,            KEY_C,            KEY_D,            KEY_E,            KEY_F,            KEY_G,
78                 KEY_H,            KEY_I,            KEY_J,            KEY_K,            KEY_L,            KEY_M,            KEY_N,            KEY_O,
79                 KEY_P,            KEY_Q,            KEY_R,            KEY_S,            KEY_T,            KEY_U,            KEY_V,            KEY_W,
80                 KEY_X,            KEY_Y,            KEY_Z,                0,                0,                0,        KEY_TILDE,    KEY_BACKSPACE
81     };
83     // Note: the mapping 0x7f should by rights be KEY_DELETE
84     // however if you press "backspace" 0x7f is reported
85     // whereas for "delete" 0xf728 gets reported
87     // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons
88     // tab alone is reported as 0x09 (as expected) but shift-tab is
89     // reported as 0x19 (end of medium)
91     static sal_uInt16 aFunctionKeyCodeMap[ 128 ] =
92     {
93             KEY_UP,         KEY_DOWN,         KEY_LEFT,        KEY_RIGHT,           KEY_F1,           KEY_F2,           KEY_F3,           KEY_F4,
94             KEY_F5,           KEY_F6,           KEY_F7,           KEY_F8,           KEY_F9,          KEY_F10,          KEY_F11,          KEY_F12,
95            KEY_F13,          KEY_F14,          KEY_F15,          KEY_F16,          KEY_F17,          KEY_F18,          KEY_F19,          KEY_F20,
96            KEY_F21,          KEY_F22,          KEY_F23,          KEY_F24,          KEY_F25,          KEY_F26,                0,                0,
97                  0,                0,                0,                0,                0,                0,                0,       KEY_INSERT,
98         KEY_DELETE,         KEY_HOME,                0,          KEY_END,        KEY_PAGEUP,    KEY_PAGEDOWN,                0,                0,
99                  0,                0,                0,                0,                 0,        KEY_MENU,                0,                0,
100                  0,                0,                0,                0,                 0,               0,                0,                0,
101                  0,                0,                0,         KEY_UNDO,        KEY_REPEAT,        KEY_FIND,         KEY_HELP,                0,
102                  0,                0,                0,                0,                 0,               0,                0,                0,
103                  0,                0,                0,                0,                 0,               0,                0,                0,
104                  0,                0,                0,                0,                 0,               0,                0,                0,
105                  0,                0,                0,                0,                 0,               0,                0,                0,
106                  0,                0,                0,                0,                 0,               0,                0,                0,
107                  0,                0,                0,                0,                 0,               0,                0,                0,
108                  0,                0,                0,                0,                 0,               0,                0,                0
109     };
111     sal_uInt16 nKeyCode = 0;
112     if( aCode < SAL_N_ELEMENTS( aKeyCodeMap)  )
113         nKeyCode = aKeyCodeMap[ aCode ];
114     else if( aCode >= 0xf700 && aCode < 0xf780 )
115         nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ];
116     return nKeyCode;
119 static sal_uInt16 ImplMapKeyCode(sal_uInt16 nKeyCode)
121     /*
122       http://stackoverflow.com/questions/2080312/where-can-i-find-a-list-of-key-codes-for-use-with-cocoas-nsevent-class/2080324#2080324
123       /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
124      */
126     static sal_uInt16 aKeyCodeMap[ 0x80 ] =
127     {
128             KEY_A,            KEY_S,            KEY_D,            KEY_F,            KEY_H,            KEY_G,            KEY_Z,            KEY_X,
129             KEY_C,            KEY_V,                0,            KEY_B,            KEY_Q,            KEY_W,            KEY_E,            KEY_R,
130             KEY_Y,            KEY_T,            KEY_1,            KEY_2,            KEY_3,            KEY_4,            KEY_6,            KEY_5,
131         KEY_EQUAL,            KEY_9,            KEY_7,     KEY_SUBTRACT,            KEY_8,            KEY_0, KEY_BRACKETRIGHT,            KEY_0,
132             KEY_U,  KEY_BRACKETLEFT,            KEY_I,            KEY_P,       KEY_RETURN,            KEY_L,            KEY_J,   KEY_QUOTERIGHT,
133             KEY_K,    KEY_SEMICOLON,                0,        KEY_COMMA,       KEY_DIVIDE,            KEY_N,            KEY_M,        KEY_POINT,
134           KEY_TAB,        KEY_SPACE,    KEY_QUOTELEFT,       KEY_DELETE,                0,       KEY_ESCAPE,                0,                0,
135                 0,     KEY_CAPSLOCK,                0,                0,                0,                0,                0,                0,
136           KEY_F17,      KEY_DECIMAL,                0,     KEY_MULTIPLY,                0,          KEY_ADD,                0,                0,
137                 0,                0,                0,       KEY_DIVIDE,       KEY_RETURN,                0,     KEY_SUBTRACT,          KEY_F18,
138           KEY_F19,        KEY_EQUAL,                0,                0,                0,                0,                0,                0,
139                 0,                0,          KEY_F20,                0,                0,                0,                0,                0,
140            KEY_F5,           KEY_F6,           KEY_F7,           KEY_F3,           KEY_F8,           KEY_F9,                0,          KEY_F11,
141                 0,          KEY_F13,          KEY_F16,          KEY_F14,                0,          KEY_F10,                0,          KEY_F12,
142                 0,          KEY_F15,         KEY_HELP,         KEY_HOME,       KEY_PAGEUP,       KEY_DELETE,           KEY_F4,          KEY_END,
143            KEY_F2,     KEY_PAGEDOWN,           KEY_F1,         KEY_LEFT,        KEY_RIGHT,         KEY_DOWN,           KEY_UP,                0
144     };
146     if (nKeyCode < SAL_N_ELEMENTS(aKeyCodeMap))
147         return aKeyCodeMap[nKeyCode];
148     return 0;
151 // store the frame the mouse last entered
152 static AquaSalFrame* s_pMouseFrame = nullptr;
153 // store the last pressed button for enter/exit events
154 // which lack that information
155 static sal_uInt16 s_nLastButton = 0;
157 static AquaSalFrame* getMouseContainerFrame()
159     AquaSalFrame* pDispatchFrame = nullptr;
160     NSArray* aWindows = [NSWindow windowNumbersWithOptions:0];
161     for(NSUInteger i = 0; i < [aWindows count] && ! pDispatchFrame; i++ )
162     {
163         NSWindow* pWin = [NSApp windowWithWindowNumber:[[aWindows objectAtIndex:i] integerValue]];
164         if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [static_cast<SalFrameWindow*>(pWin) containsMouse] )
165             pDispatchFrame = [static_cast<SalFrameWindow*>(pWin) getSalFrame];
166     }
167     return pDispatchFrame;
170 @implementation SalFrameWindow
171 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
173     mDraggingDestinationHandler = nil;
174     mpFrame = pFrame;
175     NSRect aRect = { { static_cast<CGFloat>(pFrame->maGeometry.nX), static_cast<CGFloat>(pFrame->maGeometry.nY) },
176                      { static_cast<CGFloat>(pFrame->maGeometry.nWidth), static_cast<CGFloat>(pFrame->maGeometry.nHeight) } };
177     pFrame->VCLToCocoa( aRect );
178     NSWindow* pNSWindow = [super initWithContentRect: aRect
179                                  styleMask: mpFrame->getStyleMask()
180                                  backing: NSBackingStoreBuffered
181                                  defer: Application::IsHeadlessModeEnabled()];
183     // Disallow full-screen mode on macOS >= 10.11 where it is enabled by default. We don't want it
184     // for now as it will just be confused with LibreOffice's home-grown full-screen concept, with
185     // which it has nothing to do, and one can get into all kinds of weird states by using them
186     // intermixedly.
188     // Ideally we should use the system full-screen mode and adapt the code for the home-grown thing
189     // to be in sync with that instead. (And we would then not need the button to get out of
190     // full-screen mode, as the normal way to get out of it is to either click on the green bubble
191     // again, or invoke the keyboard command again.)
193     // (Confusingly, at the moment the home-grown full-screen mode is bound to Cmd+Shift+F, which is
194     // the keyboard command normally used in apps to get in and out of the system full-screen mode.)
196     // Disabling system full-screen mode makes the green button on the title bar (on macOS >= 10.11)
197     // show a plus sign instead, and clicking it becomes identical to double-clicking the title bar,
198     // i.e. it maximizes / unmaximises the window. Sure, that state can also be confused with LO's
199     // home-grown full-screen mode. Oh well.
201     [pNSWindow setCollectionBehavior: NSWindowCollectionBehaviorFullScreenNone];
203     // Disable window restoration until we support it directly
204     [pNSWindow setRestorable: NO];
206     // tdf#137468: Restrict to 24-bit RGB as that is all that we can
207     // handle anyway. HDR is far off in the future for LibreOffice.
208     [pNSWindow setDynamicDepthLimit: NO];
209     [pNSWindow setDepthLimit: NSWindowDepthTwentyfourBitRGB];
211     return static_cast<SalFrameWindow *>(pNSWindow);
214 -(AquaSalFrame*)getSalFrame
216     return mpFrame;
219 -(void)displayIfNeeded
221     if( GetSalData() && GetSalData()->mpInstance )
222     {
223         SolarMutexGuard aGuard;
224         [super displayIfNeeded];
225     }
228 -(BOOL)containsMouse
230     // is this event actually inside that NSWindow ?
231     NSPoint aPt = [NSEvent mouseLocation];
232     NSRect aFrameRect = [self frame];
233     bool bInRect = NSPointInRect( aPt, aFrameRect );
234     return bInRect;
237 -(BOOL)canBecomeKeyWindow
239     if( (mpFrame->mnStyle &
240             ( SalFrameStyleFlags::FLOAT                 |
241               SalFrameStyleFlags::TOOLTIP               |
242               SalFrameStyleFlags::INTRO
243             )) == SalFrameStyleFlags::NONE )
244         return YES;
245     if( mpFrame->mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION )
246         return YES;
247     if( mpFrame->mbFullScreen )
248         return YES;
249     return [super canBecomeKeyWindow];
252 -(void)windowDidBecomeKey: (NSNotification*)pNotification
254     (void)pNotification;
255     SolarMutexGuard aGuard;
257     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
258     {
259         static const SalFrameStyleFlags nGuessDocument = SalFrameStyleFlags::MOVEABLE|
260                                             SalFrameStyleFlags::SIZEABLE|
261                                             SalFrameStyleFlags::CLOSEABLE;
263         if( mpFrame->mpMenu )
264             mpFrame->mpMenu->setMainMenu();
265         else if( ! mpFrame->mpParent &&
266                  ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help
267                     mpFrame->mbFullScreen ) )                               // set default menu for e.g. presentation
268         {
269             AquaSalMenu::setDefaultMenu();
270         }
271         #if 0
272         // FIXME: we should disable menus while in modal mode
273         // however from down here there is currently no reliable way to
274         // find out when to do this
275         if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) )
276             AquaSalMenu::enableMainMenu( false );
277         #endif
278         mpFrame->CallCallback( SalEvent::GetFocus, nullptr );
279         mpFrame->SendPaintEvent(); // repaint controls as active
280     }
283 -(void)windowDidResignKey: (NSNotification*)pNotification
285     (void)pNotification;
286     SolarMutexGuard aGuard;
288     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
289     {
290         mpFrame->CallCallback(SalEvent::LoseFocus, nullptr);
291         mpFrame->SendPaintEvent(); // repaint controls as inactive
292     }
295 -(void)windowDidChangeScreen: (NSNotification*)pNotification
297     (void)pNotification;
298     SolarMutexGuard aGuard;
300     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
301         mpFrame->screenParametersChanged();
304 -(void)windowDidMove: (NSNotification*)pNotification
306     (void)pNotification;
307     SolarMutexGuard aGuard;
309     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
310     {
311         mpFrame->UpdateFrameGeometry();
312         mpFrame->CallCallback( SalEvent::Move, nullptr );
313     }
316 -(void)windowDidResize: (NSNotification*)pNotification
318     (void)pNotification;
319     SolarMutexGuard aGuard;
321     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
322     {
323         mpFrame->UpdateFrameGeometry();
324         mpFrame->CallCallback( SalEvent::Resize, nullptr );
325         mpFrame->SendPaintEvent();
326     }
329 -(void)windowDidMiniaturize: (NSNotification*)pNotification
331     (void)pNotification;
332     SolarMutexGuard aGuard;
334     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
335     {
336         mpFrame->mbShown = false;
337         mpFrame->UpdateFrameGeometry();
338         mpFrame->CallCallback( SalEvent::Resize, nullptr );
339     }
342 -(void)windowDidDeminiaturize: (NSNotification*)pNotification
344     (void)pNotification;
345     SolarMutexGuard aGuard;
347     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
348     {
349         mpFrame->mbShown = true;
350         mpFrame->UpdateFrameGeometry();
351         mpFrame->CallCallback( SalEvent::Resize, nullptr );
352     }
355 -(BOOL)windowShouldClose: (NSNotification*)pNotification
357     (void)pNotification;
358     SolarMutexGuard aGuard;
360     bool bRet = true;
361     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
362     {
363         // #i84461# end possible input
364         mpFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
365         if( AquaSalFrame::isAlive( mpFrame ) )
366         {
367             mpFrame->CallCallback( SalEvent::Close, nullptr );
368             bRet = false; // application will close the window or not, AppKit shouldn't
369             AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
370             assert( pTimer );
371             pTimer->handleWindowShouldClose();
372         }
373     }
375     return bRet;
378 -(void)windowDidEnterFullScreen: (NSNotification*)pNotification
380     SolarMutexGuard aGuard;
382     if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
383         return;
384     mpFrame->mbFullScreen = true;
385     (void)pNotification;
388 -(void)windowDidExitFullScreen: (NSNotification*)pNotification
390     SolarMutexGuard aGuard;
392     if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
393         return;
394     mpFrame->mbFullScreen = false;
395     (void)pNotification;
398 -(void)dockMenuItemTriggered: (id)sender
400     (void)sender;
401     SolarMutexGuard aGuard;
403     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
404         mpFrame->ToTop( SalFrameToTop::RestoreWhenMin | SalFrameToTop::GrabFocus );
407 -(css::uno::Reference < css::accessibility::XAccessibleContext >)accessibleContext
409     return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
412 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
414   return [mDraggingDestinationHandler draggingEntered: sender];
417 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
419   return [mDraggingDestinationHandler draggingUpdated: sender];
422 -(void)draggingExited:(id <NSDraggingInfo>)sender
424   [mDraggingDestinationHandler draggingExited: sender];
427 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
429   return [mDraggingDestinationHandler prepareForDragOperation: sender];
432 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
434   return [mDraggingDestinationHandler performDragOperation: sender];
437 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
439   [mDraggingDestinationHandler concludeDragOperation: sender];
442 -(void)registerDraggingDestinationHandler:(id)theHandler
444   mDraggingDestinationHandler = theHandler;
447 -(void)unregisterDraggingDestinationHandler:(id)theHandler
449     (void)theHandler;
450     mDraggingDestinationHandler = nil;
453 @end
455 @implementation SalFrameView
456 +(void)unsetMouseFrame: (AquaSalFrame*)pFrame
458     if( pFrame == s_pMouseFrame )
459         s_pMouseFrame = nullptr;
462 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
464     if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getNSWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil)
465     {
466         mDraggingDestinationHandler = nil;
467         mpFrame = pFrame;
468         mMarkedRange = NSMakeRange(NSNotFound, 0);
469         mSelectedRange = NSMakeRange(NSNotFound, 0);
470         mpReferenceWrapper = nil;
471         mpMouseEventListener = nil;
472         mpLastSuperEvent = nil;
473     }
475     mfLastMagnifyTime = 0.0;
476     return self;
479 -(AquaSalFrame*)getSalFrame
481     return mpFrame;
484 -(void)resetCursorRects
486     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
487     {
488         // FIXME: does this leak the returned NSCursor of getCurrentCursor ?
489         const NSRect aRect = { NSZeroPoint, NSMakeSize( mpFrame->maGeometry.nWidth, mpFrame->maGeometry.nHeight) };
490         [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()];
491     }
494 -(BOOL)acceptsFirstResponder
496     return YES;
499 -(BOOL)acceptsFirstMouse: (NSEvent*)pEvent
501     (void)pEvent;
502     return YES;
505 -(BOOL)isOpaque
507     if( !mpFrame)
508         return YES;
509     if( !AquaSalFrame::isAlive( mpFrame))
510         return YES;
511     if( !mpFrame->getClipPath())
512         return YES;
513     return NO;
516 -(void)drawRect: (NSRect)aRect
518     AquaSalInstance *pInstance = GetSalData()->mpInstance;
519     assert(pInstance);
520     if (!pInstance)
521         return;
523     SolarMutexGuard aGuard;
524     if (!mpFrame || !AquaSalFrame::isAlive(mpFrame))
525         return;
527     const bool bIsLiveResize = [self inLiveResize];
528     const bool bWasLiveResize = pInstance->mbIsLiveResize;
529     if (bWasLiveResize != bIsLiveResize)
530     {
531         pInstance->mbIsLiveResize = bIsLiveResize;
532         Scheduler::ProcessTaskScheduling();
533     }
535     AquaSalGraphics* pGraphics = mpFrame->mpGraphics;
536     if (pGraphics)
537     {
538         pGraphics->UpdateWindow(aRect);
539         if (mpFrame->getClipPath())
540             [mpFrame->getNSWindow() invalidateShadow];
541     }
544 -(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(SalEvent)nEvent
546     SolarMutexGuard aGuard;
548     AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
549     bool bIsCaptured = false;
550     if( pDispatchFrame )
551     {
552         bIsCaptured = true;
553         if( nEvent == SalEvent::MouseLeave ) // no leave events if mouse is captured
554             nEvent = SalEvent::MouseMove;
555     }
556     else if( s_pMouseFrame )
557         pDispatchFrame = s_pMouseFrame;
558     else
559         pDispatchFrame = mpFrame;
561     /* #i81645# Cocoa reports mouse events while a button is pressed
562        to the window in which it was first pressed. This is reasonable and fine and
563        gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
564        however vcl expects mouse events to occur in the window the mouse is over, unless the
565        mouse is explicitly captured. So we need to find the window the mouse is actually
566        over for conformance with other platforms.
567     */
568     if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
569     {
570         // is this event actually inside that NSWindow ?
571         NSPoint aPt = [NSEvent mouseLocation];
572         NSRect aFrameRect = [pDispatchFrame->getNSWindow() frame];
574         if ( ! NSPointInRect( aPt, aFrameRect ) )
575         {
576             // no, it is not
577             // now we need to find the one it may be in
578             /* #i93756# we ant to get enumerate the application windows in z-order
579                to check if any contains the mouse. This could be elegantly done with this
580                code:
582                // use NSApp to check windows in ZOrder whether they contain the mouse pointer
583                NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
584                if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
585                    pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
587                However if a non SalFrameWindow is on screen (like e.g. the file dialog)
588                it can be hit with the containsMouse selector, which it doesn't support.
589                Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
590                I assume) whether a window supports a selector before sending it.
591             */
592             AquaSalFrame* pMouseFrame = getMouseContainerFrame();
593             if( pMouseFrame )
594                 pDispatchFrame = pMouseFrame;
595         }
596     }
598     if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
599     {
600         pDispatchFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
601         pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
603         NSPoint aPt = [NSEvent mouseLocation];
604         pDispatchFrame->CocoaToVCL( aPt );
606         sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
607         // #i82284# emulate ctrl left
608         if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
609         {
610             nModMask    = 0;
611             nButton     = MOUSE_RIGHT;
612         }
614         SalMouseEvent aEvent;
615         aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
616         aEvent.mnX      = static_cast<tools::Long>(aPt.x) - pDispatchFrame->maGeometry.nX;
617         aEvent.mnY      = static_cast<tools::Long>(aPt.y) - pDispatchFrame->maGeometry.nY;
618         aEvent.mnButton = nButton;
619         aEvent.mnCode   =  aEvent.mnButton | nModMask;
621         if( AllSettings::GetLayoutRTL() )
622             aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
624         pDispatchFrame->CallCallback( nEvent, &aEvent );
625     }
628 -(void)mouseDown: (NSEvent*)pEvent
630     if ( mpMouseEventListener != nil &&
631         [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
632     {
633         [mpMouseEventListener mouseDown: [pEvent copyWithZone: nullptr]];
634     }
636     s_nLastButton = MOUSE_LEFT;
637     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SalEvent::MouseButtonDown];
640 -(void)mouseDragged: (NSEvent*)pEvent
642     if ( mpMouseEventListener != nil &&
643          [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
644     {
645         [mpMouseEventListener mouseDragged: [pEvent copyWithZone: nullptr]];
646     }
647     s_nLastButton = MOUSE_LEFT;
648     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SalEvent::MouseMove];
651 -(void)mouseUp: (NSEvent*)pEvent
653     s_nLastButton = 0;
654     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SalEvent::MouseButtonUp];
657 -(void)mouseMoved: (NSEvent*)pEvent
659     s_nLastButton = 0;
660     [self sendMouseEventToFrame:pEvent button:0 eventtype:SalEvent::MouseMove];
663 -(void)mouseEntered: (NSEvent*)pEvent
665     s_pMouseFrame = mpFrame;
667     // #i107215# the only mouse events we get when inactive are enter/exit
668     // actually we would like to have all of them, but better none than some
669     if( [NSApp isActive] )
670         [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SalEvent::MouseMove];
673 -(void)mouseExited: (NSEvent*)pEvent
675     if( s_pMouseFrame == mpFrame )
676         s_pMouseFrame = nullptr;
678     // #i107215# the only mouse events we get when inactive are enter/exit
679     // actually we would like to have all of them, but better none than some
680     if( [NSApp isActive] )
681         [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SalEvent::MouseLeave];
684 -(void)rightMouseDown: (NSEvent*)pEvent
686     s_nLastButton = MOUSE_RIGHT;
687     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SalEvent::MouseButtonDown];
690 -(void)rightMouseDragged: (NSEvent*)pEvent
692     s_nLastButton = MOUSE_RIGHT;
693     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SalEvent::MouseMove];
696 -(void)rightMouseUp: (NSEvent*)pEvent
698     s_nLastButton = 0;
699     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SalEvent::MouseButtonUp];
702 -(void)otherMouseDown: (NSEvent*)pEvent
704     if( [pEvent buttonNumber] == 2 )
705     {
706         s_nLastButton = MOUSE_MIDDLE;
707         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SalEvent::MouseButtonDown];
708     }
709     else
710         s_nLastButton = 0;
713 -(void)otherMouseDragged: (NSEvent*)pEvent
715     if( [pEvent buttonNumber] == 2 )
716     {
717         s_nLastButton = MOUSE_MIDDLE;
718         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SalEvent::MouseMove];
719     }
720     else
721         s_nLastButton = 0;
724 -(void)otherMouseUp: (NSEvent*)pEvent
726     s_nLastButton = 0;
727     if( [pEvent buttonNumber] == 2 )
728         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SalEvent::MouseButtonUp];
731 - (void)magnifyWithEvent: (NSEvent*)pEvent
733     SolarMutexGuard aGuard;
735     // TODO: ??  -(float)magnification;
736     if( AquaSalFrame::isAlive( mpFrame ) )
737     {
738         const NSTimeInterval fMagnifyTime = [pEvent timestamp];
739         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( fMagnifyTime * 1000.0 );
740         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
742         // check if this is a new series of magnify events
743         static const NSTimeInterval fMaxDiffTime = 0.3;
744         const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime);
746         if( bNewSeries )
747             mfMagnifyDeltaSum = 0.0;
748         mfMagnifyDeltaSum += [pEvent magnification];
750         mfLastMagnifyTime = [pEvent timestamp];
751 // TODO: change to 0.1 when CommandWheelMode::ZOOM handlers allow finer zooming control
752         static const float fMagnifyFactor = 0.25*500; // steps are 500 times smaller for -magnification
753         static const float fMinMagnifyStep = 15.0 / fMagnifyFactor;
754         if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep )
755             return;
757         // adapt NSEvent-sensitivity to application expectations
758         // TODO: rather make CommandWheelMode::ZOOM handlers smarter
759         const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor;
760         int nDeltaZ = FRound( fDeltaZ );
761         if( !nDeltaZ )
762         {
763             // handle new series immediately
764             if( !bNewSeries )
765                 return;
766             nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1;
767         }
768         // eventually give credit for delta sum
769         mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor;
771         NSPoint aPt = [NSEvent mouseLocation];
772         mpFrame->CocoaToVCL( aPt );
774         SalWheelMouseEvent aEvent;
775         aEvent.mnTime           = mpFrame->mnLastEventTime;
776         aEvent.mnX              = static_cast<tools::Long>(aPt.x) - mpFrame->maGeometry.nX;
777         aEvent.mnY              = static_cast<tools::Long>(aPt.y) - mpFrame->maGeometry.nY;
778         aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
779         aEvent.mnCode           |= KEY_MOD1; // we want zooming, no scrolling
780         aEvent.mbDeltaIsPixel   = true;
782         if( AllSettings::GetLayoutRTL() )
783             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
785         aEvent.mnDelta = nDeltaZ;
786         aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1;
787         if( aEvent.mnDelta == 0 )
788             aEvent.mnDelta = aEvent.mnNotchDelta;
789         aEvent.mbHorz = false;
790         sal_uInt32 nScrollLines = nDeltaZ;
791         if (nScrollLines == 0)
792             nScrollLines = 1;
793         aEvent.mnScrollLines = nScrollLines;
794         mpFrame->CallCallback( SalEvent::WheelMouse, &aEvent );
795     }
798 - (void)rotateWithEvent: (NSEvent*)pEvent
800     //Rotation : -(float)rotation;
801     // TODO: create new CommandType so rotation is available to the applications
802     (void)pEvent;
805 - (void)swipeWithEvent: (NSEvent*)pEvent
807     SolarMutexGuard aGuard;
809     if( AquaSalFrame::isAlive( mpFrame ) )
810     {
811         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
812         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
814         // merge pending scroll wheel events
815         CGFloat dX = 0.0;
816         CGFloat dY = 0.0;
817         for(;;)
818         {
819             dX += [pEvent deltaX];
820             dY += [pEvent deltaY];
821 SAL_WNODEPRECATED_DECLARATIONS_PUSH
822     // 'NSScrollWheelMask' is deprecated: first deprecated in macOS 10.12
823             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
824 SAL_WNODEPRECATED_DECLARATIONS_POP
825             untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
826             if( !pNextEvent )
827                 break;
828             pEvent = pNextEvent;
829         }
831         NSPoint aPt = [NSEvent mouseLocation];
832         mpFrame->CocoaToVCL( aPt );
834         SalWheelMouseEvent aEvent;
835         aEvent.mnTime           = mpFrame->mnLastEventTime;
836         aEvent.mnX              = static_cast<tools::Long>(aPt.x) - mpFrame->maGeometry.nX;
837         aEvent.mnY              = static_cast<tools::Long>(aPt.y) - mpFrame->maGeometry.nY;
838         aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
839         aEvent.mbDeltaIsPixel   = true;
841         if( AllSettings::GetLayoutRTL() )
842             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
844         if( dX != 0.0 )
845         {
846             aEvent.mnDelta = static_cast<tools::Long>(floor(dX));
847             aEvent.mnNotchDelta = (dX < 0) ? -1 : +1;
848             if( aEvent.mnDelta == 0 )
849                 aEvent.mnDelta = aEvent.mnNotchDelta;
850             aEvent.mbHorz = true;
851             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
852             mpFrame->CallCallback( SalEvent::WheelMouse, &aEvent );
853         }
854         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
855         {
856             aEvent.mnDelta = static_cast<tools::Long>(floor(dY));
857             aEvent.mnNotchDelta = (dY < 0) ? -1 : +1;
858             if( aEvent.mnDelta == 0 )
859                 aEvent.mnDelta = aEvent.mnNotchDelta;
860             aEvent.mbHorz = false;
861             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
862             mpFrame->CallCallback( SalEvent::WheelMouse, &aEvent );
863         }
864     }
867 -(void)scrollWheel: (NSEvent*)pEvent
869     SolarMutexGuard aGuard;
871     if( AquaSalFrame::isAlive( mpFrame ) )
872     {
873         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
874         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
876         // merge pending scroll wheel events
877         CGFloat dX = 0.0;
878         CGFloat dY = 0.0;
879         for(;;)
880         {
881             dX += [pEvent deltaX];
882             dY += [pEvent deltaY];
883 SAL_WNODEPRECATED_DECLARATIONS_PUSH
884     // 'NSScrollWheelMask' is deprecated: first deprecated in macOS 10.12
885             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
886 SAL_WNODEPRECATED_DECLARATIONS_POP
887                 untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
888             if( !pNextEvent )
889                 break;
890             pEvent = pNextEvent;
891         }
893         NSPoint aPt = [NSEvent mouseLocation];
894         mpFrame->CocoaToVCL( aPt );
896         SalWheelMouseEvent aEvent;
897         aEvent.mnTime         = mpFrame->mnLastEventTime;
898         aEvent.mnX            = static_cast<tools::Long>(aPt.x) - mpFrame->maGeometry.nX;
899         aEvent.mnY            = static_cast<tools::Long>(aPt.y) - mpFrame->maGeometry.nY;
900         aEvent.mnCode         = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
901         aEvent.mbDeltaIsPixel = false;
903         if( AllSettings::GetLayoutRTL() )
904             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
906         if( dX != 0.0 )
907         {
908             aEvent.mnDelta = static_cast<tools::Long>(floor(dX));
909             aEvent.mnNotchDelta = (dX < 0) ? -1 : +1;
910             if( aEvent.mnDelta == 0 )
911                 aEvent.mnDelta = aEvent.mnNotchDelta;
912             aEvent.mbHorz = true;
913             sal_uInt32 nScrollLines = fabs(dX) / WHEEL_EVENT_FACTOR;
914             if (nScrollLines == 0)
915                 nScrollLines = 1;
916             aEvent.mnScrollLines = nScrollLines;
918             mpFrame->CallCallback( SalEvent::WheelMouse, &aEvent );
919         }
920         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
921         {
922             aEvent.mnDelta = static_cast<tools::Long>(floor(dY));
923             aEvent.mnNotchDelta = (dY < 0) ? -1 : +1;
924             if( aEvent.mnDelta == 0 )
925                 aEvent.mnDelta = aEvent.mnNotchDelta;
926             aEvent.mbHorz = false;
927             sal_uInt32 nScrollLines = fabs(dY) / WHEEL_EVENT_FACTOR;
928             if (nScrollLines == 0)
929                 nScrollLines = 1;
930             aEvent.mnScrollLines = nScrollLines;
932             mpFrame->CallCallback( SalEvent::WheelMouse, &aEvent );
933         }
934     }
938 -(void)keyDown: (NSEvent*)pEvent
940     SolarMutexGuard aGuard;
942     if( AquaSalFrame::isAlive( mpFrame ) )
943     {
944         mpLastEvent = pEvent;
945         mbInKeyInput = true;
946         mbNeedSpecialKeyHandle = false;
947         mbKeyHandled = false;
949         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
950         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
952         if( ! [self handleKeyDownException: pEvent] )
953         {
954             NSArray* pArray = [NSArray arrayWithObject: pEvent];
955             [self interpretKeyEvents: pArray];
956         }
958         mbInKeyInput = false;
959     }
962 -(BOOL)handleKeyDownException:(NSEvent*)pEvent
964     // check for a very special set of modified characters
965     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
967     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
968     {
969         /* #i103102# key events with command and alternate don't make it through
970            interpretKeyEvents (why?). Try to dispatch them here first,
971            if not successful continue normally
972         */
973 SAL_WNODEPRECATED_DECLARATIONS_PUSH
974     // 'NSAlternateKeyMask' is deprecated: first deprecated in macOS 10.12
975     // 'NSCommandKeyMask' is deprecated: first deprecated in macOS 10.12
976         if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
977                     == (NSAlternateKeyMask | NSCommandKeyMask) )
978 SAL_WNODEPRECATED_DECLARATIONS_POP
979         {
980             if( [self sendSingleCharacter: mpLastEvent] )
981                 return YES;
982         }
983     }
984     return NO;
987 -(void)flagsChanged: (NSEvent*)pEvent
989     SolarMutexGuard aGuard;
991     if( AquaSalFrame::isAlive( mpFrame ) )
992     {
993         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
994         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
995     }
998 -(void)insertText:(id)aString replacementRange:(NSRange)replacementRange
1000     (void) replacementRange; // FIXME: surely it must be used
1002     SolarMutexGuard aGuard;
1004     if( AquaSalFrame::isAlive( mpFrame ) )
1005     {
1006         NSString* pInsert = nil;
1007         if( [aString isMemberOfClass: [NSAttributedString class]] )
1008             pInsert = [aString string];
1009         else
1010             pInsert = aString;
1012         int nLen = 0;
1013         if( pInsert && ( nLen = [pInsert length] ) > 0 )
1014         {
1015             OUString aInsertString( GetOUString( pInsert ) );
1016              // aCharCode initializer is safe since aInsertString will at least contain '\0'
1017             sal_Unicode aCharCode = *aInsertString.getStr();
1019             if( nLen == 1 &&
1020                 aCharCode < 0x80 &&
1021                 aCharCode > 0x1f &&
1022                 ! [self hasMarkedText ]
1023                 )
1024             {
1025                 sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode );
1026                 unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
1028                 // #i99567#
1029                 // find out the unmodified key code
1031 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1032     // 'NSAlternateKeyMask' is deprecated: first deprecated in macOS 10.12
1033     // 'NSCommandKeyMask' is deprecated: first deprecated in macOS 10.12
1034     // 'NSControlKeyMask' is deprecated: first deprecated in macOS 10.12
1035     // 'NSKeyDown' is deprecated: first deprecated in macOS 10.12
1036     // 'NSKeyUp' is deprecated: first deprecated in macOS 10.12
1037                 // sanity check
1038                 if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
1039                 {
1040                     // get unmodified string
1041                     NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers];
1042                     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1043                     {
1044                         // map the unmodified key code
1045                         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1046                         nKeyCode = ImplMapCharCode( keyChar );
1047                     }
1048                     nLastModifiers = [mpLastEvent modifierFlags];
1050                 }
1051                 // #i99567#
1052                 // applications and vcl's edit fields ignore key events with ALT
1053                 // however we're at a place where we know text should be inserted
1054                 // so it seems we need to strip the Alt modifier here
1055                 if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
1056                     == NSAlternateKeyMask )
1057                 {
1058                     nLastModifiers = 0;
1059                 }
1060 SAL_WNODEPRECATED_DECLARATIONS_POP
1061                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
1062             }
1063             else
1064             {
1065                 SalExtTextInputEvent aEvent;
1066                 aEvent.maText           = aInsertString;
1067                 aEvent.mpTextAttr       = nullptr;
1068                 aEvent.mnCursorPos      = aInsertString.getLength();
1069                 aEvent.mnCursorFlags    = 0;
1070                 mpFrame->CallCallback( SalEvent::ExtTextInput, &aEvent );
1071                 if( AquaSalFrame::isAlive( mpFrame ) )
1072                     mpFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
1073             }
1074         }
1075         else
1076         {
1077             SalExtTextInputEvent aEvent;
1078             aEvent.maText.clear();
1079             aEvent.mpTextAttr       = nullptr;
1080             aEvent.mnCursorPos      = 0;
1081             aEvent.mnCursorFlags    = 0;
1082             mpFrame->CallCallback( SalEvent::ExtTextInput, &aEvent );
1083             if( AquaSalFrame::isAlive( mpFrame ) )
1084                 mpFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
1086         }
1087         mbKeyHandled = true;
1088         [self unmarkText];
1089     }
1092 -(void)insertTab: (id)aSender
1094     (void)aSender;
1095     [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
1098 -(void)insertBacktab: (id)aSender
1100     (void)aSender;
1101     [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
1104 -(void)moveLeft: (id)aSender
1106     (void)aSender;
1107     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
1110 -(void)moveLeftAndModifySelection: (id)aSender
1112     (void)aSender;
1113 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1114         // 'NSShiftKeyMask' is deprecated: first deprecated in macOS 10.12
1115     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
1116 SAL_WNODEPRECATED_DECLARATIONS_POP
1119 -(void)moveBackwardAndModifySelection: (id)aSender
1121     (void)aSender;
1122     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1125 -(void)moveRight: (id)aSender
1127     (void)aSender;
1128     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1131 -(void)moveRightAndModifySelection: (id)aSender
1133     (void)aSender;
1134 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1135         // 'NSShiftKeyMask' is deprecated: first deprecated in macOS 10.12
1136     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1137 SAL_WNODEPRECATED_DECLARATIONS_POP
1140 -(void)moveForwardAndModifySelection: (id)aSender
1142     (void)aSender;
1143     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1146 -(void)moveWordLeft: (id)aSender
1148     (void)aSender;
1149     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1152 -(void)moveWordBackward: (id)aSender
1154     (void)aSender;
1155     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1158 -(void)moveWordBackwardAndModifySelection: (id)aSender
1160     (void)aSender;
1161     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1164 -(void)moveWordLeftAndModifySelection: (id)aSender
1166     (void)aSender;
1167     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1170 -(void)moveWordRight: (id)aSender
1172     (void)aSender;
1173     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1176 -(void)moveWordForward: (id)aSender
1178     (void)aSender;
1179     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1182 -(void)moveWordForwardAndModifySelection: (id)aSender
1184     (void)aSender;
1185     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1188 -(void)moveWordRightAndModifySelection: (id)aSender
1190     (void)aSender;
1191     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1194 -(void)moveToEndOfLine: (id)aSender
1196     (void)aSender;
1197     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1200 -(void)moveToRightEndOfLine: (id)aSender
1202     (void)aSender;
1203     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1206 -(void)moveToEndOfLineAndModifySelection: (id)aSender
1208     (void)aSender;
1209     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1212 -(void)moveToRightEndOfLineAndModifySelection: (id)aSender
1214     (void)aSender;
1215     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1218 -(void)moveToBeginningOfLine: (id)aSender
1220     (void)aSender;
1221     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1224 -(void)moveToLeftEndOfLine: (id)aSender
1226     (void)aSender;
1227     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1230 -(void)moveToBeginningOfLineAndModifySelection: (id)aSender
1232     (void)aSender;
1233     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1236 -(void)moveToLeftEndOfLineAndModifySelection: (id)aSender
1238     (void)aSender;
1239     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1242 -(void)moveToEndOfParagraph: (id)aSender
1244     (void)aSender;
1245     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1248 -(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1250     (void)aSender;
1251     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1254 -(void)moveParagraphForward: (id)aSender
1256     (void)aSender;
1257     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1260 -(void)moveParagraphForwardAndModifySelection: (id)aSender
1262     (void)aSender;
1263     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1266 -(void)moveToBeginningOfParagraph: (id)aSender
1268     (void)aSender;
1269     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1272 -(void)moveParagraphBackward: (id)aSender
1274     (void)aSender;
1275     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1278 -(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender
1280     (void)aSender;
1281     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1284 -(void)moveParagraphBackwardAndModifySelection: (id)aSender
1286     (void)aSender;
1287     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1290 -(void)moveToEndOfDocument: (id)aSender
1292     (void)aSender;
1293     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1296 -(void)scrollToEndOfDocument: (id)aSender
1298     (void)aSender;
1299     // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent
1300     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1303 -(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1305     (void)aSender;
1306     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1309 -(void)moveToBeginningOfDocument: (id)aSender
1311     (void)aSender;
1312     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1315 -(void)scrollToBeginningOfDocument: (id)aSender
1317     (void)aSender;
1318     // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent
1319     [self sendKeyInputAndReleaseToFrame: css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1322 -(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1324     (void)aSender;
1325     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1328 -(void)moveUp: (id)aSender
1330     (void)aSender;
1331     [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1334 -(void)moveDown: (id)aSender
1336     (void)aSender;
1337     [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1340 -(void)insertNewline: (id)aSender
1342     (void)aSender;
1343     // #i91267# make enter and shift-enter work by evaluating the modifiers
1344     [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1347 -(void)deleteBackward: (id)aSender
1349     (void)aSender;
1350     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1353 -(void)deleteForward: (id)aSender
1355     (void)aSender;
1356     [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1359 -(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1361     (void)aSender;
1362     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1365 -(void)deleteWordBackward: (id)aSender
1367     (void)aSender;
1368     [self sendKeyInputAndReleaseToFrame: css::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1371 -(void)deleteWordForward: (id)aSender
1373     (void)aSender;
1374     [self sendKeyInputAndReleaseToFrame: css::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1377 -(void)deleteToBeginningOfLine: (id)aSender
1379     (void)aSender;
1380     [self sendKeyInputAndReleaseToFrame: css::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1383 -(void)deleteToEndOfLine: (id)aSender
1385     (void)aSender;
1386     [self sendKeyInputAndReleaseToFrame: css::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1389 -(void)deleteToBeginningOfParagraph: (id)aSender
1391     (void)aSender;
1392     [self sendKeyInputAndReleaseToFrame: css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1395 -(void)deleteToEndOfParagraph: (id)aSender
1397     (void)aSender;
1398     [self sendKeyInputAndReleaseToFrame: css::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1401 -(void)insertLineBreak: (id)aSender
1403     (void)aSender;
1404     [self sendKeyInputAndReleaseToFrame: css::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1407 -(void)insertParagraphSeparator: (id)aSender
1409     (void)aSender;
1410     [self sendKeyInputAndReleaseToFrame: css::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1413 -(void)selectWord: (id)aSender
1415     (void)aSender;
1416     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1419 -(void)selectLine: (id)aSender
1421     (void)aSender;
1422     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1425 -(void)selectParagraph: (id)aSender
1427     (void)aSender;
1428     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1431 -(void)selectAll: (id)aSender
1433     (void)aSender;
1434     [self sendKeyInputAndReleaseToFrame: css::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1437 -(void)cancelOperation: (id)aSender
1439     (void)aSender;
1440     [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1443 -(void)noop: (id)aSender
1445     (void)aSender;
1446     if( ! mbKeyHandled )
1447     {
1448         if( ! [self sendSingleCharacter:mpLastEvent] )
1449         {
1450             /* prevent recursion */
1451             if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1452             {
1453                 id pLastSuperEvent = mpLastSuperEvent;
1454                 mpLastSuperEvent = mpLastEvent;
1455                 [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1456                 mpLastSuperEvent = pLastSuperEvent;
1458                 std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1459                 if( it != GetSalData()->maKeyEventAnswer.end() )
1460                     it->second = true;
1461             }
1462         }
1463     }
1466 -(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar
1468     return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1471 -(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1473     return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1474            [self sendSingleCharacter: mpLastEvent];
1477 -(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1479     SolarMutexGuard aGuard;
1481     bool nRet = false;
1482     if( AquaSalFrame::isAlive( mpFrame ) )
1483     {
1484         SalKeyEvent aEvent;
1485         aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1486         aEvent.mnCharCode       = aChar;
1487         aEvent.mnRepeat         = FALSE;
1488         nRet = mpFrame->CallCallback( SalEvent::KeyInput, &aEvent );
1489         std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1490         if( it != GetSalData()->maKeyEventAnswer.end() )
1491             it->second = nRet;
1492         if( AquaSalFrame::isAlive( mpFrame ) )
1493             mpFrame->CallCallback( SalEvent::KeyUp, &aEvent );
1494     }
1495     return nRet;
1499 -(BOOL)sendSingleCharacter: (NSEvent *)pEvent
1501     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
1503     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1504     {
1505         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1506         sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
1507         if (nKeyCode == 0)
1508         {
1509             sal_uInt16 nOtherKeyCode = [pEvent keyCode];
1510             nKeyCode = ImplMapKeyCode(nOtherKeyCode);
1511         }
1512         if( nKeyCode != 0 )
1513         {
1514             // don't send code points in the private use area
1515             if( keyChar >= 0xf700 && keyChar < 0xf780 )
1516                 keyChar = 0;
1517             bool bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1518             mbInKeyInput = false;
1520             return bRet;
1521         }
1522     }
1523     return NO;
1527 // NSTextInput/NSTextInputClient protocol
1528 - (NSArray *)validAttributesForMarkedText
1530     return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1533 - (BOOL)hasMarkedText
1535     bool bHasMarkedText;
1537     bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1538                      ( mMarkedRange.length != 0 );
1539     // hack to check keys like "Control-j"
1540     if( mbInKeyInput )
1541     {
1542         mbNeedSpecialKeyHandle = true;
1543     }
1545     // FIXME:
1546     // #i106901#
1547     // if we come here outside of mbInKeyInput, this is likely to be because
1548     // of the keyboard viewer. For unknown reasons having no marked range
1549     // in this case causes a crash. So we say we have a marked range anyway
1550     // This is a hack, since it is not understood what a) causes that crash
1551     // and b) why we should have a marked range at this point.
1552     if( ! mbInKeyInput )
1553         bHasMarkedText = true;
1555     return bHasMarkedText;
1558 - (NSRange)markedRange
1560     // FIXME:
1561     // #i106901#
1562     // if we come here outside of mbInKeyInput, this is likely to be because
1563     // of the keyboard viewer. For unknown reasons having no marked range
1564     // in this case causes a crash. So we say we have a marked range anyway
1565     // This is a hack, since it is not understood what a) causes that crash
1566     // and b) why we should have a marked range at this point.
1567     if( ! mbInKeyInput )
1568         return NSMakeRange( 0, 0 );
1570     return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1573 - (NSRange)selectedRange
1575     return mSelectedRange;
1578 - (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange replacementRange:(NSRange)replacementRange
1580     (void) replacementRange; // FIXME - use it!
1582     SolarMutexGuard aGuard;
1584     if( ![aString isKindOfClass:[NSAttributedString class]] )
1585         aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1586     NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1587     if( rangeToReplace.location == NSNotFound )
1588     {
1589         mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1590         mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1591     }
1592     else
1593     {
1594         mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1595         mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1596     }
1598     int len = [aString length];
1599     SalExtTextInputEvent aInputEvent;
1600     if( len > 0 ) {
1601         NSString *pString = [aString string];
1602         OUString aInsertString( GetOUString( pString ) );
1603         std::vector<ExtTextInputAttr> aInputFlags( std::max( 1, len ), ExtTextInputAttr::NONE );
1604         for ( int i = 0; i < len; i++ )
1605         {
1606             unsigned int nUnderlineValue;
1607             NSRange effectiveRange;
1609             effectiveRange = NSMakeRange(i, 1);
1610             nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1612             switch (nUnderlineValue & 0xff) {
1613             case NSUnderlineStyleSingle:
1614                 aInputFlags[i] = ExtTextInputAttr::Underline;
1615                 break;
1616             case NSUnderlineStyleThick:
1617                 aInputFlags[i] = ExtTextInputAttr::Underline | ExtTextInputAttr::Highlight;
1618                 break;
1619             case NSUnderlineStyleDouble:
1620                 aInputFlags[i] = ExtTextInputAttr::BoldUnderline;
1621                 break;
1622             default:
1623                 aInputFlags[i] = ExtTextInputAttr::Highlight;
1624                 break;
1625             }
1626         }
1628         aInputEvent.maText = aInsertString;
1629         aInputEvent.mnCursorPos = selRange.location;
1630         aInputEvent.mpTextAttr = aInputFlags.data();
1631         mpFrame->CallCallback( SalEvent::ExtTextInput, static_cast<void *>(&aInputEvent) );
1632     } else {
1633         aInputEvent.maText.clear();
1634         aInputEvent.mnCursorPos = 0;
1635         aInputEvent.mnCursorFlags = 0;
1636         aInputEvent.mpTextAttr = nullptr;
1637         mpFrame->CallCallback( SalEvent::ExtTextInput, static_cast<void *>(&aInputEvent) );
1638         mpFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
1639     }
1640     mbKeyHandled= true;
1643 - (void)unmarkText
1645     mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1648 - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
1650     (void) aRange;
1651     (void) actualRange;
1653     // FIXME - Implement
1654     return nil;
1657 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
1659     (void)thePoint;
1660     // FIXME
1661     return 0;
1664 - (NSInteger)conversationIdentifier
1666     return reinterpret_cast<long>(self);
1669 - (void)doCommandBySelector:(SEL)aSelector
1671     if( AquaSalFrame::isAlive( mpFrame ) )
1672     {
1673         if( (mpFrame->mnICOptions & InputContextFlags::Text) &&
1674             aSelector != nullptr && [self respondsToSelector: aSelector] )
1675         {
1676             [self performSelector: aSelector];
1677         }
1678         else
1679         {
1680             [self sendSingleCharacter:mpLastEvent];
1681         }
1682     }
1684     mbKeyHandled = true;
1687 -(void)clearLastEvent
1689     mpLastEvent = nil;
1692 - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
1694      // FIXME - These should probably be used?
1695     (void) aRange;
1696     (void) actualRange;
1698     SolarMutexGuard aGuard;
1700     SalExtTextInputPosEvent aPosEvent;
1701     mpFrame->CallCallback( SalEvent::ExtTextInputPos, static_cast<void *>(&aPosEvent) );
1703     NSRect rect;
1705     rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1706     rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1707     rect.size.width = aPosEvent.mnWidth;
1708     rect.size.height = aPosEvent.mnHeight;
1710     mpFrame->VCLToCocoa( rect );
1711     return rect;
1714 -(id)parentAttribute {
1715     return reinterpret_cast<NSView*>(mpFrame->getNSWindow());
1716         //TODO: odd cast really needed for fdo#74121?
1719 -(css::accessibility::XAccessibleContext *)accessibleContext
1721     if ( !mpReferenceWrapper ) {
1722         // some frames never become visible ..
1723         vcl::Window *pWindow = mpFrame -> GetWindow();
1724         if ( ! pWindow )
1725             return nil;
1727         mpReferenceWrapper = new ReferenceWrapper;
1728         mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1729         [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1730     }
1731     return [ super accessibleContext ];
1734 -(NSWindow*)windowForParent
1736     return mpFrame->getNSWindow();
1739 -(void)registerMouseEventListener: (id)theListener
1741   mpMouseEventListener = theListener;
1744 -(void)unregisterMouseEventListener: (id)theListener
1746     (void)theListener;
1747     mpMouseEventListener = nil;
1750 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1752   return [mDraggingDestinationHandler draggingEntered: sender];
1755 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1757   return [mDraggingDestinationHandler draggingUpdated: sender];
1760 -(void)draggingExited:(id <NSDraggingInfo>)sender
1762   [mDraggingDestinationHandler draggingExited: sender];
1765 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1767   return [mDraggingDestinationHandler prepareForDragOperation: sender];
1770 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
1772   return [mDraggingDestinationHandler performDragOperation: sender];
1775 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1777   [mDraggingDestinationHandler concludeDragOperation: sender];
1780 -(void)registerDraggingDestinationHandler:(id)theHandler
1782   mDraggingDestinationHandler = theHandler;
1785 -(void)unregisterDraggingDestinationHandler:(id)theHandler
1787     (void)theHandler;
1788     mDraggingDestinationHandler = nil;
1791 @end
1793 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */