Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
authorSam Lantinga <slouken@libsdl.org>
Sat, 19 Sep 2009 13:29:40 +0000
changeset 328000cace2d9080
parent 3279 fd207dce9f94
child 3281 2d3a9f229ba1
Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
build-scripts/showrev.sh
include/SDL_events.h
include/SDL_keyboard.h
src/SDL_compat.c
src/events/SDL_keyboard.c
src/events/SDL_keyboard_c.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/cocoa/SDL_cocoaevents.m
src/video/cocoa/SDL_cocoakeyboard.h
src/video/cocoa/SDL_cocoakeyboard.m
src/video/cocoa/SDL_cocoamodes.m
src/video/cocoa/SDL_cocoavideo.h
src/video/cocoa/SDL_cocoavideo.m
test/Makefile.in
test/configure.in
test/testime.c
     1.1 --- a/build-scripts/showrev.sh	Sat Sep 19 12:48:52 2009 +0000
     1.2 +++ b/build-scripts/showrev.sh	Sat Sep 19 13:29:40 2009 +0000
     1.3 @@ -9,4 +9,7 @@
     1.4      (svnversion -c 2>/dev/null || svnversion .) | \
     1.5          sed -e 's,\([0-9]*\)[A-Z]*,\1,' \
     1.6              -e 's,[0-9]*:\([0-9]*\)[A-Z]*,\1,'
     1.7 +else
     1.8 +     cd $srcdir
     1.9 +     git svn info | grep Revision | awk '{ print $2 }'
    1.10  fi
     2.1 --- a/include/SDL_events.h	Sat Sep 19 12:48:52 2009 +0000
     2.2 +++ b/include/SDL_events.h	Sat Sep 19 13:29:40 2009 +0000
     2.3 @@ -60,6 +60,7 @@
     2.4      SDL_WINDOWEVENT,            /**< Window state change */
     2.5      SDL_KEYDOWN,                /**< Keys pressed */
     2.6      SDL_KEYUP,                  /**< Keys released */
     2.7 +    SDL_TEXTEDITING,            /**< Keyboard text editing (composition) */
     2.8      SDL_TEXTINPUT,              /**< Keyboard text input */
     2.9      SDL_MOUSEMOTION,            /**< Mouse moved */
    2.10      SDL_MOUSEBUTTONDOWN,        /**< Mouse button pressed */
    2.11 @@ -97,6 +98,7 @@
    2.12      SDL_KEYDOWNMASK = SDL_EVENTMASK(SDL_KEYDOWN),
    2.13      SDL_KEYUPMASK = SDL_EVENTMASK(SDL_KEYUP),
    2.14      SDL_KEYEVENTMASK = SDL_EVENTMASK(SDL_KEYDOWN) | SDL_EVENTMASK(SDL_KEYUP),
    2.15 +    SDL_TEXTEDITINGMASK = SDL_EVENTMASK(SDL_TEXTEDITING),
    2.16      SDL_TEXTINPUTMASK = SDL_EVENTMASK(SDL_TEXTINPUT),
    2.17      SDL_MOUSEMOTIONMASK = SDL_EVENTMASK(SDL_MOUSEMOTION),
    2.18      SDL_MOUSEBUTTONDOWNMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN),
    2.19 @@ -149,6 +151,20 @@
    2.20  } SDL_KeyboardEvent;
    2.21  
    2.22  /**
    2.23 + * \struct SDL_TextEditingEvent
    2.24 + *
    2.25 + * \brief Keyboard text editing event structure (event.edit.*)
    2.26 + */
    2.27 +#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32)
    2.28 +typedef struct SDL_TextEditingEvent
    2.29 +{
    2.30 +    Uint8 type;                                 /**< SDL_TEXTEDITING */
    2.31 +    char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE];  /**< The editing text */
    2.32 +    int start;                                  /**< The start cursor of selected editing text */
    2.33 +    int length;                                 /**< The length of selected editing text */
    2.34 +} SDL_TextEditingEvent;
    2.35 +
    2.36 +/**
    2.37   * \struct SDL_TextInputEvent
    2.38   *
    2.39   * \brief Keyboard text input event structure (event.text.*)
    2.40 @@ -350,6 +366,7 @@
    2.41      Uint8 type;                     /**< Event type, shared with all events */
    2.42      SDL_WindowEvent window;         /**< Window event data */
    2.43      SDL_KeyboardEvent key;          /**< Keyboard event data */
    2.44 +    SDL_TextEditingEvent edit;      /**< Text editing event data */
    2.45      SDL_TextInputEvent text;        /**< Text input event data */
    2.46      SDL_MouseMotionEvent motion;    /**< Mouse motion event data */
    2.47      SDL_MouseButtonEvent button;    /**< Mouse button event data */
     3.1 --- a/include/SDL_keyboard.h	Sat Sep 19 12:48:52 2009 +0000
     3.2 +++ b/include/SDL_keyboard.h	Sat Sep 19 13:29:40 2009 +0000
     3.3 @@ -154,6 +154,34 @@
     3.4   */
     3.5  extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDLKey key);
     3.6  
     3.7 +/**
     3.8 + * \fn void SDL_StartTextInput(void)
     3.9 + *
    3.10 + * \brief Start accepting Unicode text input events.
    3.11 + *
    3.12 + * \sa SDL_StopTextInput()
    3.13 + * \sa SDL_SetTextInputRect()
    3.14 + */
    3.15 +extern DECLSPEC void SDLCALL SDL_StartTextInput(void);
    3.16 +
    3.17 +/**
    3.18 + * \fn void SDL_StopTextInput(void)
    3.19 + *
    3.20 + * \brief Stop receiving any text input events.
    3.21 + *
    3.22 + * \sa SDL_StartTextInput()
    3.23 + */
    3.24 +extern DECLSPEC void SDLCALL SDL_StopTextInput(void);
    3.25 +
    3.26 +/**
    3.27 + * \fn void SDL_SetTextInputRect(SDL_Rect *rect)
    3.28 + *
    3.29 + * \brief Set the rectangle used to type Unicode text inputs.
    3.30 + *
    3.31 + * \sa SDL_StartTextInput()
    3.32 + */
    3.33 +extern DECLSPEC void SDLCALL SDL_SetTextInputRect(SDL_Rect *rect);
    3.34 +
    3.35  
    3.36  /* Ends C function definitions when using C++ */
    3.37  #ifdef __cplusplus
     4.1 --- a/src/SDL_compat.c	Sat Sep 19 12:48:52 2009 +0000
     4.2 +++ b/src/SDL_compat.c	Sat Sep 19 13:29:40 2009 +0000
     4.3 @@ -40,6 +40,7 @@
     4.4  static Uint32 SDL_VideoFlags = 0;
     4.5  static char *wm_title = NULL;
     4.6  static SDL_Surface *SDL_VideoIcon;
     4.7 +static int SDL_enabled_UNICODE = 0;
     4.8  
     4.9  char *
    4.10  SDL_AudioDriverName(char *namebuf, int maxlen)
    4.11 @@ -1720,7 +1721,19 @@
    4.12  int
    4.13  SDL_EnableUNICODE(int enable)
    4.14  {
    4.15 -    return SDL_EventState(SDL_TEXTINPUT, enable);
    4.16 +    int previous = SDL_enabled_UNICODE;
    4.17 +
    4.18 +    switch (enable) {
    4.19 +    case 1:
    4.20 +        SDL_enabled_UNICODE = 1;
    4.21 +        SDL_StartTextInput();
    4.22 +        break;
    4.23 +    case 0:
    4.24 +        SDL_enabled_UNICODE = 0;
    4.25 +        SDL_StopTextInput();
    4.26 +        break;
    4.27 +    }
    4.28 +    return previous;
    4.29  }
    4.30  
    4.31  /* vi: set ts=4 sw=4 expandtab: */
     5.1 --- a/src/events/SDL_keyboard.c	Sat Sep 19 12:48:52 2009 +0000
     5.2 +++ b/src/events/SDL_keyboard.c	Sat Sep 19 13:29:40 2009 +0000
     5.3 @@ -852,6 +852,24 @@
     5.4      return (posted);
     5.5  }
     5.6  
     5.7 +int
     5.8 +SDL_SendEditingText(const char *text, int start, int length)
     5.9 +{
    5.10 +    int posted;
    5.11 +
    5.12 +    /* Post the event, if desired */
    5.13 +    posted = 0;
    5.14 +    if (SDL_ProcessEvents[SDL_TEXTEDITING] == SDL_ENABLE) {
    5.15 +        SDL_Event event;
    5.16 +        event.edit.type = SDL_TEXTEDITING;
    5.17 +        event.edit.start = start;
    5.18 +        event.edit.length = length;
    5.19 +        SDL_strlcpy(event.edit.text, text, SDL_arraysize(event.text.text));
    5.20 +        posted = (SDL_PushEvent(&event) > 0);
    5.21 +    }
    5.22 +    return (posted);
    5.23 +}
    5.24 +
    5.25  void
    5.26  SDL_KeyboardQuit(void)
    5.27  {
     6.1 --- a/src/events/SDL_keyboard_c.h	Sat Sep 19 12:48:52 2009 +0000
     6.2 +++ b/src/events/SDL_keyboard_c.h	Sat Sep 19 13:29:40 2009 +0000
     6.3 @@ -81,6 +81,9 @@
     6.4  /* Send keyboard text input for a keyboard at an index */
     6.5  extern int SDL_SendKeyboardText(int index, const char *text);
     6.6  
     6.7 +/* Send editing text for selected range from start to end */
     6.8 +extern int SDL_SendEditingText(const char *text, int start, int end);
     6.9 +
    6.10  /* Shutdown the keyboard subsystem */
    6.11  extern void SDL_KeyboardQuit(void);
    6.12  
     7.1 --- a/src/video/SDL_sysvideo.h	Sat Sep 19 12:48:52 2009 +0000
     7.2 +++ b/src/video/SDL_sysvideo.h	Sat Sep 19 13:29:40 2009 +0000
     7.3 @@ -277,6 +277,11 @@
     7.4      /* Suspend the screensaver */
     7.5      void (*SuspendScreenSaver) (_THIS);
     7.6  
     7.7 +    /* Text input */
     7.8 +    void (*StartTextInput) (_THIS);
     7.9 +    void (*StopTextInput) (_THIS);
    7.10 +    void (*SetTextInputRect) (_THIS, SDL_Rect *rect);
    7.11 +
    7.12      /* * * */
    7.13      /* Data common to all drivers */
    7.14      SDL_bool suspend_screensaver;
     8.1 --- a/src/video/SDL_video.c	Sat Sep 19 12:48:52 2009 +0000
     8.2 +++ b/src/video/SDL_video.c	Sat Sep 19 13:29:40 2009 +0000
     8.3 @@ -3233,4 +3233,32 @@
     8.4      return (_this->GetWindowWMInfo(_this, window, info));
     8.5  }
     8.6  
     8.7 +void
     8.8 +SDL_StartTextInput(void)
     8.9 +{
    8.10 +    if (_this->StartTextInput) {
    8.11 +        _this->StartTextInput(_this);
    8.12 +    }
    8.13 +    SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
    8.14 +    SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
    8.15 +}
    8.16 +
    8.17 +void
    8.18 +SDL_StopTextInput(void)
    8.19 +{
    8.20 +    if (_this->StopTextInput) {
    8.21 +        _this->StopTextInput(_this);
    8.22 +    }
    8.23 +    SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
    8.24 +    SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
    8.25 +}
    8.26 +
    8.27 +void
    8.28 +SDL_SetTextInputRect(SDL_Rect *rect)
    8.29 +{
    8.30 +    if (_this->SetTextInputRect) {
    8.31 +        _this->SetTextInputRect(_this, rect);
    8.32 +    }
    8.33 +}
    8.34 +
    8.35  /* vi: set ts=4 sw=4 expandtab: */
     9.1 --- a/src/video/cocoa/SDL_cocoaevents.m	Sat Sep 19 12:48:52 2009 +0000
     9.2 +++ b/src/video/cocoa/SDL_cocoaevents.m	Sat Sep 19 13:29:40 2009 +0000
     9.3 @@ -193,6 +193,10 @@
     9.4              Cocoa_HandleKeyEvent(_this, event);
     9.5              /* Fall through to pass event to NSApp; er, nevermind... */
     9.6              /* FIXME: Find a way to stop the beeping, using delegate */
     9.7 +
     9.8 +            /* Add to support system-wide keyboard shortcuts like CMD+Space */
     9.9 +            if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged)
    9.10 +               [NSApp sendEvent: event];
    9.11              break;
    9.12          default:
    9.13              [NSApp sendEvent:event];
    10.1 --- a/src/video/cocoa/SDL_cocoakeyboard.h	Sat Sep 19 12:48:52 2009 +0000
    10.2 +++ b/src/video/cocoa/SDL_cocoakeyboard.h	Sat Sep 19 13:29:40 2009 +0000
    10.3 @@ -28,6 +28,10 @@
    10.4  extern void Cocoa_HandleKeyEvent(_THIS, NSEvent * event);
    10.5  extern void Cocoa_QuitKeyboard(_THIS);
    10.6  
    10.7 +extern void Cocoa_StartTextInput(_THIS);
    10.8 +extern void Cocoa_StopTextInput(_THIS);
    10.9 +extern void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect);
   10.10 +
   10.11  #endif /* _SDL_cocoakeyboard_h */
   10.12  
   10.13  /* vi: set ts=4 sw=4 expandtab: */
    11.1 --- a/src/video/cocoa/SDL_cocoakeyboard.m	Sat Sep 19 12:48:52 2009 +0000
    11.2 +++ b/src/video/cocoa/SDL_cocoakeyboard.m	Sat Sep 19 13:29:40 2009 +0000
    11.3 @@ -28,6 +28,8 @@
    11.4  
    11.5  #include <Carbon/Carbon.h>
    11.6  
    11.7 +//#define DEBUG_IME NSLog
    11.8 +#define DEBUG_IME
    11.9  
   11.10  #ifndef NX_DEVICERCTLKEYMASK
   11.11      #define NX_DEVICELCTLKEYMASK    0x00000001
   11.12 @@ -54,14 +56,142 @@
   11.13      #define NX_DEVICERCTLKEYMASK    0x00002000
   11.14  #endif
   11.15  
   11.16 -@interface SDLTranslatorResponder : NSTextView
   11.17 +@interface SDLTranslatorResponder : NSView <NSTextInput>
   11.18  {
   11.19 +    NSString *_markedText;
   11.20 +    NSRange   _markedRange;
   11.21 +    NSRange   _selectedRange;
   11.22 +    SDL_Rect  _inputRect;
   11.23 +    int       _keyboard;
   11.24  }
   11.25  - (void) doCommandBySelector:(SEL)myselector;
   11.26 +- (void) setInputRect:(SDL_Rect *) rect;
   11.27 +- (void) setKeyboard:(int) keyboard;
   11.28  @end
   11.29  
   11.30  @implementation SDLTranslatorResponder
   11.31 -- (void) doCommandBySelector:(SEL) myselector {}
   11.32 +
   11.33 +- (void) setKeyboard:(int) keyboard
   11.34 +{
   11.35 +    _keyboard = keyboard;
   11.36 +}
   11.37 +
   11.38 +- (void) setInputRect:(SDL_Rect *) rect
   11.39 +{
   11.40 +    _inputRect = *rect;
   11.41 +}
   11.42 +
   11.43 +- (void) insertText:(id) aString
   11.44 +{
   11.45 +    const char *str;
   11.46 +
   11.47 +    DEBUG_IME(@"insertText: %@", aString);
   11.48 +
   11.49 +    /* Could be NSString or NSAttributedString, so we have
   11.50 +     * to test and convert it before return as SDL event */
   11.51 +    if ([aString isKindOfClass: [NSAttributedString class]])
   11.52 +        str = [[aString string] UTF8String];
   11.53 +    else
   11.54 +        str = [aString UTF8String];
   11.55 +
   11.56 +    SDL_SendKeyboardText(_keyboard, str);
   11.57 +}
   11.58 +
   11.59 +- (void) doCommandBySelector:(SEL) myselector
   11.60 +{
   11.61 +    [super doCommandBySelector: myselector];
   11.62 +}
   11.63 +
   11.64 +- (BOOL) hasMarkedText
   11.65 +{
   11.66 +    return _markedText != nil;
   11.67 +}
   11.68 +
   11.69 +- (NSRange) markedRange
   11.70 +{
   11.71 +    return _markedRange;
   11.72 +}
   11.73 +
   11.74 +- (NSRange) selectedRange
   11.75 +{
   11.76 +    return _selectedRange;
   11.77 +}
   11.78 +
   11.79 +- (void) setMarkedText:(id) aString
   11.80 +         selectedRange:(NSRange) selRange
   11.81 +{
   11.82 +    if ([aString isKindOfClass: [NSAttributedString class]])
   11.83 +        aString = [aString string];
   11.84 +
   11.85 +    if ([aString length] == 0)
   11.86 +    {
   11.87 +        [self unmarkText];
   11.88 +        return;
   11.89 +    }
   11.90 +
   11.91 +    if (_markedText != aString)
   11.92 +    {
   11.93 +        [_markedText release];
   11.94 +        _markedText = [aString retain];
   11.95 +    }
   11.96 +
   11.97 +    _selectedRange = selRange;
   11.98 +    _markedRange = NSMakeRange(0, [aString length]);
   11.99 +
  11.100 +    SDL_SendEditingText([aString UTF8String], selRange.location, selRange.length);
  11.101 +
  11.102 +    DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
  11.103 +          selRange.location, selRange.length);
  11.104 +}
  11.105 +
  11.106 +- (void) unmarkText
  11.107 +{
  11.108 +    [_markedText release];
  11.109 +    _markedText = nil;
  11.110 +}
  11.111 +
  11.112 +- (NSRect) firstRectForCharacterRange: (NSRange) theRange
  11.113 +{
  11.114 +    float windowHeight = [[self window] frame].size.height;
  11.115 +    NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
  11.116 +                             _inputRect.w, _inputRect.h);
  11.117 +
  11.118 +    DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
  11.119 +            theRange.location, theRange.length, windowHeight,
  11.120 +            NSStringFromRect(rect));
  11.121 +    rect.origin = [[self window] convertBaseToScreen: rect.origin];
  11.122 +
  11.123 +    return rect;
  11.124 +}
  11.125 +
  11.126 +- (NSAttributedString *) attributedSubstringFromRange: (NSRange) theRange
  11.127 +{
  11.128 +    DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", theRange.location, theRange.length);
  11.129 +    return nil;
  11.130 +}
  11.131 +
  11.132 +- (NSInteger) conversationIdentifier
  11.133 +{
  11.134 +    return (NSInteger) self;
  11.135 +}
  11.136 +
  11.137 +// This method returns the index for character that is 
  11.138 +// nearest to thePoint.  thPoint is in screen coordinate system.
  11.139 +- (NSUInteger) characterIndexForPoint:(NSPoint) thePoint
  11.140 +{
  11.141 +    DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
  11.142 +    return 0;
  11.143 +}
  11.144 +
  11.145 +// This method is the key to attribute extension. 
  11.146 +// We could add new attributes through this method.
  11.147 +// NSInputServer examines the return value of this
  11.148 +// method & constructs appropriate attributed string.
  11.149 +- (NSArray *) validAttributesForMarkedText
  11.150 +{
  11.151 +    return [NSArray array];
  11.152 +}
  11.153 +
  11.154  @end
  11.155  
  11.156  /* This is the original behavior, before support was added for 
  11.157 @@ -478,12 +608,7 @@
  11.158  {
  11.159      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.160      SDL_Keyboard keyboard;
  11.161 -    NSAutoreleasePool *pool;
  11.162  
  11.163 -    pool = [[NSAutoreleasePool alloc] init];
  11.164 -    data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)];
  11.165 -    [pool release];
  11.166 -    
  11.167      SDL_zero(keyboard);
  11.168      data->keyboard = SDL_AddKeyboard(&keyboard, -1);
  11.169      UpdateKeymap(data);
  11.170 @@ -498,6 +623,47 @@
  11.171  }
  11.172  
  11.173  void
  11.174 +Cocoa_StartTextInput(_THIS)
  11.175 +{
  11.176 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.177 +    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  11.178 +    NSView *parentView = [[NSApp keyWindow] contentView];
  11.179 +
  11.180 +    data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)];
  11.181 +    [data->fieldEdit setKeyboard: data->keyboard];
  11.182 +
  11.183 +    if (! [[data->fieldEdit superview] isEqual: parentView])
  11.184 +    {
  11.185 +        // DEBUG_IME(@"add fieldEdit to window contentView");
  11.186 +        [data->fieldEdit removeFromSuperview];
  11.187 +        [parentView addSubview: data->fieldEdit];
  11.188 +        [[NSApp keyWindow] makeFirstResponder: data->fieldEdit];
  11.189 +    }
  11.190 +
  11.191 +    [pool release];
  11.192 +}
  11.193 +
  11.194 +void
  11.195 +Cocoa_StopTextInput(_THIS)
  11.196 +{
  11.197 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.198 +
  11.199 +    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  11.200 +    [data->fieldEdit removeFromSuperview];
  11.201 +    [data->fieldEdit release];
  11.202 +    data->fieldEdit = nil;
  11.203 +    [pool release];
  11.204 +}
  11.205 +
  11.206 +void
  11.207 +Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
  11.208 +{
  11.209 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.210 +
  11.211 +    [data->fieldEdit setInputRect: rect];
  11.212 +}
  11.213 +
  11.214 +void
  11.215  Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
  11.216  {
  11.217      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.218 @@ -533,11 +699,13 @@
  11.219          if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
  11.220              /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
  11.221              [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
  11.222 +#if 0
  11.223              text = [[event characters] UTF8String];
  11.224              if(text && *text) {
  11.225                  SDL_SendKeyboardText(data->keyboard, text);
  11.226                  [data->fieldEdit setString:@""];
  11.227              }
  11.228 +#endif
  11.229          }
  11.230          break;
  11.231      case NSKeyUp:
  11.232 @@ -559,10 +727,6 @@
  11.233      NSAutoreleasePool *pool;
  11.234  
  11.235      SDL_DelKeyboard(data->keyboard);
  11.236 -
  11.237 -    pool = [[NSAutoreleasePool alloc] init];
  11.238 -    [data->fieldEdit release];
  11.239 -    [pool release];
  11.240  }
  11.241  
  11.242  /* vi: set ts=4 sw=4 expandtab: */
    12.1 --- a/src/video/cocoa/SDL_cocoamodes.m	Sat Sep 19 12:48:52 2009 +0000
    12.2 +++ b/src/video/cocoa/SDL_cocoamodes.m	Sat Sep 19 13:29:40 2009 +0000
    12.3 @@ -250,6 +250,8 @@
    12.4          CGReleaseDisplayFadeReservation(fade_token);
    12.5      }
    12.6  
    12.7 +    [[NSApp mainWindow] makeKeyAndOrderFront: nil];
    12.8 +
    12.9  #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
   12.10      /* 
   12.11          There is a bug in Cocoa where NSScreen doesn't synchronize
    13.1 --- a/src/video/cocoa/SDL_cocoavideo.h	Sat Sep 19 12:48:52 2009 +0000
    13.2 +++ b/src/video/cocoa/SDL_cocoavideo.h	Sat Sep 19 13:29:40 2009 +0000
    13.3 @@ -41,6 +41,8 @@
    13.4  
    13.5  /* Private display data */
    13.6  
    13.7 +@class SDLTranslatorResponder;
    13.8 +
    13.9  typedef struct SDL_VideoData
   13.10  {
   13.11      SInt32 osversion;
   13.12 @@ -48,7 +50,7 @@
   13.13      int mouse;
   13.14      int keyboard;
   13.15      void *key_layout;
   13.16 -    NSText *fieldEdit;
   13.17 +    SDLTranslatorResponder *fieldEdit;
   13.18      Uint32 screensaver_activity;
   13.19  } SDL_VideoData;
   13.20  
    14.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Sat Sep 19 12:48:52 2009 +0000
    14.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Sat Sep 19 13:29:40 2009 +0000
    14.3 @@ -102,6 +102,10 @@
    14.4      device->GL_DeleteContext = Cocoa_GL_DeleteContext;
    14.5  #endif
    14.6  
    14.7 +    device->StartTextInput = Cocoa_StartTextInput;
    14.8 +    device->StopTextInput = Cocoa_StopTextInput;
    14.9 +    device->SetTextInputRect = Cocoa_SetTextInputRect;
   14.10 +
   14.11      device->free = Cocoa_DeleteDevice;
   14.12  
   14.13      return device;
    15.1 --- a/test/Makefile.in	Sat Sep 19 12:48:52 2009 +0000
    15.2 +++ b/test/Makefile.in	Sat Sep 19 13:29:40 2009 +0000
    15.3 @@ -7,7 +7,7 @@
    15.4  CFLAGS  = @CFLAGS@
    15.5  LIBS	= @LIBS@
    15.6  
    15.7 -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) testatomic$(EXE)
    15.8 +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) testatomic$(EXE) testime$(EXE)
    15.9  
   15.10  all: Makefile $(TARGETS)
   15.11  
   15.12 @@ -149,6 +149,9 @@
   15.13  testatomic$(EXE): $(srcdir)/testatomic.c
   15.14  	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
   15.15   
   15.16 +testime$(EXE): $(srcdir)/testime.c
   15.17 +	$(CC) -o $@ $? $(CFLAGS) $(LIBS) @SDL_TTF_LIB@
   15.18 +
   15.19  clean:
   15.20  	rm -f $(TARGETS)
   15.21  
    16.1 --- a/test/configure.in	Sat Sep 19 12:48:52 2009 +0000
    16.2 +++ b/test/configure.in	Sat Sep 19 13:29:40 2009 +0000
    16.3 @@ -128,5 +128,23 @@
    16.4  
    16.5  AC_SUBST(GLLIB)
    16.6  
    16.7 +dnl Check for SDL_ttf
    16.8 +AC_MSG_CHECKING(for SDL_ttf)
    16.9 +have_SDL_ttf=no
   16.10 +AC_TRY_COMPILE([
   16.11 + #include "SDL_ttf.h"
   16.12 +],[
   16.13 +],[
   16.14 +have_SDL_ttf=yes
   16.15 +])
   16.16 +AC_MSG_RESULT($have_SDL_ttf)
   16.17 +
   16.18 +if test x$have_SDL_ttf = xyes; then
   16.19 +    CFLAGS="$CFLAGS -DHAVE_SDL_TTF"
   16.20 +    SDL_TTF_LIB="-lSDL_ttf"
   16.21 +fi
   16.22 +
   16.23 +AC_SUBST(SDL_TTF_LIB)
   16.24 +
   16.25  dnl Finally create all the generated files
   16.26  AC_OUTPUT([Makefile])
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/test/testime.c	Sat Sep 19 13:29:40 2009 +0000
    17.3 @@ -0,0 +1,275 @@
    17.4 +/* A simple program to test the Input Method support in the SDL library (1.3+) */
    17.5 + 
    17.6 +#include <stdlib.h>
    17.7 +#include <stdio.h>
    17.8 +#include <string.h>
    17.9 +
   17.10 +#include "SDL.h"
   17.11 +#ifdef HAVE_SDL_TTF
   17.12 +#include "SDL_ttf.h"
   17.13 +#endif
   17.14 + 
   17.15 +#define DEFAULT_PTSIZE  30
   17.16 +#define DEFAULT_FONT    "/System/Library/Fonts/华文细黑.ttf"
   17.17 +#define MAX_TEXT_LENGTH 256
   17.18 +
   17.19 +SDL_Surface *screen;
   17.20 +
   17.21 +#ifdef HAVE_SDL_TTF
   17.22 +TTF_Font *font;
   17.23 +#endif
   17.24 +SDL_Rect textRect, markedRect;
   17.25 +Uint32 lineColor, backColor;
   17.26 +SDL_Color textColor = { 0, 0, 0 };
   17.27 +char text[MAX_TEXT_LENGTH], *markedText;
   17.28 +
   17.29 +void usage()
   17.30 +{
   17.31 +    printf("usage: testime [--font fontfile] [--fullscreen]\n");
   17.32 +    exit(0);
   17.33 +}
   17.34 +
   17.35 +void InitVideo(int argc, char *argv[])
   17.36 +{
   17.37 +    int width = 500, height = 250;
   17.38 +    int flags = SDL_HWSURFACE;
   17.39 +    const char *fontname = DEFAULT_FONT;
   17.40 +    int fullscreen = 0;
   17.41 +
   17.42 +    for (argc--, argv++; argc > 0; argc--, argv++)
   17.43 +    {
   17.44 +        if (strcmp(argv[0], "--help") == 0)
   17.45 +            usage();
   17.46 +
   17.47 +        else if (strcmp(argv[0], "--fullscreen") == 0)
   17.48 +            fullscreen = 1;
   17.49 +
   17.50 +        else if (strcmp(argv[0], "--font") == 0)
   17.51 +        {
   17.52 +            argc--;
   17.53 +            argv++;
   17.54 +
   17.55 +            if (argc > 0)
   17.56 +                fontname = argv[0];
   17.57 +            else
   17.58 +                usage();
   17.59 +        }
   17.60 +    }
   17.61 +
   17.62 +    SDL_putenv("SDL_VIDEO_WINDOW_POS=center");
   17.63 +    if (SDL_Init(SDL_INIT_VIDEO) < 0)
   17.64 +    {
   17.65 +        fprintf(stderr, "Unable to init SDL: %s\n", TTF_GetError());
   17.66 +        exit(-1);
   17.67 +    }
   17.68 +
   17.69 +#ifdef HAVE_SDL_TTF
   17.70 +    /* Initialize fonts */
   17.71 +    TTF_Init();
   17.72 +
   17.73 +    font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
   17.74 +    if (! font)
   17.75 +    {
   17.76 +        fprintf(stderr, "Failed to find font: %s\n", SDL_GetError());
   17.77 +        exit(-1);
   17.78 +    }
   17.79 +#endif
   17.80 +
   17.81 +    printf("Using font: %s\n", fontname);
   17.82 +    atexit(SDL_Quit);
   17.83 +
   17.84 +    if (fullscreen)
   17.85 +    {
   17.86 +        SDL_DisplayMode mode;
   17.87 +        SDL_GetDesktopDisplayMode(&mode);
   17.88 +
   17.89 +        width = mode.w;
   17.90 +        height = mode.h;
   17.91 +        fprintf(stderr, "%dx%d\n", width, height);
   17.92 +        flags |= SDL_FULLSCREEN;
   17.93 +    }
   17.94 +
   17.95 +    /* Create window */
   17.96 +    screen = SDL_SetVideoMode(width, height, 32, flags);
   17.97 +    if (screen == NULL)
   17.98 +    {
   17.99 +        fprintf(stderr, "Unable to set %dx%d video: %s\n",
  17.100 +                width, height, SDL_GetError());
  17.101 +        exit(-1);
  17.102 +    }
  17.103 +}
  17.104 +
  17.105 +void CleanupVideo()
  17.106 +{
  17.107 +    SDL_StopTextInput();
  17.108 +#ifdef HAVE_SDL_TTF
  17.109 +    TTF_CloseFont(font);
  17.110 +    TTF_Quit();
  17.111 +#endif
  17.112 +}
  17.113 +
  17.114 +void InitInput()
  17.115 +{
  17.116 +    backColor = SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF);
  17.117 +    lineColor = SDL_MapRGB(screen->format, 0x0, 0x0, 0x0);
  17.118 +
  17.119 +    /* Prepare a rect for text input */
  17.120 +    textRect.x = textRect.y = 100;
  17.121 +    textRect.w = screen->w - 2 * textRect.x;
  17.122 +    textRect.h = 50;
  17.123 +
  17.124 +    text[0] = 0;
  17.125 +    markedRect = textRect;
  17.126 +    markedText = NULL;
  17.127 +
  17.128 +    SDL_StartTextInput();
  17.129 +}
  17.130 +
  17.131 +#ifdef HAVE_SDL_TTF
  17.132 +static void RenderText(SDL_Surface *sur,
  17.133 +                        TTF_Font *font,
  17.134 +                        const char *text,
  17.135 +                        int x, int y,
  17.136 +                        SDL_Color color)
  17.137 +{
  17.138 +    SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, color);
  17.139 +    SDL_Rect dest = { x, y, textSur->w, textSur->h };
  17.140 +
  17.141 +    SDL_BlitSurface(textSur, NULL, sur, &dest);
  17.142 +    SDL_FreeSurface(textSur);
  17.143 +}
  17.144 +#endif
  17.145 +
  17.146 +void Redraw()
  17.147 +{
  17.148 +    int w = 0, h = textRect.h;
  17.149 +    SDL_Rect cursorRect, underlineRect;
  17.150 +
  17.151 +    SDL_FillRect(screen, &textRect, backColor);
  17.152 +
  17.153 +#ifdef HAVE_SDL_TTF
  17.154 +    if (strlen(text))
  17.155 +    {
  17.156 +        RenderText(screen, font, text, textRect.x, textRect.y, textColor);
  17.157 +        TTF_SizeUTF8(font, text, &w, &h);
  17.158 +    }
  17.159 +#endif
  17.160 +
  17.161 +    markedRect.x = textRect.x + w;
  17.162 +    markedRect.w = textRect.w - w;
  17.163 +    if (markedRect.w < 0)
  17.164 +    {
  17.165 +        SDL_Flip(screen);
  17.166 +        // Stop text input because we cannot hold any more characters
  17.167 +        SDL_StopTextInput();
  17.168 +        return;
  17.169 +    }
  17.170 +
  17.171 +    cursorRect = markedRect;
  17.172 +    cursorRect.w = 2;
  17.173 +    cursorRect.h = h;
  17.174 +
  17.175 +    SDL_FillRect(screen, &markedRect, backColor);
  17.176 +    if (markedText)
  17.177 +    {
  17.178 +#ifdef HAVE_SDL_TTF
  17.179 +        RenderText(screen, font, markedText, markedRect.x, markedRect.y, textColor);
  17.180 +        TTF_SizeUTF8(font, markedText, &w, &h);
  17.181 +#endif
  17.182 +
  17.183 +        underlineRect = markedRect;
  17.184 +        underlineRect.y += (h - 2);
  17.185 +        underlineRect.h = 2;
  17.186 +        underlineRect.w = w;
  17.187 +
  17.188 +        cursorRect.x += w + 1;
  17.189 +
  17.190 +        SDL_FillRect(screen, &underlineRect, lineColor);
  17.191 +    }
  17.192 +
  17.193 +    SDL_FillRect(screen, &cursorRect, lineColor);
  17.194 +
  17.195 +    SDL_Flip(screen);
  17.196 +
  17.197 +    SDL_SetTextInputRect(&markedRect);
  17.198 +}
  17.199 +
  17.200 +void
  17.201 +HotKey_ToggleFullScreen(void)
  17.202 +{
  17.203 +    SDL_Surface *screen;
  17.204 +
  17.205 +    screen = SDL_GetVideoSurface();
  17.206 +    if (SDL_WM_ToggleFullScreen(screen)) {
  17.207 +        printf("Toggled fullscreen mode - now %s\n",
  17.208 +               (screen->flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed");
  17.209 +    } else {
  17.210 +        printf("Unable to toggle fullscreen mode\n");
  17.211 +    }
  17.212 +}
  17.213 +
  17.214 +int main(int argc, char *argv[])
  17.215 +{
  17.216 +    InitVideo(argc, argv);
  17.217 +    InitInput();
  17.218 +    Redraw();
  17.219 +
  17.220 +    SDL_Event event;
  17.221 +    int done = 0;
  17.222 +
  17.223 +    while (! done && SDL_WaitEvent(&event))
  17.224 +    {
  17.225 +        switch (event.type)
  17.226 +        {
  17.227 +        case SDL_KEYDOWN:
  17.228 +            if (event.key.keysym.sym == SDLK_ESCAPE) {
  17.229 +                done = 1;
  17.230 +                break;
  17.231 +            }
  17.232 +
  17.233 +            fprintf(stderr,
  17.234 +                    "Keyboard %d: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
  17.235 +                    event.key.which, event.key.keysym.scancode,
  17.236 +                    SDL_GetScancodeName(event.key.keysym.scancode),
  17.237 +                    event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
  17.238 +            break;
  17.239 +
  17.240 +        case SDL_TEXTINPUT:
  17.241 +            if (strlen(event.text.text) == 0 || event.text.text[0] == '\n' ||
  17.242 +                markedRect.w < 0)
  17.243 +                break;
  17.244 +
  17.245 +            fprintf(stderr, "Keyboard %d: text input \"%s\"\n",
  17.246 +                    event.text.which, event.text.text);
  17.247 +
  17.248 +            if (strlen(text) + strlen(event.text.text) < sizeof(text))
  17.249 +                strcpy(text + strlen(text), event.text.text);
  17.250 +
  17.251 +            fprintf(stderr, "text inputed: %s\n", text);
  17.252 +
  17.253 +            // After text inputed, we can clear up markedText because it
  17.254 +            // is committed
  17.255 +            markedText = NULL;
  17.256 +            Redraw();
  17.257 +            break;
  17.258 +
  17.259 +        case SDL_TEXTEDITING:
  17.260 +            fprintf(stderr, "text editing \"%s\", selected range (%d, %d)\n",
  17.261 +                    event.edit.text, event.edit.start, event.edit.length);
  17.262 +
  17.263 +            markedText = event.edit.text;
  17.264 +            Redraw();
  17.265 +            break;
  17.266 +
  17.267 +        case SDL_QUIT:
  17.268 +            done = 1;
  17.269 +            break;
  17.270 +
  17.271 +        default:
  17.272 +            break;
  17.273 +        }
  17.274 +    }
  17.275 +
  17.276 +    CleanupVideo();
  17.277 +    return 0;
  17.278 +}