2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * Modified by Josh Aas of Mozilla Corporation.
28 #import "ComplexTextInputPanel.h"
31 #include "mozilla/Preferences.h"
32 #include "nsChildView.h"
33 #include "nsCocoaFeatures.h"
35 using namespace mozilla;
37 #define kInputWindowHeight 20
39 @implementation ComplexTextInputPanel
41 + (ComplexTextInputPanel*)sharedComplexTextInputPanel
43 static ComplexTextInputPanel *sComplexTextInputPanel;
44 if (!sComplexTextInputPanel)
45 sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
46 return sComplexTextInputPanel;
51 // In the original Apple code the style mask is given by a function which is not open source.
52 // What could possibly be worth hiding in that function, I do not know.
53 // Courtesy of gdb: stylemask: 011000011111, 0x61f
54 self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
58 // Set the frame size.
59 NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
60 NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, kInputWindowHeight);
62 [self setFrame:frame display:NO];
64 mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
65 mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
67 NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
68 scrollView.documentView = mInputTextView;
69 self.contentView = scrollView;
72 [self setFloatingPanel:YES];
74 [[NSNotificationCenter defaultCenter] addObserver:self
75 selector:@selector(keyboardInputSourceChanged:)
76 name:NSTextInputContextKeyboardSelectionDidChangeNotification
84 [[NSNotificationCenter defaultCenter] removeObserver:self];
86 [mInputTextView release];
91 - (void)keyboardInputSourceChanged:(NSNotification *)notification
93 static int8_t sDoCancel = -1;
94 if (!sDoCancel || ![self inComposition]) {
98 bool cancelComposition = false;
99 static const char* kPrefName =
100 "ui.plugin.cancel_composition_at_input_source_changed";
101 nsresult rv = Preferences::GetBool(kPrefName, &cancelComposition);
102 NS_ENSURE_SUCCESS(rv, );
103 sDoCancel = cancelComposition ? 1 : 0;
106 [self cancelComposition];
110 - (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
112 BOOL hadMarkedText = [mInputTextView hasMarkedText];
116 if (![[mInputTextView inputContext] handleEvent:event])
119 if ([mInputTextView hasMarkedText]) {
120 // Don't show the input method window for dead keys
121 if ([[event characters] length] > 0)
122 [self orderFront:nil];
128 NSString *text = [[mInputTextView textStorage] string];
129 if ([text length] > 0)
130 *string = [[text copy] autorelease];
133 [mInputTextView setString:@""];
134 return hadMarkedText;
137 - (NSTextInputContext*)inputContext
139 return [mInputTextView inputContext];
142 - (void)cancelComposition
144 [mInputTextView setString:@""];
148 - (BOOL)inComposition
150 return [mInputTextView hasMarkedText];
153 - (void)adjustTo:(NSView*)view
155 NSRect viewRect = [view frame];
156 viewRect.origin.x = 0;
157 viewRect.origin.y = 0;
158 viewRect = [view convertRect:viewRect toView:nil];
159 if (nsCocoaFeatures::OnLionOrLater()) {
160 viewRect = [[view window] convertRectToScreen:viewRect];
162 viewRect.origin = [[view window] convertBaseToScreen:viewRect.origin];
164 NSRect selfRect = [self frame];
165 CGFloat minWidth = static_cast<CGFloat>(
166 Preferences::GetUint("ui.plugin.panel.min-width", 500));
167 NSRect rect = NSMakeRect(viewRect.origin.x,
168 viewRect.origin.y - selfRect.size.height,
169 std::max(viewRect.size.width, minWidth),
170 selfRect.size.height);
173 NSRect screenRect = [[NSScreen mainScreen] visibleFrame];
174 if (rect.origin.x < screenRect.origin.x) {
175 rect.origin.x = screenRect.origin.x;
177 if (rect.origin.y < screenRect.origin.y) {
178 rect.origin.y = screenRect.origin.y;
180 CGFloat xMostOfScreen = screenRect.origin.x + screenRect.size.width;
181 CGFloat yMostOfScreen = screenRect.origin.y + screenRect.size.height;
182 CGFloat xMost = rect.origin.x + rect.size.width;
183 CGFloat yMost = rect.origin.y + rect.size.height;
184 if (xMostOfScreen < xMost) {
185 rect.origin.x -= xMost - xMostOfScreen;
187 if (yMostOfScreen < yMost) {
188 rect.origin.y -= yMost - yMostOfScreen;
191 [self setFrame:rect display:[self isVisible]];