merge the formfield patch from ooo-build
[ooovba.git] / vcl / aqua / source / window / salframeview.mm
blob68ea2c2062f2a0ecffaf1a3750d9da0d68704af7
1 /*n***********************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  * 
5  * Copyright 2008 by Sun Microsystems, Inc.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * $RCSfile: salframeview.mm,v $
10  * $Revision: 1.12.22.2 $
11  *
12  * This file is part of OpenOffice.org.
13  *
14  * OpenOffice.org is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License version 3
16  * only, as published by the Free Software Foundation.
17  *
18  * OpenOffice.org is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU Lesser General Public License version 3 for more details
22  * (a copy is included in the LICENSE file that accompanied this code).
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * version 3 along with OpenOffice.org.  If not, see
26  * <http://www.openoffice.org/license.html>
27  * for a copy of the LGPLv3 License.
28  *
29  ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include "salinst.h"
35 #include "salgdi.h"
36 #include "salframe.h"
37 #include "salframeview.h"
38 #include "aqua11yfactory.h"
39 #include <sal/alloca.h>
40 #include "vcl/window.hxx"
42 #include "vcl/svapp.hxx"
44 static USHORT ImplGetModifierMask( unsigned int nMask )
46     USHORT nRet = 0;
47     if( (nMask & NSShiftKeyMask) != 0 )
48         nRet |= KEY_SHIFT;
49     if( (nMask & NSControlKeyMask) != 0 )
50         nRet |= KEY_MOD3;
51     if( (nMask & NSAlternateKeyMask) != 0 )
52         nRet |= KEY_MOD2;
53     if( (nMask & NSCommandKeyMask) != 0 )
54         nRet |= KEY_MOD1;
55     return nRet;
58 static USHORT ImplMapCharCode( sal_Unicode aCode )
60     static USHORT aKeyCodeMap[ 128 ] =
61     {
62         0, 0, 0, 0, 0, 0, 0, 0,
63         KEY_BACKSPACE, KEY_TAB, KEY_RETURN, 0, 0, KEY_RETURN, 0, 0,
64         0, 0, 0, 0, 0, 0, 0, 0,
65         0, KEY_TAB, 0, KEY_ESCAPE, 0, 0, 0, 0,
66         KEY_SPACE, 0, 0, 0, 0, 0, 0, 0,
67         0, 0, KEY_MULTIPLY, KEY_ADD, KEY_COMMA, KEY_SUBTRACT, KEY_POINT, KEY_DIVIDE,
68         KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
69         KEY_8, KEY_9, 0, 0, KEY_LESS, KEY_EQUAL, KEY_GREATER, 0,
70         0, 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, 0, 0,
74         KEY_QUOTELEFT, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
75         KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
76         KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
77         KEY_X, KEY_Y, KEY_Z, 0, 0, 0, KEY_TILDE, KEY_BACKSPACE
78     };
79     
80     // Note: the mapping 0x7f should by rights be KEY_DELETE
81     // however if you press "backspace" 0x7f is reported
82     // whereas for "delete" 0xf728 gets reported
83     
84     // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons
85     // tab alone is reported as 0x09 (as expected) but shift-tab is
86     // reported as 0x19 (end of medium)
87     
88     static USHORT aFunctionKeyCodeMap[ 128 ] =
89     {
90         KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4,
91         KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,
92         KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
93         KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_F25, KEY_F26, 0, 0,
94         0, 0, 0, 0, 0, 0, 0, KEY_INSERT,
95         KEY_DELETE, KEY_HOME, 0, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN, 0, 0,
96         0, 0, 0, 0, 0, KEY_MENU, 0, 0,
97         0, 0, 0, 0, 0, 0, 0, 0,
98         0, 0, 0, KEY_UNDO, KEY_REPEAT, KEY_FIND, KEY_HELP, 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         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     };
107     
108     USHORT nKeyCode = 0;
109     if( aCode < sizeof( aKeyCodeMap) / sizeof( aKeyCodeMap[0] ) )
110         nKeyCode = aKeyCodeMap[ aCode ];
111     else if( aCode >= 0xf700 && aCode < 0xf780 )
112         nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ]; 
113     return nKeyCode;
116 // store the frame the mouse last entered
117 static AquaSalFrame* s_pMouseFrame = NULL;
118 // store the last pressed button for enter/exit events
119 // which lack that information
120 static USHORT s_nLastButton = 0;
122 // combinations of keys we need to handle ourselves
123 static const struct ExceptionalKey
125     const USHORT        nKeyCode;
126     const unsigned int  nModifierMask;
127 } aExceptionalKeys[] =
129     { KEY_D, NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask },
130     { KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask }
133 static AquaSalFrame* getMouseContainerFrame()
135     int nWindows = 0;
136     NSCountWindows( &nWindows );
137     int* pWindows = (int*)alloca( nWindows * sizeof(int) );
138     // note: NSWindowList is supposed to be in z-order front to back
139     NSWindowList( nWindows, pWindows );
140     AquaSalFrame* pDispatchFrame = NULL;
141     for(int i = 0; i < nWindows && ! pDispatchFrame; i++ )
142     {
143         NSWindow* pWin = [NSApp windowWithWindowNumber: pWindows[i]];
144         if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] )
145             pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame];
146     }
147     return pDispatchFrame;
150 @implementation SalFrameWindow
151 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
153         mDraggingDestinationHandler = nil;
154     mpFrame = pFrame;
155     NSRect aRect = { { pFrame->maGeometry.nX, pFrame->maGeometry.nY },
156                      { pFrame->maGeometry.nWidth, pFrame->maGeometry.nHeight } };
157     pFrame->VCLToCocoa( aRect );
158     return [super initWithContentRect: aRect styleMask: mpFrame->getStyleMask() backing: NSBackingStoreBuffered defer: NO ];
161 -(AquaSalFrame*)getSalFrame
163     return mpFrame;
166 -(MacOSBOOL)containsMouse
168     // is this event actually inside that NSWindow ?
169     NSPoint aPt = [NSEvent mouseLocation];
170     NSRect aFrameRect = [self frame];
171     MacOSBOOL bInRect = NSPointInRect( aPt, aFrameRect );
172     return bInRect;
175 -(MacOSBOOL)canBecomeKeyWindow
177     if( (mpFrame->mnStyle & 
178             ( SAL_FRAME_STYLE_FLOAT                 |
179               SAL_FRAME_STYLE_TOOLTIP               |
180               SAL_FRAME_STYLE_INTRO
181             )) == 0 )
182         return YES;
183     if( (mpFrame->mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) != 0 )
184         return YES;
185     if( mpFrame->mbFullScreen )
186         return YES;
187     if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
188         return YES;
189     return [super canBecomeKeyWindow];
192 -(void)windowDidBecomeKey: (NSNotification*)pNotification
194     YIELD_GUARD;
196     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
197     {
198         static const ULONG nGuessDocument = SAL_FRAME_STYLE_MOVEABLE|
199                                             SAL_FRAME_STYLE_SIZEABLE|
200                                             SAL_FRAME_STYLE_CLOSEABLE;
201         
202         if( mpFrame->mpMenu )
203             mpFrame->mpMenu->setMainMenu();
204         else if( ! mpFrame->mpParent &&
205                  ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help
206                     mpFrame->mbFullScreen ) )                               // ser default menu for e.g. presentation
207         {
208             AquaSalMenu::setDefaultMenu();
209         }
210         #if 0
211         // FIXME: we should disable menus while in modal mode
212         // however from down here there is currently no reliable way to
213         // find out when to do this
214         if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) )
215             AquaSalMenu::enableMainMenu( false );
216         #endif
217         mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
218     }
221 -(void)windowDidResignKey: (NSNotification*)pNotification
223     YIELD_GUARD;
225     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
226         mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0);
229 -(void)windowDidChangeScreen: (NSNotification*)pNotification
231     YIELD_GUARD;
233     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
234         mpFrame->screenParametersChanged();
237 -(void)windowDidMove: (NSNotification*)pNotification
239     YIELD_GUARD;
241     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
242     {
243         mpFrame->UpdateFrameGeometry();
244         mpFrame->CallCallback( SALEVENT_MOVE, 0 );
245     }
248 -(void)windowDidResize: (NSNotification*)pNotification
250     YIELD_GUARD;
252     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
253     {
254         mpFrame->UpdateFrameGeometry();
255         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
256         mpFrame->SendPaintEvent();
257     }
260 -(void)windowDidMiniaturize: (NSNotification*)pNotification
262     YIELD_GUARD;
264     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
265     {
266         mpFrame->mbShown = false;
267         mpFrame->UpdateFrameGeometry();
268         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
269     }
272 -(void)windowDidDeminiaturize: (NSNotification*)pNotification
274     YIELD_GUARD;
276     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
277     {
278         mpFrame->mbShown = true;
279         mpFrame->UpdateFrameGeometry();
280         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
281     }
284 -(MacOSBOOL)windowShouldClose: (NSNotification*)pNotification
286     YIELD_GUARD;
288     MacOSBOOL bRet = YES;
289     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
290     {
291         // #i84461# end possible input
292         mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
293         if( AquaSalFrame::isAlive( mpFrame ) )
294         {
295             mpFrame->CallCallback( SALEVENT_CLOSE, 0 );
296             bRet = NO; // application will close the window or not, AppKit shouldn't
297         }
298     }
300     return bRet;
303 -(void)dockMenuItemTriggered: (id)sender
305     YIELD_GUARD;
307     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
308         mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS );
311 -(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext
313     return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
316 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
318   return [mDraggingDestinationHandler draggingEntered: sender];
321 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
323   return [mDraggingDestinationHandler draggingUpdated: sender];
326 -(void)draggingExited:(id <NSDraggingInfo>)sender
328   [mDraggingDestinationHandler draggingExited: sender];
331 -(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
333   return [mDraggingDestinationHandler prepareForDragOperation: sender];
336 -(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender
338   return [mDraggingDestinationHandler performDragOperation: sender];
341 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
343   [mDraggingDestinationHandler concludeDragOperation: sender];
346 -(void)registerDraggingDestinationHandler:(id)theHandler
348   mDraggingDestinationHandler = theHandler;
351 -(void)unregisterDraggingDestinationHandler:(id)theHandler
353     mDraggingDestinationHandler = nil;
356 @end
358 @implementation SalFrameView
359 +(void)unsetMouseFrame: (AquaSalFrame*)pFrame
361     if( pFrame == s_pMouseFrame )
362         s_pMouseFrame = NULL;
365 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
367     if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil)
368     {
369         mDraggingDestinationHandler = nil;
370         mpFrame = pFrame;
371         mMarkedRange = NSMakeRange(NSNotFound, 0);
372         mSelectedRange = NSMakeRange(NSNotFound, 0);
373         mpReferenceWrapper = nil;
374                 mpMouseEventListener = nil;
375         mpLastSuperEvent = nil;
376     }
378     return self;
381 -(void)resetCursorRects
383     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
384     {
385         // FIXME: does this leak the returned NSCursor of getCurrentCursor ?
386         NSRect aRect = { { 0, 0 }, { mpFrame->maGeometry.nWidth, mpFrame->maGeometry.nHeight } };
387         [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()];
388     }
391 -(MacOSBOOL)acceptsFirstResponder
393     return YES;
396 -(MacOSBOOL)acceptsFirstMouse: (NSEvent*)pEvent
398     return YES;
401 -(MacOSBOOL)isOpaque
403     return mpFrame ? (mpFrame->getClipPath() != 0 ? NO : YES) : YES;
406 // helper class similar to a vos::OGuard for the SalYieldMutex
407 // the difference is that it only does tryToAcquire instead of aquire
408 // so dreaded deadlocks like #i93512# are prevented
409 class TryGuard
411 public:
412                         TryGuard()  { mbGuarded = ImplSalYieldMutexTryToAcquire(); }
413                         ~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); }
414         bool    IsGuarded() { return mbGuarded; }
415 private:
416         bool    mbGuarded;
419 -(void)drawRect: (NSRect)aRect
421         // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
422         TryGuard aTryGuard;
423         if( !aTryGuard.IsGuarded() )
424         {
425                 // NOTE: the mpFrame access below is not guarded yet!
426                 // TODO: mpFrame et al need to be guarded by an independent mutex
427                 AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL;
428                 if( pGraphics )
429                 {
430                         // we did not get the mutex so we cannot draw now => request to redraw later
431                         // convert the NSRect to a CGRect for Refreshrect()
432                         const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}};
433                         pGraphics->RefreshRect( aCGRect );
434                 }
435                 return;
436         }
438     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
439     {
440         if( mpFrame->mpGraphics )
441         {
442             mpFrame->mpGraphics->UpdateWindow( aRect );
443             if( mpFrame->getClipPath() )
444                 [mpFrame->getWindow() invalidateShadow];
445         }
446     }
449 -(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(USHORT)nButton eventtype:(USHORT)nEvent
451     YIELD_GUARD;
453     AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
454     bool bIsCaptured = false;
455     if( pDispatchFrame )
456     {
457         bIsCaptured = true;
458         if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured
459             nEvent = SALEVENT_MOUSEMOVE;
460     }
461     else if( s_pMouseFrame )
462         pDispatchFrame = s_pMouseFrame;
463     else
464         pDispatchFrame = mpFrame;
465     
466     /* #i81645# Cocoa reports mouse events while a button is pressed
467        to the window in which it was first pressed. This is reasonable and fine and
468        gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
469        however vcl expects mouse events to occur in the window the mouse is over, unless the
470        mouse is explicitly captured. So we need to find the window the mouse is actually
471        over for conformance with other platforms.
472     */
473     if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
474     {
475         // is this event actually inside that NSWindow ?
476         NSPoint aPt = [NSEvent mouseLocation];
477         NSRect aFrameRect = [pDispatchFrame->getWindow() frame];
478         
479         if ( ! NSPointInRect( aPt, aFrameRect ) )
480         {
481             // no, it is not
482             // now we need to find the one it may be in
483             /* #i93756# we ant to get enumerate the application windows in z-order
484                to check if any contains the mouse. This could be elegantly done with this
485                code:
487                // use NSApp to check windows in ZOrder whether they contain the mouse pointer
488                NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
489                if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
490                    pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
491                
492                However if a non SalFrameWindow is on screen (like e.g. the file dialog)
493                it can be hit with the containsMouse selector, which it doesn't support.
494                Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
495                I assume) whether a window supports a selector before sending it. 
496             */
497             AquaSalFrame* pMouseFrame = getMouseContainerFrame();
498             if( pMouseFrame )
499                 pDispatchFrame = pMouseFrame;
500         }
501     }
502     
503     if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
504     {
505         pDispatchFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
506         pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
508         NSPoint aPt = [NSEvent mouseLocation];
509         pDispatchFrame->CocoaToVCL( aPt );
510         
511         USHORT nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
512         // #i82284# emulate ctrl left
513         if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
514         {
515             nModMask    = 0;
516             nButton     = MOUSE_RIGHT;
517         }
519         SalMouseEvent aEvent;
520         aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
521         aEvent.mnX      = static_cast<long>(aPt.x) - pDispatchFrame->maGeometry.nX;
522         aEvent.mnY      = static_cast<long>(aPt.y) - pDispatchFrame->maGeometry.nY;
523         aEvent.mnButton = nButton;
524         aEvent.mnCode   =  aEvent.mnButton | nModMask;
526         // --- RTL --- (mirror mouse pos)
527         if( Application::GetSettings().GetLayoutRTL() )
528             aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
529         
530         pDispatchFrame->CallCallback( nEvent, &aEvent );
531     }
534 -(void)mouseDown: (NSEvent*)pEvent
536     if ( mpMouseEventListener != nil && 
537             [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
538         {
539             [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]];
540         }
542     s_nLastButton = MOUSE_LEFT;
543     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN];
546 -(void)mouseDragged: (NSEvent*)pEvent
548     if ( mpMouseEventListener != nil && 
549              [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
550         {
551             [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]];
552         }
553     s_nLastButton = MOUSE_LEFT;
554     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE];
557 -(void)mouseUp: (NSEvent*)pEvent
559     s_nLastButton = 0;
560     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP];
563 -(void)mouseMoved: (NSEvent*)pEvent
565     s_nLastButton = 0;
566     [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE];
569 -(void)mouseEntered: (NSEvent*)pEvent
571     s_pMouseFrame = mpFrame;
572     
573     [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE];
576 -(void)mouseExited: (NSEvent*)pEvent
578     if( s_pMouseFrame == mpFrame )
579         s_pMouseFrame = NULL;
581     [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE];
584 -(void)rightMouseDown: (NSEvent*)pEvent
586     s_nLastButton = MOUSE_RIGHT;
587     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN];
590 -(void)rightMouseDragged: (NSEvent*)pEvent
592     s_nLastButton = MOUSE_RIGHT;
593     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE];
596 -(void)rightMouseUp: (NSEvent*)pEvent
598     s_nLastButton = 0;
599     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP];
602 -(void)otherMouseDown: (NSEvent*)pEvent
604     if( [pEvent buttonNumber] == 2 )
605     {
606         s_nLastButton = MOUSE_MIDDLE;
607         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN];
608     }
609     else
610         s_nLastButton = 0;
613 -(void)otherMouseDragged: (NSEvent*)pEvent
615     if( [pEvent buttonNumber] == 2 )
616     {
617         s_nLastButton = MOUSE_MIDDLE;
618         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE];
619     }
620     else
621         s_nLastButton = 0;
624 -(void)otherMouseUp: (NSEvent*)pEvent
626     s_nLastButton = 0;
627     if( [pEvent buttonNumber] == 2 )
628         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP];
631 - (void)magnifyWithEvent: (NSEvent*)pEvent
633     YIELD_GUARD;
634     
635     // TODO: ??  -(float)magnification;
636     if( AquaSalFrame::isAlive( mpFrame ) )
637     {
638         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
639         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
640         
641         float dZ = 0.0;
642         for(;;)
643         {
644             dZ += [pEvent deltaZ];
645             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
646             untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
647             if( !pNextEvent )
648                 break;
649             pEvent = pNextEvent;
650         }
651         
652         NSPoint aPt = [NSEvent mouseLocation];
653         mpFrame->CocoaToVCL( aPt );
654         
655         SalWheelMouseEvent aEvent;
656         aEvent.mnTime   = mpFrame->mnLastEventTime;
657         aEvent.mnX      = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
658         aEvent.mnY      = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
659         aEvent.mnCode   = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
660         aEvent.mnCode   |= KEY_MOD1; // we want zooming, no scrolling
661         
662         // --- RTL --- (mirror mouse pos)
663         if( Application::GetSettings().GetLayoutRTL() )
664             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
665         
666         if( dZ != 0.0 )
667         {
668             aEvent.mnDelta = static_cast<long>(floor(dZ));
669             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
670             if( aEvent.mnNotchDelta == 0 )
671                 aEvent.mnNotchDelta = dZ < 0.0 ? -1 : 1;
672             aEvent.mbHorz = FALSE;
673             aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta;
674             if( aEvent.mnScrollLines == 0 )
675                 aEvent.mnScrollLines = 1;
676             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
677         }
678     }
681 - (void)rotateWithEvent: (NSEvent*)pEvent
683     //Rotation : -(float)rotation;
684     // TODO: create new CommandType so rotation is available to the applications
687 - (void)swipeWithEvent: (NSEvent*)pEvent
689     YIELD_GUARD;
690     
691     if( AquaSalFrame::isAlive( mpFrame ) )
692     {
693         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
694         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
695         
696         // merge pending scroll wheel events
697         float dX = 0.0;
698         float dY = 0.0;
699         for(;;)
700         {
701             dX += [pEvent deltaX];
702             dY += [pEvent deltaY];
703             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
704             untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
705             if( !pNextEvent )
706                 break;
707             pEvent = pNextEvent;
708         }
709         
710         NSPoint aPt = [NSEvent mouseLocation];
711         mpFrame->CocoaToVCL( aPt );
712         
713         SalWheelMouseEvent aEvent;
714         aEvent.mnTime   = mpFrame->mnLastEventTime;
715         aEvent.mnX      = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
716         aEvent.mnY      = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
717         aEvent.mnCode   = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
718         
719         // --- RTL --- (mirror mouse pos)
720         if( Application::GetSettings().GetLayoutRTL() )
721             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
722         
723         if( dX != 0.0 )
724         {
725             aEvent.mnDelta = static_cast<long>(floor(dX));
726             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
727             if( aEvent.mnNotchDelta == 0 )
728                 aEvent.mnNotchDelta = dX < 0.0 ? -1 : 1;
729             aEvent.mbHorz = TRUE;
730             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
731             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
732         }
733         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
734         {
735             aEvent.mnDelta = static_cast<long>(floor(dY));
736             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
737             if( aEvent.mnNotchDelta == 0 )
738                 aEvent.mnNotchDelta = dY < 0.0 ? -1 : 1;
739             aEvent.mbHorz = FALSE;
740             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
741             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
742         }
743     }
746 -(void)scrollWheel: (NSEvent*)pEvent
748     YIELD_GUARD;
749     
750     if( AquaSalFrame::isAlive( mpFrame ) )
751     {
752         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
753         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
755         // merge pending scroll wheel events
756         float dX = 0.0;
757         float dY = 0.0;
758         for(;;)
759         {
760             dX += [pEvent deltaX];
761             dY += [pEvent deltaY];
762             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
763                 untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
764             if( !pNextEvent )
765                 break;
766             pEvent = pNextEvent;
767         }
769         NSPoint aPt = [NSEvent mouseLocation];
770         mpFrame->CocoaToVCL( aPt );
772         SalWheelMouseEvent aEvent;
773         aEvent.mnTime   = mpFrame->mnLastEventTime;
774         aEvent.mnX      = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
775         aEvent.mnY      = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
776         aEvent.mnCode   = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
778         // --- RTL --- (mirror mouse pos)
779         if( Application::GetSettings().GetLayoutRTL() )
780             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
782         if( dX != 0.0 )
783         {
784             aEvent.mnDelta = static_cast<long>(floor(dX));
785             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
786             if( aEvent.mnNotchDelta == 0 )
787                 aEvent.mnNotchDelta = dX < 0.0 ? -1 : 1;
788             aEvent.mbHorz = TRUE;
789             aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta;
790             if( aEvent.mnScrollLines == 0 )
791                 aEvent.mnScrollLines = 1;
792             if( aEvent.mnScrollLines > 15 )
793                 aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
794             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
795         }
796         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
797         {
798             aEvent.mnDelta = static_cast<long>(floor(dY));
799             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
800             if( aEvent.mnNotchDelta == 0 )
801                 aEvent.mnNotchDelta = dY < 0.0 ? -1 : 1;
802             aEvent.mbHorz = FALSE;
803             aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta;
804             if( aEvent.mnScrollLines == 0 )
805                 aEvent.mnScrollLines = 1;
806             if( aEvent.mnScrollLines > 15 )
807                 aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
808             
809             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
810         }
811     }
815 -(void)keyDown: (NSEvent*)pEvent
817     YIELD_GUARD;
818     
819     if( AquaSalFrame::isAlive( mpFrame ) )
820     {
821         mpLastEvent = pEvent;
822         mbInKeyInput = true;
823         mbNeedSpecialKeyHandle = false;
824         mbKeyHandled = false;
826         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
827         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
828         
829         if( ! [self handleKeyDownException: pEvent] )
830         {
831             NSArray* pArray = [NSArray arrayWithObject: pEvent];
832             [self interpretKeyEvents: pArray];
833         }
835         mbInKeyInput = false;
836     }
839 -(MacOSBOOL)handleKeyDownException:(NSEvent*)pEvent
841     // check for a very special set of modified characters
842     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; 
844     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
845     {
846         /* #i103102# key events with command and alternate don't make it through
847            interpretKeyEvents (why ?). Try to dispatch them here first,
848            if not successful continue normally
849         */
850         if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
851                     == (NSAlternateKeyMask | NSCommandKeyMask) )
852         {
853             if( [self sendSingleCharacter: mpLastEvent] )
854                 return YES;
855         }
856         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
857         USHORT nKeyCode = ImplMapCharCode( keyChar );
858         
859         // Caution: should the table grow to more than 5 or 6 entries,
860         // we must consider moving it to a kind of hash map
861         const unsigned int nExceptions = sizeof( aExceptionalKeys ) / sizeof( aExceptionalKeys[0] );
862         for( unsigned int i = 0; i < nExceptions; i++ )
863         {
864             if( nKeyCode == aExceptionalKeys[i].nKeyCode &&
865                 (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask)
866                 == aExceptionalKeys[i].nModifierMask )
867             {
868                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0];
870                 return YES;
871             }
872         }
873     }
874     return NO;
877 -(void)flagsChanged: (NSEvent*)pEvent
879     YIELD_GUARD;
880     
881     if( AquaSalFrame::isAlive( mpFrame ) )
882     {
883         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
884         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
885     }
888 -(void)insertText:(id)aString
890     YIELD_GUARD;
891     
892     if( AquaSalFrame::isAlive( mpFrame ) )
893     {
894         NSString* pInsert = nil;
895         if( [aString isMemberOfClass: [NSAttributedString class]] )
896             pInsert = [aString string];
897         else
898             pInsert = aString;
899         
900         int nLen = 0;
901         if( pInsert && ( nLen = [pInsert length] ) > 0 )
902         {
903             OUString aInsertString( GetOUString( pInsert ) );
904              // aCharCode initializer is safe since aInsertString will at least contain '\0'
905             sal_Unicode aCharCode = *aInsertString.getStr();
906             
907             if( nLen == 1 &&
908                 aCharCode < 0x80 &&
909                 aCharCode > 0x1f &&
910                                 ! [self hasMarkedText ]
911                 )
912             {
913                 USHORT nKeyCode = ImplMapCharCode( aCharCode );
914                 unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
916                 // #i99567#
917                 // find out the unmodified key code
918     
919                 // sanity check
920                 if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
921                 {
922                     // get unmodified string
923                     NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers]; 
924                     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
925                     {
926                         // map the unmodified key code
927                         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
928                         nKeyCode = ImplMapCharCode( keyChar );
929                     }
930                     nLastModifiers = [mpLastEvent modifierFlags];
932                 }
933                 // #i99567#
934                 // applications and vcl's edit fields ignore key events with ALT
935                 // however we're at a place where we know text should be inserted
936                 // so it seems we need to strip the Alt modifier here
937                 if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
938                     == NSAlternateKeyMask )
939                 {
940                     nLastModifiers = 0;
941                 }
942                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
943             }
944             else
945             {
946                 SalExtTextInputEvent aEvent;
947                 aEvent.mnTime           = mpFrame->mnLastEventTime;
948                 aEvent.maText           = aInsertString;
949                 aEvent.mpTextAttr       = NULL;
950                 aEvent.mnCursorPos      = aInsertString.getLength();
951                 aEvent.mnDeltaStart     = 0;
952                 aEvent.mnCursorFlags    = 0;
953                 aEvent.mbOnlyCursor     = FALSE;
954                 mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
955                 if( AquaSalFrame::isAlive( mpFrame ) )
956                     mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
957             }
958         }
959         else
960         {
961             SalExtTextInputEvent aEvent;
962             aEvent.mnTime           = mpFrame->mnLastEventTime;
963             aEvent.maText           = String();
964             aEvent.mpTextAttr       = NULL;
965             aEvent.mnCursorPos      = 0;
966             aEvent.mnDeltaStart     = 0;
967             aEvent.mnCursorFlags    = 0;
968             aEvent.mbOnlyCursor     = FALSE;
969             mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
970             if( AquaSalFrame::isAlive( mpFrame ) )
971                 mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
973         }
974         mbKeyHandled = true;
975         [self unmarkText];
976     }
979 -(void)insertTab: (id)aSender
981     [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
984 -(void)insertBacktab: (id)aSender
986     [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
989 -(void)moveLeft: (id)aSender
991     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
994 -(void)moveLeftAndModifySelection: (id)aSender
996     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
999 -(void)moveBackwardAndModifySelection: (id)aSender
1001     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1004 -(void)moveRight: (id)aSender
1006     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1009 -(void)moveRightAndModifySelection: (id)aSender
1011     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1014 -(void)moveForwardAndModifySelection: (id)aSender
1016     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1019 -(void)moveWordLeft: (id)aSender
1021     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1024 -(void)moveWordBackward: (id)aSender
1026     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1029 -(void)moveWordBackwardAndModifySelection: (id)aSender
1031     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1034 -(void)moveWordLeftAndModifySelection: (id)aSender
1036     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1039 -(void)moveWordRight: (id)aSender
1041     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1044 -(void)moveWordForward: (id)aSender
1046     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1049 -(void)moveWordForwardAndModifySelection: (id)aSender
1051     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1054 -(void)moveWordRightAndModifySelection: (id)aSender
1056     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1059 -(void)moveToEndOfLine: (id)aSender
1061     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1064 -(void)moveToEndOfLineAndModifySelection: (id)aSender
1066     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1069 -(void)moveToBeginningOfLine: (id)aSender
1071     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1074 -(void)moveToBeginningOfLineAndModifySelection: (id)aSender
1076     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1079 -(void)moveToEndOfParagraph: (id)aSender
1081     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1084 -(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1086     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1089 -(void)moveParagraphForward: (id)aSender
1091     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1094 -(void)moveParagraphForwardAndModifySelection: (id)aSender
1096     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1099 -(void)moveToBeginningOfParagraph: (id)aSender
1101     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1104 -(void)moveParagraphBackward: (id)aSender
1106     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1109 -(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender
1111     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1114 -(void)moveParagraphBackwardAndModifySelection: (id)aSender
1116     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1119 -(void)moveToEndOfDocument: (id)aSender
1121     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1124 -(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1126     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1129 -(void)moveToBeginningOfDocument: (id)aSender
1131     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1134 -(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1136     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1139 -(void)moveUp: (id)aSender
1141     [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1144 -(void)moveDown: (id)aSender
1146     [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1149 -(void)insertNewline: (id)aSender
1151     // #i91267# make enter and shift-enter work by evaluating the modifiers
1152     [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1155 -(void)deleteBackward: (id)aSender
1157     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1160 -(void)deleteForward: (id)aSender
1162     [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1165 -(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1167     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1170 -(void)deleteWordBackward: (id)aSender
1172     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1175 -(void)deleteWordForward: (id)aSender
1177     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1180 -(void)deleteToBeginningOfLine: (id)aSender
1182     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1185 -(void)deleteToEndOfLine: (id)aSender
1187     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1190 -(void)deleteToBeginningOfParagraph: (id)aSender
1192     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1195 -(void)deleteToEndOfParagraph: (id)aSender
1197     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1200 -(void)insertLineBreak: (id)aSender
1202     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1205 -(void)insertParagraphSeparator: (id)aSender
1207     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1210 -(void)selectWord: (id)aSender
1212     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1215 -(void)selectLine: (id)aSender
1217     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1220 -(void)selectParagraph: (id)aSender
1222     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1225 -(void)selectAll: (id)aSender
1227     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1230 -(void)cancelOperation: (id)aSender
1232     [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1235 -(void)noop: (id)aSender
1237     if( ! mbKeyHandled )
1238     {
1239         if( ! [self sendSingleCharacter:mpLastEvent] )
1240         {
1241             /* prevent recursion */
1242             if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1243             {
1244                 id pLastSuperEvent = mpLastSuperEvent;
1245                 mpLastSuperEvent = mpLastEvent;
1246                 [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1247                 mpLastSuperEvent = pLastSuperEvent;
1248                 
1249                 std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1250                 if( it != GetSalData()->maKeyEventAnswer.end() )
1251                     it->second = true;
1252             }
1253         }
1254     }
1257 -(MacOSBOOL)sendKeyInputAndReleaseToFrame: (USHORT)nKeyCode character: (sal_Unicode)aChar
1259     return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1262 -(MacOSBOOL)sendKeyInputAndReleaseToFrame: (USHORT)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1264     return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1265            [self sendSingleCharacter: mpLastEvent];
1268 -(MacOSBOOL)sendKeyToFrameDirect: (USHORT)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1270     YIELD_GUARD;
1271     
1272     long nRet = 0;
1273     if( AquaSalFrame::isAlive( mpFrame ) )
1274     {
1275         SalKeyEvent aEvent;
1276         aEvent.mnTime           = mpFrame->mnLastEventTime;
1277         aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1278         aEvent.mnCharCode       = aChar;
1279         aEvent.mnRepeat         = FALSE;
1280         nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent );
1281         std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1282         if( it != GetSalData()->maKeyEventAnswer.end() )
1283             it->second = nRet ? true : false;
1284         if( AquaSalFrame::isAlive( mpFrame ) )
1285             mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent );
1286     }
1287     return nRet ? YES : NO;
1291 -(MacOSBOOL)sendSingleCharacter: (NSEvent *)pEvent
1293     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; 
1295     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1296     {
1297         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1298         USHORT nKeyCode = ImplMapCharCode( keyChar );
1299         if( nKeyCode != 0 )
1300         {
1301             // don't send unicodes in the private use area
1302             if( keyChar >= 0xf700 && keyChar < 0xf780 )
1303                 keyChar = 0;
1304             MacOSBOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1305             mbInKeyInput = false;
1307             return bRet;
1308         }
1309     }
1310     return NO;
1314 // NSTextInput protocol
1315 - (NSArray *)validAttributesForMarkedText
1317     return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1320 - (MacOSBOOL)hasMarkedText
1322     MacOSBOOL bHasMarkedText;
1324     bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1325                      ( mMarkedRange.length != 0 );
1326     // hack to check keys like "Control-j"
1327     if( mbInKeyInput )
1328     {
1329         mbNeedSpecialKeyHandle = true;
1330     }
1331     return bHasMarkedText;
1334 - (NSRange)markedRange
1336     return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1339 - (NSRange)selectedRange
1341     return mSelectedRange;
1344 - (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
1346     if( ![aString isKindOfClass:[NSAttributedString class]] )
1347         aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1348     NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1349     if( rangeToReplace.location == NSNotFound )
1350     {
1351         mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1352         mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1353     }
1354     else
1355     {
1356         mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1357         mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1358     }
1360     int len = [aString length];
1361     SalExtTextInputEvent aInputEvent;
1362     aInputEvent.mnTime = mpFrame->mnLastEventTime;
1363     aInputEvent.mnDeltaStart = 0;
1364     aInputEvent.mbOnlyCursor = FALSE;
1365     if( len > 0 ) {
1366         NSString *pString = [aString string];
1367         OUString aInsertString( GetOUString( pString ) );
1368         std::vector<USHORT> aInputFlags = std::vector<USHORT>( std::max( 1, len ), 0 );
1369         for ( int i = 0; i < len; i++ )
1370         {
1371             unsigned int nUnderlineValue;
1372             NSRange effectiveRange;
1373             
1374             effectiveRange = NSMakeRange(i, 1);
1375             nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1377             switch (nUnderlineValue & 0xff) {
1378             case NSUnderlineStyleSingle:
1379                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
1380                 break;
1381             case NSUnderlineStyleThick:
1382                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1383                 break;
1384             case NSUnderlineStyleDouble:
1385                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
1386                 break;
1387             default:
1388                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1389                 break;
1390             }
1391         }
1393         aInputEvent.maText = aInsertString;
1394         aInputEvent.mnCursorPos = selRange.location;
1395         aInputEvent.mpTextAttr = &aInputFlags[0];
1396         mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1397     } else {
1398         aInputEvent.maText = String();
1399         aInputEvent.mnCursorPos = 0;
1400         aInputEvent.mnCursorFlags = 0;
1401         aInputEvent.mpTextAttr = 0;
1402         mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1403         mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1404     }
1405     mbKeyHandled= true;
1408 - (void)unmarkText
1410     mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1413 - (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
1415     // FIXME
1416     return nil;
1419 - (unsigned int)characterIndexForPoint:(NSPoint)thePoint
1421     // FIXME
1422     return 0;
1425 #if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
1426 /* build target 10.5 or greater */
1427 - (NSInteger)conversationIdentifier
1428 #else
1429 /* build target 10.4 */ 
1430 - (long)conversationIdentifier
1431 #endif
1433     return (long)self;
1436 - (void)doCommandBySelector:(SEL)aSelector
1438     if( AquaSalFrame::isAlive( mpFrame ) )
1439     {
1440         if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 &&
1441             aSelector != NULL && [self respondsToSelector: aSelector] )
1442         {
1443             [self performSelector: aSelector];
1444         }
1445         else
1446         {
1447             [self sendSingleCharacter:mpLastEvent];
1448         }
1449     }
1451     mbKeyHandled = true;
1454 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
1456     SalExtTextInputPosEvent aPosEvent;
1457     mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent );
1459     NSRect rect;
1461     rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1462     rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1463     rect.size.width = aPosEvent.mnWidth;
1464     rect.size.height = aPosEvent.mnHeight;
1466     mpFrame->VCLToCocoa( rect );
1467     return rect;
1470 -(id)parentAttribute {
1471     return (NSView *) mpFrame -> mpWindow;
1474 -(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext
1476     if ( mpReferenceWrapper == nil ) {
1477         // some frames never become visible ..
1478         Window *pWindow = mpFrame -> GetWindow();
1479         if ( ! pWindow ) 
1480             return nil;
1482         mpReferenceWrapper = new ReferenceWrapper;
1483         mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1484         [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1485     }
1486     return [ super accessibleContext ];
1489 -(NSView *)viewElementForParent
1491     return (NSView *) mpFrame -> mpWindow;
1494 -(void)registerMouseEventListener: (id)theListener
1496   mpMouseEventListener = theListener;
1499 -(void)unregisterMouseEventListener: (id)theListener
1501   mpMouseEventListener = nil;
1504 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1506   return [mDraggingDestinationHandler draggingEntered: sender];
1509 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1511   return [mDraggingDestinationHandler draggingUpdated: sender];
1514 -(void)draggingExited:(id <NSDraggingInfo>)sender
1516   [mDraggingDestinationHandler draggingExited: sender];
1519 -(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1521   return [mDraggingDestinationHandler prepareForDragOperation: sender];
1524 -(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender
1526   return [mDraggingDestinationHandler performDragOperation: sender];
1529 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1531   [mDraggingDestinationHandler concludeDragOperation: sender];
1534 -(void)registerDraggingDestinationHandler:(id)theHandler
1536   mDraggingDestinationHandler = theHandler;
1539 -(void)unregisterDraggingDestinationHandler:(id)theHandler
1541   mDraggingDestinationHandler = nil;
1544 @end