[Anthy-dev 2390] Re: IM切り替え時のプリエディット消去について

Back to archive index

YamaKen yamak****@bp*****
2005年 9月 16日 (金) 20:57:28 JST


ヤマケンです。こんばんは。

At Mon, 12 Sep 2005 15:22:43 +0900,
ekato****@ees***** wrote:
> On Sun, Sep 11, 2005 at 11:09:14PM +0900,
> YamaKen <yamak****@bp*****> wrote:
> 徳永さんも uim @ fdo でおっしゃっていましたが、reset に関して議論してい
> る場合におこる解釈の違いは、reset という概念に、input spot の変化を含
> むかそうでないかということだと思います。ぼくや、おそらく、James Su さ
> んは、gtk+ が gtk_im_context_reset() を input spot の変化に使うことを
> 前提にした話に基づいているので、ヤマケンとの解釈に違いがでているという
> ことだと思います。
> 
> http://developer.gnome.org/doc/API/2.0/gtk/GtkIMContext.html#gtk-im-context-reset
> 
> Notify the input method that a change such as a change in cursor
> position has been made. This will typically cause the input method to
> clear the preedit state.
> 
> もちろん、gtk_im_context_reset() が「本当の reset」 について呼ばれるの
> であれば絶対にコミットすべきでないに同意します。ただ現状はそうでは
> ないわけで、commit もありうる (Korean input method のように) というこ
> とでした。

なるほど。やっと話が噛み合わない原因が理解できました。

"reset"という名前を保持しつつ別の機能が期待されていたわけですね。

私はずっと「本物のreset」の仕様について語ってきたつもりで、GTK+ 
側も"reset"という名前を付けている以上、名実不一致な現状はバグだ
という発想しかできませんでした。
#まあほとんどの言語では(カーソル移動通知 == reset)で済むので区別
#が無いのもしょうがないんですが。

現状のGTK+が"reset"という名前でカーソル移動を通知しているとして
もuimがそれに従う必要はないので、私としてはuim側では本物のreset
とカーソル移動通知は分離すべきと考えます。

> ただし、init 時以外に「本当の reset」というものがどういった状況で呼ば
> れるのかは、想像できませんでした。

少なくともQtは「本物のreset」を必要としています。

うろ憶えなんですが、text widgetに対するpaste等の操作を行うのに先
立ってwidget内部のpreeditをクリアした上でIMのresetを発行し、新規
テキスト挿入可能な内部状態になっている事を仮定するからです。
resetをトリガとしてIMからpreedit eventが飛んでくるのはコード的に
illegalだったはずです。

以下、せっかくなので本物のresetについての意見です。「本物の」
resetについてなら加藤さんも同様に考えていると認識してますが、一
応確認お願いします。


各IMのresetハンドラでプリエディットのクリアを行う事にすると本物
のreset発行時には以下のようなresetの行き/帰りが発生しwidgetの
preeditが二重にクリアされる事になりますが、w->reset()に対する
w.peのクリアがuim-fooからのプリエディット更新指示によってなされ
るのは責任の所在の観点からおかしいと思います。

w->reset()発行の時点でプリエディットのクリアが目的である事は自明
なのだから、行きの経路上でそれぞれの要素が責任を持って各自の保持
するプリエディットのクリアを行うべきで、GTK+のようにwidget自体が
プリエディットのクリアを行わない場合にはbridgeがそれを吸収すべき
というのが私の主張です。

uim-fooのresetハンドラにその責任を移譲するという事はプリエディッ
トのクリアを行なう/行わないという選択権をuim-fooに与えるという事
ですが、それが正しい設計だとは思えません。

もちろん「本物のreset」ではないカーソル移動通知としてのresetに対
しては適切な対処が必要でしょう。しかしそういったクライアント毎の
事情はbridgeで隠蔽し、libuim以下はあくまで本物のresetやカーソル
移動通知のみを扱うべきだと思います。


行き:
 application
     |
     |  w->paste(str)
     v
  toolkit
     |
     |  w->reset()
     v
   widget     w.pe = ""
     |
     |  ic->reset()
     v
  UimContext (bridge)
     |
     |  uim_reset_context()
     v
  libuim
     |
     |  (reset-handler)
     v
  uim-foo     (uim-foo-set-preedit! ic ())


