Blame clutter/osx/clutter-event-osx.c

Packit 31ecd5
/* Clutter -  An OpenGL based 'interactive canvas' library.
Packit 31ecd5
 * OSX backend - event loops integration
Packit 31ecd5
 *
Packit 31ecd5
 * Copyright (C) 2007-2008  Tommi Komulainen <tommi.komulainen@iki.fi>
Packit 31ecd5
 * Copyright (C) 2007  OpenedHand Ltd.
Packit 31ecd5
 * Copyright (C) 2011  Crystalnix  <vgachkaylo@crystalnix.com>
Packit 31ecd5
 *
Packit 31ecd5
 * This library is free software; you can redistribute it and/or
Packit 31ecd5
 * modify it under the terms of the GNU Lesser General Public
Packit 31ecd5
 * License as published by the Free Software Foundation; either
Packit 31ecd5
 * version 2 of the License, or (at your option) any later version.
Packit 31ecd5
 *
Packit 31ecd5
 * This library is distributed in the hope that it will be useful,
Packit 31ecd5
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 31ecd5
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 31ecd5
 * Lesser General Public License for more details.
Packit 31ecd5
 *
Packit 31ecd5
 * You should have received a copy of the GNU Lesser General Public
Packit 31ecd5
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Packit 31ecd5
 *
Packit 31ecd5
 *
Packit 31ecd5
 */
