カウンター
- 197,840 アクセス
ちょっとした文章とかメモ書きとか。
Wineのペンタブレットのサポートの状況はこちら→http://wiki.winehq.org/TabletSupport
そのままではwintab32.dllとwinex11.drvが上手く働いていないようです。
wine 1.5.10まではWineの筆圧感知パッチにて解説されてます。
wine 1.5.11が8/17にリリースされたため、これでも有効にしてみます。
追記:wine 1.5.12が8/31にリリースされ、ppaに来たので追加しました。
パッチはtablet pressure sensitivity not working in Sai and many other key graphic applicationsから拾ってきました。wintab32.dll.soに当てるパッチは正常に当てられましたが、もうひとつのwinex11.drv.soに当てるパッチが当たらなかったので微修正しました。
以下、修正済みパッチ:
--- a/dlls/winex11.drv/wintab.c 2012-08-18 03:12:53.000000000 +0900 +++ b/dlls/winex11.drv/wintab.c.edited 2012-08-21 08:20:28.298200055 +0900 @@ -265,6 +265,7 @@ static int proximity_out_type; static HWND hwndTabletDefault; +static HWND gActiveOwner; static WTPACKET gMsgPacket; static DWORD gSerial; @@ -854,7 +855,8 @@ memset(&gMsgPacket,0,sizeof(WTPACKET)); - TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum); + TRACE("hwnd=%p, motion->deviceid=%d, cursornum=%d, gActiveOwner=%p\n", + hwnd, (int)motion->deviceid, curnum, gActiveOwner); /* Set cursor to inverted if cursor is the eraser */ gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0); @@ -870,7 +872,8 @@ * (gMsgPacket.pkStatus & TPS_INVERT?-1:1)); gMsgPacket.pkNormalPressure = motion->axis_data[2]; gMsgPacket.pkButtons = get_button_state(curnum); - SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd); + SendMessageW(hwndTabletDefault, WT_PACKET, gMsgPacket.pkSerialNumber, + (LPARAM)gActiveOwner); } static void button_event( HWND hwnd, XEvent *event ) @@ -883,7 +886,9 @@ memset(&gMsgPacket,0,sizeof(WTPACKET)); - TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release"); + TRACE("event->type=%s, hwnd=%p, gActiveOwner=%p\n", + (event->type == button_press_type)? "press":"release", + hwnd, gActiveOwner); /* Set cursor to inverted if cursor is the eraser */ gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0); @@ -899,15 +904,15 @@ * (gMsgPacket.pkStatus & TPS_INVERT?-1:1)); gMsgPacket.pkNormalPressure = button->axis_data[2]; gMsgPacket.pkButtons = get_button_state(curnum); - SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd); + SendMessageW(hwndTabletDefault, WT_PACKET, gMsgPacket.pkSerialNumber, + (LPARAM)gActiveOwner); } static void key_event( HWND hwnd, XEvent *event ) { - if (event->type == key_press_type) - FIXME("Received tablet key press event\n"); - else - FIXME("Received tablet key release event\n"); + FIXME("Stub! event->type=%s, hwnd=%p, gActiveOwner=%p\n", + (event->type == key_press_type)? "press":"release", hwnd, + gActiveOwner); } static void proximity_event( HWND hwnd, XEvent *event ) @@ -917,7 +922,8 @@ int curnum = cursor_from_device(proximity->deviceid, &cursor); LPARAM proximity_info; - TRACE("hwnd=%p\n", hwnd); + TRACE("event->type=%s, hwnd=%p, gActiveOwner=%p\n", + (event->type == proximity_out_type)? "out":"in", hwnd, gActiveOwner); if (curnum < 0) return; @@ -948,7 +954,25 @@ */ proximity_info = MAKELPARAM((event->type == proximity_in_type), (event->type == proximity_in_type) || (event->type == proximity_out_type)); - SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info); + SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)gActiveOwner, + proximity_info); +} + +/* Guaranteed closest x11 window for your hwnd */ +static Window X11DRV_get_x11_window_from_hwnd(HWND hwnd) +{ + Window win; + + if ((win = X11DRV_get_whole_window(hwnd))) {} + else if ((win = X11DRV_get_whole_window(GetAncestor(hwnd, GA_PARENT)))) {} + else if ((win = X11DRV_get_whole_window(GetAncestor(hwnd, GA_ROOTOWNER)))) {} + else if ((win = X11DRV_get_whole_window(GetAncestor(hwnd, GA_ROOT)))) {} + /* this should always work */ + else if ((win = X11DRV_get_whole_window(GetDesktopWindow()))) {} + /* shouldn't ever get here */ + else { ERR("Couldn't find X11 window!\n"); } + + return win; } /*********************************************************************** @@ -964,12 +988,15 @@ XDeviceInfo *target = NULL; XDevice *the_device; XEventClass event_list[7]; - Window win = X11DRV_get_whole_window( hOwner ); + /* we should never fail to find an x11 window if wine is running */ + Window win = X11DRV_get_x11_window_from_hwnd(hOwner); - if (!win || !xinput_handle) return 0; + if (!xinput_handle) return 0; TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors); + gActiveOwner = hOwner; + devices = pXListInputDevices(data->display, &num_devices); X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
となりました。
バイナリを得るにはパッチを適用してソースからコンパイルする必要があります。
え?コンパイルがめんどくさい?
コンパイル済みバイナリと使用したパッチをDropboxに置いておきます。
上記よりダウンロードしたwinex11.drv.soとwintab32.dll.soを解凍して
と入れ替えてください。
wintabを使うアプリケーションではペンタブレットの筆圧検知が使えるようになっているはずです。
SAIの場合のwintabを使う設定はmisc.iniにあります。
TabletMouseSimulation = 0
の0を1にしてSAIを起動するとSAIはwintabを使うようになります。
追記:1.5.13以降はこのパッチを当てても筆圧検知が働きません。
はじめまして。
大変勉強になりました。ありがとうございます。
この方法を応用してmacのmikuinstaller上でsaiの筆圧感知を行うことは可能でしょうか。
自分なりに試したのですが、うまく行きませんでした。
可能でしたら、ご教授お願いできないでしょうか。
>匿名さん
この方法はLinux上のWine1.5系統の話なので、OSXのそれとでは事情が異なるかと思います。OSXのMikuInstallerのWineのバージョンはかなり古かったと記憶している為、このパッチが動くかは分かりません。
もしも、この方法を試したいなら以下を試してしてみてください:
MikuInstallerはWineをMikuInstaller.appパッケージ配下に持っているはずです。用いたパッチは公開しているのでWineのバージョン1.5.11又は1.5.12のソースコードをダウンロードした後、パッチを当てたものを自前でmakeしてみてください。
その後MikuInstaller.appのパッケージ内容を表示し、Wineを入れ替えてみては如何でしょうか。
この方法が有効ならばMacでも同様にWine上のSAIの筆圧検知が有効になるはずです。
お返事ありがとうございます。
先日質問した者です。
実際にWineのバージョン1.5.11にて、ご教授いただいた方法を試してみたのですが、saiの実行はされるものの筆圧感知はしないままでした。
やはりOSが違うので諦めるしかないですかね。
もしこの話に進展があれば、記事を更新してもらえると助かります。
ありがとうございました。
すごいですね。憧れのsaiが使えるかも!とチャレンジしてみました。mikuinstallerとXQuartz-2.7.6を使ってsaiをインストールし、筆圧感知を調べてこのページに出会いました。saiの設定はアプリケーションサポート内に発見できたのですが/usr/lib/i386-linux-gnu/wine/winex11.drv.so
/usr/lib/i386-linux-gnu/wine/wintab32.dll.soが検索しても発見できません。ライブラリ内かなと思ったのですが。どこか深い階層に隠れているのでしょうか?
>tomohidepostさん
XQuartzと見えるのでMac OSXでしょうか?
このパッチとDropBoxに置いているバイナリはUbuntu Linux用です。
また、筆圧検知は動作するようになりますが、とても実用に耐えるシロモノではなく、動くかなぁ程度のものでした。
前のコメントにも有る通り、OSXでは動きません、あしからず。