JavaFXの非矩形ウィンドウにおけるWindowsとMacでのマウスイベントの違い

しばらく blog を書いていなかったので先日気がついた小ネタでも書きます。

かなり昔に JavaFX で xeyes のクローンを作ってみた話 を書いたことがあったのですが、最近あれをイチから作り直してみました。コードも GitHub にアップしています。 *1

github.com

以前のブログエントリからは次のようにかなり作りが変わっています。

  • 以前は Mac 上で Swing の EDT を実行すると HeadlessException が飛ぶ問題があり、仕方なく Swing を土台として作っていたのですが、現在はこの問題は解消されているので、JavaFX を土台としたものに変更しています。
    • 唯一、グローバルなマウスカーソルのアドレスを取得するのに AWT に頼っていますが、JavaFX 11 で待望の Robot クラスが追加されるので、11 になれば "Pure JavaFX" なアプリケーションにできる見込みです。
  • マウスカーソルの座標を取得するタイミングを以前は Swing の Timer で起こしていたのですが、これを JavaFXAnimationTimer を利用するように変更し、より滑らかに目玉が動くようになっています。
  • Stage のスタイルを StageStyle.TRANSPARENT に変更し、本家 xeyes のように背景を透過するようにしました。

f:id:aoe-tk:20180825210949p:plain

最後のポイントに書いたように、Stage のスタイルを StageStyle.TRANSPARENT に変更したため、ウィンドウのタイトルバーやウィンドウ枠がなくなるため、ウィンドウの移動やリサイズを自力で実装する必要があります。

その際に気が付いたことがありました。リサイズや移動が可能であることをが分かるように、アプリケーション上でのマウスカーソルの位置によってマウスカーソルの形状を変えるようにしました。ところが Windows 上で動かした場合と Mac 上で動かした場合に次のような違いが見られたのです。

  • Mac 上で動かした場合、マウスカーソルが (透明になっている) ウィンドウの端や隅に到達してもちゃんとカーソル形状が変わる。
  • Windows 上で動かした場合、「目」の上でしかマウスカーソルの形状が変更しない。
    • と言うか、マウスイベントが全て「目」の上でしか発生しない。

この動きの違いに悩んで色々調べてみたのですが、どうも JavaFX 側の考え方としては Windows 版の動きが正 のようです。Mac 版の動きについて次のようなバグチケットが作られていました。

https://bugs.openjdk.java.net/browse/JDK-8088104

まあ考えてみれば理屈は分かります。非矩形に作ったのにマウスが矩形に沿って反応するのは確かに不自然です。自分が作ったこの xeyes については Windows 版ではウィンドウの四隅からリサイズが行えないという不便な点がありますが、縦方向と横方向のリサイズは可能なので、まあこれでいっかーとそのままにしましたw

というわけで小ネタでした。

*1:完全に自分用に作ったので IntelliJ 形式のプロジェクトそのままでアップしてます。まあ特殊なライブラリは一切使っていないので、他の IDE やエディタでも普通に扱えるはずです。