1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements.  See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership.  The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License.  You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied.  See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23// MARKER(update_precomp.py): autogen include statement, do not remove
24#include "precompiled_vcl.hxx"
25
26#include <sal/alloca.h>
27
28#include "vcl/window.hxx"
29#include "vcl/svapp.hxx"
30
31#include "aqua/salinst.h"
32#include "aqua/salgdi.h"
33#include "aqua/salframe.h"
34#include "aqua/salframeview.h"
35#include "aqua/aqua11yfactory.h"
36
37#define WHEEL_EVENT_FACTOR 1.5
38
39
40static sal_uInt16 ImplGetModifierMask( unsigned int nMask )
41{
42    sal_uInt16 nRet = 0;
43    if( (nMask & NSShiftKeyMask) != 0 )
44        nRet |= KEY_SHIFT;
45    if( (nMask & NSControlKeyMask) != 0 )
46        nRet |= KEY_MOD3;
47    if( (nMask & NSAlternateKeyMask) != 0 )
48        nRet |= KEY_MOD2;
49    if( (nMask & NSCommandKeyMask) != 0 )
50        nRet |= KEY_MOD1;
51    return nRet;
52}
53
54static sal_uInt16 ImplMapCharCode( sal_Unicode aCode )
55{
56    static sal_uInt16 aKeyCodeMap[ 128 ] =
57    {
58        0, 0, 0, 0, 0, 0, 0, 0,
59        KEY_BACKSPACE, KEY_TAB, KEY_RETURN, 0, 0, KEY_RETURN, 0, 0,
60        0, 0, 0, 0, 0, 0, 0, 0,
61        0, KEY_TAB, 0, KEY_ESCAPE, 0, 0, 0, 0,
62        KEY_SPACE, 0, 0, 0, 0, 0, 0, 0,
63        0, 0, KEY_MULTIPLY, KEY_ADD, KEY_COMMA, KEY_SUBTRACT, KEY_POINT, KEY_DIVIDE,
64        KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
65        KEY_8, KEY_9, 0, 0, KEY_LESS, KEY_EQUAL, KEY_GREATER, 0,
66        0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
67        KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
68        KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
69        KEY_X, KEY_Y, KEY_Z, 0, 0, 0, 0, 0,
70        KEY_QUOTELEFT, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
71        KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
72        KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
73        KEY_X, KEY_Y, KEY_Z, 0, 0, 0, KEY_TILDE, KEY_BACKSPACE
74    };
75
76    // Note: the mapping 0x7f should by rights be KEY_DELETE
77    // however if you press "backspace" 0x7f is reported
78    // whereas for "delete" 0xf728 gets reported
79
80    // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons
81    // tab alone is reported as 0x09 (as expected) but shift-tab is
82    // reported as 0x19 (end of medium)
83
84    static sal_uInt16 aFunctionKeyCodeMap[ 128 ] =
85    {
86        KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4,
87        KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,
88        KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
89        KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_F25, KEY_F26, 0, 0,
90        0, 0, 0, 0, 0, 0, 0, KEY_INSERT,
91        KEY_DELETE, KEY_HOME, 0, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN, 0, 0,
92        0, 0, 0, 0, 0, KEY_MENU, 0, 0,
93        0, 0, 0, 0, 0, 0, 0, 0,
94        0, 0, 0, KEY_UNDO, KEY_REPEAT, KEY_FIND, KEY_HELP, 0,
95        0, 0, 0, 0, 0, 0, 0, 0,
96        0, 0, 0, 0, 0, 0, 0, 0,
97        0, 0, 0, 0, 0, 0, 0, 0,
98        0, 0, 0, 0, 0, 0, 0, 0,
99        0, 0, 0, 0, 0, 0, 0, 0,
100        0, 0, 0, 0, 0, 0, 0, 0,
101        0, 0, 0, 0, 0, 0, 0, 0
102    };
103
104    sal_uInt16 nKeyCode = 0;
105    if( aCode < sizeof( aKeyCodeMap) / sizeof( aKeyCodeMap[0] ) )
106        nKeyCode = aKeyCodeMap[ aCode ];
107    else if( aCode >= 0xf700 && aCode < 0xf780 )
108        nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ];
109    return nKeyCode;
110}
111
112// store the frame the mouse last entered
113static AquaSalFrame* s_pMouseFrame = NULL;
114// store the last pressed button for enter/exit events
115// which lack that information
116static sal_uInt16 s_nLastButton = 0;
117
118// combinations of keys we need to handle ourselves
119static const struct ExceptionalKey
120{
121    const sal_uInt16        nKeyCode;
122    const unsigned int  nModifierMask;
123} aExceptionalKeys[] =
124{
125    { KEY_D, NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask },
126    { KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask }
127};
128
129static AquaSalFrame* getMouseContainerFrame()
130{
131    NSInteger nWindows = 0;
132    NSCountWindows( &nWindows );
133    NSInteger* pWindows = (NSInteger*)alloca( nWindows * sizeof(NSInteger) );
134    // note: NSWindowList is supposed to be in z-order front to back
135    NSWindowList( nWindows, pWindows );
136    AquaSalFrame* pDispatchFrame = NULL;
137    for(int i = 0; i < nWindows && ! pDispatchFrame; i++ )
138    {
139        NSWindow* pWin = [NSApp windowWithWindowNumber: pWindows[i]];
140        if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] )
141            pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame];
142    }
143    return pDispatchFrame;
144}
145
146@implementation SalFrameWindow
147-(id)initWithSalFrame: (AquaSalFrame*)pFrame
148{
149	mDraggingDestinationHandler = nil;
150    mpFrame = pFrame;
151    NSRect aRect = NSMakeRect( pFrame->maGeometry.nX, pFrame->maGeometry.nY,
152                     pFrame->maGeometry.nWidth, pFrame->maGeometry.nHeight);
153    pFrame->VCLToCocoa( aRect );
154    NSWindow* pNSWindow = [super initWithContentRect: aRect styleMask: mpFrame->getStyleMask() backing: NSBackingStoreBuffered defer: NO ];
155    [pNSWindow useOptimizedDrawing: YES]; // OSX recommendation when there are no overlapping subviews within the receiver
156
157    // enable OSX>=10.7 fullscreen options if available and useful
158    bool bAllowFullScreen = (0 == (mpFrame->mnStyle & (SAL_FRAME_STYLE_DIALOG | SAL_FRAME_STYLE_TOOLTIP | SAL_FRAME_STYLE_SYSTEMCHILD | SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_TOOLWINDOW | SAL_FRAME_STYLE_INTRO)));
159    bAllowFullScreen &= (0 == (~mpFrame->mnStyle & (SAL_FRAME_STYLE_SIZEABLE)));
160    bAllowFullScreen &= (mpFrame->mpParent == NULL);
161    const SEL setCollectionBehavior = @selector(setCollectionBehavior:);
162    if( bAllowFullScreen && [pNSWindow respondsToSelector: setCollectionBehavior])
163    {
164        const int bMode= (bAllowFullScreen ? NSWindowCollectionBehaviorFullScreenPrimary : NSWindowCollectionBehaviorFullScreenAuxiliary);
165        [pNSWindow performSelector:setCollectionBehavior withObject:(id)bMode];
166    }
167
168    // disable OSX>=10.7 window restoration until we support it directly
169    const SEL setRestorable = @selector(setRestorable:);
170    if( [pNSWindow respondsToSelector: setRestorable]) {
171        [pNSWindow performSelector:setRestorable withObject:(id)NO];
172    }
173
174    return (SalFrameWindow*)pNSWindow;
175}
176
177-(AquaSalFrame*)getSalFrame
178{
179    return mpFrame;
180}
181
182-(void)displayIfNeeded
183{
184    if( GetSalData() && GetSalData()->mpFirstInstance )
185    {
186        vos::IMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex();
187        if( pMutex )
188        {
189            pMutex->acquire();
190            [super displayIfNeeded];
191            pMutex->release();
192        }
193    }
194}
195
196-(BOOL)containsMouse
197{
198    // is this event actually inside that NSWindow ?
199    NSPoint aPt = [NSEvent mouseLocation];
200    NSRect aFrameRect = [self frame];
201    BOOL bInRect = NSPointInRect( aPt, aFrameRect );
202    return bInRect;
203}
204
205-(BOOL)canBecomeKeyWindow
206{
207    if( (mpFrame->mnStyle &
208            ( SAL_FRAME_STYLE_FLOAT                 |
209              SAL_FRAME_STYLE_TOOLTIP               |
210              SAL_FRAME_STYLE_INTRO
211            )) == 0 )
212        return YES;
213    if( (mpFrame->mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) != 0 )
214        return YES;
215    if( mpFrame->mbFullScreen )
216        return YES;
217    if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
218        return YES;
219    return [super canBecomeKeyWindow];
220}
221
222-(void)windowDidBecomeKey: (NSNotification*)pNotification
223{
224    (void)pNotification;
225    YIELD_GUARD;
226
227    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
228    {
229        static const sal_uLong nGuessDocument = SAL_FRAME_STYLE_MOVEABLE|
230                                            SAL_FRAME_STYLE_SIZEABLE|
231                                            SAL_FRAME_STYLE_CLOSEABLE;
232
233        if( mpFrame->mpMenu )
234            mpFrame->mpMenu->setMainMenu();
235        else if( ! mpFrame->mpParent &&
236                 ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help
237                    mpFrame->mbFullScreen ) )                               // ser default menu for e.g. presentation
238        {
239            AquaSalMenu::setDefaultMenu();
240        }
241        #if 0
242        // FIXME: we should disable menus while in modal mode
243        // however from down here there is currently no reliable way to
244        // find out when to do this
245        if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) )
246            AquaSalMenu::enableMainMenu( false );
247        #endif
248        mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
249        mpFrame->SendPaintEvent(); // repaint controls as active
250    }
251}
252
253-(void)windowDidResignKey: (NSNotification*)pNotification
254{
255    (void)pNotification;
256    YIELD_GUARD;
257
258    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
259    {
260        mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0);
261        mpFrame->SendPaintEvent(); // repaint controls as inactive
262    }
263}
264
265-(void)windowDidChangeScreen: (NSNotification*)pNotification
266{
267    (void)pNotification;
268    YIELD_GUARD;
269
270    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
271        mpFrame->screenParametersChanged();
272}
273
274-(void)windowDidMove: (NSNotification*)pNotification
275{
276    (void)pNotification;
277    YIELD_GUARD;
278
279    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
280    {
281        mpFrame->UpdateFrameGeometry();
282        mpFrame->CallCallback( SALEVENT_MOVE, 0 );
283    }
284}
285
286-(void)windowDidResize: (NSNotification*)pNotification
287{
288    (void)pNotification;
289    YIELD_GUARD;
290
291    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
292    {
293        mpFrame->UpdateFrameGeometry();
294        mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
295        mpFrame->SendPaintEvent();
296    }
297}
298
299-(void)windowDidMiniaturize: (NSNotification*)pNotification
300{
301    (void)pNotification;
302    YIELD_GUARD;
303
304    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
305    {
306        mpFrame->mbShown = false;
307        mpFrame->UpdateFrameGeometry();
308        mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
309    }
310}
311
312-(void)windowDidDeminiaturize: (NSNotification*)pNotification
313{
314    (void)pNotification;
315    YIELD_GUARD;
316
317    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
318    {
319        mpFrame->mbShown = true;
320        mpFrame->UpdateFrameGeometry();
321        mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
322    }
323}
324
325-(BOOL)windowShouldClose: (NSNotification*)pNotification
326{
327    (void)pNotification;
328    YIELD_GUARD;
329
330    BOOL bRet = YES;
331    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
332    {
333        // #i84461# end possible input
334        mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
335        if( AquaSalFrame::isAlive( mpFrame ) )
336        {
337            mpFrame->CallCallback( SALEVENT_CLOSE, 0 );
338            bRet = NO; // application will close the window or not, AppKit shouldn't
339        }
340    }
341
342    return bRet;
343}
344
345-(void)windowDidEnterFullScreen: (NSNotification*)pNotification
346{
347    YIELD_GUARD;
348
349    if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
350        return;
351    mpFrame->mbFullScreen = true;
352    (void)pNotification;
353}
354
355-(void)windowDidExitFullScreen: (NSNotification*)pNotification
356{
357    YIELD_GUARD;
358
359    if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
360        return;
361    mpFrame->mbFullScreen = false;
362    (void)pNotification;
363}
364
365-(void)dockMenuItemTriggered: (id)sender
366{
367    (void)sender;
368    YIELD_GUARD;
369
370    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
371        mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS );
372}
373
374-(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext
375{
376    return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
377}
378
379-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
380{
381  return [mDraggingDestinationHandler draggingEntered: sender];
382}
383
384-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
385{
386  return [mDraggingDestinationHandler draggingUpdated: sender];
387}
388
389-(void)draggingExited:(id <NSDraggingInfo>)sender
390{
391  [mDraggingDestinationHandler draggingExited: sender];
392}
393
394-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
395{
396  return [mDraggingDestinationHandler prepareForDragOperation: sender];
397}
398
399-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
400{
401  return [mDraggingDestinationHandler performDragOperation: sender];
402}
403
404-(void)concludeDragOperation:(id <NSDraggingInfo>)sender
405{
406  [mDraggingDestinationHandler concludeDragOperation: sender];
407}
408
409-(void)registerDraggingDestinationHandler:(id)theHandler
410{
411  mDraggingDestinationHandler = theHandler;
412}
413
414-(void)unregisterDraggingDestinationHandler:(id)theHandler
415{
416    (void)theHandler;
417    mDraggingDestinationHandler = nil;
418}
419
420@end
421
422@implementation SalFrameView
423+(void)unsetMouseFrame: (AquaSalFrame*)pFrame
424{
425    if( pFrame == s_pMouseFrame )
426        s_pMouseFrame = NULL;
427}
428
429-(id)initWithSalFrame: (AquaSalFrame*)pFrame
430{
431    if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getNSWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil)
432    {
433        mDraggingDestinationHandler = nil;
434        mpFrame = pFrame;
435        mMarkedRange = NSMakeRange(NSNotFound, 0);
436        mSelectedRange = NSMakeRange(NSNotFound, 0);
437        mpReferenceWrapper = nil;
438		mpMouseEventListener = nil;
439        mpLastSuperEvent = nil;
440    }
441
442    mfLastMagnifyTime = 0.0;
443    return self;
444}
445
446-(AquaSalFrame*)getSalFrame
447{
448    return mpFrame;
449}
450
451-(void)resetCursorRects
452{
453    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
454    {
455        // FIXME: does this leak the returned NSCursor of getCurrentCursor ?
456        const NSRect aRect = { NSZeroPoint, NSMakeSize( mpFrame->maGeometry.nWidth, mpFrame->maGeometry.nHeight) };
457        [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()];
458    }
459}
460
461-(BOOL)acceptsFirstResponder
462{
463    return YES;
464}
465
466-(BOOL)acceptsFirstMouse: (NSEvent*)pEvent
467{
468    (void)pEvent;
469    return YES;
470}
471
472-(BOOL)isOpaque
473{
474	if( !mpFrame)
475		return YES;
476	if( !AquaSalFrame::isAlive( mpFrame))
477		return YES;
478	if( !mpFrame->getClipPath())
479		return YES;
480	return NO;
481}
482
483// helper class similar to a vos::OGuard for the SalYieldMutex
484// the difference is that it only does tryToAcquire instead of acquire
485// so dreaded deadlocks like #i93512# are prevented
486class TryGuard
487{
488public:
489			TryGuard()  { mbGuarded = ImplSalYieldMutexTryToAcquire(); }
490			~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); }
491	bool	IsGuarded() { return mbGuarded; }
492private:
493	bool	mbGuarded;
494};
495
496-(void)drawRect: (NSRect)aRect
497{
498	// HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
499	TryGuard aTryGuard;
500	if( !aTryGuard.IsGuarded() )
501	{
502		// NOTE: the mpFrame access below is not guarded yet!
503		// TODO: mpFrame et al need to be guarded by an independent mutex
504		AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL;
505		if( pGraphics )
506		{
507			// we did not get the mutex so we cannot draw now => request to redraw later
508			// convert the NSRect to a CGRect for Refreshrect()
509			const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}};
510			pGraphics->RefreshRect( aCGRect );
511		}
512		return;
513	}
514
515    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
516    {
517        if( mpFrame->mpGraphics )
518        {
519            mpFrame->mpGraphics->UpdateWindow( aRect );
520            if( mpFrame->getClipPath() )
521                [mpFrame->getNSWindow() invalidateShadow];
522        }
523    }
524}
525
526-(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent
527{
528    YIELD_GUARD;
529
530    AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
531    bool bIsCaptured = false;
532    if( pDispatchFrame )
533    {
534        bIsCaptured = true;
535        if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured
536            nEvent = SALEVENT_MOUSEMOVE;
537    }
538    else if( s_pMouseFrame )
539        pDispatchFrame = s_pMouseFrame;
540    else
541        pDispatchFrame = mpFrame;
542
543    /* #i81645# Cocoa reports mouse events while a button is pressed
544       to the window in which it was first pressed. This is reasonable and fine and
545       gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
546       however vcl expects mouse events to occur in the window the mouse is over, unless the
547       mouse is explicitly captured. So we need to find the window the mouse is actually
548       over for conformance with other platforms.
549    */
550    if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
551    {
552        // is this event actually inside that NSWindow ?
553        NSPoint aPt = [NSEvent mouseLocation];
554        NSRect aFrameRect = [pDispatchFrame->getNSWindow() frame];
555
556	if ( ! NSPointInRect( aPt, aFrameRect ) )
557        {
558            // no, it is not
559            // now we need to find the one it may be in
560            /* #i93756# we ant to get enumerate the application windows in z-order
561               to check if any contains the mouse. This could be elegantly done with this
562               code:
563
564               // use NSApp to check windows in ZOrder whether they contain the mouse pointer
565               NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
566               if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
567                   pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
568
569               However if a non SalFrameWindow is on screen (like e.g. the file dialog)
570               it can be hit with the containsMouse selector, which it doesn't support.
571               Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
572               I assume) whether a window supports a selector before sending it.
573            */
574            AquaSalFrame* pMouseFrame = getMouseContainerFrame();
575            if( pMouseFrame )
576                pDispatchFrame = pMouseFrame;
577        }
578    }
579
580    if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
581    {
582        pDispatchFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
583        pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
584
585        NSPoint aPt = [NSEvent mouseLocation];
586        pDispatchFrame->CocoaToVCL( aPt );
587
588        sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
589        // #i82284# emulate ctrl left
590        if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
591        {
592            nModMask    = 0;
593            nButton     = MOUSE_RIGHT;
594        }
595
596        SalMouseEvent aEvent;
597        aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
598        aEvent.mnX      = static_cast<long>(aPt.x) - pDispatchFrame->maGeometry.nX;
599        aEvent.mnY      = static_cast<long>(aPt.y) - pDispatchFrame->maGeometry.nY;
600        aEvent.mnButton = nButton;
601        aEvent.mnCode   =  aEvent.mnButton | nModMask;
602
603        // --- RTL --- (mirror mouse pos)
604        if( Application::GetSettings().GetLayoutRTL() )
605            aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
606
607        pDispatchFrame->CallCallback( nEvent, &aEvent );
608    }
609}
610
611-(void)mouseDown: (NSEvent*)pEvent
612{
613    if ( mpMouseEventListener != nil &&
614	    [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
615	{
616	    [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]];
617	}
618
619    s_nLastButton = MOUSE_LEFT;
620    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN];
621}
622
623-(void)mouseDragged: (NSEvent*)pEvent
624{
625    if ( mpMouseEventListener != nil &&
626	     [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
627	{
628	    [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]];
629	}
630    s_nLastButton = MOUSE_LEFT;
631    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE];
632}
633
634-(void)mouseUp: (NSEvent*)pEvent
635{
636    s_nLastButton = 0;
637    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP];
638}
639
640-(void)mouseMoved: (NSEvent*)pEvent
641{
642    s_nLastButton = 0;
643    [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE];
644}
645
646-(void)mouseEntered: (NSEvent*)pEvent
647{
648    s_pMouseFrame = mpFrame;
649
650    // #i107215# the only mouse events we get when inactive are enter/exit
651    // actually we would like to have all of them, but better none than some
652    if( [NSApp isActive] )
653        [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE];
654}
655
656-(void)mouseExited: (NSEvent*)pEvent
657{
658    if( s_pMouseFrame == mpFrame )
659        s_pMouseFrame = NULL;
660
661    // #i107215# the only mouse events we get when inactive are enter/exit
662    // actually we would like to have all of them, but better none than some
663    if( [NSApp isActive] )
664        [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE];
665}
666
667-(void)rightMouseDown: (NSEvent*)pEvent
668{
669    s_nLastButton = MOUSE_RIGHT;
670    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN];
671}
672
673-(void)rightMouseDragged: (NSEvent*)pEvent
674{
675    s_nLastButton = MOUSE_RIGHT;
676    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE];
677}
678
679-(void)rightMouseUp: (NSEvent*)pEvent
680{
681    s_nLastButton = 0;
682    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP];
683}
684
685-(void)otherMouseDown: (NSEvent*)pEvent
686{
687    if( [pEvent buttonNumber] == 2 )
688    {
689        s_nLastButton = MOUSE_MIDDLE;
690        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN];
691    }
692    else
693        s_nLastButton = 0;
694}
695
696-(void)otherMouseDragged: (NSEvent*)pEvent
697{
698    if( [pEvent buttonNumber] == 2 )
699    {
700        s_nLastButton = MOUSE_MIDDLE;
701        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE];
702    }
703    else
704        s_nLastButton = 0;
705}
706
707-(void)otherMouseUp: (NSEvent*)pEvent
708{
709    s_nLastButton = 0;
710    if( [pEvent buttonNumber] == 2 )
711        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP];
712}
713
714- (void)magnifyWithEvent: (NSEvent*)pEvent
715{
716    YIELD_GUARD;
717
718    // TODO: ??  -(float)magnification;
719    if( AquaSalFrame::isAlive( mpFrame ) )
720	{
721		const NSTimeInterval fMagnifyTime = [pEvent timestamp];
722        mpFrame->mnLastEventTime = static_cast<sal_uLong>( fMagnifyTime * 1000.0 );
723        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
724
725        // check if this is a new series of magnify events
726        static const NSTimeInterval fMaxDiffTime = 0.3;
727        const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime);
728
729        if( bNewSeries )
730            mfMagnifyDeltaSum = 0.0;
731        mfMagnifyDeltaSum += [pEvent deltaZ];
732
733		mfLastMagnifyTime = [pEvent timestamp];
734		// TODO: change to 0.1 when COMMAND_WHEEL_ZOOM handlers allow finer zooming control
735		static const float fMagnifyFactor = 0.25;
736        static const float fMinMagnifyStep = 15.0 / fMagnifyFactor;
737        if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep )
738            return;
739
740        // adapt NSEvent-sensitivity to application expectations
741        // TODO: rather make COMMAND_WHEEL_ZOOM handlers smarter
742        const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor;
743        int nDeltaZ = FRound( fDeltaZ );
744        if( !nDeltaZ )
745        {
746            // handle new series immediately
747            if( !bNewSeries )
748                return;
749            nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1;
750        }
751        // eventually give credit for delta sum
752        mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor;
753
754        NSPoint aPt = [NSEvent mouseLocation];
755        mpFrame->CocoaToVCL( aPt );
756
757        SalWheelMouseEvent aEvent;
758        aEvent.mnTime           = mpFrame->mnLastEventTime;
759        aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
760        aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
761        aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
762        aEvent.mnCode           |= KEY_MOD1; // we want zooming, no scrolling
763        aEvent.mbDeltaIsPixel   = TRUE;
764
765        // --- RTL --- (mirror mouse pos)
766        if( Application::GetSettings().GetLayoutRTL() )
767            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
768
769        aEvent.mnDelta = nDeltaZ;
770        aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1;
771        if( aEvent.mnDelta == 0 )
772            aEvent.mnDelta = aEvent.mnNotchDelta;
773        aEvent.mbHorz = FALSE;
774        aEvent.mnScrollLines = nDeltaZ;
775        if( aEvent.mnScrollLines == 0 )
776            aEvent.mnScrollLines = 1;
777        mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
778    }
779}
780
781- (void)rotateWithEvent: (NSEvent*)pEvent
782{
783    //Rotation : -(float)rotation;
784    // TODO: create new CommandType so rotation is available to the applications
785    (void)pEvent;
786}
787
788- (void)swipeWithEvent: (NSEvent*)pEvent
789{
790    YIELD_GUARD;
791
792    if( AquaSalFrame::isAlive( mpFrame ) )
793    {
794        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
795        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
796
797        // merge pending scroll wheel events
798        CGFloat dX = 0.0;
799        CGFloat dY = 0.0;
800        for(;;)
801        {
802            dX += [pEvent deltaX];
803            dY += [pEvent deltaY];
804            NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
805            untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
806            if( !pNextEvent )
807                break;
808            pEvent = pNextEvent;
809        }
810
811        NSPoint aPt = [NSEvent mouseLocation];
812        mpFrame->CocoaToVCL( aPt );
813
814        SalWheelMouseEvent aEvent;
815        aEvent.mnTime           = mpFrame->mnLastEventTime;
816        aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
817        aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
818        aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
819        aEvent.mbDeltaIsPixel   = TRUE;
820
821        // --- RTL --- (mirror mouse pos)
822        if( Application::GetSettings().GetLayoutRTL() )
823            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
824
825        if( dX != 0.0 )
826        {
827            aEvent.mnDelta = static_cast<long>(floor(dX));
828            aEvent.mnNotchDelta = (dX < 0) ? -1 : +1;
829            if( aEvent.mnDelta == 0 )
830                aEvent.mnDelta = aEvent.mnNotchDelta;
831            aEvent.mbHorz = TRUE;
832            aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
833            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
834        }
835        if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
836        {
837            aEvent.mnDelta = static_cast<long>(floor(dY));
838            aEvent.mnNotchDelta = (dY < 0) ? -1 : +1;
839            if( aEvent.mnDelta == 0 )
840                aEvent.mnDelta = aEvent.mnNotchDelta;
841            aEvent.mbHorz = FALSE;
842            aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
843            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
844        }
845    }
846}
847
848-(void)scrollWheel: (NSEvent*)pEvent
849{
850    YIELD_GUARD;
851
852    if( AquaSalFrame::isAlive( mpFrame ) )
853    {
854        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
855        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
856
857        // merge pending scroll wheel events
858        CGFloat dX = 0.0;
859        CGFloat dY = 0.0;
860        for(;;)
861        {
862            dX += [pEvent deltaX];
863    	    dY += [pEvent deltaY];
864            NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
865                untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
866            if( !pNextEvent )
867                break;
868            pEvent = pNextEvent;
869        }
870
871        NSPoint aPt = [NSEvent mouseLocation];
872        mpFrame->CocoaToVCL( aPt );
873
874        SalWheelMouseEvent aEvent;
875        aEvent.mnTime         = mpFrame->mnLastEventTime;
876        aEvent.mnX            = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
877        aEvent.mnY            = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
878        aEvent.mnCode         = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
879        aEvent.mbDeltaIsPixel = TRUE;
880
881        // --- RTL --- (mirror mouse pos)
882        if( Application::GetSettings().GetLayoutRTL() )
883            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
884
885        if( dX != 0.0 )
886        {
887            aEvent.mnDelta = static_cast<long>(floor(dX));
888            aEvent.mnNotchDelta = (dX < 0) ? -1 : +1;
889            if( aEvent.mnDelta == 0 )
890                aEvent.mnDelta = aEvent.mnNotchDelta;
891            aEvent.mbHorz = TRUE;
892            aEvent.mnScrollLines = fabs(dX) / WHEEL_EVENT_FACTOR;
893            if( aEvent.mnScrollLines == 0 )
894                aEvent.mnScrollLines = 1;
895
896            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
897        }
898        if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
899        {
900            aEvent.mnDelta = static_cast<long>(floor(dY));
901            aEvent.mnNotchDelta = (dY < 0) ? -1 : +1;
902            if( aEvent.mnDelta == 0 )
903                aEvent.mnDelta = aEvent.mnNotchDelta;
904            aEvent.mbHorz = FALSE;
905            aEvent.mnScrollLines = fabs(dY) / WHEEL_EVENT_FACTOR;
906            if( aEvent.mnScrollLines == 0 )
907                aEvent.mnScrollLines = 1;
908
909            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
910        }
911    }
912}
913
914
915-(void)keyDown: (NSEvent*)pEvent
916{
917    YIELD_GUARD;
918
919    if( AquaSalFrame::isAlive( mpFrame ) )
920    {
921        mpLastEvent = pEvent;
922        mbInKeyInput = true;
923        mbNeedSpecialKeyHandle = false;
924        mbKeyHandled = false;
925
926        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
927        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
928
929        if( ! [self handleKeyDownException: pEvent] )
930        {
931            NSArray* pArray = [NSArray arrayWithObject: pEvent];
932            [self interpretKeyEvents: pArray];
933        }
934
935        mbInKeyInput = false;
936    }
937}
938
939-(BOOL)handleKeyDownException:(NSEvent*)pEvent
940{
941    // check for a very special set of modified characters
942    NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
943
944    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
945    {
946        /* #i103102# key events with command and alternate don't make it through
947           interpretKeyEvents (why ?). Try to dispatch them here first,
948           if not successful continue normally
949        */
950        if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
951                    == (NSAlternateKeyMask | NSCommandKeyMask) )
952        {
953            if( [self sendSingleCharacter: mpLastEvent] )
954                return YES;
955        }
956        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
957        sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
958
959        // Caution: should the table grow to more than 5 or 6 entries,
960        // we must consider moving it to a kind of hash map
961        const unsigned int nExceptions = sizeof( aExceptionalKeys ) / sizeof( aExceptionalKeys[0] );
962        for( unsigned int i = 0; i < nExceptions; i++ )
963        {
964            if( nKeyCode == aExceptionalKeys[i].nKeyCode &&
965                (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask)
966                == aExceptionalKeys[i].nModifierMask )
967            {
968                [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0];
969
970                return YES;
971            }
972        }
973    }
974    return NO;
975}
976
977-(void)flagsChanged: (NSEvent*)pEvent
978{
979    YIELD_GUARD;
980
981    if( AquaSalFrame::isAlive( mpFrame ) )
982    {
983        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
984        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
985    }
986}
987
988-(void)insertText:(id)aString
989{
990    YIELD_GUARD;
991
992    if( AquaSalFrame::isAlive( mpFrame ) )
993    {
994        NSString* pInsert = nil;
995        if( [aString isMemberOfClass: [NSAttributedString class]] )
996            pInsert = [aString string];
997        else
998            pInsert = aString;
999
1000        int nLen = 0;
1001        if( pInsert && ( nLen = [pInsert length] ) > 0 )
1002        {
1003            OUString aInsertString( GetOUString( pInsert ) );
1004             // aCharCode initializer is safe since aInsertString will at least contain '\0'
1005            sal_Unicode aCharCode = *aInsertString.getStr();
1006
1007            if( nLen == 1 &&
1008                aCharCode < 0x80 &&
1009                aCharCode > 0x1f &&
1010				! [self hasMarkedText ]
1011                )
1012            {
1013                sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode );
1014                unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
1015
1016                // #i99567#
1017                // find out the unmodified key code
1018
1019                // sanity check
1020                if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
1021                {
1022                    // get unmodified string
1023                    NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers];
1024                    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1025                    {
1026                        // map the unmodified key code
1027                        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1028                        nKeyCode = ImplMapCharCode( keyChar );
1029                    }
1030                    nLastModifiers = [mpLastEvent modifierFlags];
1031
1032                }
1033                // #i99567#
1034                // applications and vcl's edit fields ignore key events with ALT
1035                // however we're at a place where we know text should be inserted
1036                // so it seems we need to strip the Alt modifier here
1037                if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
1038                    == NSAlternateKeyMask )
1039                {
1040                    nLastModifiers = 0;
1041                }
1042                [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
1043            }
1044            else
1045            {
1046                SalExtTextInputEvent aEvent;
1047                aEvent.mnTime           = mpFrame->mnLastEventTime;
1048                aEvent.maText           = aInsertString;
1049                aEvent.mpTextAttr       = NULL;
1050                aEvent.mnCursorPos      = aInsertString.getLength();
1051                aEvent.mnDeltaStart     = 0;
1052                aEvent.mnCursorFlags    = 0;
1053                aEvent.mbOnlyCursor     = FALSE;
1054                mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1055                if( AquaSalFrame::isAlive( mpFrame ) )
1056                    mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1057            }
1058        }
1059        else
1060        {
1061            SalExtTextInputEvent aEvent;
1062            aEvent.mnTime           = mpFrame->mnLastEventTime;
1063            aEvent.maText           = String();
1064            aEvent.mpTextAttr       = NULL;
1065            aEvent.mnCursorPos      = 0;
1066            aEvent.mnDeltaStart     = 0;
1067            aEvent.mnCursorFlags    = 0;
1068            aEvent.mbOnlyCursor     = FALSE;
1069            mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1070            if( AquaSalFrame::isAlive( mpFrame ) )
1071                mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1072
1073        }
1074        mbKeyHandled = true;
1075        [self unmarkText];
1076    }
1077}
1078
1079-(void)insertTab: (id)aSender
1080{
1081    (void)aSender;
1082    [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
1083}
1084
1085-(void)insertBacktab: (id)aSender
1086{
1087    (void)aSender;
1088    [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
1089}
1090
1091-(void)moveLeft: (id)aSender
1092{
1093    (void)aSender;
1094    [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
1095}
1096
1097-(void)moveLeftAndModifySelection: (id)aSender
1098{
1099    (void)aSender;
1100    [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
1101}
1102
1103-(void)moveBackwardAndModifySelection: (id)aSender
1104{
1105    (void)aSender;
1106    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1107}
1108
1109-(void)moveRight: (id)aSender
1110{
1111    (void)aSender;
1112    [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1113}
1114
1115-(void)moveRightAndModifySelection: (id)aSender
1116{
1117    (void)aSender;
1118    [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1119}
1120
1121-(void)moveForwardAndModifySelection: (id)aSender
1122{
1123    (void)aSender;
1124    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1125}
1126
1127-(void)moveWordLeft: (id)aSender
1128{
1129    (void)aSender;
1130    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1131}
1132
1133-(void)moveWordBackward: (id)aSender
1134{
1135    (void)aSender;
1136    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1137}
1138
1139-(void)moveWordBackwardAndModifySelection: (id)aSender
1140{
1141    (void)aSender;
1142    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1143}
1144
1145-(void)moveWordLeftAndModifySelection: (id)aSender
1146{
1147    (void)aSender;
1148    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1149}
1150
1151-(void)moveWordRight: (id)aSender
1152{
1153    (void)aSender;
1154    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1155}
1156
1157-(void)moveWordForward: (id)aSender
1158{
1159    (void)aSender;
1160    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1161}
1162
1163-(void)moveWordForwardAndModifySelection: (id)aSender
1164{
1165    (void)aSender;
1166    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1167}
1168
1169-(void)moveWordRightAndModifySelection: (id)aSender
1170{
1171    (void)aSender;
1172    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1173}
1174
1175-(void)moveToEndOfLine: (id)aSender
1176{
1177    (void)aSender;
1178    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1179}
1180
1181-(void)moveToRightEndOfLine: (id)aSender
1182{
1183    (void)aSender;
1184    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1185}
1186
1187-(void)moveToEndOfLineAndModifySelection: (id)aSender
1188{
1189    (void)aSender;
1190    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1191}
1192
1193-(void)moveToRightEndOfLineAndModifySelection: (id)aSender
1194{
1195    (void)aSender;
1196    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1197}
1198
1199-(void)moveToBeginningOfLine: (id)aSender
1200{
1201    (void)aSender;
1202    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1203}
1204
1205-(void)moveToLeftEndOfLine: (id)aSender
1206{
1207    (void)aSender;
1208    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1209}
1210
1211-(void)moveToBeginningOfLineAndModifySelection: (id)aSender
1212{
1213    (void)aSender;
1214    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1215}
1216
1217-(void)moveToLeftEndOfLineAndModifySelection: (id)aSender
1218{
1219    (void)aSender;
1220    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1221}
1222
1223-(void)moveToEndOfParagraph: (id)aSender
1224{
1225    (void)aSender;
1226    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1227}
1228
1229-(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1230{
1231    (void)aSender;
1232    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1233}
1234
1235-(void)moveParagraphForward: (id)aSender
1236{
1237    (void)aSender;
1238    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1239}
1240
1241-(void)moveParagraphForwardAndModifySelection: (id)aSender
1242{
1243    (void)aSender;
1244    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1245}
1246
1247-(void)moveToBeginningOfParagraph: (id)aSender
1248{
1249    (void)aSender;
1250    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1251}
1252
1253-(void)moveParagraphBackward: (id)aSender
1254{
1255    (void)aSender;
1256    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1257}
1258
1259-(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender
1260{
1261    (void)aSender;
1262    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1263}
1264
1265-(void)moveParagraphBackwardAndModifySelection: (id)aSender
1266{
1267    (void)aSender;
1268    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1269}
1270
1271-(void)moveToEndOfDocument: (id)aSender
1272{
1273    (void)aSender;
1274    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1275}
1276
1277-(void)scrollToEndOfDocument: (id)aSender
1278{
1279    (void)aSender;
1280    // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent
1281    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1282}
1283
1284-(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1285{
1286    (void)aSender;
1287    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1288}
1289
1290-(void)moveToBeginningOfDocument: (id)aSender
1291{
1292    (void)aSender;
1293    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1294}
1295
1296-(void)scrollToBeginningOfDocument: (id)aSender
1297{
1298    (void)aSender;
1299    // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent
1300    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1301}
1302
1303-(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1304{
1305    (void)aSender;
1306    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1307}
1308
1309-(void)moveUp: (id)aSender
1310{
1311    (void)aSender;
1312    [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1313}
1314
1315-(void)moveDown: (id)aSender
1316{
1317    (void)aSender;
1318    [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1319}
1320
1321-(void)insertNewline: (id)aSender
1322{
1323    (void)aSender;
1324    // #i91267# make enter and shift-enter work by evaluating the modifiers
1325    [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1326}
1327
1328-(void)deleteBackward: (id)aSender
1329{
1330    (void)aSender;
1331    [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1332}
1333
1334-(void)deleteForward: (id)aSender
1335{
1336    (void)aSender;
1337    [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1338}
1339
1340-(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1341{
1342    (void)aSender;
1343    [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1344}
1345
1346-(void)deleteWordBackward: (id)aSender
1347{
1348    (void)aSender;
1349    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1350}
1351
1352-(void)deleteWordForward: (id)aSender
1353{
1354    (void)aSender;
1355    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1356}
1357
1358-(void)deleteToBeginningOfLine: (id)aSender
1359{
1360    (void)aSender;
1361    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1362}
1363
1364-(void)deleteToEndOfLine: (id)aSender
1365{
1366    (void)aSender;
1367    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1368}
1369
1370-(void)deleteToBeginningOfParagraph: (id)aSender
1371{
1372    (void)aSender;
1373    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1374}
1375
1376-(void)deleteToEndOfParagraph: (id)aSender
1377{
1378    (void)aSender;
1379    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1380}
1381
1382-(void)insertLineBreak: (id)aSender
1383{
1384    (void)aSender;
1385    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1386}
1387
1388-(void)insertParagraphSeparator: (id)aSender
1389{
1390    (void)aSender;
1391    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1392}
1393
1394-(void)selectWord: (id)aSender
1395{
1396    (void)aSender;
1397    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1398}
1399
1400-(void)selectLine: (id)aSender
1401{
1402    (void)aSender;
1403    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1404}
1405
1406-(void)selectParagraph: (id)aSender
1407{
1408    (void)aSender;
1409    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1410}
1411
1412-(void)selectAll: (id)aSender
1413{
1414    (void)aSender;
1415    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1416}
1417
1418-(void)cancelOperation: (id)aSender
1419{
1420    (void)aSender;
1421    [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1422}
1423
1424-(void)noop: (id)aSender
1425{
1426    (void)aSender;
1427    if( ! mbKeyHandled )
1428    {
1429        if( ! [self sendSingleCharacter:mpLastEvent] )
1430        {
1431            /* prevent recursion */
1432            if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1433            {
1434                id pLastSuperEvent = mpLastSuperEvent;
1435                mpLastSuperEvent = mpLastEvent;
1436                [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1437                mpLastSuperEvent = pLastSuperEvent;
1438
1439                std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1440                if( it != GetSalData()->maKeyEventAnswer.end() )
1441                    it->second = true;
1442            }
1443        }
1444    }
1445}
1446
1447-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar
1448{
1449    return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1450}
1451
1452-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1453{
1454    return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1455           [self sendSingleCharacter: mpLastEvent];
1456}
1457
1458-(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1459{
1460    YIELD_GUARD;
1461
1462    long nRet = 0;
1463    if( AquaSalFrame::isAlive( mpFrame ) )
1464    {
1465        SalKeyEvent aEvent;
1466        aEvent.mnTime           = mpFrame->mnLastEventTime;
1467        aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1468        aEvent.mnCharCode       = aChar;
1469        aEvent.mnRepeat         = FALSE;
1470        nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent );
1471        std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1472        if( it != GetSalData()->maKeyEventAnswer.end() )
1473            it->second = nRet ? true : false;
1474        if( AquaSalFrame::isAlive( mpFrame ) )
1475            mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent );
1476    }
1477    return nRet ? YES : NO;
1478}
1479
1480
1481-(BOOL)sendSingleCharacter: (NSEvent *)pEvent
1482{
1483    NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
1484
1485    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1486    {
1487        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1488        sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
1489        if( nKeyCode != 0 )
1490        {
1491            // don't send unicodes in the private use area
1492            if( keyChar >= 0xf700 && keyChar < 0xf780 )
1493                keyChar = 0;
1494            BOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1495            mbInKeyInput = false;
1496
1497            return bRet;
1498        }
1499    }
1500    return NO;
1501}
1502
1503
1504// NSTextInput protocol
1505- (NSArray *)validAttributesForMarkedText
1506{
1507    return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1508}
1509
1510- (BOOL)hasMarkedText
1511{
1512    BOOL bHasMarkedText;
1513
1514    bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1515                     ( mMarkedRange.length != 0 );
1516    // hack to check keys like "Control-j"
1517    if( mbInKeyInput )
1518    {
1519        mbNeedSpecialKeyHandle = true;
1520    }
1521
1522    // FIXME:
1523    // #i106901#
1524    // if we come here outside of mbInKeyInput, this is likely to be because
1525    // of the keyboard viewer. For unknown reasons having no marked range
1526    // in this case causes a crash. So we say we have a marked range anyway
1527    // This is a hack, since it is not understood what a) causes that crash
1528    // and b) why we should have a marked range at this point.
1529    if( ! mbInKeyInput )
1530        bHasMarkedText = YES;
1531
1532    return bHasMarkedText;
1533}
1534
1535- (NSRange)markedRange
1536{
1537    // FIXME:
1538    // #i106901#
1539    // if we come here outside of mbInKeyInput, this is likely to be because
1540    // of the keyboard viewer. For unknown reasons having no marked range
1541    // in this case causes a crash. So we say we have a marked range anyway
1542    // This is a hack, since it is not understood what a) causes that crash
1543    // and b) why we should have a marked range at this point.
1544    if( ! mbInKeyInput )
1545        return NSMakeRange( 0, 0 );
1546
1547    return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1548}
1549
1550- (NSRange)selectedRange
1551{
1552    return mSelectedRange;
1553}
1554
1555- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
1556{
1557    if( ![aString isKindOfClass:[NSAttributedString class]] )
1558        aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1559    NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1560    if( rangeToReplace.location == NSNotFound )
1561    {
1562        mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1563        mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1564    }
1565    else
1566    {
1567        mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1568        mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1569    }
1570
1571    int len = [aString length];
1572    SalExtTextInputEvent aInputEvent;
1573    aInputEvent.mnTime = mpFrame->mnLastEventTime;
1574    aInputEvent.mnDeltaStart = 0;
1575    aInputEvent.mbOnlyCursor = FALSE;
1576    if( len > 0 ) {
1577        NSString *pString = [aString string];
1578        OUString aInsertString( GetOUString( pString ) );
1579        std::vector<sal_uInt16> aInputFlags = std::vector<sal_uInt16>( std::max( 1, len ), 0 );
1580        for ( int i = 0; i < len; i++ )
1581        {
1582            unsigned int nUnderlineValue;
1583            NSRange effectiveRange;
1584
1585            effectiveRange = NSMakeRange(i, 1);
1586            nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1587
1588            switch (nUnderlineValue & 0xff) {
1589            case NSUnderlineStyleSingle:
1590                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
1591                break;
1592            case NSUnderlineStyleThick:
1593                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1594                break;
1595            case NSUnderlineStyleDouble:
1596                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
1597                break;
1598            default:
1599                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1600                break;
1601            }
1602        }
1603
1604        aInputEvent.maText = aInsertString;
1605        aInputEvent.mnCursorPos = selRange.location;
1606        aInputEvent.mpTextAttr = &aInputFlags[0];
1607        mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1608    } else {
1609        aInputEvent.maText = String();
1610        aInputEvent.mnCursorPos = 0;
1611        aInputEvent.mnCursorFlags = 0;
1612        aInputEvent.mpTextAttr = 0;
1613        mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1614        mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1615    }
1616    mbKeyHandled= true;
1617}
1618
1619- (void)unmarkText
1620{
1621    mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1622}
1623
1624- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
1625{
1626    (void)theRange;
1627    // FIXME
1628    return nil;
1629}
1630
1631- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
1632{
1633    (void)thePoint;
1634    // FIXME
1635    return 0;
1636}
1637
1638#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
1639/* build target 10.5 or greater */
1640- (NSInteger)conversationIdentifier
1641#else
1642/* build target 10.4 */
1643- (long)conversationIdentifier
1644#endif
1645{
1646    return (long)self;
1647}
1648
1649- (void)doCommandBySelector:(SEL)aSelector
1650{
1651    if( AquaSalFrame::isAlive( mpFrame ) )
1652    {
1653        #if OSL_DEBUG_LEVEL > 1
1654        // fprintf( stderr, "SalFrameView: doCommandBySelector %s\n", (char*)aSelector );
1655        #endif
1656        if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 &&
1657            aSelector != NULL && [self respondsToSelector: aSelector] )
1658        {
1659            [self performSelector: aSelector];
1660        }
1661        else
1662        {
1663            [self sendSingleCharacter:mpLastEvent];
1664        }
1665    }
1666
1667    mbKeyHandled = true;
1668}
1669
1670-(void)clearLastEvent
1671{
1672    mpLastEvent = nil;
1673}
1674
1675- (NSRect)firstRectForCharacterRange:(NSRange)theRange
1676{
1677    (void)theRange;
1678    SalExtTextInputPosEvent aPosEvent;
1679    mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent );
1680
1681    NSRect rect;
1682
1683    rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1684    rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1685    rect.size.width = aPosEvent.mnWidth;
1686    rect.size.height = aPosEvent.mnHeight;
1687
1688    mpFrame->VCLToCocoa( rect );
1689    return rect;
1690}
1691
1692-(id)parentAttribute {
1693    return mpFrame->getNSWindow();
1694}
1695
1696-(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext
1697{
1698    if ( mpReferenceWrapper == nil ) {
1699        // some frames never become visible ..
1700        Window *pWindow = mpFrame -> GetWindow();
1701        if ( ! pWindow )
1702            return nil;
1703
1704        mpReferenceWrapper = new ReferenceWrapper;
1705        mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1706        [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1707    }
1708    return [ super accessibleContext ];
1709}
1710
1711-(NSWindow*)windowForParent
1712{
1713    return mpFrame->getNSWindow();
1714}
1715
1716-(void)registerMouseEventListener: (id)theListener
1717{
1718  mpMouseEventListener = theListener;
1719}
1720
1721-(void)unregisterMouseEventListener: (id)theListener
1722{
1723    (void)theListener;
1724    mpMouseEventListener = nil;
1725}
1726
1727-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1728{
1729  return [mDraggingDestinationHandler draggingEntered: sender];
1730}
1731
1732-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1733{
1734  return [mDraggingDestinationHandler draggingUpdated: sender];
1735}
1736
1737-(void)draggingExited:(id <NSDraggingInfo>)sender
1738{
1739  [mDraggingDestinationHandler draggingExited: sender];
1740}
1741
1742-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1743{
1744  return [mDraggingDestinationHandler prepareForDragOperation: sender];
1745}
1746
1747-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
1748{
1749  return [mDraggingDestinationHandler performDragOperation: sender];
1750}
1751
1752-(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1753{
1754  [mDraggingDestinationHandler concludeDragOperation: sender];
1755}
1756
1757-(void)registerDraggingDestinationHandler:(id)theHandler
1758{
1759  mDraggingDestinationHandler = theHandler;
1760}
1761
1762-(void)unregisterDraggingDestinationHandler:(id)theHandler
1763{
1764    (void)theHandler;
1765    mDraggingDestinationHandler = nil;
1766}
1767
1768@end
1769
1770