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