Home | History | Annotate | Download | only in mozilla
      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 
     41 static 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