クリップボード共有デーモン。 Java で書くと言ったものの、 なぜか Java で書いたもの以外のアプリケーションと 同期してくれないので仕方なく Ruby で書くことにした。 Windows 側も最初の目論見通り C# でいってみよう。
とか言ってると結局全部の言語で書くことになったりする。
Ruby の TCPSocket と X イベントを同時に待つために
rb_thread_wait_fd(ConnectionNumber(display));
としてみたが、一瞬で終わってしまう。なぜだ……。
とりあえず諦めた (早っ)。
むがー! なんで生の select ではうまくいくんだあーっ!
あー! わかたー! シングルスレッドだからだ! シングルスレッドだから rb_thread_schedule がすぐ戻るんだ! くそう、そういえばこれは自分で RHG に書いたような気がする……
肝心のデーモン作りに着手した。 即座に謎の同期バグに遭遇。
プログラムの最初で stdout をフラッシュしとくと動く。 消すとブロックする。 print しても動いてしまうのでデバッグできない。
ちなみに肝心の内容はこれだけっす。
def main .... require 'clipshare/xclipboard' x_main end def x_main $defout.flush # I don't know why this statement is needed. content = ClipShare::XClipboard.get_string while true ClipShare::XClipboard.put_string content content = ClipShare::XClipboard.get_string puts "owner changed; content=#{content.inspect}" end end main
put_string は selection オーナーでなくなるまでブロックするので、 put_string が終わったら別のアプリケーションがオーナーになったということ。 そうしたら即座にクリップボードの中身をそっくり奪って自分がオーナーに復帰する。 puts してるとこで TCPSocket 使ってオーナー宣言してやれば完成〜。
とりあえず動いているようだ。
甘かった。クリップボードインターフェイスなんかより、 複数ホスト間で同期をとるほうがずっと難しいじゃないか。 かなり慎重に伝達経路をチェックしないとあっさり無限ループになるな。
とりあえず Linux(Ruby) → Windows(Ruby+C#) の push 実験は成功した。
To do
Windows 側は完全 C# 化した。 あとはクリップボードの内容変更を検出することだけど、 これはポーリングしてみるしかないのかな。 COM に触るとできたりするんだろうか。 ま、とりあえずはポーリングでいいか。 富豪で行こう。
そういえばプログラム初心者のころ、 polling と言われるとどうしても 温泉を掘るボーリングを思い浮かべてしまって困りました。 今でも poll(2) を見ると地盤に杭を打ちこんで ファイルディスクリプタを調べている様がありありと脳内に投射されます。
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
daveさんの Xselection が役に立つかも。
http://www.yasgursfarm.us/rdic/xselection.html.ja
いま書いたやつとほとんど同じでした……。がくり。