|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// メイン画面パネル
//
#include "wxmainview.h"
#include "wxmainframe.h"
#include "wxuimessage.h"
#include "config.h"
#include "keyboard.h"
#include "renderer.h"
#include <wx/event.h>
//#define KEYDEBUG 1
//#define MOUSEDEBUG 1
#if defined(KEYDEBUG)
#define DKPRINTF(...) printf(__VA_ARGS__)
#else
#define DKPRINTF(...) /**/
#endif
#if defined(MOUSEDEBUG)
#define DMPRINTF(...) printf(__VA_ARGS__)
#else
#define DMPRINTF(...) /**/
#endif
// 再描画矩形の指定方法について。
// DoRefresh() にて、VM スレッドが自発的に画面を更新する際は、
// パフォーマンスの観点からも更新矩形だけを再描画すべき。
// これを wxWidgets に指示するのが wxWindow::Refresh{,Rect}() であるが
// 一部のプラットフォームではこれを呼び出すと、アプリケーションウィンドウ
// 全体がささってしまい、MainView だけでなくメニューバーも含めたすべてが
// 再描画できなくなってしまう。仕方がないので、これらのプラットフォームでは
// Refresh{,Rect}() を呼ばず、再描画矩形を画面全体として運用する。
// ちょっと無駄なだけなので (動かないことに比べれば) 気にしない。
//
// 今のところ NetBSD (5.0 以降) と OpenBSD(/amd64)(-6.7)
// (と Linux (CentOS 6.3/x86_64)) が該当する。
#if defined(__NetBSD__) || defined(__OpenBSD__)
#define DONT_USE_REFRESH 1
#endif
wxDEFINE_EVENT(NONO_EVT_MOUSEMODE, wxCommandEvent);
wxBEGIN_EVENT_TABLE(WXMainView, inherited)
EVT_PAINT(WXMainView::OnPaint)
EVT_KEY_DOWN(WXMainView::OnKeyDown)
EVT_KEY_UP(WXMainView::OnKeyUp)
EVT_CHAR(WXMainView::OnChar)
EVT_MOUSE_EVENTS(WXMainView::OnMouse)
EVT_MOUSE_CAPTURE_LOST(WXMainView::OnMouseCaptureLost)
wxEND_EVENT_TABLE()
WXMainView::WXMainView(wxWindow *parent)
: inherited(parent)
{
SetName("WXMainView");
// デバイスを取得。
renderer = GetVideoRenderer();
// rich dumb
// -------- -------
// NULL NULL キー入力機能なし
// NULL avail シリアル入力機能のみ
// avail avail キー入力機能あり (2つは同じポインタ)
dumbkbd = gMainApp.FindObject<DumbKeyboard>(OBJ_KEYBOARD);
if (dumbkbd) {
richkbd = dynamic_cast<Keyboard *>(dumbkbd);
}
// マウスモード変更イベント
Bind(NONO_EVT_MOUSEMODE, &WXMainView::OnMouseMode, this);
// VM からの通知を受け取る
WXUIMessage::Connect(UIMessage::RENDER, this,
wxCommandEventHandler(WXMainView::OnRender));
// 実画面 (ウィンドウの大きさ)
DoResize(screen_scale);
// 更新間隔 [msec]
renderer->SetRefreshInterval(33);
// 最初に一度描画
Refresh();
}
WXMainView::~WXMainView()
{
// マウスをリリースしないと Assert される
if (HasCapture()) {
ReleaseMouse();
}
WXUIMessage::Disconnect(UIMessage::RENDER, this,
wxCommandEventHandler(WXMainView::OnRender));
}
// (設定反映などの) 初期化
bool
WXMainView::Init()
{
if (richkbd) {
// キーボードの入力モードの初期値設定
const ConfigItem& item_input = gConfig->Find("hostkbd-input");
const std::string input_mode = item_input.AsString();
if (input_mode == "char") {
SetCharInputMode(true);
} else if (input_mode == "jp") {
// 今は二択しかないのでちょっと噛み合ってないが
SetCharInputMode(false);
} else {
item_input.Err();
return false;
}
} else if (dumbkbd) {
// シリアルキーボードのみなら常に文字入力。
SetCharInputMode(true);
}
return true;
}
// 終了用に描画を停止する
void
WXMainView::Close()
{
// これで OnPaint() が何もせず帰るようになる。
viewwidth = 0;
viewheight = 0;
}
// リフレッシュ要求イベント
void
WXMainView::OnRender(wxCommandEvent& event)
{
#if defined(DONT_USE_REFRESH)
// Refresh{,Rect}() が使えないので、再描画範囲は常に全体とする
#else
// 再描画範囲を更新矩形に限定
// XXX のはずだが、今の所全体
RefreshRect(wxRect(0, 0, viewwidth, viewheight), false);
#endif
// 実際に再描画する
Refresh();
// TODO: ビデオモニタにも通知する
}
// 描画イベント
void
WXMainView::OnPaint(wxPaintEvent& event)
{
if (__predict_false(viewwidth == 0 || viewheight == 0)) {
return;
}
BitmapRGB *bitmap24 = renderer->GetBitmap();
if (__predict_false(bitmap24 == NULL)) {
return;
}
wxImage image(viewwidth, viewheight, bitmap24->GetBuf(), true);
wxBitmap bmp(image);
// 実画面 DC にコピー
wxPaintDC dstDC(this);
dstDC.DrawBitmap(bmp, 0, 0);
}
// リサイズ (UI スレッドから呼ぶこと)
void
WXMainView::DoResize(double scale)
{
screen_scale = scale;
int width = (double)renderer->GetWidth() * scale;
int height = (double)renderer->GetHeight() * scale;
if (viewwidth != width || viewheight != height) {
viewwidth = width;
viewheight = height;
// レンダラにリサイズ指示。
renderer->ResizeView(viewwidth, viewheight);
// ウィンドウサイズ変更
SetSize(viewwidth, viewheight);
SetMinSize(wxSize(viewwidth, viewheight));
}
}
// 現在のスケールを返す。
// screen_scale は public static なので見えるんだけど一応お行儀で。
double
WXMainView::GetScale() const
{
return screen_scale;
}
// 現在のスケール
/*static*/ double WXMainView::screen_scale;
//
// マウス入力
//
// マウスモード変更要求イベント
void
WXMainView::OnMouseMode(wxCommandEvent& event)
{
SetMouseMode(event.GetInt());
}
// マウスモード設定
void
WXMainView::SetMouseMode(bool mode)
{
// XXX マウスモード ON にした時の座標を記憶してそこに戻るのはどうか
mousemode = mode;
if (mousemode) {
// マウスモードを ON にする
DMPRINTF("SetMouseMode ON\n");
// マウスカーソル OFF
::wxSetCursor(wxCursor(wxCURSOR_BLANK));
if (!HasCapture()) {
CaptureMouse();
}
// このウィンドウから外れないように移動を検出し続けるため、
// マウスカーソルをウィンドウ中央に移す。
// ウィンドウとメニューバーが分離してる wxOSX のために必要。
MyWarpPointer(GetSize() / 2);
} else {
// マウスモードを OFF にする
DMPRINTF("SetMouseMode OFF\n");
if (HasCapture()) {
ReleaseMouse();
}
// 分かりやすさのため、マウスカーソルを中央へ戻してから復帰
wxSize pt = GetSize() / 2;
WarpPointer(pt.x, pt.y);
// マウスカーソル ON
::wxSetCursor(wxNullCursor);
}
// マウスモードなら、タイトルにマウスモードの抜け方を表示したい。
auto frame = dynamic_cast<WXMainFrame *>(GetParent());
frame->SetMyTitle(mousemode);
}
// マウスカーソルをクライアント座標 (x, y) に移動
void
WXMainView::MyWarpPointer(wxSize pos)
{
DMPRINTF("MyWarpPointer %d,%d\n", pos.x, pos.y);
// この後の MDWarpPointer() でもう一度 EVT_MOTION が飛ぶので
// それを判別するためのフラグ。
motion_by_warp_pointer = true;
WarpPointer(pos.x, pos.y);
}
// マウスイベント
void
WXMainView::OnMouse(wxMouseEvent& event)
{
// マウスモードの時だけ処理。
// XXX 本当はイベントごと Disconnect したい
if (mousemode) {
bool leaving = event.Leaving();
bool moving = event.Moving();
bool dragging = event.Dragging();
// LeftDown() 等は押された時、LeftIsDown() 等は押されてる間 true。
bool rb = event.RightIsDown();
bool lb = event.LeftIsDown();
bool mb = event.MiddleIsDown();
const wxPoint& pos = event.GetPosition();
int dx = 0;
int dy = 0;
#if defined(MOUSEDEBUG)
std::string dstr = "OnMouse";
if (moving || dragging || motion_by_warp_pointer) {
dstr += string_format(" (%d,%d)", pos.x, pos.y);
}
if (moving)
dstr += " Moving";
if (dragging)
dstr += " Dragging";
if (motion_by_warp_pointer)
dstr += " MotionByWarp";
if (lb || mb || rb) {
dstr += string_format(" Button(%c%c%c)",
(lb ? 'L' : '-'),
(mb ? 'M' : '-'),
(rb ? 'R' : '-'));
}
if (leaving)
dstr += " Leaving";
printf("%s\n", dstr.c_str());
#endif
if (leaving) {
// タスクスイッチした時とかのための自動リリース。
// メインウィンドウの上にサブウィンドウが乗っているときも
// leaving が発生するので、メインウィンドウの外に出た場合のみ
// リリースする。
auto sz = GetSize();
if (pos.x < 0 || pos.x > sz.x || pos.y < 0 || pos.y > sz.y) {
SetMouseMode(false);
}
}
if (moving || dragging) {
// (My)WarpPointer() で自発的にマウスカーソルを移動させたことで
// 来る EVT_MOTION は無視する。
if (motion_by_warp_pointer) {
motion_by_warp_pointer = false;
// ここを基準点にする
prevpos = pos;
} else {
// 前回からの差を求める
dx = pos.x - prevpos.x;
dy = pos.y - prevpos.y;
prevpos = pos;
// マウスカーソルを中心に戻す
if (dx != 0 || dy != 0) {
MyWarpPointer(GetSize() / 2);
}
}
}
// VM に入力
if (dx != 0 ||
dy != 0 ||
lb != prevlb ||
mb != prevmb ||
rb != prevrb )
{
DMPRINTF(" Input dx=%d dy=%d %c%c%c\n",
dx, dy,
(lb ? 'L' : '-'),
(mb ? 'M' : '-'),
(rb ? 'R' : '-'));
if (richkbd) {
richkbd->MouseInput(dx, dy, rb, lb, mb);
}
}
prevlb = lb;
prevmb = mb;
prevrb = rb;
}
// EVT_LEFT_DOWN をデフォルト処理するため
event.Skip();
}
// マウスキャプチャロスト
void
WXMainView::OnMouseCaptureLost(wxMouseCaptureLostEvent& event)
{
// 外部要因でマウスキャプチャをロストしたので、マウスモードを抜ける。
SetMouseMode(false);
}
// アクティベートイベント。
// この(トップレベル)ウィンドウにフォーカスが当たるか外れるかで飛んでくる。
// 実際には WXMainFrame 宛てに飛んできたイベントをこちらに転送してある。
// マウスモード中にこのウィンドウからフォーカスが外れたら (例えば ALT+TAB の
// ようなウィンドウを切り替える操作)、マウスモードを解除するため。
void
WXMainView::OnActivate(wxActivateEvent& event)
{
// フォーカスが外れる際にマウスモード中ならマウスモードを解除
if (event.GetActive() == false) {
DMPRINTF("OnActivate FocusOut\n");
if (mousemode) {
SetMouseMode(false);
}
} else {
DMPRINTF("OnActivate FocusIn\n");
}
}
//
// キー入力
//
// wxKeyEvent でキーコードを得るためのメソッドは
// GetKeyCode()、GetRawKeyCode()、GetRawKeyFlags() の3つが用意されていて
// wxWidgets の port (wxGTK、wxOSX とか) によってそれぞれ内容の定義が違う。
//
// wxGTK の場合
// GetKeyCode() が論理キーコードなのでこれをメインに使う。ただし左右 [SHIFT]
// のように論理キーコードだけでは区別の付かないものについては物理キー番号で
// ある GetRawKeyFlags() を併用する。
//
// 以下詳細。
// GetKeyCode() は wxWidgets の WXK_* (/usr/pkg/include/wx-3.0/wx/defs.h)。
// これは概ね論理キーコードであり、xorg.conf の swapcaps 設定や Xmodmap の
// 影響をうける。
// o 基本的に [SHIFT] キーの影響を受けないが、一部例外がある。
// - [^] (0x5e) と [SHIFT]+[^] (0x30)
// - [,] (0x2c) と [SHIFT]+[,] (0x3c)
// o [\] と [_] は同じ 0x5c になる ([SHIFT] 押しながらでも同様)。
// o [SHIFT], [CTRL], [ALT] の各左右キーは同じコードになる。
//
// GetRawKeyFlags() は物理キー番号ようだ。GDK の hardware keycode らしいが、
// それ以上の詳細は不明。
// o 環境 (OS か X かライブラリ?) によって異なるようだ。
// 少なくとも NetBSD9 と Ubuntu20.04 では一部の値が異なる。
// o [SHIFT] キーの影響を受けない。
// GetKeyCode() では影響を受けた例外キーもここでは影響を受けない。
// o [SHIFT], [CTRL], [ALT] の各左右キーは違うコードになる。
//
// GetRawKeyCode() は GDK の keycode っぽい?
// (/usr/pkg/include/gtk-2.0/gdk/gdkkeysyms.h)。
// X11 の keysym から来てる? (/usr/X11R7/include/X11/keysymdef.h)。
// ただし [A] と [SHIFT]+[A] が違うコードを返すというか、文字コードで表現
// 出来る時は文字コード、みたいな感じになっているのでここでは使いづらい。
// 左右の SHIFT は区別可能。
//
// wxOSX の場合
// GetKeyCode()
// 英字キー [A] と [SHIFT]+[A] は同じコードになるが、
// 記号キー [1] と [SHIFT]+[1] は別になる体系のようだ。
// 左右の [SHIFT] は区別できない。
//
// GetRawKeyCode()
// これがたぶん物理キー番号。
// [1] と [SHIFT]+[1] は同じコードを返す。
// 左右の [SHIFT] は区別可能。
//
// GetRawKeyFlags() は状態フラグか何かのようだ。
//
// 入力モード変更
void
WXMainView::SetCharInputMode(bool enable)
{
is_charinput = enable;
}
// キーを押した
void
WXMainView::OnKeyDown(wxKeyEvent& event)
{
// メニューのアクセラレータのために必要
event.Skip();
if (is_charinput) {
return;
}
DKPRINTF("KeyDown ");
int keycode = GetKeyCode(event);
if (richkbd) {
richkbd->MakeKey(keycode);
}
}
// キーを離した
void
WXMainView::OnKeyUp(wxKeyEvent& event)
{
if (is_charinput) {
return;
}
DKPRINTF("KeyUp ");
int keycode = GetKeyCode(event);
if (richkbd) {
richkbd->BreakKey(keycode);
}
}
// 文字による入力モード
void
WXMainView::OnChar(wxKeyEvent& event)
{
// メニューのアクセラレータのために必要
event.Skip();
if (!is_charinput) {
return;
}
uint ukey = event.GetUnicodeKey();
uint ukey_orig = ukey;
DKPRINTF("Char uni=0x%02x", ukey);
if (0x20 <= ukey && ukey < 0x7f) {
DKPRINTF(" '%c'", ukey);
}
bool ctrl = event.ControlDown();
if (ctrl) {
DKPRINTF(" CTRL");
// Ctrl + A .. Ctrl + Z までは 0x01(^A) .. 0x1a(^Z) の文字が来るが、
// Ctrl + 記号は記号の文字コードだけが送られてくるようだ。
// Ctrl + [ は 0x1b('^[') ではなく 0x5b('[') のような感じ。
// そこでこの場合は Ctrl キーが押されているかどうかを別途判定する。
if (0x40 <= ukey && ukey <= 0x5f) {
ukey -= 0x40;
// Ctrl+@ ('\0') はそのまま通せないので、別文字にエスケープ。
if (ukey == 0) {
ukey = CC_NUL;
}
}
}
// 文字コードが拾えなければキーコードから
if (ukey == WXK_NONE) {
uint wxkey = event.GetKeyCode();
DKPRINTF(" key=%3u(0x%03x)", wxkey, wxkey);
// 一部の特殊キーをここで対応。
// キーボード国籍による違いはないだろう。
switch (wxkey) {
case WXK_LEFT: ukey = CC_left; break;
case WXK_UP: ukey = CC_up; break;
case WXK_RIGHT: ukey = CC_right; break;
case WXK_DOWN: ukey = CC_down; break;
case WXK_F1: ukey = CC_F1; break;
case WXK_F2: ukey = CC_F2; break;
case WXK_F3: ukey = CC_F3; break;
case WXK_F4: ukey = CC_F4; break;
case WXK_F5: ukey = CC_F5; break;
case WXK_F6: ukey = CC_F6; break;
case WXK_F7: ukey = CC_F7; break;
case WXK_F8: ukey = CC_F8; break;
case WXK_F9: ukey = CC_F9; break;
case WXK_F10: ukey = CC_F10; break;
case WXK_F11: ukey = CC_F10; break;
default:
ukey = 0;
break;
}
}
if (ukey != ukey_orig) {
DKPRINTF(" -> 0x%02x", ukey);
}
DKPRINTF("\n");
if (ukey == 0) {
return;
}
ukey &= 0xff;
if (dumbkbd) {
dumbkbd->CharInput(ukey);
}
}
// 共通キーコードを取得する。
// 対応するキーがない場合は -1 を返す。
int
WXMainView::GetKeyCode(wxKeyEvent& event)
{
uint32 wxcode __unused = event.GetKeyCode();
uint32 rawcode __unused = event.GetRawKeyCode();
uint32 rawflags __unused = event.GetRawKeyFlags();
uint32 raw;
int keycode;
// wx キーコードは10進、16進併記しないと読みづらい
DKPRINTF("key=%3d(0x%03x) ", wxcode, wxcode);
#if defined(__WXOSX__)
// wxOSX では raw が物理キー、flags はフラグっぽいものなので不要
DKPRINTF("raw=0x%02x (flags=0x%06x) ", rawcode, rawflags);
raw = rawcode;
#else
// wxGTK では flags が物理キー、raw は文字コードっぽいものなので不要
DKPRINTF("flags=0x%02x (raw=0x%04x) ", rawflags, rawcode);
raw = rawflags;
#endif
// まず wx キーコードでテーブルを引く
if (wxcode < countof(keycode_table)) {
keycode = keycode_table[wxcode];
} else {
keycode = KC_none;
}
// wx キーコードは論理キーコードなので [SHIFT] キーの左右を区別できないが
// ここでは左右を区別したいので、物理キー番号を見て区別する。
if (keycode == KC_SHIFT) {
#if defined(__WXOSX__)
if (raw == 0x3c)
#else
if (raw == 0x3e)
#endif
{
keycode = KC_SHIFT_R;
} else {
keycode = KC_SHIFT_L;
}
}
#if defined(__WXGTK__)
// wxGTK では日本語キーボードの一部のキーが論理キーコードだけでは
// 判定できないようだ
// その上 raw キーコードも OS (か何か) によってところどころ体系が
// 異なるようだ。orz
//
// OS [^] [0] [_] [\]
// --------------- ----- ----- ----- -----
// NetBSD9 0x15 0x13 0xd3 0x85
// OpenBSD7.1 0x15 0x13 0xd3 0x85
// Ubuntu20.04 0x15 0x13 0x61 0x84
// [0] と [SHIFT]+[^] が同じキーコードになるようだ
if (keycode == KC_0) {
if (raw == 0x15) {
keycode = KC_circum;
} else {
keycode = KC_0;
}
}
// [\] と [_] が同じキーコードになるようだ。
// その時の raw は OS によって(?)異なるようだ。
if (keycode == KC_backslash) {
switch (raw) {
case 0xd3: // NetBSD9
case 0x61: // Ubuntu20.04
keycode = KC_underscore;
break;
default:
keycode = KC_backslash;
break;
}
}
#endif
DKPRINTF("keycode=%d %s\n", keycode, Keyboard::GetKeyName(keycode).c_str());
return keycode;
}
// wx キーコード(WXK_*)を共通キーコードに変換するテーブル。
// 一部このテーブルだけでは判定できないものがある。すぐ上の GetKeyCode() 参照。
// 値 0 は本当は KC_none と書くべきだが、こっちのほうが読みやすいので。
//
// XXX: OSX の [CAPS] は押す離すで一回分の Down しか来ないのでちょっと放置。
// XXX: OSX の [英数] と [かな] もちょっと放置。
/*static*/ const int
WXMainView::keycode_table[0x190] = {
0, // 0x00
0, // 0x01
0, // 0x02
0, // 0x03
0, // 0x04
0, // 0x05
0, // 0x06
0, // 0x07
KC_BS, // 0x08 WXK_BACK
KC_TAB, // 0x09 WXK_TAB
0, // 0x0a
0, // 0x0b
0, // 0x0c
KC_enter, // 0x0d WXK_RETURN
0, // 0x0e
0, // 0x0f
0, // 0x10
0, // 0x11
0, // 0x12
0, // 0x13
0, // 0x14
0, // 0x15
0, // 0x16
0, // 0x17
0, // 0x18
0, // 0x19
0, // 0x1a
KC_ESC, // 0x1b WXK_ESCAPE
0, // 0x1c
0, // 0x1d
0, // 0x1e
0, // 0x1f
KC_space, // 0x20 WXK_SPACE
KC_1, // 0x21 (OSX: [SHIFT]+[1])
KC_2, // 0x22 (OSX: [SHIFT]+[2])
KC_3, // 0x23 (OSX: [SHIFT]+[3])
KC_4, // 0x24 (OSX: [SHIFT]+[4])
KC_5, // 0x25 (OSX: [SHIFT]+[5])
KC_6, // 0x26 (OSX: [SHIFT]+[6])
KC_7, // 0x27 (OSX: [SHIFT]+[7])
KC_8, // 0x28 (OSX: [SHIFT]+[8])
KC_9, // 0x29 (OSX: [SHIFT]+[9])
KC_colon, // 0x2a (OSX: [SHIFT]+[:])
KC_semicolon, // 0x2b (OSX: [SHIFT]+[;])
KC_comma, // 0x2c
KC_minus, // 0x2d
KC_period, // 0x2e
KC_slash, // 0x2f
KC_0, // 0x30 (GTK: [0] と [SHIFT]+[^])
KC_1, // 0x31
KC_2, // 0x32
KC_3, // 0x33
KC_4, // 0x34
KC_5, // 0x35
KC_6, // 0x36
KC_7, // 0x37
KC_8, // 0x38
KC_9, // 0x39
KC_colon, // 0x3a
KC_semicolon, // 0x3b
KC_comma, // 0x3c (GTK: [,]は0x2c だが [SHIFT]+[,]は0x3c)
KC_minus, // 0x3d (OSX: [SHIFT]+[-])
KC_period, // 0x3e (OSX: [SHIFT]+[.])
KC_slash, // 0x3f (OSX: [SHIFT]+[/])
KC_at, // 0x40
KC_A, // 0x41
KC_B, // 0x42
KC_C, // 0x43
KC_D, // 0x44
KC_E, // 0x45
KC_F, // 0x46
KC_G, // 0x47
KC_H, // 0x48
KC_I, // 0x49
KC_J, // 0x4a
KC_K, // 0x4b
KC_L, // 0x4c
KC_M, // 0x4d
KC_N, // 0x4e
KC_O, // 0x4f
KC_P, // 0x50
KC_Q, // 0x51
KC_R, // 0x52
KC_S, // 0x53
KC_T, // 0x54
KC_U, // 0x55
KC_V, // 0x56
KC_W, // 0x57
KC_X, // 0x58
KC_Y, // 0x59
KC_Z, // 0x5a
KC_bracketleft, // 0x5b
KC_backslash, // 0x5c (GTK: [\] と [_])
KC_bracketright,// 0x5d
KC_circum, // 0x5e
KC_underscore, // 0x5f (OSX: [_])
KC_at, // 0x60 (OSX: [SHIFT]+[@])
0, // 0x61
0, // 0x62
0, // 0x63
0, // 0x64
0, // 0x65
0, // 0x66
0, // 0x67
0, // 0x68
0, // 0x69
0, // 0x6a
0, // 0x6b
0, // 0x6c
0, // 0x6d
0, // 0x6e
0, // 0x6f
0, // 0x70
0, // 0x71
0, // 0x72
0, // 0x73
0, // 0x74
0, // 0x75
0, // 0x76
0, // 0x77
0, // 0x78
0, // 0x79
0, // 0x7a
KC_bracketleft, // 0x7b (OSX: [SHIFT]+[[])
KC_backslash, // 0x7c (OSX: [SHIFT]+[\])
KC_bracketright,// 0x7d (OSX: [SHIFT]+[]])
KC_circum, // 0x7e (OSX: [SHIFT]+[^])
KC_DEL, // 0x7f
0,0,0,0, 0,0,0,0, // 0x80
0,0,0,0, 0,0,0,0, // 0x88
0,0,0,0, 0,0,0,0, // 0x90
0,0,0,0, 0,0,0,0, // 0x98
0, // 0xa0
0, // 0xa1
0, // 0xa2
0, // 0xa3
0, // 0xa4
KC_backslash, // 0xa5 (OSX: [\])
0, // 0xa6
0, // 0xa7
0, // 0xa8
0, // 0xa9
0, // 0xaa
0, // 0xab
0, // 0xac
0, // 0xad
0, // 0xae
0, // 0xaf
0,0,0,0, 0,0,0,0, // 0xb0
0,0,0,0, 0,0,0,0, // 0xb8
0, // 0xc0=192
0, // 193 WXK_SPECIAL1
0, // 194 WXK_SPECIAL2
0, // 195 WXK_SPECIAL3
0, // 196 WXK_SPECIAL4
0, // 197 WXK_SPECIAL5
0, // 198 WXK_SPECIAL6
0, // 199 WXK_SPECIAL7
0, // 200 WXK_SPECIAL8
0, // 201 WXK_SPECIAL9
0, // 202 WXK_SPECIAL10
0, // 203 WXK_SPECIAL11
0, // 204 WXK_SPECIAL12
0, // 205 WXK_SPECIAL13
0, // 206 WXK_SPECIAL14
0, // 207 WXK_SPECIAL15
0, // 208 WXK_SPECIAL16
0, // 209 WXK_SPECIAL17
0, // 210 WXK_SPECIAL18
0, // 211 WXK_SPECIAL19
0, // 212 WXK_SPECIAL20
0, // 0xd5
0, // 0xd6
0, // 0xd7
0,0,0,0, 0,0,0,0, // 0xd8
0,0,0,0, 0,0,0,0, // 0xe0
0,0,0,0, 0,0,0,0, // 0xe8
0,0,0,0, 0,0,0,0, // 0xf0
0,0,0,0, 0,0,0,0, // 0xf8
0,0,0,0, 0,0,0,0, // 0x100
0,0,0,0, 0,0,0,0, // 0x108
0,0,0,0, 0,0,0,0, // 0x110
0,0,0,0, 0,0,0,0, // 0x118
0,0,0,0, 0,0,0,0, // 0x120
0, // 0x128
0, // 0x129
0, // 0x12a
0, // 0x12b
//
// WXK_* は10進数で定義されていて、特殊キーは 300 (=0x12c) から。
//
0, // 300 WXK_START
0, // 301 WXK_LBUTTON
0, // 302 WXK_RBUTTON
0, // 303 WXK_CANCEL
0, // 304 WXK_MBUTTON
0, // 305 WXK_CLEAR
KC_SHIFT, // 306 WXK_SHIFT (左右[SHIFT])
0, // 307 WXK_ALT
KC_CTRL, // 308 WXK_CONTROL (ゲストに右[CTRL]はないので区別不要)
0, // 309 WXK_MENU
0, // 310 WXK_PAUSE
0, // 311 WXK_CAPITAL
KC_UNDO, // 312 WXK_END
KC_HOME, // 313 WXK_HOME
KC_left, // 314 WXK_LEFT
KC_up, // 315 WXK_UP
KC_right, // 316 WXK_RIGHT
KC_down, // 317 WXK_DOWN
0, // 318 WXK_SELECT
0, // 319 WXK_PRINT
0, // 320 WXK_EXECUTE
0, // 321 WXK_SNAPSHOT
KC_INS, // 322 WXK_INSERT
0, // 323 WXK_HELP
KC_PAD_0, // 324 WXK_NUMPAD0
KC_PAD_1, // 325 WXK_NUMPAD1
KC_PAD_2, // 326 WXK_NUMPAD2
KC_PAD_3, // 327 WXK_NUMPAD3
KC_PAD_4, // 328 WXK_NUMPAD4
KC_PAD_5, // 329 WXK_NUMPAD5
KC_PAD_6, // 330 WXK_NUMPAD6
KC_PAD_7, // 331 WXK_NUMPAD7
KC_PAD_8, // 332 WXK_NUMPAD8
KC_PAD_9, // 333 WXK_NUMPAD9
0, // 334 WXK_MULTIPLY
0, // 335 WXK_ADD
0, // 336 WXK_SEPARATOR
0, // 337 WXK_SUBTRACT
0, // 338 WXK_DECIMAL
0, // 339 WXK_DIVIDE
KC_F1, // 340 WXK_F1
KC_F2, // 341 WXK_F2
KC_F3, // 342 WXK_F3
KC_F4, // 343 WXK_F4
KC_F5, // 344 WXK_F5
KC_F6, // 345 WXK_F6
KC_F7, // 346 WXK_F7
KC_F8, // 347 WXK_F8
KC_F9, // 348 WXK_F9
KC_F10, // 349 WXK_F10
KC_F10, // 350 WXK_F11
0, // 351 WXK_F12
0, // 352 WXK_F13
0, // 353 WXK_F14
0, // 354 WXK_F15
0, // 355 WXK_F16
0, // 356 WXK_F17
0, // 357 WXK_F18
0, // 358 WXK_F19
0, // 359 WXK_F20
0, // 360 WXK_F21
0, // 361 WXK_F22
0, // 362 WXK_F23
0, // 363 WXK_F24
0, // 364 WXK_NUMLOCK
0, // 365 WXK_SCROLL
KC_ROLLUP, // 366 WXK_PAGEUP
KC_ROLLDOWN, // 367 WXK_PAGEDOWN
0, // 368 WXK_NUMPAD_SPACE
0, // 369 WXK_NUMPAD_TAB
KC_PAD_enter, // 370 WXK_NUMPAD_ENTER
0, // 371 WXK_NUMPAD_F1
0, // 372 WXK_NUMPAD_F2
0, // 373 WXK_NUMPAD_F3
0, // 374 WXK_NUMPAD_F4
0, // 375 WXK_NUMPAD_HOME
0, // 376 WXK_NUMPAD_LEFT
0, // 377 WXK_NUMPAD_UP
0, // 378 WXK_NUMPAD_RIGHT
0, // 379 WXK_NUMPAD_DOWN
0, // 380 WXK_NUMPAD_PAGEUP
0, // 381 WXK_NUMPAD_PAGEDOWN
0, // 382 WXK_NUMPAD_END
0, // 383 WXK_NUMPAD_BEGIN
0, // 384 WXK_NUMPAD_INSERT
0, // 385 WXK_NUMPAD_DELETE
KC_PAD_equal, // 386 WXK_NUMPAD_EQUAL
KC_PAD_multiply,// 387 WXK_NUMPAD_MULTIPLY
KC_PAD_plus, // 388 WXK_NUMPAD_ADD
0, // 389 WXK_NUMPAD_SEPARATOR
KC_PAD_minus, // 390 WXK_NUMPAD_SUBTRACT
KC_PAD_decimal, // 391 WXK_NUMPAD_DECIMAL
KC_PAD_divide, // 392 WXK_NUMPAD_DIVIDE
0, // 393 WXK_WINDOWS_LEFT
0, // 394 WXK_WINDOWS_RIGHT
0, // 395 WXK_WINDOWS_MENU
// WXK_RAW_CONTROL は wxOSX でのみ定義してあり (wxOSX 以外では別名)、
// wxOSX とそれ以外とで定義済みキーの最大値が違う。そこが可変だとこの
// テーブルが困るので、wxOSX 以外でも常に WXK_RAW_CONTROL 分の枠は用意
// することにする。wxOSX 以外だと飛んでこないというだけで害はない。
KC_CTRL, // 396 WXK_RAW_CONTROL (OSX)
0, // 397
0, // 398
0, // 399=0x18f
};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.