Windows 11 で USB ThinkPad トラックポイント・キーボードの縦スクロールがダウンする

USB (有線)版の ThinkPad トラックポイント・キーボードで、真ん中ボタンによる縦スクロールを行った場合に「ThinkPad 優先スクローリング」機能がダウンする場合があります。抜本的に解決できませんでしたがメモ。

利用しているドライバー(Windows 11 は対応しておらず古い)

ThinkPad Compact USB Keyboard with Trackpoint Driver (18.8 MB)

https://support.lenovo.com/jp/ja/solutions/pd026745-thinkpad-compact-usb-keyboard-with-trackpoint-overview-and-service-parts

このドライバーを導入すると、マウスのプロパティーに次の設定が追加されます。

ThinkPad 優先スクローリング機能はおそらく、ソフトウェアの中ボタン処理を無効にして、スクロールイベントを発生させる機能です。(中ボタンを押したときに、スクロールバーアイコンになれば機能しています)

この機能が特定のソフトウェアで動作した場合にダウンし(Visual Studio 2022 で確認)、スクロール機能が動かなくなるようです。

なお、ThinkPad 優先スクローリングを無効にすると、アプリ側のスクロールが効くので動くようになりますが、Microsoft Edge などが微妙な動きになります。

残念ながら対応する方法は分かりませんでしたが、以下の .exe を起動することで、OS の再起動をすることなく復帰は可能なようです。スタートメニューにピン止めしておくといいかもです。

“C:\Program Files (x86)\Lenovo\ThinkPad Compact Keyboard with TrackPoint driver\HScrollFun.exe”

Visual Studio 利用時は ThinkPad 優先スクロールのチェックを外すことにより対応。

古い製品なのでしょうがないですかね。。対応されたドライバーがでるといいのですが。いったんがまんして使うこととします。

追伸。同件を書かれている方がいらっしゃいました。Bluetooth 版でも発生するようです。 Visual Studio で起きるのも同じですね。。とほほ。

ThinkPad Bluetooth キーボードで縦・横スクロールが出来なくなった場合の対処法

トラックポイントとセンターボタンによる、縦および横スクロールが全くできない

UPDATE 2024-01 気分転換に新型トラックポイントキーボードII に買い替えたところ、該当の事象は発生しなくなりました。Windows 11 の場合は接続するだけでドライバ・ユーティリティも自動導入されるようです。快調。

Lenovo(レノボ)USB-C ThinkPad トラックポイント キーボード 89キー 日本語配列 4Y40X49522

4Y40X49522

Cubase で複数の YAMAHA Steinberg USB ASIO 機器がある場合にひとつしか表示されない

新規の Windows 11 に Cubase を導入していて分からなくなったので備忘録にて。

Windows に ASIO 機器を複数台接続した場合に、Cubase 上に選択したい機器のポートが表示されませんでした。

  • YAMAHA MODX7
  • YAHAMA AG06

いずれも YAMAHA Steinberg USB Driver にて管理。

Cubase のスタジオ設定より USB ASIO 項目からコントロールパネルを開き Device で使いたい機器を選択して OK ボタンを押下すると、その機器のポートがスタジオ設定に現れます。(ここが分からなかった)

接続機器を変更すると、オーディオコネクションが外れて発音しなくなるかもなので、Cubase -> スタジオ -> オーディオコネクションから再割当て。

ASIO コントロールパネルの Device 選択設定に Cubase が連動しているのに気がつくのに時間がかかりました。タブが ASIO として独立していることに納得。

以上です。(短い)

ついでにメモ。 opsix Native 単体起動時の ASIO と MIDI IN の設定は、右上ハンバーガメニューより「Sound Settings」から次の部分。

YAMAHA Steinberg USB ASIO は選択時にエラーになる場合があるけれど、がちゃがちゃしていると機器を見るけるようだメモ。

AssemblyScript で WebAssembly を知る

毎年恒例 ゆるWeb勉強会@札幌 Advent Calendar 2022 への投稿です…!

札幌で開催しているWeb系勉強会、「ゆるWeb勉強会@札幌」の2022年アドベントカレンダーです。

