update dev300-m58
[ooovba.git] / vcl / aqua / source / window / salframeview.mm
blobc7facd8c6c09003db043e17e22f0ac58b0078ac9
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     return [super canBecomeKeyWindow];
190 -(void)windowDidBecomeKey: (NSNotification*)pNotification
192     YIELD_GUARD;
194     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
195     {
196         static const ULONG nGuessDocument = SAL_FRAME_STYLE_MOVEABLE|
197                                             SAL_FRAME_STYLE_SIZEABLE|
198                                             SAL_FRAME_STYLE_CLOSEABLE;
199         
200         if( mpFrame->mpMenu )
201             mpFrame->mpMenu->setMainMenu();
202         else if( ! mpFrame->mpParent &&
203                  ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help
204                     mpFrame->mbFullScreen ) )                               // ser default menu for e.g. presentation
205         {
206             AquaSalMenu::setDefaultMenu();
207         }
208         #if 0
209         // FIXME: we should disable menus while in modal mode
210         // however from down here there is currently no reliable way to
211         // find out when to do this
212         if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) )
213             AquaSalMenu::enableMainMenu( false );
214         #endif
215         mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
216     }
219 -(void)windowDidResignKey: (NSNotification*)pNotification
221     YIELD_GUARD;
223     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
224         mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0);
227 -(void)windowDidChangeScreen: (NSNotification*)pNotification
229     YIELD_GUARD;
231     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
232         mpFrame->screenParametersChanged();
235 -(void)windowDidMove: (NSNotification*)pNotification
237     YIELD_GUARD;
239     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
240     {
241         mpFrame->UpdateFrameGeometry();
242         mpFrame->CallCallback( SALEVENT_MOVE, 0 );
243     }
246 -(void)windowDidResize: (NSNotification*)pNotification
248     YIELD_GUARD;
250     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
251     {
252         mpFrame->UpdateFrameGeometry();
253         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
254         mpFrame->SendPaintEvent();
255     }
258 -(void)windowDidMiniaturize: (NSNotification*)pNotification
260     YIELD_GUARD;
262     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
263     {
264         mpFrame->mbShown = false;
265         mpFrame->UpdateFrameGeometry();
266         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
267     }
270 -(void)windowDidDeminiaturize: (NSNotification*)pNotification
272     YIELD_GUARD;
274     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
275     {
276         mpFrame->mbShown = true;
277         mpFrame->UpdateFrameGeometry();
278         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
279     }
282 -(MacOSBOOL)windowShouldClose: (NSNotification*)pNotification
284     YIELD_GUARD;
286     MacOSBOOL bRet = YES;
287     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
288     {
289         // #i84461# end possible input
290         mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
291         if( AquaSalFrame::isAlive( mpFrame ) )
292         {
293             mpFrame->CallCallback( SALEVENT_CLOSE, 0 );
294             bRet = NO; // application will close the window or not, AppKit shouldn't
295         }
296     }
298     return bRet;
301 -(void)dockMenuItemTriggered: (id)sender
303     YIELD_GUARD;
305     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
306         mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS );
309 -(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext
311     return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
314 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
316   return [mDraggingDestinationHandler draggingEntered: sender];
319 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
321   return [mDraggingDestinationHandler draggingUpdated: sender];
324 -(void)draggingExited:(id <NSDraggingInfo>)sender
326   [mDraggingDestinationHandler draggingExited: sender];
329 -(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
331   return [mDraggingDestinationHandler prepareForDragOperation: sender];
334 -(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender
336   return [mDraggingDestinationHandler performDragOperation: sender];
339 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
341   [mDraggingDestinationHandler concludeDragOperation: sender];
344 -(void)registerDraggingDestinationHandler:(id)theHandler
346   mDraggingDestinationHandler = theHandler;
349 -(void)unregisterDraggingDestinationHandler:(id)theHandler
351     mDraggingDestinationHandler = nil;
354 @end
356 @implementation SalFrameView
357 +(void)unsetMouseFrame: (AquaSalFrame*)pFrame
359     if( pFrame == s_pMouseFrame )
360         s_pMouseFrame = NULL;
363 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
365     if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil)
366     {
367         mDraggingDestinationHandler = nil;
368         mpFrame = pFrame;
369         mMarkedRange = NSMakeRange(NSNotFound, 0);
370         mSelectedRange = NSMakeRange(NSNotFound, 0);
371         mpReferenceWrapper = nil;
372                 mpMouseEventListener = nil;
373         mpLastSuperEvent = nil;
374     }
376     return self;
379 -(void)resetCursorRects
381     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
382     {
383         // FIXME: does this leak the returned NSCursor of getCurrentCursor ?
384         NSRect aRect = { { 0, 0 }, { mpFrame->maGeometry.nWidth, mpFrame->maGeometry.nHeight } };
385         [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()];
386     }
389 -(MacOSBOOL)acceptsFirstResponder
391     return YES;
394 -(MacOSBOOL)acceptsFirstMouse: (NSEvent*)pEvent
396     return YES;
399 -(MacOSBOOL)isOpaque
401     return mpFrame ? (mpFrame->getClipPath() != 0 ? NO : YES) : YES;
404 // helper class similar to a vos::OGuard for the SalYieldMutex
405 // the difference is that it only does tryToAcquire instead of aquire
406 // so dreaded deadlocks like #i93512# are prevented
407 class TryGuard
409 public:
410                         TryGuard()  { mbGuarded = ImplSalYieldMutexTryToAcquire(); }
411                         ~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); }
412         bool    IsGuarded() { return mbGuarded; }
413 private:
414         bool    mbGuarded;
417 -(void)drawRect: (NSRect)aRect
419         // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
420         TryGuard aTryGuard;
421         if( !aTryGuard.IsGuarded() )
422         {
423                 // NOTE: the mpFrame access below is not guarded yet!
424                 // TODO: mpFrame et al need to be guarded by an independent mutex
425                 AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL;
426                 if( pGraphics )
427                 {
428                         // we did not get the mutex so we cannot draw now => request to redraw later
429                         // convert the NSRect to a CGRect for Refreshrect()
430                         const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}};
431                         pGraphics->RefreshRect( aCGRect );
432                 }
433                 return;
434         }
436     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
437     {
438         if( mpFrame->mpGraphics )
439         {
440             mpFrame->mpGraphics->UpdateWindow( aRect );
441             if( mpFrame->getClipPath() )
442                 [mpFrame->getWindow() invalidateShadow];
443         }
444     }
447 -(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(USHORT)nButton eventtype:(USHORT)nEvent
449     YIELD_GUARD;
451     AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
452     bool bIsCaptured = false;
453     if( pDispatchFrame )
454     {
455         bIsCaptured = true;
456         if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured
457             nEvent = SALEVENT_MOUSEMOVE;
458     }
459     else if( s_pMouseFrame )
460         pDispatchFrame = s_pMouseFrame;
461     else
462         pDispatchFrame = mpFrame;
463     
464     /* #i81645# Cocoa reports mouse events while a button is pressed
465        to the window in which it was first pressed. This is reasonable and fine and
466        gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
467        however vcl expects mouse events to occur in the window the mouse is over, unless the
468        mouse is explicitly captured. So we need to find the window the mouse is actually
469        over for conformance with other platforms.
470     */
471     if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
472     {
473         // is this event actually inside that NSWindow ?
474         NSPoint aPt = [NSEvent mouseLocation];
475         NSRect aFrameRect = [pDispatchFrame->getWindow() frame];
476         
477         if ( ! NSPointInRect( aPt, aFrameRect ) )
478         {
479             // no, it is not
480             // now we need to find the one it may be in
481             /* #i93756# we ant to get enumerate the application windows in z-order
482                to check if any contains the mouse. This could be elegantly done with this
483                code:
485                // use NSApp to check windows in ZOrder whether they contain the mouse pointer
486                NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
487                if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
488                    pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
489                
490                However if a non SalFrameWindow is on screen (like e.g. the file dialog)
491                it can be hit with the containsMouse selector, which it doesn't support.
492                Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
493                I assume) whether a window supports a selector before sending it. 
494             */
495             AquaSalFrame* pMouseFrame = getMouseContainerFrame();
496             if( pMouseFrame )
497                 pDispatchFrame = pMouseFrame;
498         }
499     }
500     
501     if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
502     {
503         pDispatchFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
504         pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
506         NSPoint aPt = [NSEvent mouseLocation];
507         pDispatchFrame->CocoaToVCL( aPt );
508         
509         USHORT nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
510         // #i82284# emulate ctrl left
511         if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
512         {
513             nModMask    = 0;
514             nButton     = MOUSE_RIGHT;
515         }
517         SalMouseEvent aEvent;
518         aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
519         aEvent.mnX      = static_cast<long>(aPt.x) - pDispatchFrame->maGeometry.nX;
520         aEvent.mnY      = static_cast<long>(aPt.y) - pDispatchFrame->maGeometry.nY;
521         aEvent.mnButton = nButton;
522         aEvent.mnCode   =  aEvent.mnButton | nModMask;
524         // --- RTL --- (mirror mouse pos)
525         if( Application::GetSettings().GetLayoutRTL() )
526             aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
527         
528         pDispatchFrame->CallCallback( nEvent, &aEvent );
529     }
532 -(void)mouseDown: (NSEvent*)pEvent
534     if ( mpMouseEventListener != nil && 
535             [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
536         {
537             [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]];
538         }
540     s_nLastButton = MOUSE_LEFT;
541     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN];
544 -(void)mouseDragged: (NSEvent*)pEvent
546     if ( mpMouseEventListener != nil && 
547              [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
548         {
549             [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]];
550         }
551     s_nLastButton = MOUSE_LEFT;
552     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE];
555 -(void)mouseUp: (NSEvent*)pEvent
557     s_nLastButton = 0;
558     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP];
561 -(void)mouseMoved: (NSEvent*)pEvent
563     s_nLastButton = 0;
564     [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE];
567 -(void)mouseEntered: (NSEvent*)pEvent
569     s_pMouseFrame = mpFrame;
570     
571     [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE];
574 -(void)mouseExited: (NSEvent*)pEvent
576     if( s_pMouseFrame == mpFrame )
577         s_pMouseFrame = NULL;
579     [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE];
582 -(void)rightMouseDown: (NSEvent*)pEvent
584     s_nLastButton = MOUSE_RIGHT;
585     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN];
588 -(void)rightMouseDragged: (NSEvent*)pEvent
590     s_nLastButton = MOUSE_RIGHT;
591     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE];
594 -(void)rightMouseUp: (NSEvent*)pEvent
596     s_nLastButton = 0;
597     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP];
600 -(void)otherMouseDown: (NSEvent*)pEvent
602     if( [pEvent buttonNumber] == 2 )
603     {
604         s_nLastButton = MOUSE_MIDDLE;
605         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN];
606     }
607     else
608         s_nLastButton = 0;
611 -(void)otherMouseDragged: (NSEvent*)pEvent
613     if( [pEvent buttonNumber] == 2 )
614     {
615         s_nLastButton = MOUSE_MIDDLE;
616         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE];
617     }
618     else
619         s_nLastButton = 0;
622 -(void)otherMouseUp: (NSEvent*)pEvent
624     s_nLastButton = 0;
625     if( [pEvent buttonNumber] == 2 )
626         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP];
629 - (void)magnifyWithEvent: (NSEvent*)pEvent
631     YIELD_GUARD;
632     
633     // TODO: ??  -(float)magnification;
634     if( AquaSalFrame::isAlive( mpFrame ) )
635     {
636         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
637         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
638         
639         float dZ = 0.0;
640         for(;;)
641         {
642             dZ += [pEvent deltaZ];
643             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
644             untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
645             if( !pNextEvent )
646                 break;
647             pEvent = pNextEvent;
648         }
649         
650         NSPoint aPt = [NSEvent mouseLocation];
651         mpFrame->CocoaToVCL( aPt );
652         
653         SalWheelMouseEvent aEvent;
654         aEvent.mnTime   = mpFrame->mnLastEventTime;
655         aEvent.mnX      = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
656         aEvent.mnY      = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
657         aEvent.mnCode   = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
658         aEvent.mnCode   |= KEY_MOD1; // we want zooming, no scrolling
659         
660         // --- RTL --- (mirror mouse pos)
661         if( Application::GetSettings().GetLayoutRTL() )
662             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
663         
664         if( dZ != 0.0 )
665         {
666             aEvent.mnDelta = static_cast<long>(floor(dZ));
667             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
668             if( aEvent.mnNotchDelta == 0 )
669                 aEvent.mnNotchDelta = dZ < 0.0 ? -1 : 1;
670             aEvent.mbHorz = FALSE;
671             aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta;
672             if( aEvent.mnScrollLines == 0 )
673                 aEvent.mnScrollLines = 1;
674             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
675         }
676     }
679 - (void)rotateWithEvent: (NSEvent*)pEvent
681     //Rotation : -(float)rotation;
682     // TODO: create new CommandType so rotation is available to the applications
685 - (void)swipeWithEvent: (NSEvent*)pEvent
687     YIELD_GUARD;
688     
689     if( AquaSalFrame::isAlive( mpFrame ) )
690     {
691         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
692         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
693         
694         // merge pending scroll wheel events
695         float dX = 0.0;
696         float dY = 0.0;
697         for(;;)
698         {
699             dX += [pEvent deltaX];
700             dY += [pEvent deltaY];
701             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
702             untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
703             if( !pNextEvent )
704                 break;
705             pEvent = pNextEvent;
706         }
707         
708         NSPoint aPt = [NSEvent mouseLocation];
709         mpFrame->CocoaToVCL( aPt );
710         
711         SalWheelMouseEvent aEvent;
712         aEvent.mnTime   = mpFrame->mnLastEventTime;
713         aEvent.mnX      = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
714         aEvent.mnY      = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
715         aEvent.mnCode   = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
716         
717         // --- RTL --- (mirror mouse pos)
718         if( Application::GetSettings().GetLayoutRTL() )
719             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
720         
721         if( dX != 0.0 )
722         {
723             aEvent.mnDelta = static_cast<long>(floor(dX));
724             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
725             if( aEvent.mnNotchDelta == 0 )
726                 aEvent.mnNotchDelta = dX < 0.0 ? -1 : 1;
727             aEvent.mbHorz = TRUE;
728             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
729             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
730         }
731         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
732         {
733             aEvent.mnDelta = static_cast<long>(floor(dY));
734             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
735             if( aEvent.mnNotchDelta == 0 )
736                 aEvent.mnNotchDelta = dY < 0.0 ? -1 : 1;
737             aEvent.mbHorz = FALSE;
738             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
739             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
740         }
741     }
744 -(void)scrollWheel: (NSEvent*)pEvent
746     YIELD_GUARD;
747     
748     if( AquaSalFrame::isAlive( mpFrame ) )
749     {
750         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
751         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
753         // merge pending scroll wheel events
754         float dX = 0.0;
755         float dY = 0.0;
756         for(;;)
757         {
758             dX += [pEvent deltaX];
759             dY += [pEvent deltaY];
760             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
761                 untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
762             if( !pNextEvent )
763                 break;
764             pEvent = pNextEvent;
765         }
767         NSPoint aPt = [NSEvent mouseLocation];
768         mpFrame->CocoaToVCL( aPt );
770         SalWheelMouseEvent aEvent;
771         aEvent.mnTime   = mpFrame->mnLastEventTime;
772         aEvent.mnX      = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
773         aEvent.mnY      = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
774         aEvent.mnCode   = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
776         // --- RTL --- (mirror mouse pos)
777         if( Application::GetSettings().GetLayoutRTL() )
778             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
780         if( dX != 0.0 )
781         {
782             aEvent.mnDelta = static_cast<long>(floor(dX));
783             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
784             if( aEvent.mnNotchDelta == 0 )
785                 aEvent.mnNotchDelta = dX < 0.0 ? -1 : 1;
786             aEvent.mbHorz = TRUE;
787             aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta;
788             if( aEvent.mnScrollLines == 0 )
789                 aEvent.mnScrollLines = 1;
790             if( aEvent.mnScrollLines > 15 )
791                 aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
792             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
793         }
794         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
795         {
796             aEvent.mnDelta = static_cast<long>(floor(dY));
797             aEvent.mnNotchDelta = aEvent.mnDelta / 8;
798             if( aEvent.mnNotchDelta == 0 )
799                 aEvent.mnNotchDelta = dY < 0.0 ? -1 : 1;
800             aEvent.mbHorz = FALSE;
801             aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta;
802             if( aEvent.mnScrollLines == 0 )
803                 aEvent.mnScrollLines = 1;
804             if( aEvent.mnScrollLines > 15 )
805                 aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
806             
807             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
808         }
809     }
813 -(void)keyDown: (NSEvent*)pEvent
815     YIELD_GUARD;
816     
817     if( AquaSalFrame::isAlive( mpFrame ) )
818     {
819         mpLastEvent = pEvent;
820         mbInKeyInput = true;
821         mbNeedSpecialKeyHandle = false;
822         mbKeyHandled = false;
824         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
825         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
826         
827         if( ! [self handleKeyDownException: pEvent] )
828         {
829             NSArray* pArray = [NSArray arrayWithObject: pEvent];
830             [self interpretKeyEvents: pArray];
831         }
833         mbInKeyInput = false;
834     }
837 -(MacOSBOOL)handleKeyDownException:(NSEvent*)pEvent
839     // check for a very special set of modified characters
840     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; 
842     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
843     {
844         /* #i103102# key events with command and alternate don't make it through
845            interpretKeyEvents (why ?). Try to dispatch them here first,
846            if not successful continue normally
847         */
848         if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
849                     == (NSAlternateKeyMask | NSCommandKeyMask) )
850         {
851             if( [self sendSingleCharacter: mpLastEvent] )
852                 return YES;
853         }
854         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
855         USHORT nKeyCode = ImplMapCharCode( keyChar );
856         
857         // Caution: should the table grow to more than 5 or 6 entries,
858         // we must consider moving it to a kind of hash map
859         const unsigned int nExceptions = sizeof( aExceptionalKeys ) / sizeof( aExceptionalKeys[0] );
860         for( unsigned int i = 0; i < nExceptions; i++ )
861         {
862             if( nKeyCode == aExceptionalKeys[i].nKeyCode &&
863                 (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask)
864                 == aExceptionalKeys[i].nModifierMask )
865             {
866                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0];
868                 return YES;
869             }
870         }
871     }
872     return NO;
875 -(void)flagsChanged: (NSEvent*)pEvent
877     YIELD_GUARD;
878     
879     if( AquaSalFrame::isAlive( mpFrame ) )
880     {
881         mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 );
882         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
883     }
886 -(void)insertText:(id)aString
888     YIELD_GUARD;
889     
890     if( AquaSalFrame::isAlive( mpFrame ) )
891     {
892         NSString* pInsert = nil;
893         if( [aString isMemberOfClass: [NSAttributedString class]] )
894             pInsert = [aString string];
895         else
896             pInsert = aString;
897         
898         int nLen = 0;
899         if( pInsert && ( nLen = [pInsert length] ) > 0 )
900         {
901             OUString aInsertString( GetOUString( pInsert ) );
902              // aCharCode initializer is safe since aInsertString will at least contain '\0'
903             sal_Unicode aCharCode = *aInsertString.getStr();
904             
905             if( nLen == 1 &&
906                 aCharCode < 0x80 &&
907                 aCharCode > 0x1f &&
908                                 ! [self hasMarkedText ]
909                 )
910             {
911                 USHORT nKeyCode = ImplMapCharCode( aCharCode );
912                 unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
914                 // #i99567#
915                 // find out the unmodified key code
916     
917                 // sanity check
918                 if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
919                 {
920                     // get unmodified string
921                     NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers]; 
922                     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
923                     {
924                         // map the unmodified key code
925                         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
926                         nKeyCode = ImplMapCharCode( keyChar );
927                     }
928                     nLastModifiers = [mpLastEvent modifierFlags];
930                 }
931                 // #i99567#
932                 // applications and vcl's edit fields ignore key events with ALT
933                 // however we're at a place where we know text should be inserted
934                 // so it seems we need to strip the Alt modifier here
935                 if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
936                     == NSAlternateKeyMask )
937                 {
938                     nLastModifiers = 0;
939                 }
940                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
941             }
942             else
943             {
944                 SalExtTextInputEvent aEvent;
945                 aEvent.mnTime           = mpFrame->mnLastEventTime;
946                 aEvent.maText           = aInsertString;
947                 aEvent.mpTextAttr       = NULL;
948                 aEvent.mnCursorPos      = aInsertString.getLength();
949                 aEvent.mnDeltaStart     = 0;
950                 aEvent.mnCursorFlags    = 0;
951                 aEvent.mbOnlyCursor     = FALSE;
952                 mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
953                 if( AquaSalFrame::isAlive( mpFrame ) )
954                     mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
955             }
956         }
957         else
958         {
959             SalExtTextInputEvent aEvent;
960             aEvent.mnTime           = mpFrame->mnLastEventTime;
961             aEvent.maText           = String();
962             aEvent.mpTextAttr       = NULL;
963             aEvent.mnCursorPos      = 0;
964             aEvent.mnDeltaStart     = 0;
965             aEvent.mnCursorFlags    = 0;
966             aEvent.mbOnlyCursor     = FALSE;
967             mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
968             if( AquaSalFrame::isAlive( mpFrame ) )
969                 mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
971         }
972         mbKeyHandled = true;
973         [self unmarkText];
974     }
977 -(void)insertTab: (id)aSender
979     [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
982 -(void)insertBacktab: (id)aSender
984     [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
987 -(void)moveLeft: (id)aSender
989     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
992 -(void)moveLeftAndModifySelection: (id)aSender
994     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
997 -(void)moveBackwardAndModifySelection: (id)aSender
999     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1002 -(void)moveRight: (id)aSender
1004     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1007 -(void)moveRightAndModifySelection: (id)aSender
1009     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1012 -(void)moveForwardAndModifySelection: (id)aSender
1014     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1017 -(void)moveWordLeft: (id)aSender
1019     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1022 -(void)moveWordBackward: (id)aSender
1024     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1027 -(void)moveWordBackwardAndModifySelection: (id)aSender
1029     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1032 -(void)moveWordLeftAndModifySelection: (id)aSender
1034     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1037 -(void)moveWordRight: (id)aSender
1039     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1042 -(void)moveWordForward: (id)aSender
1044     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1047 -(void)moveWordForwardAndModifySelection: (id)aSender
1049     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1052 -(void)moveWordRightAndModifySelection: (id)aSender
1054     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1057 -(void)moveToEndOfLine: (id)aSender
1059     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1062 -(void)moveToEndOfLineAndModifySelection: (id)aSender
1064     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1067 -(void)moveToBeginningOfLine: (id)aSender
1069     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1072 -(void)moveToBeginningOfLineAndModifySelection: (id)aSender
1074     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1077 -(void)moveToEndOfParagraph: (id)aSender
1079     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1082 -(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1084     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1087 -(void)moveParagraphForward: (id)aSender
1089     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1092 -(void)moveParagraphForwardAndModifySelection: (id)aSender
1094     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1097 -(void)moveToBeginningOfParagraph: (id)aSender
1099     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1102 -(void)moveParagraphBackward: (id)aSender
1104     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1107 -(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender
1109     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1112 -(void)moveParagraphBackwardAndModifySelection: (id)aSender
1114     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1117 -(void)moveToEndOfDocument: (id)aSender
1119     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1122 -(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1124     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1127 -(void)moveToBeginningOfDocument: (id)aSender
1129     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1132 -(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1134     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1137 -(void)moveUp: (id)aSender
1139     [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1142 -(void)moveDown: (id)aSender
1144     [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1147 -(void)insertNewline: (id)aSender
1149     // #i91267# make enter and shift-enter work by evaluating the modifiers
1150     [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1153 -(void)deleteBackward: (id)aSender
1155     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1158 -(void)deleteForward: (id)aSender
1160     [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1163 -(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1165     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1168 -(void)deleteWordBackward: (id)aSender
1170     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1173 -(void)deleteWordForward: (id)aSender
1175     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1178 -(void)deleteToBeginningOfLine: (id)aSender
1180     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1183 -(void)deleteToEndOfLine: (id)aSender
1185     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1188 -(void)deleteToBeginningOfParagraph: (id)aSender
1190     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1193 -(void)deleteToEndOfParagraph: (id)aSender
1195     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1198 -(void)insertLineBreak: (id)aSender
1200     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1203 -(void)insertParagraphSeparator: (id)aSender
1205     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1208 -(void)selectWord: (id)aSender
1210     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1213 -(void)selectLine: (id)aSender
1215     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1218 -(void)selectParagraph: (id)aSender
1220     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1223 -(void)selectAll: (id)aSender
1225     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1228 -(void)cancelOperation: (id)aSender
1230     [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1233 -(void)noop: (id)aSender
1235     if( ! mbKeyHandled )
1236     {
1237         if( ! [self sendSingleCharacter:mpLastEvent] )
1238         {
1239             /* prevent recursion */
1240             if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1241             {
1242                 id pLastSuperEvent = mpLastSuperEvent;
1243                 mpLastSuperEvent = mpLastEvent;
1244                 [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1245                 mpLastSuperEvent = pLastSuperEvent;
1246                 
1247                 std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1248                 if( it != GetSalData()->maKeyEventAnswer.end() )
1249                     it->second = true;
1250             }
1251         }
1252     }
1255 -(MacOSBOOL)sendKeyInputAndReleaseToFrame: (USHORT)nKeyCode character: (sal_Unicode)aChar
1257     return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1260 -(MacOSBOOL)sendKeyInputAndReleaseToFrame: (USHORT)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1262     return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1263            [self sendSingleCharacter: mpLastEvent];
1266 -(MacOSBOOL)sendKeyToFrameDirect: (USHORT)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1268     YIELD_GUARD;
1269     
1270     long nRet = 0;
1271     if( AquaSalFrame::isAlive( mpFrame ) )
1272     {
1273         SalKeyEvent aEvent;
1274         aEvent.mnTime           = mpFrame->mnLastEventTime;
1275         aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1276         aEvent.mnCharCode       = aChar;
1277         aEvent.mnRepeat         = FALSE;
1278         nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent );
1279         std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1280         if( it != GetSalData()->maKeyEventAnswer.end() )
1281             it->second = nRet ? true : false;
1282         if( AquaSalFrame::isAlive( mpFrame ) )
1283             mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent );
1284     }
1285     return nRet ? YES : NO;
1289 -(MacOSBOOL)sendSingleCharacter: (NSEvent *)pEvent
1291     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; 
1293     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1294     {
1295         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1296         USHORT nKeyCode = ImplMapCharCode( keyChar );
1297         if( nKeyCode != 0 )
1298         {
1299             // don't send unicodes in the private use area
1300             if( keyChar >= 0xf700 && keyChar < 0xf780 )
1301                 keyChar = 0;
1302             MacOSBOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1303             mbInKeyInput = false;
1305             return bRet;
1306         }
1307     }
1308     return NO;
1312 // NSTextInput protocol
1313 - (NSArray *)validAttributesForMarkedText
1315     return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1318 - (MacOSBOOL)hasMarkedText
1320     MacOSBOOL bHasMarkedText;
1322     bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1323                      ( mMarkedRange.length != 0 );
1324     // hack to check keys like "Control-j"
1325     if( mbInKeyInput )
1326     {
1327         mbNeedSpecialKeyHandle = true;
1328     }
1329     return bHasMarkedText;
1332 - (NSRange)markedRange
1334     return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1337 - (NSRange)selectedRange
1339     return mSelectedRange;
1342 - (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
1344     if( ![aString isKindOfClass:[NSAttributedString class]] )
1345         aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1346     NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1347     if( rangeToReplace.location == NSNotFound )
1348     {
1349         mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1350         mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1351     }
1352     else
1353     {
1354         mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1355         mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1356     }
1358     int len = [aString length];
1359     SalExtTextInputEvent aInputEvent;
1360     aInputEvent.mnTime = mpFrame->mnLastEventTime;
1361     aInputEvent.mnDeltaStart = 0;
1362     aInputEvent.mbOnlyCursor = FALSE;
1363     if( len > 0 ) {
1364         NSString *pString = [aString string];
1365         OUString aInsertString( GetOUString( pString ) );
1366         std::vector<USHORT> aInputFlags = std::vector<USHORT>( std::max( 1, len ), 0 );
1367         for ( int i = 0; i < len; i++ )
1368         {
1369             unsigned int nUnderlineValue;
1370             NSRange effectiveRange;
1371             
1372             effectiveRange = NSMakeRange(i, 1);
1373             nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1375             switch (nUnderlineValue & 0xff) {
1376             case NSUnderlineStyleSingle:
1377                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
1378                 break;
1379             case NSUnderlineStyleThick:
1380                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1381                 break;
1382             case NSUnderlineStyleDouble:
1383                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
1384                 break;
1385             default:
1386                 aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1387                 break;
1388             }
1389         }
1391         aInputEvent.maText = aInsertString;
1392         aInputEvent.mnCursorPos = selRange.location;
1393         aInputEvent.mpTextAttr = &aInputFlags[0];
1394         mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1395     } else {
1396         aInputEvent.maText = String();
1397         aInputEvent.mnCursorPos = 0;
1398         aInputEvent.mnCursorFlags = 0;
1399         aInputEvent.mpTextAttr = 0;
1400         mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1401         mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1402     }
1403     mbKeyHandled= true;
1406 - (void)unmarkText
1408     mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1411 - (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
1413     // FIXME
1414     return nil;
1417 - (unsigned int)characterIndexForPoint:(NSPoint)thePoint
1419     // FIXME
1420     return 0;
1423 #ifdef MAC_OS_X_VERSION_10_5
1424 /* build target 10.5 or greater */
1425 - (NSInteger)conversationIdentifier
1426 #else
1427 /* build target 10.4 */ 
1428 - (long)conversationIdentifier
1429 #endif
1431     return (long)self;
1434 - (void)doCommandBySelector:(SEL)aSelector
1436     if( AquaSalFrame::isAlive( mpFrame ) )
1437     {
1438         if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 &&
1439             aSelector != NULL && [self respondsToSelector: aSelector] )
1440         {
1441             [self performSelector: aSelector];
1442         }
1443         else
1444         {
1445             [self sendSingleCharacter:mpLastEvent];
1446         }
1447     }
1449     mbKeyHandled = true;
1452 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
1454     SalExtTextInputPosEvent aPosEvent;
1455     mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent );
1457     NSRect rect;
1459     rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1460     rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1461     rect.size.width = aPosEvent.mnWidth;
1462     rect.size.height = aPosEvent.mnHeight;
1464     mpFrame->VCLToCocoa( rect );
1465     return rect;
1468 -(id)parentAttribute {
1469     return (NSView *) mpFrame -> mpWindow;
1472 -(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext
1474     if ( mpReferenceWrapper == nil ) {
1475         // some frames never become visible ..
1476         Window *pWindow = mpFrame -> GetWindow();
1477         if ( ! pWindow ) 
1478             return nil;
1480         mpReferenceWrapper = new ReferenceWrapper;
1481         mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1482         [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1483     }
1484     return [ super accessibleContext ];
1487 -(NSView *)viewElementForParent
1489     return (NSView *) mpFrame -> mpWindow;
1492 -(void)registerMouseEventListener: (id)theListener
1494   mpMouseEventListener = theListener;
1497 -(void)unregisterMouseEventListener: (id)theListener
1499   mpMouseEventListener = nil;
1502 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1504   return [mDraggingDestinationHandler draggingEntered: sender];
1507 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1509   return [mDraggingDestinationHandler draggingUpdated: sender];
1512 -(void)draggingExited:(id <NSDraggingInfo>)sender
1514   [mDraggingDestinationHandler draggingExited: sender];
1517 -(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1519   return [mDraggingDestinationHandler prepareForDragOperation: sender];
1522 -(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender
1524   return [mDraggingDestinationHandler performDragOperation: sender];
1527 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1529   [mDraggingDestinationHandler concludeDragOperation: sender];
1532 -(void)registerDraggingDestinationHandler:(id)theHandler
1534   mDraggingDestinationHandler = theHandler;
1537 -(void)unregisterDraggingDestinationHandler:(id)theHandler
1539   mDraggingDestinationHandler = nil;
1542 @end