AutoHotKeyでThinkPad Bluetooth ワイヤレス・トラックポイント・キーボードのPgUp/PgDn誤爆を防ぐ

ThinkPad Bluetooth ワイヤレス・トラックポイント・キーボードは、現存するテンキーレス薄型キーボードの中で最もすばらしい打鍵感を与えてくれる逸品であることに疑いの余地はないことと思うが、どうも最近のLenovoはキー配置を変態的にするのにご執心らしく、その完璧な工業製品の価値を損なわせていて実にもったいない話だと思う。

気に入らない部分はいろいろ*1あるが、自分が特に致命的に思うのはカーソルキーの横に移動されたPgUp/PgDnキーで、左右キーを押したつもりで誤ってPgUp/PgDnを押してしまい発狂したことは数知れない*2

そこで下記のようなAHKスクリプトを書いてひとまずの心の平穏を得た。

+PgDn::
  Send,{PgDn}
  Exit

+PgUp::
  Send,{PgUp}
  Exit

PgDn::Right
PgUp::Left

これにより、(左キーの真上にある)PgUpキーを誤って押した際は左キーに、(右キーの真上にある)PgDnは右キーに変換される。PgUp/PgDnしたいときは、Shiftを押しながらPgUp/PgDnキーを押せばよい。

デザインは今のモデルが最高なので、キー配列だけ7列時代のものに戻してくれないかな……。





Bluetooth版はOS設定で省電力を切ると、いちいちスリープしなくて使いやすくなるらしい。

会社はBluetoothが禁止されてるので、USB版を使ってる。

2014/10/22追記

Shiftとの組み合わせだと、Excel等で文字編集をしている際に誤爆することがままあったので、右Ctrlとの組み合わせに変えた。AHKスクリプトは下記の通り。

RCtrl & PgDn::
  Send,{PgDn}
  Exit

RCtrl & PgUp::
  Send,{PgUp}
  Exit

PgDn::Right
PgUp::Left

*1:ファンクションキーの区切りがなく左寄せされているため、従来のThinkpadキーボードと位置関係が変わっている点や、CtrlキーとFnキーを入れ替えられない点、HomeキーとかEndキーがファンクションキーと同列に押し込められ、ワケわかんない一に似どうしている点など

*2:個人的にはカーソルキーのキートップ形状がフラットに変更された影響も大きいと思う。カーソルキーは従来のように盛り上げておいて、PgUp/PgDnのみフラット形状としていれば押す前に気づけるのに……

一つのFormから複数のModelAttributeを受け取る場合に、バリデーションエラーが400エラーになってしまうのを回避する

最近Spring Frameworkを触っているのだけど、バリデーション時の不可思議な挙動で2時間くらいハマったのでメモ。Spring Boot固有の問題かもしれない(そこまでは調べてない)。

掲題の通り、一つのFormに複数のModelAttributeを割り当て、リクエスト値をアクションメソッドの@Validated @ModelAttributeな引数でバインドして受け取るとき、いずれかのModelAttributeでバリデーションエラーが発生するとなぜか400エラーとなってしまい、アクションメソッドの処理に入らずエラーページに飛ばされてしまう。

400エラー(Spring Boot使用時のため、Whitelabelエラーページに飛ばされる):

There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='model1'. Error count: 1