過去発表内容のまとめ、発表する機会の無かったネタ、勉強会に参加したいけどできなかったので、などなど、Webに関するキーワードを中心としつつ自由に書いていってください!

毎年 WebAssembly 関連を投稿させていただいておりますが、今年は WebAssembly が理解の手助けとなるような、入門記事を書いてみたいと思います。

AssemblyScript 言語

最初に WebAssembly のおおよそですが、 プログラムソースコードをビルドすることにより Wasm バイナリー(.wasm)を出力し、このファイルを WebAssembly ランタイムに読ませることでプログラムを動作させる技術です。

この記事で取り上げる AssemblyScript 言語は、TypeScript Like なソースコードを Wasm バイナリーにビルドできるコンパイラーです。npm で簡単にツールチェインが導入でき、また WebAssembly 専用の言語となっているため、端的に理解しやすく、入門にも最適だと感じます。

The AssemblyScript Book

AssemblyScript compiles a variant of TypeScript (opens new window) (a typed superset of JavaScript) to WebAssembly (opens new window) using Binaryen (opens new window), looking like:

WebAssembly ランタイムを持つ主要ユーザのひとつはウェブブラウザーで、モバイルを含む主要 4 ウェブブラウザーで .wasm を実行可能です。また、ウェブブラウザーから JavaScript ランタイムが node.js として取り出されたように、ウェブブラウザー外で .wasm を動かす動きも近年活発です。

なお、.wasm のビルドに対応しているプログラム言語は、大きく 2種類のパターンがあり、直接 .wasm にビルドするものと、言語のインタープリタ(ランタイム)を .wasm にして、ソースコード(もしくは中間コード)をそのまま与えて動作するものに分けられます。

前者の代表は、Rust、C/C++、TinyGo などなど、そして AssemblyScript もこの仲間です。

後者は、Python(Pyodide)、Ruby、.NET/C# などが該当します。つまり、これらのインタープリタやランタイムが C/C++ であるということに立脚すると、前者の方式で Wasm ビルドできればスクリプトファイルが実行できる、というイメージです。

というわけで、本記事では WebAssembly 自身の理解の手助けとなるよう、直接プログラムが .wasm となり、ランタイムとのインターフェースもシンプルで分かりやすい AssemblyScript を使って解説を進めていきます。

サンプルプログラム

AssemblyScript/WebAssembly を使って時計を描画するプログラムをつくってみました。

次のような要素が含まれています。

  • WebAssembly から直接画面描画をすることができないので、WebAssembly ランタイムから import した、指定した位置に「点」を描画する関数を呼び出し時計を描いている。
  • 上記のような特性を逆に利用すると、ランタイム環境に依存する処理が差し替えられるため、同一 WebAssembly プログラムを、ウェブブラウザーとマイコン(M5Stack) で動作させるマルチプラットフォームの例ともなっています。

ソースコード:

https://github.com/h1romas4/m5stack-core2-wasm3-as

M5Stack Core2 With Wasm3/AssemblyScript Demo

WebAssembly プログラムとランタイムのインターフェース

WebAssembly の上のプログラムはよく「計算しかできない」と言われます。これは Wasm がサンドボックスで動作し、その外側のリソースにアクセスできないためです。

外界との接続との唯一のインターフェースは、それぞれの関数の export/import と、メモリーのポインターです。

JavaScript からみた、.wasm は引数の型が不自由な関数が追加されているように見えます。

:ランタイムに関数を公開する AssemblyScript のソースコード:

– 引数の型が u32 という見慣れない型になっている。

export function clock(x: u32, y: u32, r: u32): void {
    analogClock = new AnalogClock(x, y, r);
}

export function tick(): void {
    if(analogClock != null) {
        analogClock.tick();
    }
}

:export function が入った AssemblyScript を .wasm にビルドしたアセンブリーが出力(抜粋):

