Improve TextEntered for OS X (close #377)
Code from pull request #401 was not used because some methods used don't exist on 10.5 which is still supported by SFML 2.1.
This commit is contained in:
parent
ef8391e507
commit
513cd7e57c
@ -84,6 +84,8 @@ else() # MACOSX
|
||||
${SRCROOT}/OSX/SFContext.mm
|
||||
${SRCROOT}/OSX/SFOpenGLView.h
|
||||
${SRCROOT}/OSX/SFOpenGLView.mm
|
||||
${SRCROOT}/OSX/SFSilentResponder.h
|
||||
${SRCROOT}/OSX/SFSilentResponder.m
|
||||
${SRCROOT}/OSX/SFWindow.h
|
||||
${SRCROOT}/OSX/SFWindow.m
|
||||
${SRCROOT}/OSX/SFWindowController.h
|
||||
|
@ -34,8 +34,10 @@ namespace sf {
|
||||
}
|
||||
}
|
||||
|
||||
@class SFSilentResponder;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Spesialized NSOpenGLView
|
||||
/// \brief Specialized NSOpenGLView
|
||||
///
|
||||
/// Handle event and send them back to the requester.
|
||||
///
|
||||
@ -64,6 +66,11 @@ namespace sf {
|
||||
BOOL m_rightAlternateWasDown;
|
||||
BOOL m_leftAlternateWasDown;
|
||||
BOOL m_controlWasDown;
|
||||
|
||||
// Hidden text view use to convert key event to actual chars.
|
||||
// To prevent sound alert we use a silent responder.
|
||||
SFSilentResponder* m_silentResponder;
|
||||
NSTextView* m_hiddenTextView;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
#import <SFML/Window/OSX/SFOpenGLView.h>
|
||||
#import <SFML/Window/OSX/SFSilentResponder.h>
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Here are define the mask value for the 'modifiers' keys (cmd, ctrl, alt, shift)
|
||||
@ -61,6 +62,15 @@ NSUInteger eraseMaskFromData(NSUInteger data, NSUInteger mask);
|
||||
////////////////////////////////////////////////////////////
|
||||
NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Returns true if `event` represents a representable character.
|
||||
///
|
||||
/// The event is assumed to be a key down event.
|
||||
/// False is returned if the event is either escape or a non text unicode.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
BOOL isValidTextUnicode(NSEvent* event);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// SFOpenGLView class : Privates Methods Declaration
|
||||
///
|
||||
@ -131,6 +141,11 @@ NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
|
||||
selector:@selector(frameDidChange:)
|
||||
name:NSViewFrameDidChangeNotification
|
||||
object:self];
|
||||
|
||||
// Create a hidden text view for parsing key down event properly
|
||||
m_silentResponder = [[SFSilentResponder alloc] init];
|
||||
m_hiddenTextView = [[NSTextView alloc] initWithFrame:NSZeroRect];
|
||||
[m_hiddenTextView setNextResponder:m_silentResponder];
|
||||
}
|
||||
|
||||
return self;
|
||||
@ -272,6 +287,10 @@ NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
|
||||
////////////////////////////////////////////////////////
|
||||
-(void)dealloc
|
||||
{
|
||||
// Release attributes
|
||||
[m_hiddenTextView release];
|
||||
[m_silentResponder release];
|
||||
|
||||
// Unregister
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[self removeTrackingRect:m_trackingTag];
|
||||
@ -538,34 +557,22 @@ NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
|
||||
}
|
||||
|
||||
|
||||
// Handle text entred event
|
||||
// We create a new event without command/ctrl modifiers
|
||||
// to prevent the OS from sending an alert
|
||||
NSUInteger modifiers = [theEvent modifierFlags];
|
||||
// Handle text entred event:
|
||||
// Ignore event if we don't want repeated keystrokes
|
||||
if (m_useKeyRepeat || ![theEvent isARepeat]) {
|
||||
// Ignore escape key and other non text keycode (See NSEvent.h)
|
||||
// because they produce a sound alert.
|
||||
if (isValidTextUnicode(theEvent)) {
|
||||
// Send the event to the hidden text view for processing
|
||||
[m_hiddenTextView interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
|
||||
}
|
||||
|
||||
if (modifiers & NSCommandKeyMask) modifiers = modifiers & ~NSCommandKeyMask;
|
||||
if (modifiers & NSControlKeyMask) modifiers = modifiers & ~NSControlKeyMask;
|
||||
// Carefully handle backspace and delete..
|
||||
// Note: the event is intentionally sent to the hidden view
|
||||
// even if we do something more specific below. This way
|
||||
// key combination are correctly interpreted.
|
||||
|
||||
NSEvent* ev = [NSEvent keyEventWithType:NSKeyDown
|
||||
location:[theEvent locationInWindow]
|
||||
modifierFlags:modifiers
|
||||
timestamp:[theEvent timestamp]
|
||||
windowNumber:[theEvent windowNumber]
|
||||
context:[theEvent context]
|
||||
characters:[theEvent characters]
|
||||
charactersIgnoringModifiers:[theEvent charactersIgnoringModifiers]
|
||||
isARepeat:[theEvent isARepeat]
|
||||
keyCode:[theEvent keyCode]];
|
||||
|
||||
if ((m_useKeyRepeat || ![ev isARepeat]) && [[ev characters] length] > 0) {
|
||||
|
||||
// Ignore escape key and non text keycode. (See NSEvent.h)
|
||||
// They produce a sound alert.
|
||||
unichar code = [[ev characters] characterAtIndex:0];
|
||||
unsigned short keycode = [ev keyCode];
|
||||
|
||||
// Backspace and Delete unicode values are badly handled by Apple.
|
||||
// We do a small workaround here :
|
||||
unsigned short keycode = [theEvent keyCode];
|
||||
|
||||
// Backspace
|
||||
if (keycode == 0x33) {
|
||||
@ -579,20 +586,17 @@ NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
|
||||
m_requester->textEntered(127);
|
||||
}
|
||||
|
||||
// All other unicode values
|
||||
else if (keycode != 0x35 && (code < 0xF700 || code > 0xF8FF)) {
|
||||
// Otherwise, let's see what our hidden field has computed
|
||||
else {
|
||||
NSString* string = [m_hiddenTextView string];
|
||||
|
||||
// Let's see if its a valid text.
|
||||
NSText* text = [[self window] fieldEditor:YES forObject:self];
|
||||
[text interpretKeyEvents:[NSArray arrayWithObject:ev]];
|
||||
|
||||
NSString* string = [text string];
|
||||
if ([string length] > 0) {
|
||||
// It's a valid TextEntered event.
|
||||
m_requester->textEntered([string characterAtIndex:0]);
|
||||
|
||||
[text setString:@""];
|
||||
// Send each character to SFML event requester
|
||||
for (NSUInteger index = 0; index < [string length]; ++index) {
|
||||
m_requester->textEntered([string characterAtIndex:index]);
|
||||
}
|
||||
|
||||
// Empty our hidden cache
|
||||
[m_hiddenTextView setString:@""];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1097,4 +1101,15 @@ NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask)
|
||||
return eraseMaskFromData(data, negative);
|
||||
}
|
||||
|
||||
BOOL isValidTextUnicode(NSEvent* event)
|
||||
{
|
||||
if ([event keyCode] == 0x35) { // Escape
|
||||
return false;
|
||||
} else if ([[event characters] length] > 0) {
|
||||
unichar code = [[event characters] characterAtIndex:0];
|
||||
return code < 0xF700 || code > 0xF8FF;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
41
src/SFML/Window/OSX/SFSilentResponder.h
Normal file
41
src/SFML/Window/OSX/SFSilentResponder.h
Normal file
@ -0,0 +1,41 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2012 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Silent Responder used to prevent sound alert with key event
|
||||
///
|
||||
/// Mainly used by SFOpenGLView and its hidden text view.
|
||||
////////////////////////////////////////////////////////////
|
||||
@interface SFSilentResponder : NSResponder
|
||||
|
||||
-(void)doCommandBySelector:(SEL)sel;
|
||||
|
||||
@end
|
||||
|
39
src/SFML/Window/OSX/SFSilentResponder.m
Normal file
39
src/SFML/Window/OSX/SFSilentResponder.m
Normal file
@ -0,0 +1,39 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2012 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#import <SFML/Window/OSX/SFSilentResponder.h>
|
||||
|
||||
@implementation SFSilentResponder
|
||||
|
||||
-(void)doCommandBySelector:(SEL)sel
|
||||
{
|
||||
// Just do nothing, to prevent sound alerts
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user