*/}}
Browse Source

Support mouse triggering signal/operator

YimingWu 4 months ago
parent
commit
d53d82f0c8
7 changed files with 157 additions and 32 deletions
  1. 4 0
      la_interface.h
  2. 24 3
      la_kernel.c
  3. 1 0
      la_resource.c
  4. 32 15
      resources/la_operators.c
  5. 2 1
      resources/la_properties.c
  6. 9 13
      resources/la_templates.c
  7. 85 0
      resources/la_widgets.c

+ 4 - 0
la_interface.h

@@ -1298,6 +1298,7 @@ extern laWidget *LA_WIDGET_MAPPER;
 extern laWidget *LA_WIDGET_IMAGE;
 extern laWidget *LA_WIDGET_SCOPE;
 extern laWidget *LA_WIDGET_KNOB;
+extern laWidget *LA_WIDGET_MOUSE_ACTION_REPORTER;
 
 #define LA_CONDITION_TRUE 1
 #define LA_CONDITION_FALSE 2
@@ -2387,6 +2388,7 @@ void laInputMappingUpdateSignal(laInputMappingEntry* ime);
 laInputMapping* laNewInputMapping(char* Name);
 laInputMappingEntry* laNewInputMappingEntry(laInputMapping* im, int DeviceType, int JoystickDevice, char* Key, int SpecialKeyBit, char* Signal);
 laInputMappingEntry* laNewInputMappingEntryP(laInputMapping* im, int DeviceType, int JoystickDevice, char* Key, int SpecialKeyBit, int Signal);
+laInputMappingEntry* laNewInputMappingMouseEntryP(laInputMapping* im, int MouseEventType, int SpecialKeyBit, int Signal);
 void laRemoveInputMappingEntry(laInputMapping* im, laInputMappingEntry* e);
 void laRemoveInputMapping(laInputMapping* im);
 
@@ -2533,6 +2535,7 @@ void laDefault2DViewOverlayRight(laUiItem *ui);
 laUiItem *laShowColumnAdjuster(laUiList *uil, laColumn *c);
 laUiItem *laShowSymbol(laUiList *uil, laColumn *c, int SymbolID, int Height);
 laPropPack* laShowCompoundValue(laUiItem* ui, int slot, laPropPack *Base, const char *Path);
+laUiItem *laShowMouseActionReporter(laUiList* uil, laColumn* c, int Height, const char* Display, const char* instructions); 
 laUiItem *laBeginRow(laUiList *uil, laColumn *c, int Expand, int Even);
 laUiItem *laEndRow(laUiList *uil, laUiItem* Begin);
 laUiItem *laMakeGroup(laUiList *uil, laColumn *c, const char *Name, laWidget* Widget);
@@ -2749,6 +2752,7 @@ extern laUiType *_LA_UI_RAW;
 extern laUiType *_LA_UI_MAPPER;
 extern laUiType *_LA_UI_IMAGE;
 extern laUiType *_LA_UI_SCOPE;
+extern laUiType *_LA_UI_MOUSE_ACTION_REPORTER;
  
 extern laUiDescriptor _LA_UI_DESCRIPTOR_REF_UI;
 extern laUiDescriptor _LA_UI_DESCRIPTOR_REF_UIE;

+ 24 - 3
la_kernel.c

