1 /* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #import "config.h" 27 #import "WKTextInputWindowController.h" 28 29 #import <WebKitSystemInterface.h> 30 31 @interface WKTextInputPanel : NSPanel { 32 NSTextView *_inputTextView; 33 } 34 35 - (NSTextInputContext *)_inputContext; 36 - (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string; 37 38 @end 39 40 #define inputWindowHeight 20 41 42 @implementation WKTextInputPanel 43 44 - (void)dealloc 45 { 46 [[NSNotificationCenter defaultCenter] removeObserver:self]; 47 48 [_inputTextView release]; 49 50 [super dealloc]; 51 } 52 53 - (id)init 54 { 55 self = [super initWithContentRect:NSZeroRect styleMask:WKGetInputPanelWindowStyle() backing:NSBackingStoreBuffered defer:YES]; 56 if (!self) 57 return nil; 58 59 // Set the frame size. 60 NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame]; 61 NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, inputWindowHeight); 62 63 [self setFrame:frame display:NO]; 64 65 _inputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]]; 66 _inputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin; 67 68 NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]]; 69 scrollView.documentView = _inputTextView; 70 self.contentView = scrollView; 71 [scrollView release]; 72 73 [self setFloatingPanel:YES]; 74 75 return self; 76 } 77 78 - (void)_keyboardInputSourceChanged 79 { 80 [_inputTextView setString:@""]; 81 [self orderOut:nil]; 82 } 83 84 - (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string 85 { 86 BOOL hadMarkedText = [_inputTextView hasMarkedText]; 87 88 *string = nil; 89 90 // Let TSM know that a bottom input window would be created for marked text. 91 EventRef carbonEvent = static_cast<EventRef>(const_cast<void*>([event eventRef])); 92 if (carbonEvent) { 93 Boolean ignorePAH = true; 94 SetEventParameter(carbonEvent, 'iPAH', typeBoolean, sizeof(ignorePAH), &ignorePAH); 95 } 96 97 if (![[_inputTextView inputContext] handleEvent:event]) 98 return NO; 99 100 if ([_inputTextView hasMarkedText]) { 101 // Don't show the input method window for dead keys 102 if ([[event characters] length] > 0) 103 [self orderFront:nil]; 104 105 return YES; 106 } 107 108 if (hadMarkedText) { 109 [self orderOut:nil]; 110 111 NSString *text = [[_inputTextView textStorage] string]; 112 if ([text length] > 0) 113 *string = [[text copy] autorelease]; 114 } 115 116 [_inputTextView setString:@""]; 117 return hadMarkedText; 118 } 119 120 - (NSTextInputContext *)_inputContext 121 { 122 return [_inputTextView inputContext]; 123 } 124 125 @end 126 127 @implementation WKTextInputWindowController 128 129 + (WKTextInputWindowController *)sharedTextInputWindowController 130 { 131 static WKTextInputWindowController *textInputWindowController; 132 if (!textInputWindowController) 133 textInputWindowController = [[WKTextInputWindowController alloc] init]; 134 135 return textInputWindowController; 136 } 137 138 - (id)init 139 { 140 self = [super init]; 141 if (!self) 142 return nil; 143 144 _panel = [[WKTextInputPanel alloc] init]; 145 146 return self; 147 } 148 149 - (NSTextInputContext *)inputContext 150 { 151 return [_panel _inputContext]; 152 } 153 154 - (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string 155 { 156 return [_panel _interpretKeyEvent:event string:string]; 157 } 158 159 - (void)keyboardInputSourceChanged 160 { 161 [_panel _keyboardInputSourceChanged]; 162 } 163 164 @end 165