*/}}
Browse Source

Pressure sensitivity

Yiming Wu 2 năm trước cách đây
mục cha
commit
82b509a86f

+ 7 - 1
source/lagui/la_interface.h

@@ -150,9 +150,11 @@ STRUCTURE(laEvent){
     int SpecialKeyBit;
 
     int p1, p2;
-
     uint32_t Input;
 
+    int IsEraser;
+    real Pressure,AngleX,AngleY;
+
     void *Localized;
 
     //void* BoardcastedData;
@@ -270,6 +272,10 @@ STRUCTURE(LA){
     Colormap cmap;
     XIM im;
     XIC ic;
+    int xi_opcode;
+    int WacomDeviceStylus; real StylusPressure, StylusAngleX, StylusAngleY;
+    int WacomDeviceEraser; real EraserPressure, EraserAngleX, EraserAngleY;
+    int PointerIsEraser;
 
     laWindow *CurrentWindow;
     laPanel *CurrentPanel;

+ 89 - 0
source/lagui/la_kernel.c

@@ -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){

+ 1 - 1
source/lagui/resources/la_widgets_viewers.c

@@ -854,7 +854,7 @@ int OPMOD_CanvasMove(laOperator *a, laEvent *e){
     laCanvasExtra *ex = a->This->EndInstance;
     laGeneralUiExtraData *uex = a->CustomData;
 
-    if (e->Type == LA_L_MOUSE_UP || e->Type == LA_R_MOUSE_DOWN){
+    if (e->Type == LA_L_MOUSE_UP || e->Type == LA_R_MOUSE_DOWN || e->Type==LA_M_MOUSE_UP){
         laSetWindowCursor(LA_ARROW);
         return LA_FINISHED;
     }