Packit 31ecd5
#include "config.h"
Packit 31ecd5
Packit 31ecd5
#include "clutter-osx.h"
Packit 31ecd5
Packit 31ecd5
#include "clutter-backend-osx.h"
Packit 31ecd5
#include "clutter-device-manager-osx.h"
Packit 31ecd5
#include "clutter-stage-osx.h"
Packit 31ecd5
Packit 31ecd5
#import <AppKit/AppKit.h>
Packit 31ecd5
Packit 31ecd5
#include <glib.h>
Packit 31ecd5
Packit 31ecd5
#include "clutter-debug.h"
Packit 31ecd5
#include "clutter-device-manager.h"
Packit 31ecd5
#include "clutter-event-private.h"
Packit 31ecd5
#include "clutter-keysyms.h"
Packit 31ecd5
#include "clutter-private.h"
Packit 31ecd5
#include "clutter-stage-private.h"
Packit 31ecd5
Packit 31ecd5
#define WHEEL_DELTA 1
Packit 31ecd5
Packit 31ecd5
/*************************************************************************/
Packit 31ecd5
@interface NSEvent (Clutter)
Packit 31ecd5
- (gint)clutterTime;
Packit 31ecd5
- (gint)clutterButton;
Packit 31ecd5
- (void)clutterX:(gfloat*)ptrX y:(gfloat*)ptrY;
Packit 31ecd5
- (gint)clutterModifierState;
Packit 31ecd5
- (guint)clutterKeyVal;
Packit 31ecd5
@end
Packit 31ecd5
Packit 31ecd5
@implementation NSEvent (Clutter)
Packit 31ecd5
- (gint)clutterTime
Packit 31ecd5
{
Packit 31ecd5
  return [self timestamp] * 1000;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
- (gint)clutterButton
Packit 31ecd5
{
Packit 31ecd5
  switch ([self buttonNumber])
Packit 31ecd5
    {
Packit 31ecd5
    case 0: return 1;   /* left   */
Packit 31ecd5
    case 1: return 3;   /* right  */
Packit 31ecd5
    case 2: return 2;   /* middle */
Packit 31ecd5
    default: return 1 + [self buttonNumber];
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
- (void)clutterX:(gfloat*)ptrX y:(gfloat*)ptrY
Packit 31ecd5
{
Packit 31ecd5
  NSView *view = [[self window] contentView];
Packit 31ecd5
  NSPoint pt = [view convertPoint:[self locationInWindow] fromView:nil];
Packit 31ecd5
Packit 31ecd5
  *ptrX = pt.x;
Packit 31ecd5
  *ptrY = pt.y;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
- (gint)clutterModifierState
Packit 31ecd5
{
Packit 31ecd5
  guint mods = [self modifierFlags];
Packit 31ecd5
  guint type = [self type];
Packit 31ecd5
  gint rv = 0;
Packit 31ecd5
Packit 31ecd5
  /* add key masks */
Packit 31ecd5
  if (mods & NSAlphaShiftKeyMask)
Packit 31ecd5
    rv |= CLUTTER_LOCK_MASK;
Packit 31ecd5
  if (mods & NSShiftKeyMask)
Packit 31ecd5
    rv |= CLUTTER_SHIFT_MASK;
Packit 31ecd5
  if (mods & NSControlKeyMask)
Packit 31ecd5
    rv |= CLUTTER_CONTROL_MASK;
Packit 31ecd5
  if (mods & NSAlternateKeyMask)
Packit 31ecd5
    rv |= CLUTTER_MOD1_MASK;
Packit 31ecd5
  if (mods & NSCommandKeyMask)
Packit 31ecd5
    rv |= CLUTTER_MOD2_MASK;
Packit 31ecd5
Packit 31ecd5
  /* add button mask */
Packit 31ecd5
  if ((type == NSLeftMouseDragged) ||
Packit 31ecd5
      (type == NSRightMouseDragged) ||
Packit 31ecd5
      (type == NSOtherMouseDragged))
Packit 31ecd5
    rv |= CLUTTER_BUTTON1_MASK << [self buttonNumber];
Packit 31ecd5
Packit 31ecd5
  return rv;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
- (guint)clutterKeyVal
Packit 31ecd5
{
Packit 31ecd5
  unichar c;
Packit 31ecd5
Packit 31ecd5
  /* FIXME: doing this right is a lot of work, see gdkkeys-quartz.c in gtk+
Packit 31ecd5
   * For now handle some common/simple keys only. Might not work with other
Packit 31ecd5
   * hardware than mine (MacBook Pro, finnish layout). Sorry.
Packit 31ecd5
   *
Packit 31ecd5
   * charactersIgnoringModifiers ignores most modifiers, not Shift though.
Packit 31ecd5
   * So, for all Shift-modified keys we'll end up reporting 'keyval' identical
Packit 31ecd5
   * to 'unicode_value'  Instead of <Shift>a or <Shift>3 you'd get <Shift>A
Packit 31ecd5
   * and <Shift>#
Packit 31ecd5
   */
Packit 31ecd5
Packit 31ecd5
  if ([self type] == NSFlagsChanged)
Packit 31ecd5
    {
Packit 31ecd5
      switch ([self keyCode])
Packit 31ecd5
        {
Packit 31ecd5
        case 54: // Right Command
Packit 31ecd5
          return CLUTTER_KEY_Meta_R;
Packit 31ecd5
        case 55: // Left Command
Packit 31ecd5
          return CLUTTER_KEY_Meta_L;
Packit 31ecd5
        case 57: // Capslock
Packit 31ecd5
          return CLUTTER_KEY_Caps_Lock;
Packit 31ecd5
        case 56: // Left Shift
Packit 31ecd5
          return CLUTTER_KEY_Shift_L;
Packit 31ecd5
        case 60: // Right Shift
Packit 31ecd5
          return CLUTTER_KEY_Shift_R;
Packit 31ecd5
        case 58: // Left Alt
Packit 31ecd5
          return CLUTTER_KEY_Alt_L;
Packit 31ecd5
        case 61: // Right Alt
Packit 31ecd5
          return CLUTTER_KEY_Alt_R;
Packit 31ecd5
        case 59: // Left Ctrl
Packit 31ecd5
          return CLUTTER_KEY_Control_L;
Packit 31ecd5
        case 62: // Right Ctrl
Packit 31ecd5
          return CLUTTER_KEY_Control_R;
Packit 31ecd5
        case 63: // Function
Packit 31ecd5
          return CLUTTER_KEY_function;
Packit 31ecd5
        default: // No such key??!??
Packit 31ecd5
          CLUTTER_NOTE (EVENT, "Got NSFlagsChanged event with keyCode not a known modifier key: %d",
Packit 31ecd5
                              [self keyCode]);
Packit 31ecd5
          return CLUTTER_KEY_VoidSymbol;
Packit 31ecd5
        }
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  c = [[self charactersIgnoringModifiers] characterAtIndex:0];
Packit 31ecd5
Packit 31ecd5
  /* Latin-1 characters, 1:1 mapping - this ought to be reliable */
Packit 31ecd5
  if ((c >= 0x0020 && c <= 0x007e) ||
Packit 31ecd5
      (c >= 0x00a0 && c <= 0x00ff))
Packit 31ecd5
    return c;
Packit 31ecd5
Packit 31ecd5
  switch (c)
Packit 31ecd5
    {
Packit 31ecd5
    /* these should be fairly standard */
Packit 31ecd5
    /* (maybe add 0x0008 (Ctrl+H) for backspace too) */
Packit 31ecd5
    case 0x000d:
Packit 31ecd5
      return CLUTTER_KEY_Return;
Packit 31ecd5
    case 0x001b:
Packit 31ecd5
      return CLUTTER_KEY_Escape;
Packit 31ecd5
    case 0x007f:
Packit 31ecd5
      return CLUTTER_KEY_BackSpace;
Packit 31ecd5
    /* Defined in NSEvent.h */
Packit 31ecd5
    case NSUpArrowFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Up;
Packit 31ecd5
    case NSDownArrowFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Down;
Packit 31ecd5
    case NSLeftArrowFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Left;
Packit 31ecd5
    case NSRightArrowFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Right;
Packit 31ecd5
    case NSF1FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F1;
Packit 31ecd5
    case NSF2FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F2;
Packit 31ecd5
    case NSF3FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F3;
Packit 31ecd5
    case NSF4FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F4;
Packit 31ecd5
    case NSF5FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F5;
Packit 31ecd5
    case NSF6FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F6;
Packit 31ecd5
    case NSF7FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F7;
Packit 31ecd5
    case NSF8FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F8;
Packit 31ecd5
    case NSF9FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F9;
Packit 31ecd5
    case NSF10FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F10;
Packit 31ecd5
    case NSF11FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F11;
Packit 31ecd5
    case NSF12FunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_F12;
Packit 31ecd5
    case NSInsertFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Insert;
Packit 31ecd5
    case NSDeleteFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Delete;
Packit 31ecd5
    case NSHomeFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Home;
Packit 31ecd5
    case NSEndFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_End;
Packit 31ecd5
    case NSPageUpFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Page_Up;
Packit 31ecd5
    case NSPageDownFunctionKey:
Packit 31ecd5
      return CLUTTER_KEY_Page_Down;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  CLUTTER_NOTE (BACKEND, "unhandled unicode key 0x%x (%d)", c, c);
Packit 31ecd5
Packit 31ecd5
  /* hardware dependent, worksforme(tm) Redundant due to above, left around as
Packit 31ecd5
   * example.
Packit 31ecd5
   */
Packit 31ecd5
  switch ([self keyCode])
Packit 31ecd5
    {
Packit 31ecd5
    case 115:
Packit 31ecd5
      return CLUTTER_KEY_Home;
Packit 31ecd5
    case 116:
Packit 31ecd5
      return CLUTTER_KEY_Page_Up;
Packit 31ecd5
    case 117:
Packit 31ecd5
      return CLUTTER_KEY_Delete;
Packit 31ecd5
    case 119:
Packit 31ecd5
      return CLUTTER_KEY_End;
Packit 31ecd5
    case 121:
Packit 31ecd5
      return CLUTTER_KEY_Page_Down;
Packit 31ecd5
    case 123:
Packit 31ecd5
      return CLUTTER_KEY_Left;
Packit 31ecd5
    case 124:
Packit 31ecd5
      return CLUTTER_KEY_Right;
Packit 31ecd5
    case 125:
Packit 31ecd5
      return CLUTTER_KEY_Down;
Packit 31ecd5
    case 126:
Packit 31ecd5
      return CLUTTER_KEY_Up;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  return 0;
Packit 31ecd5
}
Packit 31ecd5
@end
Packit 31ecd5
Packit 31ecd5
/*************************************************************************/
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
take_and_queue_event (ClutterEvent *event)
Packit 31ecd5
{
Packit 31ecd5
  _clutter_event_push (event, FALSE);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
process_scroll_event (ClutterEvent *event,
Packit 31ecd5
                      gboolean isVertical)
Packit 31ecd5
{
Packit 31ecd5
  ClutterStageWindow *impl;
Packit 31ecd5
  ClutterStageOSX *stage_osx;
Packit 31ecd5
  gfloat *scroll_pos;
Packit 31ecd5
Packit 31ecd5
  impl = _clutter_stage_get_window (event->any.stage);
Packit 31ecd5
  stage_osx = CLUTTER_STAGE_OSX (impl);
Packit 31ecd5
  
Packit 31ecd5
  scroll_pos = isVertical
Packit 31ecd5
             ? &(stage_osx->scroll_pos_y)
Packit 31ecd5
             : &(stage_osx->scroll_pos_x);
Packit 31ecd5
 
Packit 31ecd5
  while (abs (*scroll_pos) >= WHEEL_DELTA) 
Packit 31ecd5
    {
Packit 31ecd5
      ClutterEvent *event_gen = clutter_event_new (CLUTTER_SCROLL);
Packit 31ecd5
Packit 31ecd5
      event_gen->scroll.time = event->any.time;
Packit 31ecd5
      event_gen->scroll.modifier_state = event->scroll.modifier_state;
Packit 31ecd5
      event_gen->any.stage = event->any.stage;
Packit 31ecd5
Packit 31ecd5
      event_gen->scroll.x = event->scroll.x;
Packit 31ecd5
      event_gen->scroll.y = event->scroll.y;
Packit 31ecd5
Packit 31ecd5
      if (*scroll_pos > 0)
Packit 31ecd5
        {
Packit 31ecd5
          event_gen->scroll.direction = isVertical ? CLUTTER_SCROLL_UP : CLUTTER_SCROLL_RIGHT;
Packit 31ecd5
          *scroll_pos -= WHEEL_DELTA;
Packit 31ecd5
        }
Packit 31ecd5
      else
Packit 31ecd5
        {
Packit 31ecd5
          event_gen->scroll.direction = isVertical ? CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_LEFT;
Packit 31ecd5
          *scroll_pos += WHEEL_DELTA;
Packit 31ecd5
        }
Packit 31ecd5
Packit 31ecd5
      clutter_event_set_device (event_gen, clutter_event_get_device (event));
Packit 31ecd5
Packit 31ecd5
      take_and_queue_event (event_gen);
Packit 31ecd5
      
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "scroll %s at %f,%f",
Packit 31ecd5
                    (event_gen->scroll.direction == CLUTTER_SCROLL_UP) ? "UP" :
Packit 31ecd5
                    ( 
Packit 31ecd5
                    (event_gen->scroll.direction == CLUTTER_SCROLL_DOWN) ? "DOWN" :
Packit 31ecd5
                    (
Packit 31ecd5
                    (event_gen->scroll.direction == CLUTTER_SCROLL_RIGHT) ? "RIGHT" : "LEFT")),
Packit 31ecd5
                    event->scroll.x, event->scroll.y);
Packit 31ecd5
    } 
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static gboolean
Packit 31ecd5
clutter_event_osx_translate (NSEvent *nsevent,
Packit 31ecd5
                             ClutterEvent *event)
Packit 31ecd5
{
Packit 31ecd5
  ClutterDeviceManagerOSX *manager_osx;
Packit 31ecd5
  ClutterDeviceManager *manager;
Packit 31ecd5
  ClutterStageOSX *stage_osx;
Packit 31ecd5
  ClutterStageWindow *impl;
Packit 31ecd5
  ClutterStage *stage;
Packit 31ecd5
Packit 31ecd5
  manager = clutter_device_manager_get_default ();
Packit 31ecd5
  if (manager == NULL)
Packit 31ecd5
    return FALSE;
Packit 31ecd5
Packit 31ecd5
  stage = event->any.stage;
Packit 31ecd5
  impl = _clutter_stage_get_window (event->any.stage);
Packit 31ecd5
  stage_osx = CLUTTER_STAGE_OSX (impl);
Packit 31ecd5
  manager_osx = CLUTTER_DEVICE_MANAGER_OSX (manager);
Packit 31ecd5
Packit 31ecd5
  event->any.time = [nsevent clutterTime];
Packit 31ecd5
Packit 31ecd5
  switch ([nsevent type])
Packit 31ecd5
    {
Packit 31ecd5
    case NSLeftMouseDown:
Packit 31ecd5
    case NSRightMouseDown:
Packit 31ecd5
    case NSOtherMouseDown:
Packit 31ecd5
      event->type = CLUTTER_BUTTON_PRESS;
Packit 31ecd5
      /* fall through */
Packit 31ecd5
    case NSLeftMouseUp:
Packit 31ecd5
    case NSRightMouseUp:
Packit 31ecd5
    case NSOtherMouseUp:
Packit 31ecd5
      if (event->type != CLUTTER_BUTTON_PRESS)
Packit 31ecd5
        event->type = CLUTTER_BUTTON_RELEASE;
Packit 31ecd5
Packit 31ecd5
      event->button.button = [nsevent clutterButton];
Packit 31ecd5
      event->button.click_count = [nsevent clickCount];
Packit 31ecd5
      event->motion.modifier_state = [nsevent clutterModifierState];
Packit 31ecd5
      [nsevent clutterX:&(event->button.x) y:&(event->button.y)];
Packit 31ecd5
      clutter_event_set_device (event, manager_osx->core_pointer);
Packit 31ecd5
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "button %d %s at %f,%f clicks=%d",
Packit 31ecd5
                    (int)[nsevent buttonNumber],
Packit 31ecd5
                    event->type == CLUTTER_BUTTON_PRESS ? "press" : "release",
Packit 31ecd5
                    event->button.x, event->button.y,
Packit 31ecd5
                    event->button.click_count);
Packit 31ecd5
      return TRUE;
Packit 31ecd5
Packit 31ecd5
    case NSMouseMoved:
Packit 31ecd5
    case NSLeftMouseDragged:
Packit 31ecd5
    case NSRightMouseDragged:
Packit 31ecd5
    case NSOtherMouseDragged:
Packit 31ecd5
      event->type = CLUTTER_MOTION;
Packit 31ecd5
Packit 31ecd5
      [nsevent clutterX:&(event->motion.x) y:&(event->motion.y)];
Packit 31ecd5
      event->motion.modifier_state = [nsevent clutterModifierState];
Packit 31ecd5
      clutter_event_set_device (event, manager_osx->core_pointer);
Packit 31ecd5
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "motion %d at %f,%f",
Packit 31ecd5
                    (int)[nsevent buttonNumber],
Packit 31ecd5
                    event->button.x, event->button.y);
Packit 31ecd5
      return TRUE;
Packit 31ecd5
Packit 31ecd5
    case NSMouseEntered:
Packit 31ecd5
      event->type = CLUTTER_ENTER;
Packit 31ecd5
Packit 31ecd5
      [nsevent clutterX:&(event->crossing.x) y:&(event->crossing.y)];
Packit 31ecd5
      event->crossing.related = NULL;
Packit 31ecd5
      event->crossing.source = CLUTTER_ACTOR (stage);
Packit 31ecd5
      clutter_event_set_device (event, manager_osx->core_pointer);
Packit 31ecd5
Packit 31ecd5
      _clutter_input_device_set_stage (manager_osx->core_pointer, stage);
Packit 31ecd5
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "enter at %f,%f",
Packit 31ecd5
                    event->crossing.x, event->crossing.y);
Packit 31ecd5
      return TRUE;
Packit 31ecd5
Packit 31ecd5
    case NSMouseExited:
Packit 31ecd5
      event->type = CLUTTER_LEAVE;
Packit 31ecd5
Packit 31ecd5
      [nsevent clutterX:&(event->crossing.x) y:&(event->crossing.y)];
Packit 31ecd5
      event->crossing.related = NULL;
Packit 31ecd5
      event->crossing.source = CLUTTER_ACTOR (stage);
Packit 31ecd5
      clutter_event_set_device (event, manager_osx->core_pointer);
Packit 31ecd5
Packit 31ecd5
      _clutter_input_device_set_stage (manager_osx->core_pointer, NULL);
Packit 31ecd5
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "exit at %f,%f",
Packit 31ecd5
                    event->crossing.x, event->crossing.y);
Packit 31ecd5
      return TRUE;
Packit 31ecd5
Packit 31ecd5
    case NSScrollWheel:
Packit 31ecd5
      stage_osx->scroll_pos_x += [nsevent deltaX];
Packit 31ecd5
      stage_osx->scroll_pos_y += [nsevent deltaY];
Packit 31ecd5
      
Packit 31ecd5
      [nsevent clutterX:&(event->scroll.x) y:&(event->scroll.y)];
Packit 31ecd5
      event->scroll.modifier_state = [nsevent clutterModifierState];
Packit 31ecd5
      clutter_event_set_device (event, manager_osx->core_pointer);
Packit 31ecd5
      
Packit 31ecd5
      process_scroll_event (event, TRUE);
Packit 31ecd5
      process_scroll_event (event, FALSE);
Packit 31ecd5
      break;
Packit 31ecd5
      
Packit 31ecd5
    case NSFlagsChanged:
Packit 31ecd5
      // FIXME: This logic fails if the user presses both Shift keys at once, for example:
Packit 31ecd5
      // we treat releasing one of them as keyDown.
Packit 31ecd5
      switch ([nsevent keyCode])
Packit 31ecd5
        {
Packit 31ecd5
        case 54: // Right Command
Packit 31ecd5
        case 55: // Left Command
Packit 31ecd5
          if ([nsevent modifierFlags] & NSCommandKeyMask)
Packit 31ecd5
            event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
          break;
Packit 31ecd5
Packit 31ecd5
        case 57: // Capslock
Packit 31ecd5
          if ([nsevent modifierFlags] & NSAlphaShiftKeyMask)
Packit 31ecd5
            event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
          break;
Packit 31ecd5
Packit 31ecd5
        case 56: // Left Shift
Packit 31ecd5
        case 60: // Right Shift
Packit 31ecd5
          if ([nsevent modifierFlags] & NSShiftKeyMask)
Packit 31ecd5
            event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
          break;
Packit 31ecd5
Packit 31ecd5
        case 58: // Left Alt
Packit 31ecd5
        case 61: // Right Alt
Packit 31ecd5
          if ([nsevent modifierFlags] & NSAlternateKeyMask)
Packit 31ecd5
            event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
          break;
Packit 31ecd5
Packit 31ecd5
        case 59: // Left Ctrl
Packit 31ecd5
        case 62: // Right Ctrl
Packit 31ecd5
          if ([nsevent modifierFlags] & NSControlKeyMask)
Packit 31ecd5
            event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
          break;
Packit 31ecd5
Packit 31ecd5
        case 63: // Function
Packit 31ecd5
          if ([nsevent modifierFlags] & NSFunctionKeyMask)
Packit 31ecd5
            event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
          break;
Packit 31ecd5
        }
Packit 31ecd5
      /* fall through */
Packit 31ecd5
    case NSKeyDown:
Packit 31ecd5
      if ([nsevent type] == NSKeyDown)
Packit 31ecd5
        event->type = CLUTTER_KEY_PRESS;
Packit 31ecd5
      /* fall through */
Packit 31ecd5
    case NSKeyUp:
Packit 31ecd5
      if (event->type != CLUTTER_KEY_PRESS)
Packit 31ecd5
        event->type = CLUTTER_KEY_RELEASE;
Packit 31ecd5
Packit 31ecd5
      event->key.hardware_keycode = [nsevent keyCode];
Packit 31ecd5
      event->key.modifier_state = [nsevent clutterModifierState];
Packit 31ecd5
      event->key.keyval = [nsevent clutterKeyVal];
Packit 31ecd5
      event->key.unicode_value = ([nsevent type] == NSFlagsChanged)
Packit 31ecd5
                                    ? (gunichar)'\0'
Packit 31ecd5
                                    : [[nsevent characters] characterAtIndex:0];
Packit 31ecd5
      clutter_event_set_device (event, manager_osx->core_keyboard);
Packit 31ecd5
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "key %d (%s) (%s) %s, keyval %d",
Packit 31ecd5
                    [nsevent keyCode],
Packit 31ecd5
                    ([nsevent type] == NSFlagsChanged) ? "NULL" : [[nsevent characters] UTF8String],
Packit 31ecd5
                    ([nsevent type] == NSFlagsChanged) ? "NULL" : [[nsevent charactersIgnoringModifiers] UTF8String],
Packit 31ecd5
                    (event->type == CLUTTER_KEY_PRESS) ? "press" : "release",
Packit 31ecd5
                    event->key.keyval);
Packit 31ecd5
      return TRUE;
Packit 31ecd5
Packit 31ecd5
    default:
Packit 31ecd5
      CLUTTER_NOTE (EVENT, "unhandled event %d", (int)[nsevent type]);
Packit 31ecd5
      break;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  return FALSE;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
void
Packit 31ecd5
_clutter_event_osx_put (NSEvent      *nsevent,
Packit 31ecd5
                        ClutterStage *wrapper)
Packit 31ecd5
{
Packit 31ecd5
  ClutterEvent *event = clutter_event_new (CLUTTER_NOTHING);
Packit 31ecd5
Packit 31ecd5
  /* common fields */
Packit 31ecd5
  event->any.stage = wrapper;
Packit 31ecd5
  event->any.time = [nsevent clutterTime];
Packit 31ecd5
Packit 31ecd5
  if (clutter_event_osx_translate (nsevent, event))
Packit 31ecd5
    {
Packit 31ecd5
      g_assert (event->type != CLUTTER_NOTHING);
Packit 31ecd5
Packit 31ecd5
      _clutter_event_push (event, FALSE);
Packit 31ecd5
    }
Packit 31ecd5
  else
Packit 31ecd5
    clutter_event_free (event);
Packit 31ecd5
}