diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 23d3ed05..31c68ce9 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -133,6 +133,10 @@ elseif(SFML_OS_MACOSX) ${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm ${SRCROOT}/OSX/SFOpenGLView.h ${SRCROOT}/OSX/SFOpenGLView.mm + ${SRCROOT}/OSX/SFOpenGLView+keyboard.mm + ${SRCROOT}/OSX/SFOpenGLView+keyboard_priv.h + ${SRCROOT}/OSX/SFOpenGLView+mouse.mm + ${SRCROOT}/OSX/SFOpenGLView+mouse_priv.h ${SRCROOT}/OSX/SFSilentResponder.h ${SRCROOT}/OSX/SFSilentResponder.m ${SRCROOT}/OSX/SFWindow.h diff --git a/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm b/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm new file mode 100644 index 00000000..4f2d2a6d --- /dev/null +++ b/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm @@ -0,0 +1,220 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2015 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent@sfml-dev.org) +// +// 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 +//////////////////////////////////////////////////////////// +#include +#include // For localizedKeys and nonLocalizedKeys + +#import +#import +#import + +//////////////////////////////////////////////////////////// +/// In this file, we implement keyboard handling for SFOpenGLView +/// +//////////////////////////////////////////////////////////// + + +@implementation SFOpenGLView (keyboard) + + +//////////////////////////////////////////////////////// +-(BOOL)acceptsFirstResponder +{ + // Accepts key event. + return YES; +} + + +//////////////////////////////////////////////////////// +-(BOOL)canBecomeKeyView +{ + // Accepts key event. + return YES; +} + + +//////////////////////////////////////////////////////// +-(void)enableKeyRepeat +{ + m_useKeyRepeat = YES; +} + + +//////////////////////////////////////////////////////// +-(void)disableKeyRepeat +{ + m_useKeyRepeat = NO; +} + + +//////////////////////////////////////////////////////// +-(void)keyDown:(NSEvent*)theEvent +{ + // Transmit to non-SFML responder + [[self nextResponder] keyDown:theEvent]; + + if (m_requester == 0) + return; + + // Handle key down event + if (m_useKeyRepeat || ![theEvent isARepeat]) + { + sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; + + if (key.code != sf::Keyboard::Unknown) // The key is recognized. + m_requester->keyDown(key); + } + + + // Handle text entered 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 ([SFOpenGLView isValidTextUnicode:theEvent]) + { + // Send the event to the hidden text view for processing + [m_hiddenTextView interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + } + + // 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. + + unsigned short keycode = [theEvent keyCode]; + + // Backspace + if (keycode == 0x33) + { + // Send the correct Unicode value (i.e. 8) instead of 127 (which is 'delete') + m_requester->textEntered(8); + } + + // Delete + else if ((keycode == 0x75) || (keycode == NSDeleteFunctionKey)) + { + // Instead of the value 63272 we send 127. + m_requester->textEntered(127); + } + + // Otherwise, let's see what our hidden field has computed + else + { + NSString* string = [m_hiddenTextView string]; + + // 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:@""]; + } + } +} + + +//////////////////////////////////////////////////////// +-(void)sfKeyUp:(NSEvent*)theEvent +{ + // For some mystic reasons, key released events don't work the same way + // as key pressed events... We somewhat hijack the event chain of response + // in -[SFApplication sendEvent:] and resume this chain with the next + // responder. + // This is workaround to make sure key released events are fired in + // fullscreen window too. + + // Transmit to non-SFML responder + [[self nextResponder] keyUp:theEvent]; + + if (m_requester == 0) + return; + + sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; + + if (key.code != sf::Keyboard::Unknown) // The key is recognized. + m_requester->keyUp(key); +} + + +//////////////////////////////////////////////////////// +-(void)flagsChanged:(NSEvent*)theEvent +{ + // Transmit to non-SFML responder + [[self nextResponder] flagsChanged:theEvent]; + + if (m_requester == 0) + return; + + NSUInteger modifiers = [theEvent modifierFlags]; + handleModifiersChanged(modifiers, *m_requester); +} + + +//////////////////////////////////////////////////////// ++(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event +{ + // Key code + sf::Keyboard::Key key = sf::Keyboard::Unknown; + + // First we look if the key down is from a list of characters + // that depend on keyboard localization. + NSString* string = [event charactersIgnoringModifiers]; + if ([string length] > 0) + key = sf::priv::HIDInputManager::localizedKeys([string characterAtIndex:0]); + + // If the key is not a localized one, we try to find a corresponding code + // through virtual key code. + if (key == sf::Keyboard::Unknown) + key = sf::priv::HIDInputManager::nonLocalizedKeys([event keyCode]); + + return keyEventWithModifiers([event modifierFlags], key); +} + + +//////////////////////////////////////////////////////// ++(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; + } +} + +@end + diff --git a/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h b/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h new file mode 100644 index 00000000..b8846d98 --- /dev/null +++ b/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2015 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent@sfml-dev.org) +// +// 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 +//////////////////////////////////////////////////////////// +#include + +#import + + +//////////////////////////////////////////////////////////// +/// Here are defined a few private messages for keyboard +/// handling in SFOpenGLView. +/// +//////////////////////////////////////////////////////////// + + +@interface SFOpenGLView (keyboard_priv) + +//////////////////////////////////////////////////////////// +/// \brief Convert a key down/up NSEvent into an SFML key event +/// +/// The conversion is based on localizedKeys and nonLocalizedKeys functions. +/// +/// \param event a key event +/// +/// \return sf::Keyboard::Unknown as Code if the key is unknown +/// +//////////////////////////////////////////////////////////// ++(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event; + +//////////////////////////////////////////////////////////// +/// \brief Check if the event represent some Unicode text +/// +/// The event is assumed to be a key down event. +/// False is returned if the event is either escape or a non text Unicode. +/// +/// \param event a key down event +/// +/// \return true if event represents a Unicode character, false otherwise +/// +//////////////////////////////////////////////////////////// ++(BOOL)isValidTextUnicode:(NSEvent*)event; + +@end diff --git a/src/SFML/Window/OSX/SFOpenGLView+mouse.mm b/src/SFML/Window/OSX/SFOpenGLView+mouse.mm new file mode 100644 index 00000000..d12df1c2 --- /dev/null +++ b/src/SFML/Window/OSX/SFOpenGLView+mouse.mm @@ -0,0 +1,285 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2015 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent@sfml-dev.org) +// +// 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 +//////////////////////////////////////////////////////////// +#include + +#import +#import + + +//////////////////////////////////////////////////////////// +/// In this file, we implement mouse handling for SFOpenGLView +/// +//////////////////////////////////////////////////////////// + +@implementation SFOpenGLView (mouse) + +//////////////////////////////////////////////////////// +-(BOOL)isMouseInside +{ + NSPoint relativeToWindow = [[self window] mouseLocationOutsideOfEventStream]; + NSPoint relativeToView = [self convertPoint:relativeToWindow fromView:nil]; + + return NSPointInRect(relativeToView, [self bounds]); +} + + +//////////////////////////////////////////////////////// +-(void)updateMouseState +{ + BOOL mouseWasIn = m_mouseIsIn; + m_mouseIsIn = [self isMouseInside]; + + if (m_requester == 0) + return; + + // Send event if needed. + if (mouseWasIn && !m_mouseIsIn) + m_requester->mouseMovedOut(); + else if (!mouseWasIn && m_mouseIsIn) + m_requester->mouseMovedIn(); +} + + + +//////////////////////////////////////////////////////// +-(void)mouseDown:(NSEvent*)theEvent +{ + [self handleMouseDown:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] mouseDown:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)rightMouseDown:(NSEvent*)theEvent +{ + [self handleMouseDown:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] rightMouseDown:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)otherMouseDown:(NSEvent*)theEvent +{ + [self handleMouseDown:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] otherMouseDown:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)handleMouseDown:(NSEvent*)theEvent +{ + sf::Mouse::Button button = [SFOpenGLView mouseButtonFromEvent:theEvent]; + + if (m_requester != 0) + { + NSPoint loc = [self cursorPositionFromEvent:theEvent]; + + if (button != sf::Mouse::ButtonCount) + m_requester->mouseDownAt(button, loc.x, loc.y); + } +} + + +//////////////////////////////////////////////////////// +-(void)mouseUp:(NSEvent*)theEvent +{ + [self handleMouseUp:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] mouseUp:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)rightMouseUp:(NSEvent*)theEvent +{ + [self handleMouseUp:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] rightMouseUp:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)otherMouseUp:(NSEvent*)theEvent +{ + [self handleMouseUp:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] otherMouseUp:theEvent]; +} + + +//////////////////////////////////////////////////////////// +-(void)handleMouseUp:(NSEvent*)theEvent +{ + sf::Mouse::Button button = [SFOpenGLView mouseButtonFromEvent:theEvent]; + + if (m_requester != 0) + { + NSPoint loc = [self cursorPositionFromEvent:theEvent]; + + if (button != sf::Mouse::ButtonCount) + m_requester->mouseUpAt(button, loc.x, loc.y); + } +} + + +//////////////////////////////////////////////////////// +-(void)mouseMoved:(NSEvent*)theEvent +{ + [self handleMouseMove:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] mouseMoved:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)rightMouseDragged:(NSEvent*)theEvent +{ + [self handleMouseMove:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] rightMouseDragged:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)mouseDragged:(NSEvent*)theEvent +{ + [self handleMouseMove:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] mouseDragged:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)otherMouseDragged:(NSEvent*)theEvent +{ + [self handleMouseMove:theEvent]; + + // Transmit to non-SFML responder + [[self nextResponder] otherMouseUp:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)handleMouseMove:(NSEvent*)theEvent +{ + if (m_requester != 0) + { + NSPoint loc = [self cursorPositionFromEvent:theEvent]; + + // Make sure the point is inside the view. + // (mouseEntered: and mouseExited: are not immediately called + // when the mouse is dragged. That would be too easy!) + [self updateMouseState]; + if (m_mouseIsIn) + m_requester->mouseMovedAt(loc.x, loc.y); + } +} + + +//////////////////////////////////////////////////////// +-(void)scrollWheel:(NSEvent*)theEvent +{ + if (m_requester != 0) + { + NSPoint loc = [self cursorPositionFromEvent:theEvent]; + m_requester->mouseWheelScrolledAt([theEvent deltaX], [theEvent deltaY], loc.x, loc.y); + } + + // Transmit to non-SFML responder + [[self nextResponder] scrollWheel:theEvent]; +} + + +//////////////////////////////////////////////////////// +-(void)mouseEntered:(NSEvent*)theEvent +{ + (void)theEvent; + [self updateMouseState]; +} + + +//////////////////////////////////////////////////////// +-(void)mouseExited:(NSEvent*)theEvent +{ + (void)theEvent; + [self updateMouseState]; +} + + +//////////////////////////////////////////////////////// +-(NSPoint)cursorPositionFromEvent:(NSEvent*)eventOrNil +{ + NSPoint loc; + // If no event given then get current mouse pos. + if (eventOrNil == nil) + { + NSPoint rawPos = [[self window] mouseLocationOutsideOfEventStream]; + loc = [self convertPoint:rawPos fromView:nil]; + } + else + { + loc = [self convertPoint:[eventOrNil locationInWindow] fromView:nil]; + } + + // Don't forget to change to SFML coord system. + float h = [self frame].size.height; + loc.y = h - loc.y; + + return loc; +} + + +//////////////////////////////////////////////////////// ++(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event +{ + switch ([event buttonNumber]) + { + case 0: return sf::Mouse::Left; + case 1: return sf::Mouse::Right; + case 2: return sf::Mouse::Middle; + case 3: return sf::Mouse::XButton1; + case 4: return sf::Mouse::XButton2; + default: return sf::Mouse::ButtonCount; // Never happens! (hopefully) + } +} + + +@end diff --git a/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h b/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h new file mode 100644 index 00000000..d020b796 --- /dev/null +++ b/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2015 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent@sfml-dev.org) +// +// 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 +//////////////////////////////////////////////////////////// +#include + +#import + + +//////////////////////////////////////////////////////////// +/// Here are defined a few private messages for mouse +/// handling in SFOpenGLView. +/// +//////////////////////////////////////////////////////////// + + +@interface SFOpenGLView (mouse_priv) + +//////////////////////////////////////////////////////////// +/// \brief Update the mouse state (in or out) +/// +/// Fire an event if its state has changed. +/// +//////////////////////////////////////////////////////////// +-(void)updateMouseState; + +//////////////////////////////////////////////////////////// +/// \brief handle mouse down event +/// +//////////////////////////////////////////////////////////// +-(void)handleMouseDown:(NSEvent*)theEvent; + +//////////////////////////////////////////////////////////// +/// \brief handle mouse up event +/// +//////////////////////////////////////////////////////////// +-(void)handleMouseUp:(NSEvent*)theEvent; + +//////////////////////////////////////////////////////////// +/// \brief handle mouse move event +/// +//////////////////////////////////////////////////////////// +-(void)handleMouseMove:(NSEvent*)theEvent; + +//////////////////////////////////////////////////////////// +/// \brief Convert the NSEvent mouse button type to SFML type +/// +/// \param event a mouse button event +/// +/// \return Left, Right, ..., or ButtonCount if the button is unknown +/// +//////////////////////////////////////////////////////////// ++(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event; + +@end diff --git a/src/SFML/Window/OSX/SFOpenGLView.h b/src/SFML/Window/OSX/SFOpenGLView.h index 6a0d0b01..ec4078c6 100644 --- a/src/SFML/Window/OSX/SFOpenGLView.h +++ b/src/SFML/Window/OSX/SFOpenGLView.h @@ -47,6 +47,11 @@ namespace sf { /// Modifiers keys (cmd, ctrl, alt, shift) are handled by this class /// but the actual logic is done in SFKeyboardModifiersHelper.(h|mm). /// +/// The interface is subdivided into several categories in order +/// to have multiple implementation files to divide this monolithic +/// implementation. However, all attributes are defined in the main +/// interface declaration right below. +/// //////////////////////////////////////////////////////////// @interface SFOpenGLView : NSOpenGLView { @@ -105,6 +110,18 @@ namespace sf { //////////////////////////////////////////////////////////// -(NSPoint)computeGlobalPositionOfRelativePoint:(NSPoint)point; +//////////////////////////////////////////////////////////// +/// \brief Get the display scale factor +/// +/// \return e.g. 1.0 for classic display, 2.0 for retina display +/// +//////////////////////////////////////////////////////////// +-(CGFloat)displayScaleFactor; + +@end + +@interface SFOpenGLView (keyboard) + //////////////////////////////////////////////////////////// /// \brief Enable key repeat /// @@ -117,13 +134,9 @@ namespace sf { //////////////////////////////////////////////////////////// -(void)disableKeyRepeat; -//////////////////////////////////////////////////////////// -/// \brief Get the display scale factor -/// -/// \return e.g. 1.0 for classic display, 2.0 for retina display -/// -//////////////////////////////////////////////////////////// --(CGFloat)displayScaleFactor; +@end + +@interface SFOpenGLView (mouse) //////////////////////////////////////////////////////////// /// \brief Compute the position of the cursor diff --git a/src/SFML/Window/OSX/SFOpenGLView.mm b/src/SFML/Window/OSX/SFOpenGLView.mm index 627af8f4..2e7ba1e7 100644 --- a/src/SFML/Window/OSX/SFOpenGLView.mm +++ b/src/SFML/Window/OSX/SFOpenGLView.mm @@ -27,28 +27,13 @@ // Headers //////////////////////////////////////////////////////////// #include -#include // For localizedKeys and nonLocalizedKeys #include -#import #import +#import #import -//////////////////////////////////////////////////////////// -/// \brief Check if the event represent some Unicode text -/// -/// The event is assumed to be a key down event. -/// False is returned if the event is either escape or a non text Unicode. -/// -/// \param event a key down event -/// -/// \return true if event represents a Unicode character, false otherwise -/// -//////////////////////////////////////////////////////////// -BOOL isValidTextUnicode(NSEvent* event); - - //////////////////////////////////////////////////////////// /// SFOpenGLView class: Privates Methods Declaration /// @@ -67,14 +52,6 @@ BOOL isValidTextUnicode(NSEvent* event); //////////////////////////////////////////////////////////// -(void)viewDidEndLiveResize; -//////////////////////////////////////////////////////////// -/// \brief Update the mouse state (in or out) -/// -/// Fire an event if its state has changed. -/// -//////////////////////////////////////////////////////////// --(void)updateMouseState; - //////////////////////////////////////////////////////////// /// \brief Callback for focus event /// @@ -99,28 +76,6 @@ BOOL isValidTextUnicode(NSEvent* event); //////////////////////////////////////////////////////////// -(void)exitFullscreen; -//////////////////////////////////////////////////////////// -/// \brief Convert the NSEvent mouse button type to SFML type -/// -/// \param event a mouse button event -/// -/// \return Left, Right, ..., or ButtonCount if the button is unknown -/// -//////////////////////////////////////////////////////////// --(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event; - -//////////////////////////////////////////////////////////// -/// \brief Convert a key down/up NSEvent into an SFML key event -/// -/// The conversion is based on localizedKeys and nonLocalizedKeys functions. -/// -/// \param event a key event -/// -/// \return sf::Keyboard::Unknown as Code if the key is unknown -/// -//////////////////////////////////////////////////////////// -+(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event; - @end @implementation SFOpenGLView @@ -251,20 +206,6 @@ BOOL isValidTextUnicode(NSEvent* event); } -//////////////////////////////////////////////////////// --(void)enableKeyRepeat -{ - m_useKeyRepeat = YES; -} - - -//////////////////////////////////////////////////////// --(void)disableKeyRepeat -{ - m_useKeyRepeat = NO; -} - - //////////////////////////////////////////////////////// -(CGFloat)displayScaleFactor { @@ -317,34 +258,6 @@ BOOL isValidTextUnicode(NSEvent* event); m_requester->windowResized(newSize.width, newSize.height); } - -//////////////////////////////////////////////////////// --(BOOL)isMouseInside -{ - NSPoint relativeToWindow = [[self window] mouseLocationOutsideOfEventStream]; - NSPoint relativeToView = [self convertPoint:relativeToWindow fromView:nil]; - - return NSPointInRect(relativeToView, [self bounds]); -} - - -//////////////////////////////////////////////////////// --(void)updateMouseState -{ - BOOL mouseWasIn = m_mouseIsIn; - m_mouseIsIn = [self isMouseInside]; - - if (m_requester == 0) - return; - - // Send event if needed. - if (mouseWasIn && !m_mouseIsIn) - m_requester->mouseMovedOut(); - else if (!mouseWasIn && m_mouseIsIn) - m_requester->mouseMovedIn(); -} - - //////////////////////////////////////////////////////// -(void)windowDidBecomeKey:(NSNotification*)notification { @@ -426,398 +339,4 @@ BOOL isValidTextUnicode(NSEvent* event); } -//////////////////////////////////////////////////////// --(BOOL)acceptsFirstResponder -{ - // Accepts key event. - return YES; -} - - -//////////////////////////////////////////////////////// --(BOOL)canBecomeKeyView -{ - // Accepts key event. - return YES; -} - - -#pragma mark -#pragma mark Mouse-event methods - - -//////////////////////////////////////////////////////// --(void)mouseDown:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseDown:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] mouseDown:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)mouseUp:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseUp:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] mouseUp:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)mouseMoved:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseDragged:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] mouseMoved:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)scrollWheel:(NSEvent*)theEvent -{ - if (m_requester != 0) - { - NSPoint loc = [self cursorPositionFromEvent:theEvent]; - m_requester->mouseWheelScrolledAt([theEvent deltaX], [theEvent deltaY], loc.x, loc.y); - } - - // Transmit to non-SFML responder - [[self nextResponder] scrollWheel:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)mouseEntered:(NSEvent*)theEvent -{ - (void)theEvent; - [self updateMouseState]; -} - - -//////////////////////////////////////////////////////// --(void)mouseExited:(NSEvent*)theEvent -{ - (void)theEvent; - [self updateMouseState]; -} - - -//////////////////////////////////////////////////////// --(void)rightMouseDown:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseDown:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] rightMouseDown:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)rightMouseUp:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseUp:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] rightMouseUp:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)otherMouseDown:(NSEvent*)theEvent -{ - sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; - - if (m_requester != 0) - { - NSPoint loc = [self cursorPositionFromEvent:theEvent]; - - if (button != sf::Mouse::ButtonCount) - m_requester->mouseDownAt(button, loc.x, loc.y); - } - - // If the event is not forwarded by mouseDown or rightMouseDown... - if ((button != sf::Mouse::Left) && (button != sf::Mouse::Right)) - { - // ... transmit to non-SFML responder - [[self nextResponder] otherMouseDown:theEvent]; - } -} - - -//////////////////////////////////////////////////////// --(void)otherMouseUp:(NSEvent*)theEvent -{ - sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; - - if (m_requester != 0) - { - NSPoint loc = [self cursorPositionFromEvent:theEvent]; - - if (button != sf::Mouse::ButtonCount) - m_requester->mouseUpAt(button, loc.x, loc.y); - } - - // If the event is not forwarded by mouseUp or rightMouseUp... - if ((button != sf::Mouse::Left) && (button != sf::Mouse::Right)) - { - // ... transmit to non-SFML responder - [[self nextResponder] otherMouseUp:theEvent]; - } -} - - -//////////////////////////////////////////////////////// --(void)rightMouseDragged:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseDragged:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] rightMouseDragged:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)mouseDragged:(NSEvent*)theEvent -{ - // Forward to... - [self otherMouseDragged:theEvent]; - - // Transmit to non-SFML responder - [[self nextResponder] mouseDragged:theEvent]; -} - - -//////////////////////////////////////////////////////// --(void)otherMouseDragged:(NSEvent*)theEvent -{ - if (m_requester != 0) - { - NSPoint loc = [self cursorPositionFromEvent:theEvent]; - - // Make sure the point is inside the view. - // (mouseEntered: and mouseExited: are not immediately called - // when the mouse is dragged. That would be too easy!) - [self updateMouseState]; - if (m_mouseIsIn) - m_requester->mouseMovedAt(loc.x, loc.y); - } - - // If the event is not forwarded by mouseDragged or rightMouseDragged... - sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; - if ((button != sf::Mouse::Left) && (button != sf::Mouse::Right)) - { - // ... transmit to non-SFML responder - [[self nextResponder] otherMouseUp:theEvent]; - } -} - - -//////////////////////////////////////////////////////// --(NSPoint)cursorPositionFromEvent:(NSEvent*)eventOrNil -{ - NSPoint loc; - // If no event given then get current mouse pos. - if (eventOrNil == nil) - { - NSPoint rawPos = [[self window] mouseLocationOutsideOfEventStream]; - loc = [self convertPoint:rawPos fromView:nil]; - } - else - { - loc = [self convertPoint:[eventOrNil locationInWindow] fromView:nil]; - } - - // Don't forget to change to SFML coord system. - float h = [self frame].size.height; - loc.y = h - loc.y; - - return loc; -} - - -//////////////////////////////////////////////////////// --(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event -{ - switch ([event buttonNumber]) - { - case 0: return sf::Mouse::Left; - case 1: return sf::Mouse::Right; - case 2: return sf::Mouse::Middle; - case 3: return sf::Mouse::XButton1; - case 4: return sf::Mouse::XButton2; - default: return sf::Mouse::ButtonCount; // Never happens! (hopefully) - } -} - - -#pragma mark -#pragma mark Key-event methods - - -//////////////////////////////////////////////////////// --(void)keyDown:(NSEvent*)theEvent -{ - // Transmit to non-SFML responder - [[self nextResponder] keyDown:theEvent]; - - if (m_requester == 0) - return; - - // Handle key down event - if (m_useKeyRepeat || ![theEvent isARepeat]) - { - sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; - - if (key.code != sf::Keyboard::Unknown) // The key is recognized. - m_requester->keyDown(key); - } - - - // Handle text entered 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]]; - } - - // 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. - - unsigned short keycode = [theEvent keyCode]; - - // Backspace - if (keycode == 0x33) - { - // Send the correct Unicode value (i.e. 8) instead of 127 (which is 'delete') - m_requester->textEntered(8); - } - - // Delete - else if ((keycode == 0x75) || (keycode == NSDeleteFunctionKey)) - { - // Instead of the value 63272 we send 127. - m_requester->textEntered(127); - } - - // Otherwise, let's see what our hidden field has computed - else - { - NSString* string = [m_hiddenTextView string]; - - // 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:@""]; - } - } -} - - -//////////////////////////////////////////////////////// --(void)sfKeyUp:(NSEvent*)theEvent -{ - // For some mystic reasons, key released events don't work the same way - // as key pressed events... We somewhat hijack the event chain of response - // in -[SFApplication sendEvent:] and resume this chain with the next - // responder. - // This is workaround to make sure key released events are fired in - // fullscreen window too. - - // Transmit to non-SFML responder - [[self nextResponder] keyUp:theEvent]; - - if (m_requester == 0) - return; - - sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; - - if (key.code != sf::Keyboard::Unknown) // The key is recognized. - m_requester->keyUp(key); -} - - -//////////////////////////////////////////////////////// --(void)flagsChanged:(NSEvent*)theEvent -{ - // Transmit to non-SFML responder - [[self nextResponder] flagsChanged:theEvent]; - - if (m_requester == 0) - return; - - NSUInteger modifiers = [theEvent modifierFlags]; - handleModifiersChanged(modifiers, *m_requester); -} - - -//////////////////////////////////////////////////////// -+(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event -{ - // Key code - sf::Keyboard::Key key = sf::Keyboard::Unknown; - - // First we look if the key down is from a list of characters - // that depend on keyboard localization. - NSString* string = [event charactersIgnoringModifiers]; - if ([string length] > 0) - key = sf::priv::HIDInputManager::localizedKeys([string characterAtIndex:0]); - - // If the key is not a localized one, we try to find a corresponding code - // through virtual key code. - if (key == sf::Keyboard::Unknown) - key = sf::priv::HIDInputManager::nonLocalizedKeys([event keyCode]); - -//#ifdef SFML_DEBUG // Don't bother the final customers with annoying messages. -// if (key.code == sf::Keyboard::Unknown) { // The key is unknown. -// sf::err() << "This is an unknown key. Virtual key code is 0x" -// << std::hex -// << [event keyCode] -// << "." -// << std::endl; -// } -//#endif - - return keyEventWithModifiers([event modifierFlags], key); -} - @end - - -#pragma mark - C-like functions - -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; - } -} -