2
2

More than 5 years have passed since last update.

Clojureでキーボード操作をエミュレートする

Last updated at Posted at 2015-04-18

Clojureでキーボード操作をエミュレートするにはjava.awt.Robotを使えばできます。
awtbotというjava.awt.Robotをラップしたライブラリもありますが、基本的な関数しかないのでもっと簡単に使える関数を作ってみます。

robot.clj
(ns robot.sample
  (:import [java.awt Robot]
           [java.awt.event KeyEvent]
           [javax.swing KeyStroke]))

(defn static-fields [^Class class fields]
  (map #(load-string (str (.getName class) "/" %)) fields))

(defn modifiers->vks [modifiers]
  (->> (map #(when (pos? (bit-and modifiers %1)) %2)
            (static-fields KeyEvent '[SHIFT_DOWN_MASK CTRL_DOWN_MASK ALT_DOWN_MASK ALT_GRAPH_DOWN_MASK META_DOWN_MASK])
            (static-fields KeyEvent '[VK_SHIFT VK_CONTROL VK_ALT VK_ALT_GRAPH VK_META]))
       (filter identity)))

(defn stroke->vks [^String stroke]
  (let [^KeyStroke ks (KeyStroke/getKeyStroke stroke)
        vks (modifiers->vks (.getModifiers ks))]
    (concat vks [(.getKeyCode ks)])))

(def ^:dynamic *sleep-time* 100)
(defn emulate-stroke [^Robot robot ^String stroke]
  (Thread/sleep *sleep-time*)
  (let [vks (stroke->vks stroke)]
    (doseq [vk vks]
      (.keyPress robot vk))
    (doseq [vk (reverse vks)]
      (.keyRelease robot vk))))

(defn emulate-strokes [^Robot robot & strokes]
  (doseq [stroke strokes]
    (emulate-stroke robot stroke)))

これを以下のように使います。
キーの文字列はjavax.swing KeyStroke/getKeyStrokeで指定できるものが使えます。

use_robot.clj
(def bot (Robot.))
(emulate-strokes bot "P" "shift T" "B" "shift A" "TAB")

ctrlとshiftを同時押しするキーの場合、環境によってはNumLockが有効だとshiftが有効にならないという問題があるようです。
また、java.awt.ToolkitのsetLockingKeyStateやgetLockingKeyStateでNUM_LOCKの状態の設定と参照ができそうですが、バグっててうまく働かないようです。残念

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2