/* Copyright 2010 Fictive (Fictive's public key's fingerprint is "44:1a:41:70:b1:22:d4:93:3a:bb:84:62:60:0b:e4:a3")
This file is part of Sane Java Tablet.
Sane Java Tablet is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Sane Java Tablet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Sane Java Tablet. If not, see <http://www.gnu.org/licenses/>.
*/
package domain.libs.sjt.garbage;
import java.awt.Window;
import net.screwbox.libs.sjt.ConsoleLogger;
import net.screwbox.libs.sjt.TabletImplementation;
import net.screwbox.libs.sjt.TabletImplementationException;
import net.screwbox.libs.sjt.TabletInterface;
import net.screwbox.libs.sjt.windows.wintab.WinTab;
import net.screwbox.libs.sjt.windows.wintab.structs.WinTab_tagLOGCONTEXTW;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.ptr.IntByReference;
public class ErrWindowsTabletImplementation extends TabletImplementation {
private static final String classId = ErrWindowsTabletImplementation.class.getSimpleName();
private ConsoleLogger log = new ConsoleLogger(classId);
final Memory buffer = new Memory(1048576); // 1 MiB buffer
private WinTab_tagLOGCONTEXTW wt_tagLogContextW;
Pointer wt_hCtx;
private WinTabPacketThread winTabPacketThread;
public ErrWindowsTabletImplementation(
Window tabletWindow,
TabletInterface tabletInterface
) throws TabletImplementationException {
super(tabletWindow, tabletInterface);
try {
if (WinTab.WTInfoW(0, 0, Pointer.NULL) == 0) {
throw new TabletImplementationException(classId,
"wintab implementation isn't present.");
}
}
catch (UnsatisfiedLinkError e) {
throw new TabletImplementationException(classId, e,
"failed to load wintab dll.");
}
initialize();
}
private void initialize() throws TabletImplementationException {
// acquire a template of the system context (moves system mouse cursor)
if (WinTab.WTInfoW(WinTab.WTI_DEFSYSCTX, 0, buffer) == 0) {
throw new TabletImplementationException(classId,
"unable to get system context.");
}
wt_tagLogContextW = new WinTab_tagLOGCONTEXTW(buffer);
// fill in the context
/*
* Although the documentation says you can not include items in the packet that are not supported by the tablet,
* it appears that this is incorrect.
* Unsupported items may be included and will be set to zero.
*/
// personal note: api = stupid by design
// DO ME! TRUNC TO LCNAMELEN
String lcName = String.format(
"SaneJavaTablet, %s",
Long.toString(Thread.currentThread().getId(),16)
);
int lcNameLengthCapped = lcName.length();
if (lcNameLengthCapped > WinTab.LCNAMELEN) lcNameLengthCapped = WinTab.LCNAMELEN;
lcName.getChars(0, lcNameLengthCapped, wt_tagLogContextW.lcName, 0);
wt_tagLogContextW.lcOptions ^= WinTab.CXO_MESSAGES | WinTab.CXO_CSRMESSAGES;
// wt_tagLogContextW.lcPktData =
// WinTab.PK_CONTEXT |
// WinTab.PK_STATUS |
// WinTab.PK_TIME |
// WinTab.PK_CHANGED |
// WinTab.PK_SERIAL_NUMBER |
// WinTab.PK_CURSOR |
// WinTab.PK_BUTTONS |
// WinTab.PK_X |
// WinTab.PK_Y |
// WinTab.PK_Z |
// WinTab.PK_NORMAL_PRESSURE |
// WinTab.PK_TANGENT_PRESSURE |
// WinTab.PK_ORIENTATION |
// WinTab.PK_ROTATION;
wt_tagLogContextW.lcStatus |= WinTab.CXS_ONTOP;
wt_tagLogContextW.lcPktMode = 0; // absolute mode for all
wt_tagLogContextW.lcMoveMask = Integer.MAX_VALUE;
wt_tagLogContextW.lcBtnUpMask = Integer.MAX_VALUE;
// Iterate through Wintab extension indices
Memory extName = new Memory(255);
for (
int i=0, thisTag = 0;
WinTab.WTInfoW(WinTab.WTI_EXTENSIONS+i, WinTab.EXT_NAME, extName) != 0;
i++) {
// looking for the specified tag
IntByReference j = new IntByReference();
WinTab.WTInfoW(WinTab.WTI_EXTENSIONS+i, WinTab.EXT_TAG, j.getPointer());
System.out.println("ext #"+i+": "+extName.getString(0, true)+", tag: "+j.getValue());
extName.clear();
}
// System.out.println(Native.POINTER_SIZE);
wt_hCtx = WinTab.WTOpenW(
Native.getWindowPointer(getTabletWindow()),
wt_tagLogContextW,
true);
wt_tagLogContextW = new WinTab_tagLOGCONTEXTW(buffer);
// wt_tagLogContextW.read();
// System.out.println("PK_CONTEXT == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_CONTEXT) > 0));
// System.out.println("PK_STATUS == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_STATUS) > 0));
// System.out.println("PK_TIME == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_TIME) > 0));
// System.out.println("PK_CHANGED == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_CHANGED) > 0));
// System.out.println("PK_SERIAL_NUMBER == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_SERIAL_NUMBER) > 0));
// System.out.println("PK_BUTTONS == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_BUTTONS) > 0));
// System.out.println("PK_X == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_X) > 0));
// System.out.println("PK_Y == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_Y) > 0));
// System.out.println("PK_Z == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_Z) > 0));
// System.out.println("PK_NORMAL_PRESSURE == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_NORMAL_PRESSURE) > 0));
// System.out.println("PK_TANGENT_PRESSURE == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_TANGENT_PRESSURE) > 0));
// System.out.println("PK_ORIENTATION == " + ((wt_tagLogContextW.lcPktData & WinTab.PK_ORIENTATION) > 0));
int lastErrCode = Native.getLastError();
if (wt_hCtx == Pointer.NULL) {
/*
* Kernel32.getLastError() might not be the best as an error code,
* but I can't find any error codes being returned from WinTab.
*/
throw new TabletImplementationException(classId,
"failed to open wintab context. (" +
Kernel32Util.formatMessageFromLastErrorCode(
lastErrCode) + ")");
}
// set wintab packet queue size
WinTab.WTQueueSizeSet(wt_hCtx, 150);
// start packet receiving thread
winTabPacketThread = new WinTabPacketThread(this);
// winTabPacketThread.start();
} // method
@Override
protected void close() {
log.info("close");
winTabPacketThread.requestShutdown();
while (winTabPacketThread.isAlive()) { Thread.yield(); }
/*
* Kernel32.getLastError() might not be the best as an error code,
* but I can't find any error codes being returned from WinTab.
*/
if (WinTab.WTClose(wt_hCtx) != true) {
log.error("failed to close wintab context: " +
Kernel32Util.formatMessageFromLastErrorCode(
Kernel32.INSTANCE.GetLastError()
));
}
} // method
} // class
//new Memory()
//int i = CWinTab.WTInfoW(CWinTab.WTI_INTERFACE, CWinTab.IFC_NDEVICES, m);
//System.out.println(m.getInt(0));
//final String lastErrorMsg = Kernel32Util.formatMessageFromLastErrorCode(
//Kernel32.INSTANCE.GetLastError());
//final String exceptionMessage = String.format(
//"Windows tablet implementation failed to load. Kernel32.GetLastError() returned \"%s\"",
//lastErrorMsg);
//throw new TabletImplementationException(exceptionMessage);
//CWinTab.WTClose(hCtx) == 0
//CWinTab.WTInfoW(CWinTab.WTI_DEFCONTEXT, CWinTab.CTX_SYSEXTX, CWinTab.buffer);
//System.out.println("'" + CWinTab.buffer.getInt(0) + "'");
//Memory m = new Memory(64);
//int i = CWinTab.WTInfoW(CWinTab.WTI_INTERFACE, CWinTab.IFC_WINTABID, m);
//System.out.println(m.getString(0, true));// Structure.setAutoSynch(boolean)
//User32.INSTANCE.setw
//Native.getComponentPointer(c)
//WindowsTabletImplementation wti = WindowsTabletImplementation.getInstance();
//wti.numTabletsAvailable();
//IntByReference r;