雑記帳

ちょっとした文章とかメモ書きとか。

Wine 1.5.11でwintabの筆圧検知を有効にしてみる

Wineのペンタブレットのサポートの状況はこちら→http://wiki.winehq.org/TabletSupport

そのままではwintab32.dllwinex11.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);

となりました。
バイナリを得るにはパッチを適用してソースからコンパイルする必要があります。

ppaのWineのバイナリと置き換える

え?コンパイルがめんどくさい?

コンパイル済みバイナリと使用したパッチをDropboxに置いておきます。

使用したパッチ

コンパイル済みバイナリ(wine1.5.11)

コンパイル済みバイナリ(wine1.5.12)

上記よりダウンロードしたwinex11.drv.soとwintab32.dll.soを解凍して

  • /usr/lib/i386-linux-gnu/wine/winex11.drv.so
  • /usr/lib/i386-linux-gnu/wine/wintab32.dll.so

と入れ替えてください。

wintabを使うアプリケーションではペンタブレットの筆圧検知が使えるようになっているはずです。

SAIの場合

SAIの場合のwintabを使う設定はmisc.iniにあります。

TabletMouseSimulation = 0

の0を1にしてSAIを起動するとSAIはwintabを使うようになります。

参考:Wineの筆圧感知パッチ http://yusuke494.blog.fc2.com/blog-entry-6.html

追記:1.5.13以降はこのパッチを当てても筆圧検知が働きません。

Wine 1.5.11でwintabの筆圧検知を有効にしてみる」への5件のフィードバック

  1. 匿名 2012年9月30日 4:19 午後

    はじめまして。

    大変勉強になりました。ありがとうございます。
    この方法を応用してmacのmikuinstaller上でsaiの筆圧感知を行うことは可能でしょうか。
    自分なりに試したのですが、うまく行きませんでした。
    可能でしたら、ご教授お願いできないでしょうか。

    • コスモ 2012年10月1日 8:25 午後

      >匿名さん
      この方法は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の筆圧検知が有効になるはずです。

      • 匿名 2012年10月1日 10:49 午後

        お返事ありがとうございます。
        先日質問した者です。

        実際にWineのバージョン1.5.11にて、ご教授いただいた方法を試してみたのですが、saiの実行はされるものの筆圧感知はしないままでした。

        やはりOSが違うので諦めるしかないですかね。

        もしこの話に進展があれば、記事を更新してもらえると助かります。

        ありがとうございました。

  2. tomohidepost 2014年6月6日 12:54 午後

    すごいですね。憧れの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が検索しても発見できません。ライブラリ内かなと思ったのですが。どこか深い階層に隠れているのでしょうか?

    • コスモ 2014年6月15日 1:58 午前

      >tomohidepostさん
      XQuartzと見えるのでMac OSXでしょうか?
      このパッチとDropBoxに置いているバイナリはUbuntu Linux用です。
      また、筆圧検知は動作するようになりますが、とても実用に耐えるシロモノではなく、動くかなぁ程度のものでした。

      前のコメントにも有る通り、OSXでは動きません、あしからず。

コスモ への返信 コメントをキャンセル