mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 10:20:48 +00:00
Merge branch 'master' into beta
This commit is contained in:
commit
042b427f49
@ -1,5 +1,5 @@
|
||||
# Aseprite
|
||||
*Copyright (C) 2001-2016 David Capello*
|
||||
*Copyright (C) 2001-2017 David Capello*
|
||||
|
||||
[](https://travis-ci.org/aseprite/aseprite)
|
||||
[](https://gitter.im/aseprite/aseprite?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -36,7 +36,9 @@
|
||||
#include "app/ui/editor/moving_pixels_state.h"
|
||||
#include "app/ui/editor/pixels_movement.h"
|
||||
#include "app/ui/editor/play_state.h"
|
||||
#include "app/ui/editor/scrolling_state.h"
|
||||
#include "app/ui/editor/standby_state.h"
|
||||
#include "app/ui/editor/zooming_state.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
@ -1772,6 +1774,46 @@ void Editor::notifyZoomChanged()
|
||||
m_observers.notifyZoomChanged(this);
|
||||
}
|
||||
|
||||
bool Editor::checkForScroll(ui::MouseMessage* msg)
|
||||
{
|
||||
tools::Ink* clickedInk = getCurrentEditorInk();
|
||||
|
||||
// Start scroll loop
|
||||
if (msg->middle() || clickedInk->isScrollMovement()) { // TODO msg->middle() should be customizable
|
||||
startScrollingState(msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Editor::checkForZoom(ui::MouseMessage* msg)
|
||||
{
|
||||
tools::Ink* clickedInk = getCurrentEditorInk();
|
||||
|
||||
// Start scroll loop
|
||||
if (clickedInk->isZoom()) {
|
||||
startZoomingState(msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Editor::startScrollingState(ui::MouseMessage* msg)
|
||||
{
|
||||
EditorStatePtr newState(new ScrollingState);
|
||||
setState(newState);
|
||||
newState->onMouseDown(this, msg);
|
||||
}
|
||||
|
||||
void Editor::startZoomingState(ui::MouseMessage* msg)
|
||||
{
|
||||
EditorStatePtr newState(new ZoomingState);
|
||||
setState(newState);
|
||||
newState->onMouseDown(this, msg);
|
||||
}
|
||||
|
||||
void Editor::play(const bool playOnce,
|
||||
const bool playAll)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -207,6 +207,15 @@ namespace app {
|
||||
void notifyScrollChanged();
|
||||
void notifyZoomChanged();
|
||||
|
||||
// Returns true and changes to ScrollingState when "msg" says "the
|
||||
// user wants to scroll". Same for zoom.
|
||||
bool checkForScroll(ui::MouseMessage* msg);
|
||||
bool checkForZoom(ui::MouseMessage* msg);
|
||||
|
||||
// Start Scrolling/ZoomingState
|
||||
void startScrollingState(ui::MouseMessage* msg);
|
||||
void startZoomingState(ui::MouseMessage* msg);
|
||||
|
||||
// Animation control
|
||||
void play(const bool playOnce,
|
||||
const bool playAll);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -239,7 +239,8 @@ bool MovingPixelsState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||
contextBar->updateForMovingPixels();
|
||||
|
||||
// Start scroll loop
|
||||
if (checkForScroll(editor, msg) || checkForZoom(editor, msg))
|
||||
if (editor->checkForScroll(msg) ||
|
||||
editor->checkForZoom(msg))
|
||||
return true;
|
||||
|
||||
// Call the eyedropper command
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -14,6 +14,7 @@
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/loop_tag.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/scrolling_state.h"
|
||||
#include "app/ui_context.h"
|
||||
@ -116,10 +117,12 @@ bool PlayState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||
// some time, so we don't change the current frame.
|
||||
m_toScroll = true;
|
||||
|
||||
// If the active tool is the Zoom tool, we start zooming.
|
||||
if (editor->checkForZoom(msg))
|
||||
return true;
|
||||
|
||||
// Start scroll loop
|
||||
EditorStatePtr newState(new ScrollingState());
|
||||
editor->setState(newState);
|
||||
newState->onMouseDown(editor, msg);
|
||||
editor->startScrollingState(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -145,6 +148,19 @@ bool PlayState::onKeyUp(Editor* editor, KeyMessage* msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
|
||||
{
|
||||
tools::Ink* ink = editor->getCurrentEditorInk();
|
||||
if (ink) {
|
||||
if (ink->isZoom()) {
|
||||
editor->showMouseCursor(kMagnifierCursor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
editor->showMouseCursor(kScrollCursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayState::onPlaybackTick()
|
||||
{
|
||||
if (m_nextFrameTime < 0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -34,6 +34,7 @@ namespace app {
|
||||
bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||
bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override;
|
||||
bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override;
|
||||
bool onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) override;
|
||||
|
||||
private:
|
||||
void onPlaybackTick();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -126,38 +126,6 @@ void StandbyState::onActiveToolChange(Editor* editor, tools::Tool* tool)
|
||||
}
|
||||
}
|
||||
|
||||
bool StandbyState::checkForScroll(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
tools::Ink* clickedInk = editor->getCurrentEditorInk();
|
||||
|
||||
// Start scroll loop
|
||||
if (msg->middle() || clickedInk->isScrollMovement()) { // TODO msg->middle() should be customizable
|
||||
EditorStatePtr newState(new ScrollingState());
|
||||
editor->setState(newState);
|
||||
|
||||
newState->onMouseDown(editor, msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StandbyState::checkForZoom(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
tools::Ink* clickedInk = editor->getCurrentEditorInk();
|
||||
|
||||
// Start scroll loop
|
||||
if (clickedInk->isZoom()) {
|
||||
EditorStatePtr newState(new ZoomingState());
|
||||
editor->setState(newState);
|
||||
|
||||
newState->onMouseDown(editor, msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
if (editor->hasCapture())
|
||||
@ -174,7 +142,8 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||
context->setActiveView(editor->getDocumentView());
|
||||
|
||||
// Start scroll loop
|
||||
if (checkForScroll(editor, msg) || checkForZoom(editor, msg))
|
||||
if (editor->checkForScroll(msg) ||
|
||||
editor->checkForZoom(msg))
|
||||
return true;
|
||||
|
||||
// Move cel X,Y coordinates
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -45,10 +45,6 @@ namespace app {
|
||||
void startSelectionTransformation(Editor* editor, const gfx::Point& move, double angle);
|
||||
|
||||
protected:
|
||||
// Returns true and changes to ScrollingState when "msg" says "the
|
||||
// user wants to scroll".
|
||||
bool checkForScroll(Editor* editor, ui::MouseMessage* msg);
|
||||
bool checkForZoom(Editor* editor, ui::MouseMessage* msg);
|
||||
void callEyedropper(Editor* editor);
|
||||
|
||||
class Decorator : public EditorDecorator {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -34,7 +34,7 @@
|
||||
#define WEBSITE_CONTRIBUTORS WEBSITE "contributors/"
|
||||
#define WEBSITE_NEWS_RSS "http://blog.aseprite.org/rss"
|
||||
#define UPDATE_URL WEBSITE "update/?xml=1"
|
||||
#define COPYRIGHT "Copyright (C) 2001-2016 David Capello"
|
||||
#define COPYRIGHT "Copyright (C) 2001-2017 David Capello"
|
||||
|
||||
#include "base/base.h"
|
||||
#include "base/debug.h"
|
||||
|
@ -9,7 +9,7 @@ set(SHE_SOURCES
|
||||
# Allegro 4 backend
|
||||
|
||||
if(USE_ALLEG4_BACKEND)
|
||||
add_definitions(-DUSE_KEY_POLLER)
|
||||
add_definitions(-DUSE_KEY_POLLER -DUSE_MOUSE_POLLER)
|
||||
if(WIN32)
|
||||
find_package(DXGuid)
|
||||
if(NOT DXGUID_FOUND)
|
||||
@ -20,8 +20,6 @@ if(USE_ALLEG4_BACKEND)
|
||||
endif()
|
||||
endif()
|
||||
include_directories(SYSTEM ${DXGUID_INCLUDE_DIR})
|
||||
else()
|
||||
add_definitions(-DUSE_MOUSE_POLLER)
|
||||
endif()
|
||||
|
||||
list(APPEND SHE_SOURCES
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
// Copyright (C) 2012-2017 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
@ -68,6 +68,11 @@ namespace she {
|
||||
Type type() const { return m_type; }
|
||||
Display* display() const { return m_display; }
|
||||
const Files& files() const { return m_files; }
|
||||
// TODO Rename this to virtualKey(), which is the real
|
||||
// meaning. Then we need another kind of "scan code" with the
|
||||
// position in the keyboard, which might be useful to identify
|
||||
// keys by its position (e.g. WASD keys in other keyboard
|
||||
// layouts).
|
||||
KeyScancode scancode() const { return m_scancode; }
|
||||
KeyModifiers modifiers() const { return m_modifiers; }
|
||||
int unicodeChar() const { return m_unicodeChar; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2015-2016 David Capello
|
||||
// Copyright (C) 2015-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -13,13 +13,11 @@
|
||||
#include "gfx/point.h"
|
||||
#include "she/event.h"
|
||||
#include "she/event_queue.h"
|
||||
#include "she/keys.h"
|
||||
#include "she/osx/generate_drop_files.h"
|
||||
#include "she/osx/vk.h"
|
||||
#include "she/osx/window.h"
|
||||
#include "she/system.h"
|
||||
|
||||
#include <Carbon/Carbon.h> // For VK codes
|
||||
|
||||
namespace she {
|
||||
|
||||
bool osx_is_key_pressed(KeyScancode scancode);
|
||||
@ -80,51 +78,6 @@ KeyModifiers get_modifiers_from_nsevent(NSEvent* event)
|
||||
return (KeyModifiers)modifiers;
|
||||
}
|
||||
|
||||
// Based on code from:
|
||||
// http://stackoverflow.com/questions/22566665/how-to-capture-unicode-from-key-events-without-an-nstextview
|
||||
// http://stackoverflow.com/questions/12547007/convert-key-code-into-key-equivalent-string
|
||||
// http://stackoverflow.com/questions/8263618/convert-virtual-key-code-to-unicode-string
|
||||
//
|
||||
// It includes a "translateDeadKeys" flag to avoid processing dead
|
||||
// keys in case that we want to use key
|
||||
CFStringRef get_unicode_from_key_code(NSEvent* event,
|
||||
const bool translateDeadKeys)
|
||||
{
|
||||
// The "TISCopyCurrentKeyboardInputSource()" doesn't contain
|
||||
// kTISPropertyUnicodeKeyLayoutData (returns nullptr) when the input
|
||||
// source is Japanese (Romaji/Hiragana/Katakana).
|
||||
|
||||
//TISInputSourceRef inputSource = TISCopyCurrentKeyboardInputSource();
|
||||
TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
CFDataRef keyLayoutData = (CFDataRef)TISGetInputSourceProperty(inputSource, kTISPropertyUnicodeKeyLayoutData);
|
||||
const UCKeyboardLayout* keyLayout =
|
||||
(keyLayoutData ? (const UCKeyboardLayout*)CFDataGetBytePtr(keyLayoutData): nullptr);
|
||||
|
||||
UInt32 deadKeyState = (translateDeadKeys ? g_lastDeadKeyState: 0);
|
||||
UniChar output[4];
|
||||
UniCharCount length;
|
||||
|
||||
// Reference here:
|
||||
// https://developer.apple.com/reference/coreservices/1390584-uckeytranslate?language=objc
|
||||
UCKeyTranslate(
|
||||
keyLayout,
|
||||
event.keyCode,
|
||||
kUCKeyActionDown,
|
||||
((event.modifierFlags >> 16) & 0xFF),
|
||||
LMGetKbdType(),
|
||||
(translateDeadKeys ? 0: kUCKeyTranslateNoDeadKeysMask),
|
||||
&deadKeyState,
|
||||
sizeof(output) / sizeof(output[0]),
|
||||
&length,
|
||||
output);
|
||||
|
||||
if (translateDeadKeys)
|
||||
g_lastDeadKeyState = deadKeyState;
|
||||
|
||||
CFRelease(inputSource);
|
||||
return CFStringCreateWithCharacters(kCFAllocatorDefault, output, length);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool osx_is_key_pressed(KeyScancode scancode)
|
||||
@ -213,7 +166,8 @@ using namespace she;
|
||||
{
|
||||
[super keyDown:event];
|
||||
|
||||
KeyScancode scancode = cocoavk_to_scancode(event.keyCode);
|
||||
KeyScancode scancode = cocoavk_to_scancode(event.keyCode,
|
||||
event.modifierFlags);
|
||||
Event ev;
|
||||
ev.setType(Event::KeyDown);
|
||||
ev.setScancode(scancode);
|
||||
@ -223,7 +177,8 @@ using namespace she;
|
||||
|
||||
bool sendMsg = true;
|
||||
|
||||
CFStringRef strRef = get_unicode_from_key_code(event, false);
|
||||
CFStringRef strRef = get_unicode_from_key_code(event.keyCode,
|
||||
event.modifierFlags);
|
||||
if (strRef) {
|
||||
int length = CFStringGetLength(strRef);
|
||||
if (length == 1)
|
||||
@ -235,7 +190,9 @@ using namespace she;
|
||||
g_pressedKeys[scancode] = (ev.unicodeChar() ? ev.unicodeChar(): 1);
|
||||
|
||||
if (g_translateDeadKeys) {
|
||||
strRef = get_unicode_from_key_code(event, true);
|
||||
strRef = get_unicode_from_key_code(event.keyCode,
|
||||
event.modifierFlags,
|
||||
&g_lastDeadKeyState);
|
||||
if (strRef) {
|
||||
int length = CFStringGetLength(strRef);
|
||||
if (length > 0) {
|
||||
@ -261,7 +218,8 @@ using namespace she;
|
||||
{
|
||||
[super keyUp:event];
|
||||
|
||||
KeyScancode scancode = cocoavk_to_scancode(event.keyCode);
|
||||
KeyScancode scancode = cocoavk_to_scancode(event.keyCode,
|
||||
event.modifierFlags);
|
||||
if (scancode >= 0 && scancode < kKeyScancodes)
|
||||
g_pressedKeys[scancode] = 0;
|
||||
|
||||
|
26
src/she/osx/vk.h
Normal file
26
src/she/osx/vk.h
Normal file
@ -0,0 +1,26 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_OSX_VK_H_INCLUDED
|
||||
#define SHE_OSX_VK_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "she/keys.h"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
namespace she {
|
||||
|
||||
KeyScancode cocoavk_to_scancode(UInt16 keyCode,
|
||||
const NSEventModifierFlags modifierFlags);
|
||||
|
||||
CFStringRef get_unicode_from_key_code(const UInt16 keyCode,
|
||||
const NSEventModifierFlags modifierFlags,
|
||||
UInt32* deadKeyState = nullptr);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2015 David Capello
|
||||
// Copyright (C) 2015-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -8,154 +8,367 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/keys.h"
|
||||
#include "she/osx/vk.h"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Carbon/Carbon.h> // TIS functions
|
||||
|
||||
namespace she {
|
||||
|
||||
KeyScancode cocoavk_to_scancode(UInt16 vk) {
|
||||
KeyScancode cocoavk_to_scancode(UInt16 keyCode,
|
||||
const NSEventModifierFlags modifierFlags)
|
||||
{
|
||||
// Converts macOS virtual key code into a she::KeyScancode
|
||||
static KeyScancode keymap[256] = {
|
||||
// 0x00
|
||||
kKeyA, // 0x00 - kVK_ANSI_A
|
||||
kKeyS, // 0x01 - kVK_ANSI_S
|
||||
kKeyD, // 0x02 - kVK_ANSI_D
|
||||
kKeyF, // 0x03 - kVK_ANSI_F
|
||||
kKeyH, // 0x04 - kVK_ANSI_H
|
||||
kKeyG, // 0x05 - kVK_ANSI_G
|
||||
kKeyZ, // 0x06 - kVK_ANSI_Z
|
||||
kKeyX, // 0x07 - kVK_ANSI_X
|
||||
kKeyC, // 0x08 - kVK_ANSI_C
|
||||
kKeyV, // 0x09 - kVK_ANSI_V
|
||||
kKeyNil, // 0x0A - kVK_ISO_Section
|
||||
kKeyB, // 0x0B - kVK_ANSI_B
|
||||
kKeyQ, // 0x0C - kVK_ANSI_Q
|
||||
kKeyW, // 0x0D - kVK_ANSI_W
|
||||
kKeyE, // 0x0E - kVK_ANSI_E
|
||||
kKeyR, // 0x0F - kVK_ANSI_R
|
||||
// 0x10
|
||||
kKeyY, // 0x10 - kVK_ANSI_Y
|
||||
kKeyT, // 0x11 - kVK_ANSI_T
|
||||
kKey1, // 0x12 - kVK_ANSI_1
|
||||
kKey2, // 0x13 - kVK_ANSI_2
|
||||
kKey3, // 0x14 - kVK_ANSI_3
|
||||
kKey4, // 0x15 - kVK_ANSI_4
|
||||
kKey6, // 0x16 - kVK_ANSI_6
|
||||
kKey5, // 0x17 - kVK_ANSI_5
|
||||
kKeyEquals, // 0x18 - kVK_ANSI_Equal
|
||||
kKey9, // 0x19 - kVK_ANSI_9
|
||||
kKey7, // 0x1A - kVK_ANSI_7
|
||||
kKeyMinus, // 0x1B - kVK_ANSI_Minus
|
||||
kKey8, // 0x1C - kVK_ANSI_8
|
||||
kKey0, // 0x1D - kVK_ANSI_0
|
||||
// 0x00
|
||||
kKeyA, // 0x00 - kVK_ANSI_A
|
||||
kKeyS, // 0x01 - kVK_ANSI_S
|
||||
kKeyD, // 0x02 - kVK_ANSI_D
|
||||
kKeyF, // 0x03 - kVK_ANSI_F
|
||||
kKeyH, // 0x04 - kVK_ANSI_H
|
||||
kKeyG, // 0x05 - kVK_ANSI_G
|
||||
kKeyZ, // 0x06 - kVK_ANSI_Z
|
||||
kKeyX, // 0x07 - kVK_ANSI_X
|
||||
kKeyC, // 0x08 - kVK_ANSI_C
|
||||
kKeyV, // 0x09 - kVK_ANSI_V
|
||||
kKeyNil, // 0x0A - kVK_ISO_Section
|
||||
kKeyB, // 0x0B - kVK_ANSI_B
|
||||
kKeyQ, // 0x0C - kVK_ANSI_Q
|
||||
kKeyW, // 0x0D - kVK_ANSI_W
|
||||
kKeyE, // 0x0E - kVK_ANSI_E
|
||||
kKeyR, // 0x0F - kVK_ANSI_R
|
||||
// 0x10
|
||||
kKeyY, // 0x10 - kVK_ANSI_Y
|
||||
kKeyT, // 0x11 - kVK_ANSI_T
|
||||
kKey1, // 0x12 - kVK_ANSI_1
|
||||
kKey2, // 0x13 - kVK_ANSI_2
|
||||
kKey3, // 0x14 - kVK_ANSI_3
|
||||
kKey4, // 0x15 - kVK_ANSI_4
|
||||
kKey6, // 0x16 - kVK_ANSI_6
|
||||
kKey5, // 0x17 - kVK_ANSI_5
|
||||
kKeyEquals, // 0x18 - kVK_ANSI_Equal
|
||||
kKey9, // 0x19 - kVK_ANSI_9
|
||||
kKey7, // 0x1A - kVK_ANSI_7
|
||||
kKeyMinus, // 0x1B - kVK_ANSI_Minus
|
||||
kKey8, // 0x1C - kVK_ANSI_8
|
||||
kKey0, // 0x1D - kVK_ANSI_0
|
||||
kKeyClosebrace, // 0x1E - kVK_ANSI_RightBracket
|
||||
kKeyO, // 0x1F - kVK_ANSI_O
|
||||
// 0x20
|
||||
kKeyU, // 0x20 - kVK_ANSI_U
|
||||
kKeyOpenbrace, // 0x21 - kVK_ANSI_LeftBracket
|
||||
kKeyI, // 0x22 - kVK_ANSI_I
|
||||
kKeyP, // 0x23 - kVK_ANSI_P
|
||||
kKeyEnter, // 0x24 - kVK_Return
|
||||
kKeyL, // 0x25 - kVK_ANSI_L
|
||||
kKeyJ, // 0x26 - kVK_ANSI_J
|
||||
kKeyQuote, // 0x27 - kVK_ANSI_Quote
|
||||
kKeyK, // 0x28 - kVK_ANSI_K
|
||||
kKeySemicolon, // 0x29 - kVK_ANSI_Semicolon
|
||||
kKeyBackslash, // 0x2A - kVK_ANSI_Backslash
|
||||
kKeyComma, // 0x2B - kVK_ANSI_Comma
|
||||
kKeySlash, // 0x2C - kVK_ANSI_Slash
|
||||
kKeyN, // 0x2D - kVK_ANSI_N
|
||||
kKeyM, // 0x2E - kVK_ANSI_M
|
||||
kKeyStop, // 0x2F - kVK_ANSI_Period
|
||||
// 0x30
|
||||
kKeyTab, // 0x30 - kVK_Tab
|
||||
kKeySpace, // 0x31 - kVK_Space
|
||||
kKeyNil, // 0x32 - kVK_ANSI_Grave
|
||||
kKeyBackspace, // 0x33 - kVK_Delete
|
||||
kKeyNil, // 0x34 - ?
|
||||
kKeyEsc, // 0x35 - kVK_Escape
|
||||
kKeyNil, // 0x36 - ?
|
||||
kKeyCommand, // 0x37 - kVK_Command
|
||||
kKeyLShift, // 0x38 - kVK_Shift
|
||||
kKeyCapsLock, // 0x39 - kVK_CapsLock
|
||||
kKeyAlt, // 0x3A - kVK_Option
|
||||
kKeyLControl, // 0x3B - kVK_Control
|
||||
kKeyRShift, // 0x3C - kVK_RightShift
|
||||
kKeyAltGr, // 0x3D - kVK_RightOption
|
||||
kKeyRControl, // 0x3E - kVK_RightControl
|
||||
kKeyNil, // 0x3F - kVK_Function
|
||||
// 0x40
|
||||
kKeyNil, // 0x40 - kVK_F17
|
||||
kKeyNil, // 0x41 - kVK_ANSI_KeypadDecimal
|
||||
kKeyNil, // 0x42 - ?
|
||||
kKeyAsterisk, // 0x43 - kVK_ANSI_KeypadMultiply
|
||||
kKeyNil, // 0x44 - ?
|
||||
kKeyPlusPad, // 0x45 - kVK_ANSI_KeypadPlus
|
||||
kKeyNil, // 0x46 - ?
|
||||
kKeyDelPad, // 0x47 - kVK_ANSI_KeypadClear
|
||||
kKeyNil, // 0x48 - kVK_VolumeUp
|
||||
kKeyNil, // 0x49 - kVK_VolumeDown
|
||||
kKeyNil, // 0x4A - kVK_Mute
|
||||
kKeySlashPad, // 0x4B - kVK_ANSI_KeypadDivide
|
||||
kKeyEnterPad, // 0x4C - kVK_ANSI_KeypadEnter
|
||||
kKeyNil, // 0x4D - ?
|
||||
kKeyMinusPad, // 0x4E - kVK_ANSI_KeypadMinus
|
||||
kKeyNil, // 0x4F - kVK_F18
|
||||
// 0x50
|
||||
kKeyNil, // 0x50 - kVK_F19
|
||||
kKeyEqualsPad, // 0x51 - kVK_ANSI_KeypadEquals
|
||||
kKey0Pad, // 0x52 - kVK_ANSI_Keypad0
|
||||
kKey1Pad, // 0x53 - kVK_ANSI_Keypad1
|
||||
kKey2Pad, // 0x54 - kVK_ANSI_Keypad2
|
||||
kKey3Pad, // 0x55 - kVK_ANSI_Keypad3
|
||||
kKey4Pad, // 0x56 - kVK_ANSI_Keypad4
|
||||
kKey5Pad, // 0x57 - kVK_ANSI_Keypad5
|
||||
kKey6Pad, // 0x58 - kVK_ANSI_Keypad6
|
||||
kKey7Pad, // 0x59 - kVK_ANSI_Keypad7
|
||||
kKeyNil, // 0x5A - kVK_F20
|
||||
kKey8Pad, // 0x5B - kVK_ANSI_Keypad8
|
||||
kKey9Pad, // 0x5C - kVK_ANSI_Keypad9
|
||||
kKeyYen, // 0x5D - kVK_JIS_Yen
|
||||
kKeyNil, // 0x5E - kVK_JIS_Underscore
|
||||
kKeyNil, // 0x5F - kVK_JIS_KeypadComma
|
||||
// 0x60
|
||||
kKeyF5, // 0x60 - kVK_F5
|
||||
kKeyF6, // 0x61 - kVK_F6
|
||||
kKeyF7, // 0x62 - kVK_F7
|
||||
kKeyF3, // 0x63 - kVK_F3
|
||||
kKeyF8, // 0x64 - kVK_F8
|
||||
kKeyF9, // 0x65 - kVK_F9
|
||||
kKeyNil, // 0x66 - kVK_JIS_Eisu
|
||||
kKeyF11, // 0x67 - kVK_F11
|
||||
kKeyKana, // 0x68 - kVK_JIS_Kana
|
||||
kKeyNil, // 0x69 - kVK_F13
|
||||
kKeyNil, // 0x6A - kVK_F16
|
||||
kKeyNil, // 0x6B - kVK_F14
|
||||
kKeyNil, // 0x6C - ?
|
||||
kKeyF10, // 0x6D - kVK_F10
|
||||
kKeyNil, // 0x6E - ?
|
||||
kKeyF12, // 0x6F - kVK_F12
|
||||
// 0x70
|
||||
kKeyNil, // 0x70 - ?
|
||||
kKeyNil, // 0x71 - kVK_F15
|
||||
kKeyNil, // 0x72 - kVK_Help
|
||||
kKeyHome, // 0x73 - kVK_Home
|
||||
kKeyPageUp, // 0x74 - kVK_PageUp
|
||||
kKeyDel, // 0x75 - kVK_ForwardDelete
|
||||
kKeyF4, // 0x76 - kVK_F4
|
||||
kKeyEnd, // 0x77 - kVK_End
|
||||
kKeyF2, // 0x78 - kVK_F2
|
||||
kKeyPageDown, // 0x79 - kVK_PageDown
|
||||
kKeyF1, // 0x7A - kVK_F1
|
||||
kKeyLeft, // 0x7B - kVK_LeftArrow
|
||||
kKeyRight, // 0x7C - kVK_RightArrow
|
||||
kKeyDown, // 0x7D - kVK_DownArrow
|
||||
kKeyUp, // 0x7E - kVK_UpArrow
|
||||
kKeyNil // 0x7F - ?
|
||||
kKeyO, // 0x1F - kVK_ANSI_O
|
||||
// 0x20
|
||||
kKeyU, // 0x20 - kVK_ANSI_U
|
||||
kKeyOpenbrace, // 0x21 - kVK_ANSI_LeftBracket
|
||||
kKeyI, // 0x22 - kVK_ANSI_I
|
||||
kKeyP, // 0x23 - kVK_ANSI_P
|
||||
kKeyEnter, // 0x24 - kVK_Return
|
||||
kKeyL, // 0x25 - kVK_ANSI_L
|
||||
kKeyJ, // 0x26 - kVK_ANSI_J
|
||||
kKeyQuote, // 0x27 - kVK_ANSI_Quote
|
||||
kKeyK, // 0x28 - kVK_ANSI_K
|
||||
kKeySemicolon, // 0x29 - kVK_ANSI_Semicolon
|
||||
kKeyBackslash, // 0x2A - kVK_ANSI_Backslash
|
||||
kKeyComma, // 0x2B - kVK_ANSI_Comma
|
||||
kKeySlash, // 0x2C - kVK_ANSI_Slash
|
||||
kKeyN, // 0x2D - kVK_ANSI_N
|
||||
kKeyM, // 0x2E - kVK_ANSI_M
|
||||
kKeyStop, // 0x2F - kVK_ANSI_Period
|
||||
// 0x30
|
||||
kKeyTab, // 0x30 - kVK_Tab
|
||||
kKeySpace, // 0x31 - kVK_Space
|
||||
kKeyNil, // 0x32 - kVK_ANSI_Grave
|
||||
kKeyBackspace, // 0x33 - kVK_Delete
|
||||
kKeyNil, // 0x34 - ?
|
||||
kKeyEsc, // 0x35 - kVK_Escape
|
||||
kKeyNil, // 0x36 - ?
|
||||
kKeyCommand, // 0x37 - kVK_Command
|
||||
kKeyLShift, // 0x38 - kVK_Shift
|
||||
kKeyCapsLock, // 0x39 - kVK_CapsLock
|
||||
kKeyAlt, // 0x3A - kVK_Option
|
||||
kKeyLControl, // 0x3B - kVK_Control
|
||||
kKeyRShift, // 0x3C - kVK_RightShift
|
||||
kKeyAltGr, // 0x3D - kVK_RightOption
|
||||
kKeyRControl, // 0x3E - kVK_RightControl
|
||||
kKeyNil, // 0x3F - kVK_Function
|
||||
// 0x40
|
||||
kKeyNil, // 0x40 - kVK_F17
|
||||
kKeyNil, // 0x41 - kVK_ANSI_KeypadDecimal
|
||||
kKeyNil, // 0x42 - ?
|
||||
kKeyAsterisk, // 0x43 - kVK_ANSI_KeypadMultiply
|
||||
kKeyNil, // 0x44 - ?
|
||||
kKeyPlusPad, // 0x45 - kVK_ANSI_KeypadPlus
|
||||
kKeyNil, // 0x46 - ?
|
||||
kKeyDelPad, // 0x47 - kVK_ANSI_KeypadClear
|
||||
kKeyNil, // 0x48 - kVK_VolumeUp
|
||||
kKeyNil, // 0x49 - kVK_VolumeDown
|
||||
kKeyNil, // 0x4A - kVK_Mute
|
||||
kKeySlashPad, // 0x4B - kVK_ANSI_KeypadDivide
|
||||
kKeyEnterPad, // 0x4C - kVK_ANSI_KeypadEnter
|
||||
kKeyNil, // 0x4D - ?
|
||||
kKeyMinusPad, // 0x4E - kVK_ANSI_KeypadMinus
|
||||
kKeyNil, // 0x4F - kVK_F18
|
||||
// 0x50
|
||||
kKeyNil, // 0x50 - kVK_F19
|
||||
kKeyEqualsPad, // 0x51 - kVK_ANSI_KeypadEquals
|
||||
kKey0Pad, // 0x52 - kVK_ANSI_Keypad0
|
||||
kKey1Pad, // 0x53 - kVK_ANSI_Keypad1
|
||||
kKey2Pad, // 0x54 - kVK_ANSI_Keypad2
|
||||
kKey3Pad, // 0x55 - kVK_ANSI_Keypad3
|
||||
kKey4Pad, // 0x56 - kVK_ANSI_Keypad4
|
||||
kKey5Pad, // 0x57 - kVK_ANSI_Keypad5
|
||||
kKey6Pad, // 0x58 - kVK_ANSI_Keypad6
|
||||
kKey7Pad, // 0x59 - kVK_ANSI_Keypad7
|
||||
kKeyNil, // 0x5A - kVK_F20
|
||||
kKey8Pad, // 0x5B - kVK_ANSI_Keypad8
|
||||
kKey9Pad, // 0x5C - kVK_ANSI_Keypad9
|
||||
kKeyYen, // 0x5D - kVK_JIS_Yen
|
||||
kKeyNil, // 0x5E - kVK_JIS_Underscore
|
||||
kKeyNil, // 0x5F - kVK_JIS_KeypadComma
|
||||
// 0x60
|
||||
kKeyF5, // 0x60 - kVK_F5
|
||||
kKeyF6, // 0x61 - kVK_F6
|
||||
kKeyF7, // 0x62 - kVK_F7
|
||||
kKeyF3, // 0x63 - kVK_F3
|
||||
kKeyF8, // 0x64 - kVK_F8
|
||||
kKeyF9, // 0x65 - kVK_F9
|
||||
kKeyNil, // 0x66 - kVK_JIS_Eisu
|
||||
kKeyF11, // 0x67 - kVK_F11
|
||||
kKeyKana, // 0x68 - kVK_JIS_Kana
|
||||
kKeyNil, // 0x69 - kVK_F13
|
||||
kKeyNil, // 0x6A - kVK_F16
|
||||
kKeyNil, // 0x6B - kVK_F14
|
||||
kKeyNil, // 0x6C - ?
|
||||
kKeyF10, // 0x6D - kVK_F10
|
||||
kKeyNil, // 0x6E - ?
|
||||
kKeyF12, // 0x6F - kVK_F12
|
||||
// 0x70
|
||||
kKeyNil, // 0x70 - ?
|
||||
kKeyNil, // 0x71 - kVK_F15
|
||||
kKeyNil, // 0x72 - kVK_Help
|
||||
kKeyHome, // 0x73 - kVK_Home
|
||||
kKeyPageUp, // 0x74 - kVK_PageUp
|
||||
kKeyDel, // 0x75 - kVK_ForwardDelete
|
||||
kKeyF4, // 0x76 - kVK_F4
|
||||
kKeyEnd, // 0x77 - kVK_End
|
||||
kKeyF2, // 0x78 - kVK_F2
|
||||
kKeyPageDown, // 0x79 - kVK_PageDown
|
||||
kKeyF1, // 0x7A - kVK_F1
|
||||
kKeyLeft, // 0x7B - kVK_LeftArrow
|
||||
kKeyRight, // 0x7C - kVK_RightArrow
|
||||
kKeyDown, // 0x7D - kVK_DownArrow
|
||||
kKeyUp, // 0x7E - kVK_UpArrow
|
||||
kKeyNil // 0x7F - ?
|
||||
};
|
||||
if (vk < 0 || vk > 127)
|
||||
vk = 0;
|
||||
return keymap[vk];
|
||||
|
||||
// Converts an ASCII character into an macOS virtual key
|
||||
static int charmap[] = {
|
||||
-1, // 0 = 00 = NUL
|
||||
-1, // 1 = 01 = STX
|
||||
-1, // 2 = 02 = SOT
|
||||
-1, // 3 = 03 = ETX
|
||||
-1, // 4 = 04 = EOT
|
||||
-1, // 5 = 05 = ENQ
|
||||
-1, // 6 = 06 = ACK
|
||||
-1, // 7 = 07 = BEL
|
||||
kVK_Delete, // 8 = 08 = BS
|
||||
-1, // 9 = 09 = HT
|
||||
-1, // 10 =0A = LF
|
||||
-1, // 11 =0B = VT
|
||||
-1, // 12 =0C = FF
|
||||
-1, // 13 =0D = CR
|
||||
-1, // 14 =0E = SO
|
||||
-1, // 15 =0F = SI
|
||||
-1, // 16 =10 = DLE
|
||||
-1, // 17 =11 = DC1
|
||||
-1, // 18 =12 = DC2
|
||||
-1, // 19 =13 = DC3
|
||||
-1, // 20 =14 = DC4
|
||||
-1, // 21 =15 = NAK
|
||||
-1, // 22 =16 = SYN
|
||||
-1, // 23 =17 = ETB
|
||||
-1, // 24 =18 = CAN
|
||||
-1, // 25 =19 = EM
|
||||
-1, // 26 =1A = SUB
|
||||
-1, // 27 =1B = ESC
|
||||
-1, // 28 =1C = FS
|
||||
-1, // 29 =1D = GS
|
||||
-1, // 30 =1E = RS
|
||||
-1, // 31 =1F = US
|
||||
kVK_Space, // 32 =20 = Space
|
||||
-1, // 33 =21 = !
|
||||
kVK_ANSI_Quote, // 34 =22 = "
|
||||
-1, // 35 =23 = #
|
||||
-1, // 36 =24 = $
|
||||
-1, // 37 =25 = %
|
||||
-1, // 38 =26 = &
|
||||
-1, // 39 =27 = '
|
||||
-1, // 40 = 28 = (
|
||||
-1, // 41 = 29 = )
|
||||
-1, // 42 = 2A = *
|
||||
-1, // 43 = 2B = +
|
||||
kVK_ANSI_Comma, // 44 = 2C = ,
|
||||
kVK_ANSI_Minus, // 45 = 2D = -
|
||||
kVK_ANSI_Period, // 46 = 2E = .
|
||||
kVK_ANSI_Slash, // 47 = 2F = /
|
||||
kVK_ANSI_0, // 48 = 30 = 0
|
||||
kVK_ANSI_1, // 49 = 31 = 1
|
||||
kVK_ANSI_2, // 50 = 32 = 2
|
||||
kVK_ANSI_3, // 51 = 33 = 3
|
||||
kVK_ANSI_4, // 52 = 34 = 4
|
||||
kVK_ANSI_5, // 53 = 35 = 5
|
||||
kVK_ANSI_6, // 54 = 36 = 6
|
||||
kVK_ANSI_7, // 55 = 37 = 7
|
||||
kVK_ANSI_8, // 56 = 38 = 8
|
||||
kVK_ANSI_9, // 57 = 39 = 9
|
||||
-1, // 58 = 3A = :
|
||||
kVK_ANSI_Semicolon, // 59 = 3B = ;
|
||||
-1, // 60 = 3C = <
|
||||
kVK_ANSI_Equal, // 61 = 3D = =
|
||||
-1, // 62 = 3E = >
|
||||
-1, // 63 = 3F = ?
|
||||
-1, // 64 = 40 = @
|
||||
kVK_ANSI_A, // 65 = 41 = A
|
||||
kVK_ANSI_B, // 66 = 42 = B
|
||||
kVK_ANSI_C, // 67 = 43 = C
|
||||
kVK_ANSI_D, // 68 = 44 = D
|
||||
kVK_ANSI_E, // 69 = 45 = E
|
||||
kVK_ANSI_F, // 70 = 46 = F
|
||||
kVK_ANSI_G, // 71 = 47 = G
|
||||
kVK_ANSI_H, // 72 = 48 = H
|
||||
kVK_ANSI_I, // 73 = 49 = I
|
||||
kVK_ANSI_J, // 74 = 4A = J
|
||||
kVK_ANSI_K, // 75 = 4B = K
|
||||
kVK_ANSI_L, // 76 = 4C = L
|
||||
kVK_ANSI_M, // 77 = 4D = M
|
||||
kVK_ANSI_N, // 78 = 4E = N
|
||||
kVK_ANSI_O, // 79 = 4F = O
|
||||
kVK_ANSI_P, // 80 = 50 = P
|
||||
kVK_ANSI_Q, // 81 = 51 = Q
|
||||
kVK_ANSI_R, // 82 = 52 = R
|
||||
kVK_ANSI_S, // 83 = 53 = S
|
||||
kVK_ANSI_T, // 84 = 54 = T
|
||||
kVK_ANSI_U, // 85 = 55 = U
|
||||
kVK_ANSI_V, // 86 = 56 = V
|
||||
kVK_ANSI_W, // 87 = 57 = W
|
||||
kVK_ANSI_X, // 88 = 58 = X
|
||||
kVK_ANSI_Y, // 89 = 59 = Y
|
||||
kVK_ANSI_Z, // 90 = 5A = Z
|
||||
kVK_ANSI_LeftBracket, // 91 = 5B = [
|
||||
kVK_ANSI_Backslash, // 92 = 5C = backslash
|
||||
kVK_ANSI_RightBracket, // 93 = 5D = ]
|
||||
-1, // 94 = 5E = ^
|
||||
-1, // 95 = 5F = _
|
||||
kVK_ANSI_Grave, // 96 = 60 = `
|
||||
kVK_ANSI_A, // 97 = 61 = a
|
||||
kVK_ANSI_B, // 98 = 62 = b
|
||||
kVK_ANSI_C, // 99 = 63 = c
|
||||
kVK_ANSI_D, // 100 = 64 = d
|
||||
kVK_ANSI_E, // 101 = 65 = e
|
||||
kVK_ANSI_F, // 102 = 66 = f
|
||||
kVK_ANSI_G, // 103 = 67 = g
|
||||
kVK_ANSI_H, // 104 = 68 = h
|
||||
kVK_ANSI_I, // 105 = 69 = i
|
||||
kVK_ANSI_J, // 106 = 6A = j
|
||||
kVK_ANSI_K, // 107 = 6B = k
|
||||
kVK_ANSI_L, // 108 = 6C = l
|
||||
kVK_ANSI_M, // 109 = 6D = m
|
||||
kVK_ANSI_N, // 110 = 6E = n
|
||||
kVK_ANSI_O, // 111 = 6F = o
|
||||
kVK_ANSI_P, // 112 = 70 = p
|
||||
kVK_ANSI_Q, // 113 = 71 = q
|
||||
kVK_ANSI_R, // 114 = 72 = r
|
||||
kVK_ANSI_S, // 115 = 73 = s
|
||||
kVK_ANSI_T, // 116 = 74 = t
|
||||
kVK_ANSI_U, // 117 = 75 = u
|
||||
kVK_ANSI_V, // 118 = 76 = v
|
||||
kVK_ANSI_W, // 119 = 77 = w
|
||||
kVK_ANSI_X, // 120 = 78 = x
|
||||
kVK_ANSI_Y, // 121 = 79 = y
|
||||
kVK_ANSI_Z, // 122 = 7A = z
|
||||
-1, // 123 = 7B = {
|
||||
-1, // 124 = 7C = |
|
||||
-1, // 125 = 7D = }
|
||||
-1, // 126 = 7E = ~
|
||||
-1, // 127 = 7F = DEL
|
||||
};
|
||||
|
||||
// When Cmd+key is used, macOS reports the "virtual key" as a QWERTY
|
||||
// scan code, which doesn't represent the real keyboard layout
|
||||
// (which might be DVORAK, AZERTY, etc.). So here we convert this
|
||||
// QWERTY scan code into a unicode char, and finally the unicode
|
||||
// char into the real kVK_ANSI_ virtual key. In this way Cmd+N will
|
||||
// work in all keyboard layout (on Windows it works in this way
|
||||
// automatically).
|
||||
//
|
||||
// TODO We might need (in a future) another kind of code (real
|
||||
// QWERTY scan code) in case that we want to identify keys by its
|
||||
// position in the keyboard (e.g. for WASD).
|
||||
if (modifierFlags & NSCommandKeyMask) {
|
||||
CFStringRef strRef = get_unicode_from_key_code(keyCode,
|
||||
modifierFlags & ~NSCommandKeyMask);
|
||||
if (strRef) {
|
||||
int length = CFStringGetLength(strRef);
|
||||
if (length == 1) {
|
||||
UInt16 unicodeChar = CFStringGetCharacterAtIndex(strRef, 0);
|
||||
if (unicodeChar > 0 &&
|
||||
unicodeChar < sizeof(charmap) / sizeof(charmap[0]) &&
|
||||
charmap[unicodeChar] >= 0) {
|
||||
// Converts ASCII char into a macOS virtual key
|
||||
keyCode = charmap[unicodeChar];
|
||||
}
|
||||
}
|
||||
CFRelease(strRef);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyCode < 0 || keyCode > 127)
|
||||
keyCode = 0;
|
||||
|
||||
// Converts macOS virtual key into she::KeyScancode
|
||||
return keymap[keyCode];
|
||||
}
|
||||
|
||||
} // namespace shse
|
||||
// Based on code from:
|
||||
// http://stackoverflow.com/questions/22566665/how-to-capture-unicode-from-key-events-without-an-nstextview
|
||||
// http://stackoverflow.com/questions/12547007/convert-key-code-into-key-equivalent-string
|
||||
// http://stackoverflow.com/questions/8263618/convert-virtual-key-code-to-unicode-string
|
||||
//
|
||||
// If "deadKeyState" is = nullptr, it doesn't process dead keys.
|
||||
CFStringRef get_unicode_from_key_code(const UInt16 keyCode,
|
||||
const NSEventModifierFlags modifierFlags,
|
||||
UInt32* deadKeyState)
|
||||
{
|
||||
// The "TISCopyCurrentKeyboardInputSource()" doesn't contain
|
||||
// kTISPropertyUnicodeKeyLayoutData (returns nullptr) when the input
|
||||
// source is Japanese (Romaji/Hiragana/Katakana).
|
||||
|
||||
//TISInputSourceRef inputSource = TISCopyCurrentKeyboardInputSource();
|
||||
TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
CFDataRef keyLayoutData = (CFDataRef)TISGetInputSourceProperty(inputSource, kTISPropertyUnicodeKeyLayoutData);
|
||||
const UCKeyboardLayout* keyLayout =
|
||||
(keyLayoutData ? (const UCKeyboardLayout*)CFDataGetBytePtr(keyLayoutData): nullptr);
|
||||
|
||||
UInt32 deadKeyStateWrap = (deadKeyState ? *deadKeyState: 0);
|
||||
UniChar output[4];
|
||||
UniCharCount length;
|
||||
|
||||
// Reference here:
|
||||
// https://developer.apple.com/reference/coreservices/1390584-uckeytranslate?language=objc
|
||||
UCKeyTranslate(
|
||||
keyLayout,
|
||||
keyCode,
|
||||
kUCKeyActionDown,
|
||||
((modifierFlags >> 16) & 0xFF),
|
||||
LMGetKbdType(),
|
||||
(deadKeyState ? 0: kUCKeyTranslateNoDeadKeysMask),
|
||||
&deadKeyStateWrap,
|
||||
sizeof(output) / sizeof(output[0]),
|
||||
&length,
|
||||
output);
|
||||
|
||||
if (deadKeyState)
|
||||
*deadKeyState = deadKeyStateWrap;
|
||||
|
||||
CFRelease(inputSource);
|
||||
return CFStringCreateWithCharacters(kCFAllocatorDefault, output, length);
|
||||
}
|
||||
|
||||
} // namespace she
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -18,8 +18,6 @@
|
||||
|
||||
namespace she {
|
||||
class Surface;
|
||||
|
||||
KeyScancode cocoavk_to_scancode(UInt16 vk);
|
||||
}
|
||||
|
||||
class OSXWindowImpl {
|
||||
|
@ -197,9 +197,6 @@ Accelerator::Accelerator(const std::string& str)
|
||||
else if (tok == base::string_to_lower(kWinKeyName)) {
|
||||
m_modifiers = (KeyModifiers)((int)m_modifiers | (int)kKeyWinModifier);
|
||||
}
|
||||
|
||||
// Scancode
|
||||
|
||||
// Word with one character
|
||||
else if (base::utf8_length(tok) == 1) {
|
||||
std::wstring wstr = base::from_utf8(tok);
|
||||
@ -210,77 +207,74 @@ Accelerator::Accelerator(const std::string& str)
|
||||
m_unicodeChar = std::tolower(wstr[0]);
|
||||
m_scancode = kKeyNil;
|
||||
}
|
||||
// Other ones
|
||||
else {
|
||||
// F1, F2, ..., F11, F12
|
||||
if (tok[0] == 'f' && (tok.size() <= 3)) {
|
||||
int num = std::strtol(tok.c_str()+1, NULL, 10);
|
||||
if ((num >= 1) && (num <= 12))
|
||||
m_scancode = (KeyScancode)((int)kKeyF1 + num - 1);
|
||||
}
|
||||
else if ((tok == "escape") || (tok == "esc"))
|
||||
m_scancode = kKeyEsc;
|
||||
else if (tok == "backspace")
|
||||
m_scancode = kKeyBackspace;
|
||||
else if (tok == "tab")
|
||||
m_scancode = kKeyTab;
|
||||
else if (tok == "enter")
|
||||
m_scancode = kKeyEnter;
|
||||
else if (tok == "space")
|
||||
m_scancode = kKeySpace;
|
||||
else if ((tok == "insert") || (tok == "ins"))
|
||||
m_scancode = kKeyInsert;
|
||||
else if ((tok == "delete") || (tok == "del"))
|
||||
m_scancode = kKeyDel;
|
||||
else if (tok == "home")
|
||||
m_scancode = kKeyHome;
|
||||
else if (tok == "end")
|
||||
m_scancode = kKeyEnd;
|
||||
else if ((tok == "page up") || (tok == "pgup"))
|
||||
m_scancode = kKeyPageUp;
|
||||
else if ((tok == "page down") || (tok == "pgdn"))
|
||||
m_scancode = kKeyPageDown;
|
||||
else if (tok == "left")
|
||||
m_scancode = kKeyLeft;
|
||||
else if (tok == "right")
|
||||
m_scancode = kKeyRight;
|
||||
else if (tok == "up")
|
||||
m_scancode = kKeyUp;
|
||||
else if (tok == "down")
|
||||
m_scancode = kKeyDown;
|
||||
else if (tok == "0 pad")
|
||||
m_scancode = kKey0Pad;
|
||||
else if (tok == "1 pad")
|
||||
m_scancode = kKey1Pad;
|
||||
else if (tok == "2 pad")
|
||||
m_scancode = kKey2Pad;
|
||||
else if (tok == "3 pad")
|
||||
m_scancode = kKey3Pad;
|
||||
else if (tok == "4 pad")
|
||||
m_scancode = kKey4Pad;
|
||||
else if (tok == "5 pad")
|
||||
m_scancode = kKey5Pad;
|
||||
else if (tok == "6 pad")
|
||||
m_scancode = kKey6Pad;
|
||||
else if (tok == "7 pad")
|
||||
m_scancode = kKey7Pad;
|
||||
else if (tok == "8 pad")
|
||||
m_scancode = kKey8Pad;
|
||||
else if (tok == "9 pad")
|
||||
m_scancode = kKey9Pad;
|
||||
else if (tok == "/ pad" || tok == "slash pad")
|
||||
m_scancode = kKeySlashPad;
|
||||
else if (tok == "* pad" || tok == "asterisk pad" || tok == "asterisk")
|
||||
m_scancode = kKeyAsterisk;
|
||||
else if (tok == "- pad" || tok == "minus pad")
|
||||
m_scancode = kKeyMinusPad;
|
||||
else if (tok == "+ pad" || tok == "plus pad")
|
||||
m_scancode = kKeyPlusPad;
|
||||
else if (tok == "del pad" || tok == "delete pad")
|
||||
m_scancode = kKeyDelPad;
|
||||
else if (tok == "enter pad")
|
||||
m_scancode = kKeyEnterPad;
|
||||
// F1, F2, ..., F11, F12
|
||||
else if (tok[0] == 'f' && (tok.size() <= 3)) {
|
||||
int num = std::strtol(tok.c_str()+1, NULL, 10);
|
||||
if ((num >= 1) && (num <= 12))
|
||||
m_scancode = (KeyScancode)((int)kKeyF1 + num - 1);
|
||||
}
|
||||
else if ((tok == "escape") || (tok == "esc"))
|
||||
m_scancode = kKeyEsc;
|
||||
else if (tok == "backspace")
|
||||
m_scancode = kKeyBackspace;
|
||||
else if (tok == "tab")
|
||||
m_scancode = kKeyTab;
|
||||
else if (tok == "enter")
|
||||
m_scancode = kKeyEnter;
|
||||
else if (tok == "space")
|
||||
m_scancode = kKeySpace;
|
||||
else if ((tok == "insert") || (tok == "ins"))
|
||||
m_scancode = kKeyInsert;
|
||||
else if ((tok == "delete") || (tok == "del"))
|
||||
m_scancode = kKeyDel;
|
||||
else if (tok == "home")
|
||||
m_scancode = kKeyHome;
|
||||
else if (tok == "end")
|
||||
m_scancode = kKeyEnd;
|
||||
else if ((tok == "page up") || (tok == "pgup"))
|
||||
m_scancode = kKeyPageUp;
|
||||
else if ((tok == "page down") || (tok == "pgdn"))
|
||||
m_scancode = kKeyPageDown;
|
||||
else if (tok == "left")
|
||||
m_scancode = kKeyLeft;
|
||||
else if (tok == "right")
|
||||
m_scancode = kKeyRight;
|
||||
else if (tok == "up")
|
||||
m_scancode = kKeyUp;
|
||||
else if (tok == "down")
|
||||
m_scancode = kKeyDown;
|
||||
else if (tok == "0 pad")
|
||||
m_scancode = kKey0Pad;
|
||||
else if (tok == "1 pad")
|
||||
m_scancode = kKey1Pad;
|
||||
else if (tok == "2 pad")
|
||||
m_scancode = kKey2Pad;
|
||||
else if (tok == "3 pad")
|
||||
m_scancode = kKey3Pad;
|
||||
else if (tok == "4 pad")
|
||||
m_scancode = kKey4Pad;
|
||||
else if (tok == "5 pad")
|
||||
m_scancode = kKey5Pad;
|
||||
else if (tok == "6 pad")
|
||||
m_scancode = kKey6Pad;
|
||||
else if (tok == "7 pad")
|
||||
m_scancode = kKey7Pad;
|
||||
else if (tok == "8 pad")
|
||||
m_scancode = kKey8Pad;
|
||||
else if (tok == "9 pad")
|
||||
m_scancode = kKey9Pad;
|
||||
else if (tok == "/ pad" || tok == "slash pad")
|
||||
m_scancode = kKeySlashPad;
|
||||
else if (tok == "* pad" || tok == "asterisk pad" || tok == "asterisk")
|
||||
m_scancode = kKeyAsterisk;
|
||||
else if (tok == "- pad" || tok == "minus pad")
|
||||
m_scancode = kKeyMinusPad;
|
||||
else if (tok == "+ pad" || tok == "plus pad")
|
||||
m_scancode = kKeyPlusPad;
|
||||
else if (tok == "del pad" || tok == "delete pad")
|
||||
m_scancode = kKeyDelPad;
|
||||
else if (tok == "enter pad")
|
||||
m_scancode = kKeyEnterPad;
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,7 +318,8 @@ std::string Accelerator::toString() const
|
||||
buf += base::to_utf8(wideUnicodeChar);
|
||||
}
|
||||
else if (m_scancode > 0 &&
|
||||
m_scancode < scancode_to_string_size)
|
||||
m_scancode < scancode_to_string_size &&
|
||||
scancode_to_string[m_scancode])
|
||||
buf += scancode_to_string[m_scancode];
|
||||
else if (!buf.empty() && buf[buf.size()-1] == '+')
|
||||
buf.erase(buf.size()-1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -259,9 +259,6 @@ bool Manager::generateMessages()
|
||||
// Generate messages for timers
|
||||
Timer::pollTimers();
|
||||
|
||||
// Generate redraw events.
|
||||
flushRedraw();
|
||||
|
||||
if (!msg_queue.empty())
|
||||
return true;
|
||||
else
|
||||
@ -612,7 +609,17 @@ void Manager::handleWindowZOrder()
|
||||
|
||||
void Manager::dispatchMessages()
|
||||
{
|
||||
pumpQueue();
|
||||
// Send messages in the queue (mouse/key/timer/etc. events) This
|
||||
// might change the state of widgets, etc. In case pumpQueue()
|
||||
// returns a number greater than 0, it means that we've processed
|
||||
// some messages, so we've to redraw the screen.
|
||||
if (pumpQueue() > 0) {
|
||||
// Generate and send just kPaintMessages with the latest UI state.
|
||||
flushRedraw();
|
||||
pumpQueue();
|
||||
}
|
||||
|
||||
// Flip the back-buffer to the real display.
|
||||
flipDisplay();
|
||||
}
|
||||
|
||||
@ -1214,12 +1221,13 @@ void Manager::onSizeHint(SizeHintEvent& ev)
|
||||
ev.setSizeHint(gfx::Size(w, h));
|
||||
}
|
||||
|
||||
void Manager::pumpQueue()
|
||||
int Manager::pumpQueue()
|
||||
{
|
||||
#ifdef LIMIT_DISPATCH_TIME
|
||||
base::tick_t t = base::current_tick();
|
||||
#endif
|
||||
|
||||
int count = 0; // Number of processed messages
|
||||
auto it = msg_queue.begin();
|
||||
while (it != msg_queue.end()) {
|
||||
#ifdef LIMIT_DISPATCH_TIME
|
||||
@ -1284,7 +1292,10 @@ void Manager::pumpQueue()
|
||||
|
||||
// Destroy the message
|
||||
delete first_msg;
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -149,7 +149,7 @@ namespace ui {
|
||||
const double magnification);
|
||||
void handleWindowZOrder();
|
||||
|
||||
void pumpQueue();
|
||||
int pumpQueue();
|
||||
bool sendMessageToWidget(Message* msg, Widget* widget);
|
||||
|
||||
static void removeWidgetFromRecipients(Widget* widget, Message* msg);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -24,7 +24,7 @@ Message::Message(MessageType type, KeyModifiers modifiers)
|
||||
, m_used(false)
|
||||
, m_fromFilter(false)
|
||||
{
|
||||
if (modifiers == kKeyUninitializedModifier)
|
||||
if (modifiers == kKeyUninitializedModifier && she::instance())
|
||||
m_modifiers = she::instance()->keyModifiers();
|
||||
else
|
||||
m_modifiers = modifiers;
|
||||
|
Loading…
x
Reference in New Issue
Block a user