a32f553a54.devEN

9年間誰も気づいてなかった Windows で PointerEvent.twist が179度までしか取得できないとかいう Chromium のバグを直した

今年(2026年)の5月に Wacom Art Pen 2 が発売されましたね。初代 Art Pen が生産終了となり長らくペンの回転に対応してるデバイスが Apple Pencil Pro ぐらいの状況で、もうWacomはペンの回転を見捨てたのか…と思っていましたが、Art Pen 2 となって大復活を遂げました。

しかし喜び勇んで買ってChromeで試したはいいものの、肝心の PointerEvent.twist が0~179度までしか取得できないという悲しい状態だったので泣く泣くChromium本体を修正することにしました。

修正したコード

ui/views/win/pen_event_processor.cc に以下のようなコードがありました。

int rotation_angle = static_cast<int>(pointer_pen_info.rotation) % 180;
if (rotation_angle < 0) {
  rotation_angle += 180;
}

pointer_pen_info が Windows の POINTER_PEN_INFO です。

ここから PointerEvent.twist の値を取得しているのですが、何故か180で割った余りを取っていたので、rotation をそのまま使うように修正しました。

int rotation_angle = static_cast<int>(pointer_pen_info.rotation) % 180;
int rotation_angle = static_cast<int>(pointer_pen_info.rotation);
if (rotation_angle < 0) {
  rotation_angle += 180;
}

バグが発生した経緯

Chromium には PointerDetails という構造体とWeb標準の TouchEvent とは別に内部用の ui::TouchEvent というクラスがあります。

PointerDetails は筆圧やペンの傾きなどのペンやタッチ固有の情報を保持する構造体です。この PointerDetails が twist を持っているのですが、これとは別に ui::TouchEvent は rotation というプロパティを持っていました。この rotation の範囲は0~179度で、ui::TouchEvent に rotation を渡すときに180で割った余りを渡していました。

twist と rotation の両方を持っていることになりますが、2つ持ってる意味はないので rotation は twist から導出するようにリファクタされました。rotation を削除する際に、本来 rotation 用だった180で割った余りを使う処理を PointerDetails の twist に対して行うようになりました。

これだけならタッチだけの話で問題なさそうなんですが、Chromium はペンの接触中は内部処理に ui::TouchEvent を使っています。この関係でペンの方も巻き込まれて値が制限されてしまい、9年間誰も気づくことなく今日まで至る…という経緯のようです。

感想

ということで初めて Chromium にコントリビュートをしました。大したバグじゃなかったのもありますが思ったより簡単でしたね。他にもポインター関連のバグを見つけてるので隙を見てやりたいです。

このバグを見つけたのが今年(2026年)の5月に Art Pen 2 を買ってブラウザで試したときでした。そのときは Art Pen 2 も出たことだし誰か直すやろと思って特に何もしてなかったのですが、数ヶ月経っても誰も直さないどころかissueすら立たずで経緯を深堀っていったらそもそも9年間ずっとバグってたことが判明しました。

9年前の時点だと初代 Art Pen が生産終了になる前でまだ入手できたはずで、それでも9年間ずっとバグっててかつ issue も立てられてなかったということはどうやら PointerEvent.twist を真面目に使おうとしてるのはこの地球上で私だけということらしいです。南~無~

リンク