• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2009 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. ``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.
24 *
25 * Modified by Josh Aas of Mozilla Corporation.
26 */
27
28#import "ComplexTextInputPanel.h"
29
30#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
31@interface NSView (SnowLeopardMethods)
32- (NSTextInputContext *)inputContext;
33@end
34
35// This is actually an NSTextInputContext method, but we can't declare
36// that since the whole class is 10.6+.
37@interface NSObject (SnowLeopardMethods)
38- (BOOL)handleEvent:(NSEvent *)theEvent;
39@end
40
41static NSString* const NSTextInputContextKeyboardSelectionDidChangeNotification =
42    @"NSTextInputContextKeyboardSelectionDidChangeNotification";
43#endif
44
45#define kInputWindowHeight 20
46
47@implementation ComplexTextInputPanel
48
49+ (ComplexTextInputPanel*)sharedComplexTextInputPanel
50{
51  static ComplexTextInputPanel *sComplexTextInputPanel;
52  if (!sComplexTextInputPanel)
53    sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
54  return sComplexTextInputPanel;
55}
56
57- (id)init
58{
59  // In the original Apple code the style mask is given by a function which is not open source.
60  // What could possibly be worth hiding in that function, I do not know.
61  // Courtesy of gdb: stylemask: 011000011111, 0x61f
62  self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
63  if (!self)
64    return nil;
65
66  // Set the frame size.
67  NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
68  NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, kInputWindowHeight);
69
70  [self setFrame:frame display:NO];
71
72  mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
73  mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
74
75  NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
76  scrollView.documentView = mInputTextView;
77  self.contentView = scrollView;
78  [scrollView release];
79
80  [self setFloatingPanel:YES];
81
82  [[NSNotificationCenter defaultCenter] addObserver:self
83                                           selector:@selector(keyboardInputSourceChanged:)
84                                               name:NSTextInputContextKeyboardSelectionDidChangeNotification
85                                             object:nil];
86
87  return self;
88}
89
90- (void)dealloc
91{
92  [[NSNotificationCenter defaultCenter] removeObserver:self];
93
94  [mInputTextView release];
95
96  [super dealloc];
97}
98
99- (void)keyboardInputSourceChanged:(NSNotification *)notification
100{
101  [self cancelComposition];
102}
103
104- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
105{
106  BOOL hadMarkedText = [mInputTextView hasMarkedText];
107
108  *string = nil;
109
110  if (![[mInputTextView inputContext] handleEvent:event])
111    return NO;
112
113  if ([mInputTextView hasMarkedText]) {
114    // Don't show the input method window for dead keys
115    if ([[event characters] length] > 0)
116      [self orderFront:nil];
117
118    return YES;
119  } else {
120    [self orderOut:nil];
121
122    NSString *text = [[mInputTextView textStorage] string];
123    if ([text length] > 0)
124      *string = [[text copy] autorelease];
125  }
126
127  [mInputTextView setString:@""];
128  return hadMarkedText;
129}
130
131- (NSTextInputContext*)inputContext
132{
133  return [mInputTextView inputContext];
134}
135
136- (void)cancelComposition
137{
138  [mInputTextView setString:@""];
139  [self orderOut:nil];
140}
141
142- (BOOL)inComposition
143{
144  return [mInputTextView hasMarkedText];
145}
146
147@end
148