|
@@ -10,6 +10,7 @@
|
|
|
#include <X11/Xos.h>
|
|
|
#include <X11/keysymdef.h>
|
|
|
#include <X11/XKBlib.h>
|
|
|
+#include <X11/extensions/XInput2.h>
|
|
|
#include <GL/glx.h>
|
|
|
//#include <GL/glext.h>
|
|
|
//#include <GL/glu.h>
|
|
@@ -34,6 +35,66 @@ typedef void (*glXSwapIntervalEXTProc)(Display *dpy, GLXDrawable drawable, int i
|
|
|
glXCreateContextAttribsARBProc glXCreateContextAttribsF;
|
|
|
glXSwapIntervalEXTProc glXSwapIntervalEXTF;
|
|
|
|
|
|
+static void la_PrintWacomValuators(Display *display, XIAnyClassInfo **classes, int num_classes){
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < num_classes; i++) {
|
|
|
+ if (classes[i]->type == XIValuatorClass) {
|
|
|
+ XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i];
|
|
|
+ logPrint(" Valuator %d: '%s'\n", v->number, (v->label) ? XGetAtomName(display, v->label) : "No label");
|
|
|
+ logPrint(" Range: %f - %f\n", v->min, v->max);
|
|
|
+ logPrint(" Resolution: %d units/m\n", v->resolution);
|
|
|
+ logPrint(" Mode: %s\n", v->mode == XIModeAbsolute ? "absolute": "relative");
|
|
|
+ if (v->mode == XIModeAbsolute) logPrint(" Current value: %f\n", v->value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+static void la_RegisterWacomEventMasks(Display *display, int deviceid)
|
|
|
+{
|
|
|
+ XIDeviceInfo *info, *dev;
|
|
|
+ int i, ndevices;
|
|
|
+
|
|
|
+ dev = XIQueryDevice(display, deviceid, &ndevices);
|
|
|
+
|
|
|
+ XIEventMask *mask=memAcquireSimple(sizeof(XIEventMask));
|
|
|
+ mask->deviceid = deviceid;
|
|
|
+ mask->mask_len = XIMaskLen(XI_RawMotion);
|
|
|
+ mask->mask=memAcquireSimple(mask->mask_len);
|
|
|
+ memset(mask->mask, 0, mask->mask_len);
|
|
|
+ XISetMask(mask->mask, XI_RawMotion);
|
|
|
+ XISelectEvents(display, DefaultRootWindow(display), mask, 1);
|
|
|
+
|
|
|
+ logPrint(" Device Name: '%s' (%d)\n", dev->name, dev->deviceid);
|
|
|
+ //la_PrintWacomValuators(display, dev->classes, dev->num_classes);
|
|
|
+}
|
|
|
+static void la_ScanWacomDevices(Display *display, int deviceid){
|
|
|
+ XIDeviceInfo *info, *dev;
|
|
|
+ int ndevices;
|
|
|
+ int i; char * word;
|
|
|
+
|
|
|
+ int _event, _error;
|
|
|
+ if (!XQueryExtension(MAIN.dpy, "XInputExtension", &MAIN.xi_opcode, &_event, &_error)) {
|
|
|
+ logPrint("X Input extension not available, wacom pressure events are not available.\n"); return;
|
|
|
+ }
|
|
|
+
|
|
|
+ info = XIQueryDevice(display, deviceid, &ndevices);
|
|
|
+ for(i = 0; i < ndevices; i++) {
|
|
|
+ dev = &info[i];
|
|
|
+ word = strtok (dev->name," ");
|
|
|
+ while (1) {
|
|
|
+ word = strtok (NULL, " "); if (!word) break;
|
|
|
+ if (strcmp("stylus", word) == 0) MAIN.WacomDeviceStylus = dev->deviceid;
|
|
|
+ elif (strcmp("eraser", word) == 0) MAIN.WacomDeviceEraser = dev->deviceid;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(MAIN.WacomDeviceStylus || MAIN.WacomDeviceEraser){
|
|
|
+ logPrintNew("Found wacom devices:\n");
|
|
|
+ if(MAIN.WacomDeviceStylus) la_RegisterWacomEventMasks(display, MAIN.WacomDeviceStylus);
|
|
|
+ if(MAIN.WacomDeviceEraser) la_RegisterWacomEventMasks(display, MAIN.WacomDeviceEraser);
|
|
|
+ }else{
|
|
|
+ logPrintNew("No wacom pen device connected.\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
Window la_CreateWindowX11(int x, int y, int w, int h, char *title, int SyncToVBlank, GLXContext* r_glc){
|
|
|
XSetWindowAttributes swa;
|
|
|
XWindowAttributes wa;
|
|
@@ -233,6 +294,8 @@ int laGetReady(){
|
|
|
exit(0);
|
|
|
}
|
|
|
|
|
|
+ la_ScanWacomDevices(MAIN.dpy,XIAllDevices);
|
|
|
+
|
|
|
static int visual_attribs[] =
|
|
|
{
|
|
|
GLX_X_RENDERABLE , True,
|
|
@@ -604,6 +667,10 @@ void la_SaveEvent(Window hwnd, laEvent *e, int use_last_pos){
|
|
|
e->x = rx; e->y = ry;
|
|
|
}
|
|
|
}
|
|
|
+ e->Pressure=MAIN.PointerIsEraser?MAIN.EraserPressure:MAIN.StylusPressure;
|
|
|
+ e->AngleX=MAIN.PointerIsEraser?MAIN.EraserAngleX:MAIN.StylusAngleX;
|
|
|
+ e->AngleY=MAIN.PointerIsEraser?MAIN.EraserAngleY:MAIN.StylusAngleY;
|
|
|
+
|
|
|
lstAppendItem(el, (laListItem *)e);
|
|
|
laMappingRequestEval();
|
|
|
};
|
|
@@ -6076,6 +6143,21 @@ void laFinalizeOperators(){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+//=================
|
|
|
+
|
|
|
+
|
|
|
+static void la_RegisterRawMotions(XIRawEvent *event)
|
|
|
+{
|
|
|
+ double *valuator = event->valuators.values;
|
|
|
+ int IsStylus=event->deviceid==MAIN.WacomDeviceStylus;
|
|
|
+ if(!IsStylus) MAIN.PointerIsEraser = 1; else MAIN.PointerIsEraser = 0;
|
|
|
+
|
|
|
+ if(XIMaskIsSet(event->valuators.mask, 2)){ if(IsStylus) MAIN.StylusPressure=valuator[2]/65536; else MAIN.EraserPressure=valuator[2]/65536; }
|
|
|
+ if(XIMaskIsSet(event->valuators.mask, 3)){ if(IsStylus) MAIN.StylusAngleX=valuator[3]; else MAIN.EraserAngleX=valuator[3]; }
|
|
|
+ if(XIMaskIsSet(event->valuators.mask, 4)){ if(IsStylus) MAIN.StylusAngleY=valuator[4]; else MAIN.EraserAngleY=valuator[4]; }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int la_UpdateOperatorHints(laWindow* w){
|
|
|
laSafeString* ss=0;
|
|
|
for(laOperator* o=w->Operators.pFirst;o;o=o->Item.pNext){
|
|
@@ -6245,9 +6327,14 @@ int la_ProcessSysMessage(){
|
|
|
if(!MAIN.IdleTriggered && MAIN.TimeAccum-MAIN.IdleStart>MAIN.IdleTime) SendIdle=1;
|
|
|
|
|
|
while(XPending(MAIN.dpy)){
|
|
|
+ XGenericEventCookie *cookie = &e.xcookie;
|
|
|
XNextEvent(MAIN.dpy, &e);
|
|
|
if (XFilterEvent(&e, None)) continue;
|
|
|
SendIdle=0; MAIN.IdleStart=MAIN.TimeAccum; MAIN.IdleTriggered=0;
|
|
|
+
|
|
|
+ if (cookie->type == GenericEvent && cookie->extension == MAIN.xi_opcode && XGetEventData(MAIN.dpy, cookie)){
|
|
|
+ if (cookie->evtype == XI_RawMotion) la_RegisterRawMotions(cookie->data);
|
|
|
+ }
|
|
|
|
|
|
switch(e.type){
|
|
|
case ConfigureNotify:
|
|
@@ -6262,6 +6349,7 @@ int la_ProcessSysMessage(){
|
|
|
break;
|
|
|
case ButtonPress:
|
|
|
type=LA_MOUSEDOWN;
|
|
|
+ printf("down\n");
|
|
|
if(e.xbutton.button==1){type|=LA_KEY_MOUSE_LEFT;}
|
|
|
elif(e.xbutton.button==2){type|=LA_KEY_MOUSE_MIDDLE;}
|
|
|
elif(e.xbutton.button==3){type|=LA_KEY_MOUSE_RIGHT;}
|
|
@@ -6337,6 +6425,7 @@ int la_ProcessSysMessage(){
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
+ XFreeEventData(MAIN.dpy, cookie);
|
|
|
}
|
|
|
|
|
|
for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){
|