widget/cocoa/ComplexTextInputPanel.mm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /*
michael@0 2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
michael@0 3 *
michael@0 4 * Redistribution and use in source and binary forms, with or without
michael@0 5 * modification, are permitted provided that the following conditions
michael@0 6 * are met:
michael@0 7 * 1. Redistributions of source code must retain the above copyright
michael@0 8 * notice, this list of conditions and the following disclaimer.
michael@0 9 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 10 * notice, this list of conditions and the following disclaimer in the
michael@0 11 * documentation and/or other materials provided with the distribution.
michael@0 12 *
michael@0 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
michael@0 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
michael@0 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
michael@0 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
michael@0 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
michael@0 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
michael@0 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
michael@0 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 24 *
michael@0 25 * Modified by Josh Aas of Mozilla Corporation.
michael@0 26 */
michael@0 27
michael@0 28 #import "ComplexTextInputPanel.h"
michael@0 29
michael@0 30 #include <algorithm>
michael@0 31 #include "mozilla/Preferences.h"
michael@0 32 #include "nsChildView.h"
michael@0 33 #include "nsCocoaFeatures.h"
michael@0 34
michael@0 35 using namespace mozilla;
michael@0 36
michael@0 37 #define kInputWindowHeight 20
michael@0 38
michael@0 39 @implementation ComplexTextInputPanel
michael@0 40
michael@0 41 + (ComplexTextInputPanel*)sharedComplexTextInputPanel
michael@0 42 {
michael@0 43 static ComplexTextInputPanel *sComplexTextInputPanel;
michael@0 44 if (!sComplexTextInputPanel)
michael@0 45 sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
michael@0 46 return sComplexTextInputPanel;
michael@0 47 }
michael@0 48
michael@0 49 - (id)init
michael@0 50 {
michael@0 51 // In the original Apple code the style mask is given by a function which is not open source.
michael@0 52 // What could possibly be worth hiding in that function, I do not know.
michael@0 53 // Courtesy of gdb: stylemask: 011000011111, 0x61f
michael@0 54 self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
michael@0 55 if (!self)
michael@0 56 return nil;
michael@0 57
michael@0 58 // Set the frame size.
michael@0 59 NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
michael@0 60 NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, kInputWindowHeight);
michael@0 61
michael@0 62 [self setFrame:frame display:NO];
michael@0 63
michael@0 64 mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
michael@0 65 mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
michael@0 66
michael@0 67 NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
michael@0 68 scrollView.documentView = mInputTextView;
michael@0 69 self.contentView = scrollView;
michael@0 70 [scrollView release];
michael@0 71
michael@0 72 [self setFloatingPanel:YES];
michael@0 73
michael@0 74 [[NSNotificationCenter defaultCenter] addObserver:self
michael@0 75 selector:@selector(keyboardInputSourceChanged:)
michael@0 76 name:NSTextInputContextKeyboardSelectionDidChangeNotification
michael@0 77 object:nil];
michael@0 78
michael@0 79 return self;
michael@0 80 }
michael@0 81
michael@0 82 - (void)dealloc
michael@0 83 {
michael@0 84 [[NSNotificationCenter defaultCenter] removeObserver:self];
michael@0 85
michael@0 86 [mInputTextView release];
michael@0 87
michael@0 88 [super dealloc];
michael@0 89 }
michael@0 90
michael@0 91 - (void)keyboardInputSourceChanged:(NSNotification *)notification
michael@0 92 {
michael@0 93 static int8_t sDoCancel = -1;
michael@0 94 if (!sDoCancel || ![self inComposition]) {
michael@0 95 return;
michael@0 96 }
michael@0 97 if (sDoCancel < 0) {
michael@0 98 bool cancelComposition = false;
michael@0 99 static const char* kPrefName =
michael@0 100 "ui.plugin.cancel_composition_at_input_source_changed";
michael@0 101 nsresult rv = Preferences::GetBool(kPrefName, &cancelComposition);
michael@0 102 NS_ENSURE_SUCCESS(rv, );
michael@0 103 sDoCancel = cancelComposition ? 1 : 0;
michael@0 104 }
michael@0 105 if (sDoCancel) {
michael@0 106 [self cancelComposition];
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110 - (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
michael@0 111 {
michael@0 112 BOOL hadMarkedText = [mInputTextView hasMarkedText];
michael@0 113
michael@0 114 *string = nil;
michael@0 115
michael@0 116 if (![[mInputTextView inputContext] handleEvent:event])
michael@0 117 return NO;
michael@0 118
michael@0 119 if ([mInputTextView hasMarkedText]) {
michael@0 120 // Don't show the input method window for dead keys
michael@0 121 if ([[event characters] length] > 0)
michael@0 122 [self orderFront:nil];
michael@0 123
michael@0 124 return YES;
michael@0 125 } else {
michael@0 126 [self orderOut:nil];
michael@0 127
michael@0 128 NSString *text = [[mInputTextView textStorage] string];
michael@0 129 if ([text length] > 0)
michael@0 130 *string = [[text copy] autorelease];
michael@0 131 }
michael@0 132
michael@0 133 [mInputTextView setString:@""];
michael@0 134 return hadMarkedText;
michael@0 135 }
michael@0 136
michael@0 137 - (NSTextInputContext*)inputContext
michael@0 138 {
michael@0 139 return [mInputTextView inputContext];
michael@0 140 }
michael@0 141
michael@0 142 - (void)cancelComposition
michael@0 143 {
michael@0 144 [mInputTextView setString:@""];
michael@0 145 [self orderOut:nil];
michael@0 146 }
michael@0 147
michael@0 148 - (BOOL)inComposition
michael@0 149 {
michael@0 150 return [mInputTextView hasMarkedText];
michael@0 151 }
michael@0 152
michael@0 153 - (void)adjustTo:(NSView*)view
michael@0 154 {
michael@0 155 NSRect viewRect = [view frame];
michael@0 156 viewRect.origin.x = 0;
michael@0 157 viewRect.origin.y = 0;
michael@0 158 viewRect = [view convertRect:viewRect toView:nil];
michael@0 159 if (nsCocoaFeatures::OnLionOrLater()) {
michael@0 160 viewRect = [[view window] convertRectToScreen:viewRect];
michael@0 161 } else {
michael@0 162 viewRect.origin = [[view window] convertBaseToScreen:viewRect.origin];
michael@0 163 }
michael@0 164 NSRect selfRect = [self frame];
michael@0 165 CGFloat minWidth = static_cast<CGFloat>(
michael@0 166 Preferences::GetUint("ui.plugin.panel.min-width", 500));
michael@0 167 NSRect rect = NSMakeRect(viewRect.origin.x,
michael@0 168 viewRect.origin.y - selfRect.size.height,
michael@0 169 std::max(viewRect.size.width, minWidth),
michael@0 170 selfRect.size.height);
michael@0 171
michael@0 172 // Adjust to screen.
michael@0 173 NSRect screenRect = [[NSScreen mainScreen] visibleFrame];
michael@0 174 if (rect.origin.x < screenRect.origin.x) {
michael@0 175 rect.origin.x = screenRect.origin.x;
michael@0 176 }
michael@0 177 if (rect.origin.y < screenRect.origin.y) {
michael@0 178 rect.origin.y = screenRect.origin.y;
michael@0 179 }
michael@0 180 CGFloat xMostOfScreen = screenRect.origin.x + screenRect.size.width;
michael@0 181 CGFloat yMostOfScreen = screenRect.origin.y + screenRect.size.height;
michael@0 182 CGFloat xMost = rect.origin.x + rect.size.width;
michael@0 183 CGFloat yMost = rect.origin.y + rect.size.height;
michael@0 184 if (xMostOfScreen < xMost) {
michael@0 185 rect.origin.x -= xMost - xMostOfScreen;
michael@0 186 }
michael@0 187 if (yMostOfScreen < yMost) {
michael@0 188 rect.origin.y -= yMost - yMostOfScreen;
michael@0 189 }
michael@0 190
michael@0 191 [self setFrame:rect display:[self isVisible]];
michael@0 192 }
michael@0 193
michael@0 194 @end

mercurial