これを回避し、期待する動作(アクションメソッド内でBindingResult#hasErrors()を使用してバリデーションエラー時の処理を行う)をさせるには、ModelAttribute引数ごとに、個別のBindingResult引数を設定する。

つまり、下記のように、model1、model2それぞれの直後にBindingResult引数を配置する。

Controller:

@RequestMapping(value = "/hoge", method = RequestMethod.POST)
public ModelAndView newStoryComplete(
  @Validated @ModelAttribute("model1") Model1 model1,
  BindingResult result1,
  @Validated @ModelAttribute("model2") Model2 model2,
  BindingResult result2
) {

  if (result1.hasErrors() || result2.hasErrors()) {
    // エラー時処理

View (Thymeleaf):

<form action="#" th:action="@{/hoge}" method="post">
  <div>Param1: <input type="text" th:field="${model1.param1}" /><span th:errors="${model1.param1}"></span></div>
  <div>Param2: <input type="text" th:field="${model2.param2}" /><span th:errors="${model2.param2}"></span></div>
  <button type="submit">Send</button>
</form>

これで400エラーは発生せず、アクションメソッド内に入ってくれるようになる。

下記参考記事が大きなヒントになった。そろそろSpringのソースを追うしかないかな……とあきらめかけていたところだったので本当に救われた。

@ModelAttributeとBindingResultの順序を正しく設定しないとリクエストがマッピングされない件 – Springバッドノウハウ | Developers.IO

ちなみに、一つのFormに複数のModelAttributeを割り当てるのがいいことなのかは知らない。一般的なお作法では、Commandクラス(もしくはFormオブジェクト)と呼ぶPOJO1フォームごとに作って1対1にするみたいなのだけど……。値の詰め直しとか、バリデーションの定義がCommandクラスごとに散らばる(重複する)可能性とか率直に面倒と思うが、そういうものなんですかね。そもそもJSPの場合、で指定するから必然的に一つになってしまうという事情もありそうだが……。

環境

  • JDK 1.7.0_21
  • Spring MVC 4.0.7
  • Spring Boot 1.1.7
  • Thymeleaf 2.1.3

Google Chrome 37でウェイト名付きフォント名を指定できなくなったぽい

Windows 8 Pro 64bit版環境下での話なのですが。

@font-faceを使用してウェイト別に異なるフォントを割り当てる (太字に別フォントとか) - ymknの日記のようにして、太字の文字が引き延ばしのBoldではなく適切なウェイトの書体で描画されるようにしていたのだけど、Chrome 37からこれが効かなくなった。

ユーザスタイルに限った話ではなくて、Chrome本体のフォント設定でも、ウェイト名付きで表示されているフォント(M+とか)が効かなくなっている(リストから選んでも前の書体から変更されない)。

これって仕様変更なのかなあ。適当にChromeChromiumのリリースノートを見てみたけど、それっぽい記載は無いし・・。

2014/09/03追記:

直ったぽい。従来通りウェイト名付きで表示されているフォントも効くようになった。

Chromeのバージョンは37.0.2062.102 unknown-m (64-bit)。日本語グリフの描画周りに問題があって修正されたようなので、それがらみなのかも。

PHP 5.3 バージョンアップ対応の記録

最近すっかり完全放置状態の自サービス創作小説投稿コミュニティー - ぱろしょだが、サーバーホスティング元にてソフトウェアの一斉バージョンアップメンテナンスが行われるとのことで、影響確認テストを行った。

  • 最新版のXAMPP導入。PHPApacheのみ使用。MySQLはバージョンアップなしなので、別環境にある既存のMySQLを使用。
  • 本番データのバックアップをMySQLに投入して、各機能打鍵確認
  • (ついで)全ファイルの文字コードと改行コードを再確認し、統一した。従来はFTP時に変換をしていたが、変換忘れたりすると面倒なので。今後はバイナリ転送一本である

現新の環境はまとめるとこんな感じ。

環境 PHP Apache MySQL
現行 5.2.x 1.3 5.1.22
検証環境*1 5.5.11 2.4.9 5.1.73
新環境 5.3.x 2.4.9 5.1.73

検証環境のバージョンがやたら高いが、個別に用意するのが面倒なのと、PHP: PHP 5.4.x における変更点PHP: PHP 5.5.x における変更点を見た感じ、5.3から5.5の間に戻された仕様はなさそうなのでまあいいかと判断。でもさすがにノーチェックは怖いので、無影響確認のつもりで全画面一通り打鍵した。

で、下記のような問題を発見。対処した。

  • ereg系正規表現をpregに変更(ereg系は5.3.0で非推奨。警告出力される)
  • strlen関数に配列が渡された場合の仕様変更(従来は配列が渡ると文字列"Array"が渡されたものとして動作)により、自作関数の挙動に影響が出た。従来の仕様と同じになるようコードを修正
  • PHP開始タグが「<?」であるものを「<?php」に修正

最後のものはPHP 5.3とは関係なくphp.iniの設定の問題だが、個人的にはもとより<?phpで統一していたつもりだっただけに発見したときは驚いた。n年越しの潜在バグというやつだ。動作しているPHPファイルをそのまま食わせただけなのに構文エラーとなり、発見に苦労した。括弧の数があっているか追うために<?でソースを検索していたときに偶然見つけたのだ。いやはや。

これでとりあえずは安心と思っているが、バージョンアップから数日はチェックが必要かな。仕事が立て込んでいるので、何かあったら睡眠時間を削る羽目になる可能性が高い。ホント、ソフトウェアのバージョンアップ問題は頭が痛い。

*1:XAMPP 1.8.3

Policy-based QoS requires enabling QoS packet scheduler in network adapeter's property

Windows Server 2003以降で使用できるポリシーベースのQoSによるネットワーク通信の優先制御や帯域制御は、対象の通信に使用するネットワークアダプタのプロパティで「QoSパケットスケジューラ」が有効でないと機能しない。

ポリシーは確かに適用されているのにQoSが効かず大変悩んだのだが、原因がこれだった。直接的な警告もエラーも出ないため突き止めるのに大変苦労した。

なお、ポリシーベースのQoSを使用するためにQoSパケットスケジューラが必要な旨は下記参考サイトにて言及があるが、Windows Server 2003向けの部分に記載されていたため読み飛ばしていたのだった。

参考:The Cable Guy: Windows での QoS のサポート

どなたかの参考になれば幸いです。

リビングのBGM用に余ってたiPod(iPhone)とBluetoothスピーカーでネットラジオ環境作った

カフェ風(笑)なリビング空間を演出するために、iPod Touchを使ってTuneIn Radio(ほぼSKY.FMしか聞いてないけど)でネットラジオを流すなんてことをよくやるのだけど、出力に使っているのがただのMDコンポ(CD部故障)なので、iPod TouchからAUX INにステレオケーブル直刺しとかやってて、さらに充電用にUSBケーブル+USB-ACアダプタなんかも必要でケーブルだらけであり、見た目的に美しくなかった。

で、嫁さんから買い換え許可が下りたこともあり、MDコンポをBluetoothスピーカーにリプレースした。いろいろ調べた結果買ったのはP9|フィリップス Fidelio ワイヤレスポータブルスピーカーホワイト

フィリップス Fidelio P9 Bluetoothスピーカー ブラック P9BLK

フィリップス Fidelio P9 Bluetoothスピーカー ブラック P9BLK

これを選んだポイントは、↓な感じ。

  • 我が家のリビングにマッチする白色系のデザイン(白系はレア。AV製品って黒色系ばかり)
  • 大きすぎず、小さすぎず。棚の上に置くのに丁度いいサイズ(287(W) × 55(D) × 125(H)mm)
  • Bluetooth対応(iPod Touchとの接続ケーブルが不要に!)
  • 外部機器充電用のUSBポートあり(iPod Touch充電用のUSB-ACアダプタが不要に!)
  • そこそこに良い音が鳴る(らしい。レビューとかによれば)
  • 使用後はカバーを閉じれば電源が切れて良い

iPod用のDockがあるものを選ぼうか迷ったのだけど、Appleが規格を変えると無駄になるし、デザイン的に微妙なので、汎用的に使えるBluetoothを選んだ。スマホとかもつなげられるしね。

で、こんな感じになりました。すっきりおしゃれ。

f:id:ymkn:20140330101338j:plain

比較用の写真はないのでどれくらいすっきりしたのかはわかりづらいね。とり忘れたのだ。

その手前にある細長い白いのはApple Remote(初代)。iPodが挿さっているUniversal Dockとペアリング済み。離れたところから操作と言うより、普段はDockの目の前に置いて使ってる。Dockに挿したまま画面をタッチ操作するのが案外大変なので、Remoteのボタンをポチポチして再生/停止してる。便利。

あと、不満点とか。まあ、些細なポイントではある。

  • Fidelio P9の電源ONが長押しで微妙にめんどい
  • 再生停止状態で放っておくとFidelio P9の電源が切れるので、また聞きたいときは電源ボタンを押しに行かないといけない
  • USB給電はAC接続時のみ有効なため、この構成だと事実上AC常時接続が必要(内蔵バッテリーが劣化しそう)
  • Sky.fmがブチブチ切れる。プレミアム契約しろと言うことか・・


まあ、おすすめです。

ODBCのトレースログの出力はユーザ別かコンピュータ全体かに関わらず常にユーザ別

これに気づかずハマリにはまったのでメモ。

[すべてのユーザー ID のコンピューター全体のトレース]にチェックを入れれば[ログ ファイルのパス]に指定したファイルに全てのユーザのトレースログが出力されると思い込んでいたのですが、どうやら常にユーザ別のパスに出力されるらしい。

f:id:ymkn:20140224012532p:plain

どういうことかというと、ODBCを使ってDBアクセスを行うサービスservice_aをhoge_userというユーザで実行しているときに、メンテナンス用ユーザfuga_userでservice_aのODBCのトレースログを取得しようとして、fuga_userでODBC アドミニストレータを起動して上記画面の[すべてのユーザー ID のコンピューター全体のトレース]にチェックを入れ[トレースの開始]を押下しても、
[ログ ファイルのパス]に一切トレースが出力されない、という話。

どこにログが出ているのかというと、serivce_aを動かしているhoge_userの[ログ ファイルのパス]に指定された場所である。なんてこった。

[ログ ファイルのパス]は通常%TEMP%¥<数字>¥SQL.LOGとなっているので、そこを見に行けば良い。管理上場所を変更したい場合は、hoge_userでログインしてODBC アドミニストレータを起動し、[ログ ファイルのパス]を変更すれば良い。

hoge_userでログインできないときは・・

やっかいなのはhoge_userがサービス実行専用に設計されていて、デスクトップログインを許可していない場合。ODBCアドミニストレータの設定の実体は下記レジストリキーにある。

ユーザ別な設定: HKEY_CURRENT_USER\Software\ODBC\
グローバルな設定: HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\

[ログ ファイルのパス]はユーザ個別の設定なので、HEKY_CURRENT_USERのほうにある。ただ、HEKY_CURRENT_USERは現在ログイン中のユーザのレジストリである。今回修正したいのはログインできないhoge_userのもの。HEKY_USERSからhoge_userのツリーを探す必要があるが、面倒なことにユーザ名ではなくSIDでツリーが分けられている。つまり、hoge_userのSIDを調べる必要がある。

下記サイトのようにして、HKEY_LOCAL_MACHINE以下のキーから各ユーザのSIDを推測し、目的の値を修正すれば良い。

参考:レジストリキーのSIDからユーザアカウントを識別する方法 | Tipstour