– 引数が i32 という WebAssembly の型になっている。

  (export "clock" (func 16))
  (export "tick" (func 28))

  (func (;16;) (type 1) (param i32 i32 i32)
  (func (;28;) (type 2)

そしてこの関数は JavaScript から次のように呼び出すことができます。

.wasm をロードする JavaScript のソースコード:

instance.exports.wasm に定義された関数を取得できる。

async function loadWasm() {
    const response = await fetch(new URL('../dist/app.wasm', import.meta.url));
    const responseArrayBuffer = new Uint8Array(await response.arrayBuffer());
    const wasm_bytes = new Uint8Array(responseArrayBuffer).buffer;
    let module = await WebAssembly.compile(wasm_bytes);
    const instance = await WebAssembly.instantiate(module, {
        ...createImports()
    });
    wasmExports = instance.exports;
};

.wasm でエクスポートされた関数を JavaScript からコールするソースコード:

instance.exports にエクスポートされた関数の引数に number 型を渡している。

(async function() {
    await loadWasm();
    wasmExports.clock(160, 120, 120);
    setInterval(() => {
        wasmExports.tick();
        wasmExports.__collect() // clean up all garbage
    }, 500);
})();

ポイントは .wasm 関数の引数には i32, i64, f32, f64 といった WebAssembly で使える(数値)型しかとれないことです。 JavaScript のオブジェクトのようなものや、文字列、もちろん DOM などの WebIDL の型も(現在のところ)そのまま渡して処理はできません。

AssemblyScript inherits WebAssembly’s more specific integer, floating point and reference types:

逆もしかりで、.wasm 側から JavaScript の関数を呼び出す際もこれらの引数型しかとることができません。

:JavaScript の関数を import する AssemblyScript のコード:

export declare function draw_pixel(x: i32, y: i32, color: i32): void;

export declare function をビルドした .wasm のアセンブリー(抜粋):

  (type (;1;) (func (param i32 i32 i32)))
  (import "c3dev" "draw_pixel" (func (;0;) (type 1)))

:AssemblyScript に関数を公開する JavaScript のコード:

async function loadWasm() {
    // ..snip...
    const instance = await WebAssembly.instantiate(module, {
        ...createImports()
    });
    // ..snip...
};

function createImports() {
    let imports = [];
    // ..snip...
    imports['c3dev'] = {
        'draw_pixel': (x, y, color) => {
            canvasContext.fillStyle = convertRGB565toStyle(color);
            canvasContext.fillRect(x, y, 1, 1);
        },
    // ..snip...
}

.wasm 側で import した i32 という数値型 を持つ draw_pixel 関数を呼び出し、最終的に ウェブブラウザーの Canvas に指定座標にひとつ点を描いています。マイコン動作ではこの部分が LCD に点をひとつ描く C の関数が呼び出すようにしています。

(ちなみに、点が描ければ円も線も計算で描けるということで、サンプルプログラムの時計は AssemblyScript の演算処理により全て点だけで描画を行っています)

インターフェースをつくる

以上のように、WebAssembly でプログラムをかく場合は、WebAssembly ランタイムをホストしている環境との連携インターフェースの設計が肝で、特性を考慮して、どのような処理単位にすると効率的に処理できるのかを考えていきます。

また、今回の例では用いていませんが、メモリーのポインター値を共有することで、VRAM や音声波形など大きな演算結果(配列)をインターフェースすることもでき、Wasm 内の演算結果を外部に持ち出すことができます。

このようなホストへのインターフェースの標準化の実装のひとつとして WASI があり、システム時間や乱数シード、ファイルシステムやネットワークへのアクセスが規定されています。(ただしウェブブラウザーには WASI API は実装されていません)

WASI も WebAssembly 型の関数が沢山あるだけですので、覗いてみると理解しやすいかと思います。

また、Rust の wasm-pack(wasm-bindgen) や Emscripten(C/C++) など他の WebAssembly ツールチェインは、Wasm 型との引数合わせやラップ、JavaScript の呼び出しをソースコードジェネレートなどを、自動でやってくれるものとして捉えると考えやすいです。

WebAssembly のインターフェースを知ることで周辺技術が何をしているのかが見えてきそうだな、ということで本記事は書かれました。

処理を速くしたい部分や、JavaScript 外で便利なライブラリー、、圧縮展開、画像動画音声処理、言語解析器などなどを見つけたら、「WebAssembly(型) なインターフェース」を追加して呼び出す。まずは WebAssembly の実用的なユースケースのひとつと思いますので、ぜひお試しください。

関連