@@ -1643,7 +1643,7 @@ void la_InputMappingGetKeyName(int key, int special, char* name){
     char *_next=name; name[0]=0;
     if(special&LA_KEY_CTRL){ strcat(name,"Ctrl+"); }
     if(special&LA_KEY_SHIFT){ strcat(name,"Shift+"); }
-    if(special&LA_KEY_ALT){ strcat(name,"Shift+"); }
+    if(special&LA_KEY_ALT){ strcat(name,"Alt+"); }
     switch(key){
     case ' ': strcat(name,"Space"); break;
     case LA_KEY_BACKSPACE: strcat(name,"Backspace"); break;
@@ -1786,6 +1786,16 @@ laInputMappingEntry* laNewInputMappingEntryP(laInputMapping* im, int DeviceType,
     laCustomSignal* cs; if(!(cs=laFindSignalByID(Signal))) return 0;
     return laNewInputMappingEntry(im,DeviceType,JoystickDevice,Key,SpecialKeyBit,SSTR(cs->Name));
 }
+laInputMappingEntry* laNewInputMappingMouseEntryP(laInputMapping* im, int MouseEventType, int SpecialKeyBit, int Signal){
+    laCustomSignal* cs; if(!(cs=laFindSignalByID(Signal))) return 0;
+    char* Key="Mouse2";
+    if(MouseEventType&LA_KEY_MOUSE_LEFT){ Key="Mouse1"; }
+    elif(MouseEventType&LA_KEY_MOUSE_MIDDLE){ Key="Mouse2"; }
+    elif(MouseEventType&LA_KEY_MOUSE_RIGHT){ Key="Mouse3"; }
+    elif((MouseEventType&LA_KEY_MOUSE_SCROLL) && (MouseEventType&LA_STATE_UP)){ Key="MouseWheelUp"; }
+    elif((MouseEventType&LA_KEY_MOUSE_SCROLL) && (MouseEventType&LA_STATE_DOWN)){ Key="MouseWheelDown"; }
+    return laNewInputMappingEntry(im,LA_INPUT_DEVICE_MOUSE,0,Key,SpecialKeyBit,SSTR(cs->Name));
+}
 void laRemoveInputMappingEntry(laInputMapping* im, laInputMappingEntry* e){
     memAssignRef(e,&e->Parent,0); lstRemoveItem(&im->Entries,e); strSafeDestroy(&e->Signal); strSafeDestroy(&e->Key); memFree(e);
 }
@@ -1815,13 +1825,14 @@ void la_SendSignalsFromEvent(laEvent* e){
     laInputMapping* im = MAIN.InputMapping->CurrentInputMapping;
     if(!im){return;}
     for(laInputMappingEntry* ime = im->Entries.pFirst;ime;ime=ime->Item.pNext){
+        if(ime->Disabled) continue;
         if(e->type==LA_KEY_DOWN && ime->DeviceType == LA_INPUT_DEVICE_KEYBOARD){
             if(e->key == ime->KeyValue && e->SpecialKeyBit == ime->SpecialKeyBits){
                 la_SendInputMappingSignalsAuto(e->window->win,ime);
             }
         }elif((e->type&LA_MOUSE_EVENT) && ime->DeviceType == LA_INPUT_DEVICE_MOUSE){
-            int matchkey; if(!(e->type&LA_KEY_MOUSE_SCROLL)){ matchkey = (e->type&ime->KeyValue); }
-            else{ matchkey= (e->type==(ime->KeyValue&LA_MOUSE_EVENT)); }
+            int matchkey; if(!(e->type&LA_KEY_MOUSE_SCROLL)){ matchkey = ((e->type&ime->KeyValue) && (e->type&LA_STATE_DOWN)); }
+            else{ matchkey = (e->type==(ime->KeyValue&LA_MOUSE_EVENT)); }
             if(e->SpecialKeyBit == ime->SpecialKeyBits && matchkey){
                 la_SendInputMappingSignalsAuto(e->window->win,ime);
             }
@@ -4850,6 +4861,16 @@ laPropPack* laShowCompoundValue(laUiItem* ui, int slot, laPropPack *Base, const
     lstAppendItem(&ui->CompoundPPs,CPP);
     return &CPP->PP;
 }
+laUiItem *laShowMouseActionReporter(laUiList* uil, laColumn* c, int Height, const char* Display, const char* instructions){
+    laUiItem *ui = memAcquire(sizeof(laUiItem));
+    ui->C = c;
+    ui->Type=_LA_UI_MOUSE_ACTION_REPORTER;
+    ui->State=Height; if(!ui->State){ ui->State=1; }
+    if(Display) strSafeSet(&ui->Display, Display);
+    if(instructions) strSafeSet(&ui->ExtraInstructions, instructions);
+    lstAppendItem(&uil->UiItems, ui);
+    return ui;
+}
 
 laUiItem *laBeginRow(laUiList *uil, laColumn *c, int Expand, int Even){
     laUiItem *ui = memAcquireSimple(sizeof(laUiItem));

+ 1 - 0
la_resource.c

@@ -59,6 +59,7 @@ laUiType *_LA_UI_RAW;
 laUiType *_LA_UI_MAPPER;
 laUiType *_LA_UI_IMAGE;
 laUiType *_LA_UI_SCOPE;
+laUiType *_LA_UI_MOUSE_ACTION_REPORTER;
 
 laUiDefineFunc _LA_SUBPROP_DONT_CARE;
 

+ 32 - 15
resources/la_operators.c

@@ -950,6 +950,14 @@ int OPINV_RemoveInputMappingEntry(laOperator *a, laEvent *e){
     laEnableYesNoPanel(0, 0, "Confirm?", "Will remove this key map entry", e->x, e->y, 200, e);
     return LA_RUNNING;
 }
+int OPINV_ClearInputMappingFields(laOperator *a, laEvent *e){
+    if(!a->This || !a->This->EndInstance) return LA_CANCELED; laInputMappingEntry* ime=a->This->EndInstance;
+    strSafeDestroy(&ime->Operator);strSafeDestroy(&ime->OperatorName);strSafeDestroy(&ime->OperatorArguments);
+    strSafeDestroy(&ime->Key); strSafeDestroy(&ime->Signal);
+    ime->OperatorBase=ime->OperatorType=0; ime->KeyValue=ime->SpecialKeyBits=0; ime->SignalValue=0;
+    ime->JoystickDevice=ime->Axis=ime->Button=0; ime->DeviceType=0; ime->Disabled=0;
+    return LA_FINISHED;
+}
 
 int OPMOD_RemoveInputMapping(laOperator *a, laEvent *e){
     if(!a->This || !a->This->EndInstance) return LA_CANCELED; laInputMapping* im=a->This->EndInstance;
@@ -1012,6 +1020,7 @@ int OPMOD_InputMappingEntrySelectOperator(laOperator *a, laEvent *e){
             laOperatorType* at=a->ConfirmData->PointerData;
             strSafeSet(&ime->Operator,at->Identifier);
             strSafeSet(&ime->OperatorName,at->Name);
+            ime->OperatorType = at;
             laNotifyUsers("la.input_mapping");
         }
         return LA_FINISHED;
@@ -1031,7 +1040,7 @@ void laui_InputMappingEntryOperatorSelector(laUiList *uil, laPropPack *Base, laP
 
 STRUCTURE(laKeyDetectorData){
     int pad;
-    int IsController;
+    int DeviceType;
     int Key;
     int SpecialKeyBit;
     int Button, Axis, Device;
@@ -1045,7 +1054,7 @@ int OPEXT_InputMappingEntrySelectKey(laOperator* a,int exitmode){
 int OPINV_InputMappingEntrySelectKey(laOperator *a, laEvent *e){
     if(!a->This || !a->This->EndInstance) return LA_CANCELED; laInputMappingEntry* ime=a->This->EndInstance;
     a->CustomData = memAcquire(sizeof(laKeyDetectorData));
-    laEnableOperatorPanel(a,a->This,e->x-LA_RH*5,e->y-LA_RH,LA_RH*10,LA_RH*10,LA_RH*20,LA_RH*20,LA_RH*20,0,0,0,0,0,e);
+    laEnableOperatorPanel(a,a->This,e->x-LA_RH*5,e->y-LA_RH,LA_RH*10,LA_RH*10,LA_RH*20,LA_RH*20,LA_RH*10,0,0,0,0,0,e);
     laOperatorModalOver(a);
     return LA_RUNNING;
 }
@@ -1054,30 +1063,31 @@ int OPMOD_InputMappingEntrySelectKey(laOperator *a, laEvent *e){
     laKeyDetectorData* kdd=a->CustomData; if(!kdd){ return LA_FINISHED; }
     char buf[64],*_next=buf;
     if(e->type == LA_KEY_DOWN){
-        kdd->Key = e->key; la_InputMappingGetKeyName(kdd->Key,e->SpecialKeyBit,buf); strSafeSet(&kdd->Str,buf); kdd->IsController=0;
+        kdd->Key = e->key; la_InputMappingGetKeyName(kdd->Key,e->SpecialKeyBit,buf); strSafeSet(&kdd->Str,buf); kdd->DeviceType=LA_INPUT_DEVICE_KEYBOARD;
         laNotifyInstanceUsers(kdd); kdd->SpecialKeyBit=e->SpecialKeyBit;
         return LA_RUNNING;
     }elif(e->type == LA_EMPTY){
         if(MAIN.ControllerHasNewAxis){
-            kdd->Axis = MAIN.LastControllerAxis; kdd->Device = MAIN.LastControllerAxisDevice; kdd->Button =-1; kdd->IsController=1;
+            kdd->Axis = MAIN.LastControllerAxis; kdd->Device = MAIN.LastControllerAxisDevice; kdd->Button =-1; kdd->DeviceType=LA_INPUT_DEVICE_JOYSTICK;
             strSafeSet(&kdd->Str,laControllerIDGetAxisName(kdd->Device,kdd->Axis)); laNotifyInstanceUsers(kdd);
         }elif(MAIN.ControllerHasNewKey){
-            kdd->Button = MAIN.LastControllerKey; kdd->Device = MAIN.LastControllerKeyDevice; kdd->Axis = -1; kdd->IsController=1;
+            kdd->Button = MAIN.LastControllerKey; kdd->Device = MAIN.LastControllerKeyDevice; kdd->Axis = -1; kdd->DeviceType=LA_INPUT_DEVICE_JOYSTICK;
             strSafeSet(&kdd->Str,laControllerIDGetButtonName(kdd->Device,kdd->Button)); laNotifyInstanceUsers(kdd);
         }
     }
     if(a->ConfirmData){
-        if(a->ConfirmData->Mode == laConfirmString){
-            a->ConfirmData->StrData;
-            strSafeSet(&ime->Key,SSTR(kdd->Str));
-            if(kdd->IsController){ ime->DeviceType = LA_INPUT_DEVICE_JOYSTICK; ime->Axis=kdd->Axis; ime->Button=kdd->Button; ime->JoystickDevice = kdd->Device; }
-            else{ ime->DeviceType = LA_INPUT_DEVICE_KEYBOARD; ime->KeyValue = kdd->Key; ime->SpecialKeyBits=kdd->SpecialKeyBit; }
-            laNotifyInstanceUsers(ime);
+        if(a->ConfirmData->Mode == LA_CONFIRM_CUSTOM_STRING){
+            char* ReportedEvent=a->ConfirmData->StrData;
+            strSafeSet(&kdd->Str,ReportedEvent);
+            kdd->DeviceType = LA_INPUT_DEVICE_MOUSE;
+            kdd->Key = la_InputMappingGetKeyFromName(ReportedEvent,&kdd->SpecialKeyBit);
+            laNotifyInstanceUsers(kdd);
             return LA_RUNNING_PASS;
         }
         if(a->ConfirmData->Mode == LA_CONFIRM_OK){
             strSafeSet(&ime->Key,SSTR(kdd->Str));
-            if(kdd->IsController){ ime->DeviceType = LA_INPUT_DEVICE_JOYSTICK; ime->Axis=kdd->Axis; ime->Button=kdd->Button; ime->JoystickDevice = kdd->Device; }
+            if(kdd->DeviceType==LA_INPUT_DEVICE_JOYSTICK){ ime->DeviceType = LA_INPUT_DEVICE_JOYSTICK; ime->Axis=kdd->Axis; ime->Button=kdd->Button; ime->JoystickDevice = kdd->Device; }
+            elif(kdd->DeviceType==LA_INPUT_DEVICE_MOUSE){ ime->DeviceType = LA_INPUT_DEVICE_MOUSE; ime->KeyValue = kdd->Key; ime->SpecialKeyBits=kdd->SpecialKeyBit; }
             else{ ime->DeviceType = LA_INPUT_DEVICE_KEYBOARD; ime->KeyValue = kdd->Key; ime->SpecialKeyBits=kdd->SpecialKeyBit; }
             laNotifyInstanceUsers(ime);
         }
@@ -1087,19 +1097,25 @@ int OPMOD_InputMappingEntrySelectKey(laOperator *a, laEvent *e){
 }
 void laui_InputMappingEntryKeySelector(laUiList *uil, laPropPack *Base, laPropPack *OperatorInst, laColumn *ExtraColumns, int context){
     laColumn* c=laFirstColumn(uil);
+    laUiItem* b;
 
-    laShowLabel(uil,c,"Press a key:",0,0);
+    laShowLabel(uil,c,"Press a key:",0,0)->Flags|=LA_UI_FLAGS_DISABLED;
     laShowItem(uil,c,OperatorInst,"pressed_string")->Flags|=LA_UI_FLAGS_PLAIN;
 
-    laUiItem* b=laBeginRow(uil,c,0,0);
+    laShowLabel(uil,c,"Or click mouse button in:",0,0)->Flags|=LA_UI_FLAGS_DISABLED;
+    laShowMouseActionReporter(uil,c,3,0,0)->Flags|=LA_TEXT_ALIGN_CENTER;
+
+    b=laBeginRow(uil,c,0,0);
     laShowSeparator(uil,c)->Expand=1;
     laShowItem(uil,c,0,"LA_confirm");
     laEndRow(uil,b);
 }
 void laget_KeyDetectorPressedString(laKeyDetectorData* kdd, char* out, char** pivot){
-    if(kdd->IsController){
+    if(kdd->DeviceType==LA_INPUT_DEVICE_JOYSTICK){
         if(kdd->Axis>=0){ sprintf(out, "Controller %d axis \"%s\" (0x%0x)", kdd->Device, SSTR(kdd->Str), kdd->Axis); }
         else{ sprintf(out, "Controller %d button \"%s\" (0x%0x)", kdd->Device, SSTR(kdd->Str), kdd->Button); }
+    }elif(kdd->DeviceType==LA_INPUT_DEVICE_MOUSE){
+        sprintf(out, "Mouse \"%s\" (0x%0x)", SSTR(kdd->Str), kdd->Key);
     }else{
         sprintf(out, "Keyboard \"%s\" (0x%0x)", SSTR(kdd->Str), kdd->Key);
     }
@@ -2619,6 +2635,7 @@ void la_RegisterBuiltinOperators(){
     laCreateOperatorType("LA_new_input_mapping_entry", "New Entry", "New input mapping entry", 0, 0, 0, OPINV_NewInputMappingEntry, 0, '+', LA_ACTUATOR_SYSTEM);
     laCreateOperatorType("LA_remove_input_mapping", "Remove Mapping", "Remove input mapping", 0, 0, 0, OPINV_RemoveInputMapping, OPMOD_RemoveInputMapping, U'🞫', LA_ACTUATOR_SYSTEM);
     laCreateOperatorType("LA_remove_input_mapping_entry", "Remove Entry", "Remove input mapping entry", 0, 0, 0, OPINV_RemoveInputMappingEntry, OPMOD_RemoveInputMappingEntry, U'🞫', LA_ACTUATOR_SYSTEM);
+    laCreateOperatorType("LA_reset_input_mapping_fields", "Reset Entry", "Reset mapping entry", 0, 0, 0, OPINV_ClearInputMappingFields, 0, U'⮌', LA_ACTUATOR_SYSTEM);
     at = laCreateOperatorType("LA_input_mapping_entry_select_signal", "Select Signal", "Select signal for this entry", 0, 0, 0, OPINV_InputMappingEntrySelectSignal, OPMOD_InputMappingEntrySelectSignal, U'⯆', LA_ACTUATOR_SYSTEM);
     at->UiDefine = laui_InputMappingEntrySignalSelector;
     at = laCreateOperatorType("LA_input_mapping_entry_select_operator", "Select Operator", "Select operator for this entry", 0, 0, 0, OPINV_InputMappingEntrySelectOperator, OPMOD_InputMappingEntrySelectOperator, U'⯆', LA_ACTUATOR_SYSTEM);

+ 2 - 1
resources/la_properties.c

@@ -869,7 +869,7 @@ void laset_InputMappingEntryOperatorString(laInputMappingEntry* ime, char* strin
         strSafeSet(&ime->OperatorName, at->Name);
         ime->OperatorType = at;
     }else{
-        strSafeDestroy(&ime->OperatorName);
+        strSafeSet(&ime->OperatorName, string);
     }
 }
 void laset_SignalFilter(void* unused, char* sig){
@@ -1871,6 +1871,7 @@ void la_RegisterInternalProps(){
             laAddOperatorProperty(p,"select_signal","Select","Select signal","LA_input_mapping_entry_select_signal",0,0);
             laAddOperatorProperty(p,"select_operator","Select","Select operator","LA_input_mapping_entry_select_operator",0,0);
             laAddOperatorProperty(p,"select_key","Select Key","Select key","LA_input_mapping_entry_select_key",0,0);
+            laAddOperatorProperty(p,"reset","Reset","Reset entry","LA_reset_input_mapping_fields",0,0);
             laAddSubGroup(p,"parent","Parent","Parent group","la_input_mapping",0,0,0,offsetof(laInputMappingEntry,Parent),0,0,0,0,0,0,0,LA_UDF_REFER);
             ep=laAddEnumProperty(p,"use_operator","Device Type","Device type of the input event",0,0,0,0,0,offsetof(laInputMappingEntry,UseOperator),0,0,0,0,0,0,0,0,0,0);
             laAddEnumItemAs(ep, "SIGNAL", "Signal", "Send signal upon input", 0, U'⚟');

+ 9 - 13
resources/la_templates.c

@@ -1682,37 +1682,34 @@ void laui_InputMappingEntry(laUiList *uil, laPropPack *This, laPropPack *Extra,
         laShowLabel(uil,cl,"Mode:\n ",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT|LA_UI_FLAGS_DISABLED|LA_TEXT_LINE_WRAP;
 
         b2=laBeginRow(uil,crl,0,0);{
+            laShowItem(uil,crl,This,"use_operator")->Flags=LA_UI_FLAGS_ICON|LA_UI_FLAGS_PLAIN|LA_UI_FLAGS_DISABLED;
             b3=laOnConditionThat(uil,crl,laPropExpression(This,"use_operator"));{
-                laUiItem* pui = laShowInvisibleItem(uil,crl,This,"operator");
-                laShowItemFull(uil,crl,&pui->PP,"restore",0,"icon=🧹",0,0)->Flags|=LA_UI_FLAGS_ICON;
                 laUiItem* bui=laShowItemFull(uil,crl,This,"select_operator",0,"icon= ;",0,0);
                 bui->Expand=1; bui->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_UNDERNEATH;
-                laUiItem* ui=laShowItem(uil,crl,&pui->PP,"");
+                laUiItem* ui=laShowItem(uil,crl,This,"operator");
                 ui->Expand=1; ui->Flags|=LA_UI_FLAGS_PLAIN;
             }laElse(uil,b3);{
-                laUiItem* pui = laShowInvisibleItem(uil,crl,This,"signal");
-                laShowItemFull(uil,crl,&pui->PP,"restore",0,"icon=🧹",0,0)->Flags|=LA_UI_FLAGS_ICON;
                 laUiItem* bui=laShowItemFull(uil,crl,This,"select_signal",0,"icon= ;",0,0);
                 bui->Expand=1; bui->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_UNDERNEATH;
-                laUiItem* ui=laShowItem(uil,crl,&pui->PP,"");
+                laUiItem* ui=laShowItem(uil,crl,This,"signal");
                 ui->Expand=1; ui->Flags|=LA_UI_FLAGS_PLAIN;
             }laEndCondition(uil,b3);
         }laEndRow(uil,b2);
         
         b2=laBeginRow(uil,crr,0,0);{
-            laShowSeparator(uil,crr);
-            laUiItem* pui = laShowInvisibleItem(uil,crr,This,"key");
-            laShowItemFull(uil,crr,&pui->PP,"restore",0,"icon=🧹",0,0)->Flags|=LA_UI_FLAGS_ICON;
             laUiItem* bui=laShowItemFull(uil,crr,This,"select_key",0,"icon= ;",0,0);
             bui->Expand=1; bui->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_UNDERNEATH;
-            laUiItem* ui=laShowItem(uil,crr,&pui->PP,"");
+            laUiItem* ui=laShowItem(uil,crr,This,"key");
             ui->Expand=1; ui->Flags|=LA_UI_FLAGS_PLAIN;
             laShowItem(uil,crr,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
         }laEndRow(uil,b2);
 
+        b2=laBeginRow(uil,crr,0,0);{
+            laShowItem(uil,crr,This,"device_type")->Flags|=LA_UI_FLAGS_EXPAND;
+        }laEndRow(uil,b2);
         b2=laBeginRow(uil,crr,0,0);{
             laShowSeparator(uil,crr)->Expand=1;
-            laShowItem(uil,crr,This,"device_type")->Flags|=LA_UI_FLAGS_EXPAND|LA_UI_FLAGS_TRANSPOSE;
+            laShowItem(uil,crr,This,"reset");
         }laEndRow(uil,b2);
         b2=laBeginRow(uil,crl,0,0);{
             b3=laBeginRow(uil,crl,0,0);{
@@ -1741,7 +1738,6 @@ void laui_InputMappingEntry(laUiList *uil, laPropPack *This, laPropPack *Extra,
             }laEndCondition(uil,b3);
         }laEndRow(uil,b2);
         b2=laBeginRow(uil,crr,0,0);{
-            laShowSeparator(uil,crr);
             laShowItem(uil,crr,This,"device_type")->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_PLAIN;
             //laUiItem* uib=laShowItemFull(uil,crr,This,"select_key",0,"icon= ;",0,0);
             //uib->Expand=1; uib->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_UNDERNEATH;
@@ -1767,7 +1763,7 @@ void laui_InputMappingEntry(laUiList *uil, laPropPack *This, laPropPack *Extra,
 }
 void laui_InputMapping(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil);laSplitColumn(uil,c,0.3);
-    laColumn* cl=laLeftColumn(c,3),*cr=laRightColumn(c,0);laSplitColumn(uil,cr,0.6);
+    laColumn* cl=laLeftColumn(c,3),*cr=laRightColumn(c,0);laSplitColumn(uil,cr,0.55);
     laColumn* crl=laLeftColumn(cr,0),*crr=laRightColumn(cr,0);
 
     laUiItem* b=laBeginRow(uil,c,0,0);

+ 85 - 0
resources/la_widgets.c

@@ -65,6 +65,7 @@ laWidget _LA_WIDGET_MAPPER={0};
 laWidget _LA_WIDGET_IMAGE={0};
 laWidget _LA_WIDGET_SCOPE={0};
 laWidget _LA_WIDGET_KNOB={0,LA_UI_FLAGS_KNOB};
+laWidget _LA_WIDGET_MOUSE_ACTION_REPORTER={0,LA_TEXT_ALIGN_CENTER};
 
 laWidget *LA_WIDGET_FIXED_GROUP=&_LA_WIDGET_FIXED_GROUP;
 laWidget *LA_WIDGET_TAB=&_LA_WIDGET_TAB;
@@ -110,6 +111,7 @@ laWidget *LA_WIDGET_MAPPER=&_LA_WIDGET_MAPPER;
 laWidget *LA_WIDGET_IMAGE=&_LA_WIDGET_IMAGE;
 laWidget *LA_WIDGET_SCOPE=&_LA_WIDGET_SCOPE;
 laWidget *LA_WIDGET_KNOB=&_LA_WIDGET_KNOB;
+laWidget *LA_WIDGET_MOUSE_ACTION_REPORTER=&_LA_WIDGET_MOUSE_ACTION_REPORTER;
 
 //============================================== [Draw]
 
@@ -358,6 +360,14 @@ int la_ImageGetMinWidth(laUiItem *ui){
     UseW/=ra; H/=ra;
     return UseW;
 }
+int la_MouseActionReporterMinWidth(laUiItem *ui){
+    laBoxedTheme *bt = *ui->Type->Theme;
+    if(ui->Flags&LA_UI_MIN_WIDTH){ return LA_RH; }
+    if(!(SSTR(ui->Display)[0])) return 3*LA_RH;
+    int strw=tnsStringGetWidth(transLate(SSTR(ui->Display)), 0, ui->Flags&LA_TEXT_MONO);
+    if(ui->Type==_LA_UI_MENU_ROOT && strw<LA_RH)strw=LA_RH;
+    return (strw + bt->LM + bt->RM);
+}
 
 void la_SingleLineStringDrawSelection(laUiItem *ui, int Begin, int U, laBoxedTheme *bt, uint32_t *str, laStringEdit *se);
 
@@ -1988,6 +1998,51 @@ void la_ScopeDraw(laUiItem *ui, int h){
     if(s->FromSynth && laget_SynthPlaying(s->FromSynth)){ laDeferredRedraw(MAIN.CurrentPanel); }
 }
 
+void la_MouseActionReporterDraw(laUiItem *ui, int h){
+    laBoxedTheme *bt = (*ui->Type->Theme);
+    char buf[LA_RAW_CSTR_MAX_LEN] = {0};
+    char *label = 0;
+    uint32_t IconID=0;
+    int L;
+    char *Identifier;
+    laOperatorProp *ap = 0;
+    int NoDecal=ui->Flags&LA_UI_FLAGS_NO_DECAL;
+    int IconOnly=ui->Flags&LA_UI_FLAGS_ICON;
+    int IsHighlight=ui->Flags&LA_UI_FLAGS_HIGHLIGHT;
+    int IsWarning=ui->Flags&LA_UI_FLAGS_WARNING;
+    int IsDisabled=ui->Flags&LA_UI_FLAGS_DISABLED;
+
+    if(!NoDecal){
+        tnsUseNoTexture();
+        tnsColor4dv(IsDisabled?laThemeColor(bt,LA_UI_DISABLED):
+                   (IsHighlight?laAccentColor(LA_BT_ACTIVE):
+                   (IsWarning?laAccentColor(LA_BT_WARNING):laThemeColor(bt,LA_BT_NORMAL))));
+        tnsVertex2d(ui->L, ui->U); tnsVertex2d(ui->R, ui->U);
+        tnsVertex2d(ui->R, ui->B); tnsVertex2d(ui->L, ui->B);
+        tnsPackAs(GL_TRIANGLE_FAN);
+
+        tnsColor4dv(laThemeColor(bt, LA_BT_BORDER));
+        tnsVertex2d(ui->L, ui->U); tnsVertex2d(ui->R, ui->U);
+        tnsVertex2d(ui->R, ui->B); tnsVertex2d(ui->L, ui->B);
+        tnsPackAs(GL_LINE_LOOP);
+    }
+
+    if (ui->ExtraInstructions){
+        uint32_t tIconID=0;
+        la_DefaultOperatorParser(ui->Instructions, &tIconID, buf);
+        if (buf[0]) label = transLate(buf);
+        else label = transLate(SSTR(ui->Display));
+    }else{
+        label = transLate(SSTR(ui->Display));
+    }
+    if(label[0]=='\0'){ label="🖱"; }
+
+    int UseU = (ui->B-ui->U-LA_RH)/2+ui->U;
+    tnsDrawStringAuto(label,
+        IsDisabled?laThemeColor(bt,LA_BT_TEXT|LA_UI_DISABLED):laThemeColor(bt,LA_BT_TEXT),
+        ui->L, ui->R, UseU, ui->Flags);
+}
+
 void la_ConditionNodeFreeRecursive(laUiConditionNode *ucn);
 void la_GeneralUiInit(laUiItem *ui){
     ui->Extra = memAcquireSimple(sizeof(laGeneralUiExtraData));
@@ -2181,6 +2236,10 @@ void la_RegisterUiTypesBasic(){
     LA_WIDGET_SCOPE->Type=
     _LA_UI_SCOPE = la_RegisterUiType("LA_scope_default", 0, "LA_synth_scope", &_LA_THEME_BUTTON, la_ScopeDraw, la_ColorPickerGetHeight, la_GeneralUiInit, la_GeneralUiDestroy);
 
+    LA_WIDGET_MOUSE_ACTION_REPORTER->Type=
+    _LA_UI_MOUSE_ACTION_REPORTER = la_RegisterUiType("LA_mouse_action_reporter_default",0,"LA_mouse_action_reporter", &_LA_THEME_STRING,la_MouseActionReporterDraw,la_SymbolGetHeight,0,0);
+    _LA_UI_MOUSE_ACTION_REPORTER->GetMinWidth = la_MouseActionReporterMinWidth;
+
     _LA_UI_INVISIBLE.Theme=&_LA_THEME_BUTTON;
     _LA_UI_ROW_BEGIN.Theme=&_LA_THEME_BUTTON;
     _LA_UI_ROW_END.Theme=&_LA_THEME_BUTTON;
@@ -3447,6 +3506,30 @@ int OPMOD_HeightAdjuster(laOperator *a, laEvent *e){
 
     return LA_RUNNING_PASS;
 }
+int OPMOD_MouseActionReporter(laOperator *a, laEvent *e){
+    laUiItem *ui = a->Instance;
+    laBoxedTheme *bt = (*ui->Type->Theme);
+
+    if (!laIsInUiItem(ui, e->x, e->y)){ return LA_FINISHED_PASS; }
+
+    if (!(e->type&LA_MOUSE_EVENT)){ return LA_RUNNING_PASS; }
+    if (e->type==LA_MOUSEMOVE){ return LA_RUNNING_PASS; }
+
+    if((e->type&(LA_KEY_MOUSE_LEFT|LA_KEY_MOUSE_RIGHT|LA_KEY_MOUSE_MIDDLE)) && (e->type&LA_STATE_DOWN)){
+        int MouseKey = (e->type &(~(LA_MOUSE_EVENT|LA_STATE_DOWN)));
+        char buf[64];
+        la_InputMappingGetKeyName(MouseKey, e->SpecialKeyBit, buf);
+        laConfirmString(a,buf,LA_CONFIRM_CUSTOM_STRING);
+    }
+    if(e->type&(LA_KEY_MOUSE_SCROLL)){
+        int MouseKey = (e->type &(~LA_MOUSE_EVENT));
+        char buf[64];
+        la_InputMappingGetKeyName(MouseKey, e->SpecialKeyBit, buf);
+        laConfirmString(a,buf,LA_CONFIRM_CUSTOM_STRING);
+    }
+
+    return LA_RUNNING_PASS;
+}
 
 void la_ValueMapperSortPoint(laValueMapper* vm){
     laValueMapperPoint* vmp,*ivmp; laListHandle temp={0}; int Inserted=0;
@@ -3602,5 +3685,7 @@ void la_RegisterUiOperatorsBasic(){
                         0, 0, OPEXT_UiItem, OPINV_UiItem, OPMOD_HeightAdjuster, U'🖦', LA_EXTRA_TO_PANEL | LA_ACTUATOR_SYSTEM | LA_ACTUATOR_HIDDEN);
     laCreateOperatorType("LA_value_mapper", "Value mapper Operator", "Drag to set value mapping from input to output",
                         0, 0, OPEXT_UiItem, OPINV_UiItem, OPMOD_ValueMapper, U'🖦', LA_EXTRA_TO_PANEL | LA_ACTUATOR_SYSTEM | LA_ACTUATOR_HIDDEN);
+    laCreateOperatorType("LA_mouse_action_reporter", "Mouse action reporter", "Report mouse actions to caller",
+                        0, 0, OPEXT_UiItem, OPINV_UiItem, OPMOD_MouseActionReporter, U'🖦', LA_EXTRA_TO_PANEL | LA_ACTUATOR_SYSTEM | LA_ACTUATOR_HIDDEN);
 }