帰り:
 application
     ^
     |
     |
  toolkit
     ^
     |  (notify invalidated)
     |
   widget     w.pe = ""  (duplicated clear)
     ^
     |  PreeditEvent("")
     |
  UimContext (bridge)  pe.clear(), pe.push("")
     ^
     |  preedit_clear_cb(), preedit_pushback_cb(), preedit_update_cb()
     |
  libuim               im_clear_preedit(), im_update_preedit(),
     ^                 uim_release_preedit_segments()
     |
     |    (im-clear-preedit ic)
     |    (im-update-preedit ic)
  uim-foo


> > commit/focusまわりについては私は以下のような見解を持っていますが、
> > この件については必要になった時点でuim @ fdoで別途議論する方がよい
> > でしょう。
> > 
> > ・toolkit/applicationはfocus移動時にresetを発行すべきでない
> 
> この focus 移動というのがまた問題です。uim @ fdo の議論でもありましたが、
> focus in, focus out, input spot change の三種類あると思います。ぼくも
> focus_in, focus_out では reset は発行すべきでは無いと思いますが、input
> spot の変化では、現状のように gtk_im_context_reset() が発行されるのは
> 良いと思います。

実はinput spot changeの問題は失念してしまってたんですが、確かに
focus移動とは区別する必要がありますね。

前述のようにuim内ではresetという名のもとにinput spot changeに相
当するハンドリングを行うのには反対なので、今入れたいという話なら
uim @ fdoに議論を移しましょう。私の方でも考えてみましたが、もっと
細分化する必要があるように思います。

> > ・focus移動イベントはIMに通知されるべき(現時点のuimには欠けてい
> >   る)
> > ・focus移動時には、IMが必要とするならresetしてよい(この場合プリ
> >   エディットのクリアはIMが行う)
> > ・focus移動時には、IMが必要とするならcommitしてよい
> > ・bridgeやtoolkit/application層では、いかなる場合においてもプリ
> >   エディット文字列の自動commitを行うべきではない。それは各IMの責
> >   任
> 
> はい。いいと思います。現状は、focus_in, focus_out, reset を bridge が
> application/toolkit から通知されているわけで、reset 以外に、focus_in,
> focus_out も IM に通知すればいいと思います。それに加え、「本当の reset」
> を処理も必要になると思います。もちろん、現在の reset という名前を変
> えるのはいいと思います。
> 
> ヤマケンさんの以前の話では、bridge 側が commit するという方向でしたの
> で違和感を感じましたが、今回の IM 側が責任を持つ (commit し得る) とい
> う話は問題ありません。

最初に私が主張してたのは「本物のreset」の際にはプリエディットの
*update* (commitもですが)は許されず、toolkit側がプリエディットの
自動クリア(update)を行わないならbridgeが補完するべきという話で、
それは変わってません。focus/カーソル移動時のupdate/commitとは別
の話です。

At Wed, 24 Aug 2005 22:30:12 +0900,
yamak****@bp***** wrote:
> 次に、(im-update-preedit ac)は各ブリッジが実行すべきです。各IMの
> resetハンドラ内ではこれを *呼んではいけません(must not)*。ちゃん
> と仕様を書いておかなかったので後出しで申し訳ないんですが、以下の
> ような理由によります。
> 
> uimレベルでのreset操作は、uim_reset_context()を呼び出す事によっ
> て行われますが、
> 
> 例えばQtではtext widgetがresetされると、IMコンテキストをresetす
> ると共に、toolkit側でプリエディットをクリアします。IM resetはそ
> のtext widgetで各種編集操作(paste, undo等だったと記憶しています) 
> を行うのに先立って呼ばれる場合があり、IMコンテキストはreset後は
> それらの操作を妨げない初期状態になっている事が仮定されています。
> 
> Qt3ではtoolkit側でwidget毎にIM入力状態のステートマシンを持ってお
> り、update-preeditを呼ぶためにはIMStartイベントを受けて入力可能
> 状態に遷移している必要があります。このため、reset時に
> update-preeditを呼ぶという事は、たとえ空文字列のプリエディットで
> あっても入力可能状態への遷移を引き起こしてしまいます(すいません
> がうろ憶えです)。
> 
> 以上はQtの例ですが、Qtの事情で特別な考慮をしろと言っているわけで
> はなく、論理的に考えてreset時のプリエディット消去を各IMが行うの
> はresponsibility separationの観点からおかしい(layer violation)と
> いう事です。

-------------------------------
ヤマケン yamak****@bp*****



Anthy-dev メーリングリストの案内
Back to archive index