*/}}
Browse Source

Custom key maps and other optimizations

YimingWu 3 weeks ago
parent
commit
c240ee71e7
7 changed files with 245 additions and 27 deletions
  1. 29 0
      la_interface.h
  2. 157 6
      la_kernel.c
  3. 9 9
      la_resource.c
  4. 8 4
      resources/la_operators.c
  5. 19 6
      resources/la_properties.c
  6. 6 0
      resources/la_templates.c
  7. 17 2
      resources/la_widgets_viewers.c

+ 29 - 0
la_interface.h

@@ -103,6 +103,24 @@
 #define LA_KEY_DELETE    (1<<23)
 #define LA_KEY_TAB       (1<<24)
 
+#define LA_KEY_EXTRA     (1<<25)
+#define LA_KEY_NUM1      (LA_KEY_EXTRA+1)
+#define LA_KEY_NUM2      (LA_KEY_EXTRA+2)
+#define LA_KEY_NUM3      (LA_KEY_EXTRA+3)
+#define LA_KEY_NUM4      (LA_KEY_EXTRA+4)
+#define LA_KEY_NUM5      (LA_KEY_EXTRA+5)
+#define LA_KEY_NUM6      (LA_KEY_EXTRA+6)
+#define LA_KEY_NUM7      (LA_KEY_EXTRA+7)
+#define LA_KEY_NUM8      (LA_KEY_EXTRA+8)
+#define LA_KEY_NUM9      (LA_KEY_EXTRA+9)
+#define LA_KEY_NUM0      (LA_KEY_EXTRA+10)
+#define LA_KEY_NUMPLUS   (LA_KEY_EXTRA+11)
+#define LA_KEY_NUMMINUS  (LA_KEY_EXTRA+12)
+#define LA_KEY_NUMMULT   (LA_KEY_EXTRA+13)
+#define LA_KEY_NUMDIVIDE (LA_KEY_EXTRA+14)
+#define LA_KEY_NUMDOT    (LA_KEY_EXTRA+15)
+#define LA_KEY_NUMENTER  (LA_KEY_EXTRA+16)
+
 #define LA_SIGNAL_EVENT  (1<<31)
 
 #ifdef _WIN32
@@ -1254,6 +1272,7 @@ STRUCTURE(laUiConditionNode){
 #define LA_PANEL_ANIMATION_DISSOVE 3
 #define LA_PANEL_ANIMATION_COLLAPSE 4
 #define LA_PANEL_ANIMATION_MINIMIZE 5
+#define LA_PANEL_ANIMATION_FLASH 126
 #define LA_PANEL_ANIMATION_DESTROY 127
 
 NEED_STRUCTURE(laOperator);
@@ -1478,6 +1497,12 @@ STRUCTURE(laInputMappingBundle){
 #define LA_SIGNAL_CONFIRM 10002
 #define LA_SIGNAL_UNDO 10003
 #define LA_SIGNAL_REDO 10004
+#define LA_SIGNAL_OPEN 10005
+#define LA_SIGNAL_SAVE 10006
+#define LA_SIGNAL_SAVE_AS 10007
+#define LA_SIGNAL_LAYOUT_NEXT 10008
+#define LA_SIGNAL_LAYOUT_PREV 10009
+#define LA_SIGNAL_FULLSCREEN 10010
 
 STRUCTURE(laCustomSignal){
     laListItem Item;
@@ -2252,10 +2277,14 @@ void laSetMenuBarTemplates(laUiDefineFunc MenuButtons, laUiDefineFunc MenuExtras
 void laSetAboutTemplates(laUiDefineFunc AboutContent, laUiDefineFunc AboutVersion, laUiDefineFunc AboutAuthor);
 void laSetPreferenceTemplates(laUiDefineFunc PreferencePageDisplay, laUiDefineFunc PreferencePageInput, laUiDefineFunc PreferencePageResource, laUiDefineFunc PreferencePageTheme);
 
+void la_InputMappingGetKeyName(int key, int special, char* name);
+int la_InputMappingGetKeyFromName(char* name, int* special);
 laCustomSignal* laFindSignal(char* Name);
+laCustomSignal* laFindSignalByID(int ID);
 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);
 void laRemoveInputMappingEntry(laInputMapping* im, laInputMappingEntry* e);
 void laRemoveInputMapping(laInputMapping* im);
 

+ 157 - 6
la_kernel.c

@@ -1435,13 +1435,118 @@ void laSetPreferenceTemplates(laUiDefineFunc PreferencePageDisplay, laUiDefineFu
     MAIN.PreferencePageResource=PreferencePageResource; MAIN.PreferencePageTheme=PreferencePageTheme;
 }
 
+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+"); }
+    switch(key){
+    case ' ': strcat(name,"Space"); break;
+    case LA_KEY_BACKSPACE: strcat(name,"Backspace"); break;
+    case LA_KEY_ESCAPE: strcat(name,"Escape"); break;
+    case LA_KEY_ENTER: strcat(name,"Enter"); break;
+    case LA_KEY_ARRLEFT: strcat(name,"Left"); break;
+    case LA_KEY_ARRRIGHT: strcat(name,"Right"); break;
+    case LA_KEY_ARRUP: strcat(name,"Up"); break;
+    case LA_KEY_ARRDOWN: strcat(name,"Down"); break;
+    case LA_KEY_SHIFT: case LA_KEY_CTRL: case LA_KEY_ALT: break;
+    case LA_KEY_DELETE: strcat(name,"Delete"); break;
+    case LA_KEY_TAB: strcat(name,"Tab"); break;
+    case LA_KEY_NUM1: strcat(name,"Num1"); break;
+    case LA_KEY_NUM2: strcat(name,"Num2"); break;
+    case LA_KEY_NUM3: strcat(name,"Num3"); break;
+    case LA_KEY_NUM4: strcat(name,"Num4"); break;
+    case LA_KEY_NUM5: strcat(name,"Num5"); break;
+    case LA_KEY_NUM6: strcat(name,"Num6"); break;
+    case LA_KEY_NUM7: strcat(name,"Num7"); break;
+    case LA_KEY_NUM8: strcat(name,"Num8"); break;
+    case LA_KEY_NUM9: strcat(name,"Num9"); break;
+    case LA_KEY_NUM0: strcat(name,"Num0"); break;
+    case LA_KEY_NUMPLUS: strcat(name,"NumPlus"); break;
+    case LA_KEY_NUMMINUS: strcat(name,"NumMinus"); break;
+    case LA_KEY_NUMMULT: strcat(name,"NumMult"); break;
+    case LA_KEY_NUMDIVIDE: strcat(name,"NumDivide"); break;
+    case LA_KEY_NUMDOT: strcat(name,"NumDot"); break;
+    case LA_KEY_NUMENTER: strcat(name,"NumEnter"); break;
+    case LA_KEY_F1: strcat(name,"F1"); break;
+    case LA_KEY_F2: strcat(name,"F2"); break;
+    case LA_KEY_F3: strcat(name,"F3"); break;
+    case LA_KEY_F4: strcat(name,"F4"); break;
+    case LA_KEY_F5: strcat(name,"F5"); break;
+    case LA_KEY_F6: strcat(name,"F6"); break;
+    case LA_KEY_F7: strcat(name,"F7"); break;
+    case LA_KEY_F8: strcat(name,"F8"); break;
+    case LA_KEY_F9: strcat(name,"F9"); break;
+    case LA_KEY_F10: strcat(name,"F10"); break;
+    case LA_KEY_F11: strcat(name,"F11"); break;
+    case LA_KEY_F12: strcat(name,"F12"); break;
+    default:
+        name = name+strlen(name); _next=name;
+        laToUTF8(key,name,&_next); *_next=0; break;
+    }
+}
+int la_InputMappingGetKeyFromName(char* name, int* special){
+    if(!name ||name[0]==0){ *special=0; return 0; }
+    *special=0;
+    if(strstr(name,"Ctrl")) *special|=LA_KEY_CTRL;
+    if(strstr(name,"Shift")) *special|=LA_KEY_SHIFT;
+    if(strstr(name,"Alt")) *special|=LA_KEY_ALT;
+    char* p=name+strlen(name)-1;
+    while(*p!='+'){ p--; if(p<=name){p=name; break;} }
+    while(*p=='+' || *p==' '){ p++; }
+    if(strSame(p,"Space")) return ' ';
+    if(strSame(p,"Backspace")) return LA_KEY_BACKSPACE;
+    if(strSame(p,"Escape")) return LA_KEY_ESCAPE;
+    if(strSame(p,"Enter")) return LA_KEY_ENTER;
+    if(strSame(p,"Left")) return LA_KEY_ARRLEFT;
+    if(strSame(p,"Right")) return LA_KEY_ARRRIGHT;
+    if(strSame(p,"Up")) return LA_KEY_ARRUP;
+    if(strSame(p,"Down")) return LA_KEY_ARRDOWN;
+    if(strSame(p,"Delete")) return LA_KEY_DELETE;
+    if(strSame(p,"Tab")) return LA_KEY_TAB;
+    if(strSame(p,"Num1")) return LA_KEY_NUM1;
+    if(strSame(p,"Num2")) return LA_KEY_NUM2;
+    if(strSame(p,"Num3")) return LA_KEY_NUM3;
+    if(strSame(p,"Num4")) return LA_KEY_NUM4;
+    if(strSame(p,"Num5")) return LA_KEY_NUM5;
+    if(strSame(p,"Num6")) return LA_KEY_NUM6;
+    if(strSame(p,"Num7")) return LA_KEY_NUM7;
+    if(strSame(p,"Num8")) return LA_KEY_NUM8;
+    if(strSame(p,"Num9")) return LA_KEY_NUM9;
+    if(strSame(p,"Num0")) return LA_KEY_NUM0;
+    if(strSame(p,"NumPlus")) return LA_KEY_NUMPLUS;
+    if(strSame(p,"NumMinus")) return LA_KEY_NUMMINUS;
+    if(strSame(p,"NumMult")) return LA_KEY_NUMMULT;
+    if(strSame(p,"NumDivide")) return LA_KEY_NUMDIVIDE;
+    if(strSame(p,"NumDot")) return LA_KEY_NUMDOT;
+    if(strSame(p,"NumEnter")) return LA_KEY_NUMENTER;
+    if(strSame(p,"F1")) return LA_KEY_F1;
+    if(strSame(p,"F2")) return LA_KEY_F2;
+    if(strSame(p,"F3")) return LA_KEY_F3;
+    if(strSame(p,"F4")) return LA_KEY_F4;
+    if(strSame(p,"F5")) return LA_KEY_F5;
+    if(strSame(p,"F6")) return LA_KEY_F6;
+    if(strSame(p,"F7")) return LA_KEY_F7;
+    if(strSame(p,"F8")) return LA_KEY_F8;
+    if(strSame(p,"F9")) return LA_KEY_F9;
+    if(strSame(p,"F10")) return LA_KEY_F10;
+    if(strSame(p,"F11")) return LA_KEY_F11;
+    if(strSame(p,"F12")) return LA_KEY_F12;
+    int adv;
+    return laToUnicode(p,&adv);
+}
 laCustomSignal* laFindSignal(char* Name){
     for(laCustomSignal* cs=MAIN.CustomSignals.pFirst;cs;cs=cs->Item.pNext){ if(strSame(SSTR(cs->Name),Name)) return cs; }
     return 0;
 }
+laCustomSignal* laFindSignalByID(int ID){
+    for(laCustomSignal* cs=MAIN.CustomSignals.pFirst;cs;cs=cs->Item.pNext){ if(ID==cs->Signal) return cs; }
+    return 0;
+}
 void laInputMappingUpdateSignal(laInputMappingEntry* ime){
-    if(ime->DeviceType == LA_INPUT_DEVICE_KEYBOARD){ char* str=SSTR(ime->Key); if(str&&str[0]){ int adv; ime->KeyValue=laToUnicode(str,&adv); }else{ ime->KeyValue=0; } }
-    if(ime->DeviceType == LA_INPUT_DEVICE_JOYSTICK){ int key=0; sscanf(SSTR(ime->Key),"%d",&key); ime->KeyValue=key; }
+    if(ime->DeviceType == LA_INPUT_DEVICE_KEYBOARD){ char* str=SSTR(ime->Key);
+        if(str&&str[0]){ int adv; ime->KeyValue=la_InputMappingGetKeyFromName(str,&ime->SpecialKeyBits); }else{ ime->KeyValue=0; }
+    }elif(ime->DeviceType == LA_INPUT_DEVICE_JOYSTICK){ int key=0; sscanf(SSTR(ime->Key),"%d",&key); ime->KeyValue=key; }
     char* signal = SSTR(ime->Signal);
     laCustomSignal *cs=laFindSignal(signal); if(cs){ ime->SignalValue=cs->Signal; }else{ ime->SignalValue=0;}
 }
@@ -1457,6 +1562,13 @@ laInputMappingEntry* laNewInputMappingEntry(laInputMapping* im, int DeviceType,
     memAssignRef(e,&e->Parent,im);
     if(Signal){ strSafeSet(&e->Signal,Signal); } if(Key){ strSafeSet(&e->Key,Key); }
     laInputMappingUpdateSignal(e);
+    e->SpecialKeyBits=SpecialKeyBit;
+    char buf[64],*_next=buf;
+    la_InputMappingGetKeyName(e->KeyValue,e->SpecialKeyBits,buf); strSafeSet(&e->Key,buf);
+}
+laInputMappingEntry* laNewInputMappingEntryP(laInputMapping* im, int DeviceType, int JoystickDevice, char* Key, int SpecialKeyBit, int Signal){
+    laCustomSignal* cs; if(!(cs=laFindSignalByID(Signal))) return 0;
+    laNewInputMappingEntry(im,DeviceAdded,JoystickDevice,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);
@@ -1697,6 +1809,22 @@ int la_TranslateSpecialKey(int keysym){
     case XK_Shift_R:   return LA_KEY_SHIFT;
     case XK_Alt_L:     return LA_KEY_ALT;
     case XK_Alt_R:     return LA_KEY_ALT;
+    case XK_KP_1:      return LA_KEY_NUM1;
+    case XK_KP_2:      return LA_KEY_NUM2;
+    case XK_KP_3:      return LA_KEY_NUM3;
+    case XK_KP_4:      return LA_KEY_NUM4;
+    case XK_KP_5:      return LA_KEY_NUM5;
+    case XK_KP_6:      return LA_KEY_NUM6;
+    case XK_KP_7:      return LA_KEY_NUM7;
+    case XK_KP_8:      return LA_KEY_NUM8;
+    case XK_KP_9:      return LA_KEY_NUM9;
+    case XK_KP_0:      return LA_KEY_NUM0;
+    case XK_KP_Add: return LA_KEY_NUMPLUS;
+    case XK_KP_Subtract: return LA_KEY_NUMMINUS;
+    case XK_KP_Divide: return LA_KEY_NUMDIVIDE;
+    case XK_KP_Multiply: return LA_KEY_NUMMULT;
+    case XK_KP_Decimal: return LA_KEY_NUMDOT;
+    case XK_KP_Enter:  return LA_KEY_NUMENTER;
     default:           return keysym;
     }
 #endif
@@ -2145,7 +2273,7 @@ void la_PanelDrawToWindow(laPanel *p, laWindow *w){
         tnsUniformColorComposing(T->immShader,0,0,0);
     }
 
-    if (p->Mode && (!p->AnimationMode || (p->AnimationMode && p->AnimationRatio > 0.99))){
+    if (p->Mode && (!p->AnimationMode || (p->AnimationMode && p->AnimationRatio > 0.99) || p->AnimationMode==LA_PANEL_ANIMATION_FLASH)){
         tnsUseNoTexture();
         if (!p->IsMenuPanel){
             la_PanelDrawDescendBorder(p, (*p->BT), MAIN.SolidShadowLength, MAIN.FloatingAlpha);
@@ -2153,8 +2281,16 @@ void la_PanelDrawToWindow(laPanel *p, laWindow *w){
         tnsFlush();
     }
 
+    if(p->ParentOperator){
+        tnsUseNoTexture();
+        tnsColor4d(LA_COLOR3(MAIN.CurrentTheme->Color),0.7*(p->AnimationMode==LA_PANEL_ANIMATION_FLASH?1.0f:p->AnimationRatio));
+        tnsVertex2d(0,0); tnsVertex2d(w->CW,0); tnsVertex2d(w->CW,w->CH); tnsVertex2d(0,w->CH);
+        tnsPackAs(GL_TRIANGLE_FAN); tnsFlush();
+    }
+
     switch (p->AnimationMode){
-    case 0:
+    case 0: /* and */
+    case LA_PANEL_ANIMATION_FLASH:
         tnsDraw2DTextureDirectly(p->OffScr->pColor[0], p->X, p->Y, p->W, p->H);
         if(!(p->SR || p->SB || p->Parent || p->Block || p->IsMenuPanel)){
             real* color=laThemeColor(_LA_THEME_PANEL,LA_BT_TEXT); tnsColor4d(LA_COLOR3(color),color[3]*(p->ShowCorner?1:0.8));
@@ -2164,6 +2300,16 @@ void la_PanelDrawToWindow(laPanel *p, laWindow *w){
             tnsColor4dv(laThemeColor(_LA_THEME_PANEL,LA_BT_NORMAL)); tnsVertex2d(px-len,py); tnsVertex2d(px,py-len);
             tnsLineWidth(2); tnsPackAs(GL_LINES); tnsLineWidth(1);
         }
+        if(p->AnimationMode==LA_PANEL_ANIMATION_FLASH){
+            p->AnimationRatio += MAIN.PanelAnimationSpeed * 0.1 * MAIN.LastFrameTime * 60;
+            if((int)(p->AnimationRatio*6)%2){
+                tnsUseNoTexture();
+                tnsColor4dv(laAccentColor(LA_BT_SELECTED));
+                tnsVertex2d(p->X,p->Y); tnsVertex2d(p->X+p->W,p->Y); tnsVertex2d(p->X+p->W,p->Y+p->H); tnsVertex2d(p->X,p->Y+p->H); 
+                tnsPackAs(GL_TRIANGLE_FAN); tnsFlush();
+            }
+            if (p->AnimationRatio > 0.99) p->AnimationMode = 0; laRefreshWindow();
+        }
         break;
 
     case LA_PANEL_ANIMATION_DROP_DOWN:
@@ -6622,7 +6768,7 @@ int laKeyMapExecuteEvent(laOperator *from, laKeyMapper *km, laEvent *e){
     char *instructions;
     if(e->type==LA_MOUSEMOVE) return 0;
     for (kmi = km->Items.pFirst; kmi; kmi = kmi->Item.pNext){
-        if (kmi->SpecialKeyBits == e->SpecialKeyBit &&
+        if ((kmi->SpecialKeyBits == e->SpecialKeyBit||kmi->EventType==LA_SIGNAL_EVENT) &&
             kmi->EventType == e->type && ((kmi->Key == e->Input) || (kmi->Key == e->key))){
             instructions = kmi->Instructions ? kmi->Instructions->Ptr : 0;
             if (kmi->Operation)
@@ -6640,7 +6786,7 @@ int laKeyMapExecuteEventEx(laOperator *from, laPropPack *UiExtra, laKeyMapper *k
     int inv = 0; int lx = -1, ly = -1;
     if(e->type==LA_MOUSEMOVE) return 0;
     for (kmi = km->Items.pFirst; kmi; kmi = kmi->Item.pNext){
-        if (kmi->SpecialKeyBits == e->SpecialKeyBit &&
+        if ((kmi->SpecialKeyBits == e->SpecialKeyBit||kmi->EventType==LA_SIGNAL_EVENT) &&
             kmi->EventType == e->type && ((kmi->Key == e->Input) || (kmi->Key == e->key))){
             if (e->Localized){
                 lx = e->x;
@@ -7623,10 +7769,15 @@ int la_ProcessSysMessage(){
                 if (InputStatus == XLookupKeySym || InputStatus == XLookupBoth) { /*printf("status: %d\n", InputStatus);*/ }
             if (InputCount){ MAIN.InputBuf[InputCount]=0; } strToUnicode(MAIN.InputBufU,MAIN.InputBuf); int UCount=strlenU(MAIN.InputBufU);
             for(int i=0;i<UCount;i++){ if(la_AllowInput(MAIN.InputBufU[i])) la_SendInputEvent(e.xkey.window, MAIN.InputBufU[i]); }
+            XKeyboardState x; XGetKeyboardControl(MAIN.dpy, &x);
+            int numlock=0; if(x.led_mask & 2){ numlock=1; }
             if(InputKeysym=XkbKeycodeToKeysym(e.xkey.display, e.xkey.keycode, 0, 0)){
 #ifdef DEBUG
                 printf("pressed KEY: %d\n", (int)InputKeysym);
 #endif
+                if(/*numlock && */InputKeysym>=XK_KP_Space && InputKeysym<=XK_KP_9){
+                    InputKeysym=XkbKeycodeToKeysym(e.xkey.display, e.xkey.keycode, 0, 1);
+                }
                 la_SendKeyboardEvent(e.xkey.window, LA_KEY_DOWN, la_TranslateSpecialKey(InputKeysym));
             }
             break;

+ 9 - 9
la_resource.c

@@ -103,16 +103,16 @@ void la_RegisterMainUiTypes(){
 
 void la_RegisterWindowKeys(){
     laKeyMapper* km=&MAIN.KeyMap;
-    laAssignNewKey(km, 0, "LA_udf_read", 0, LA_KEY_CTRL, LA_KEY_DOWN, 'o', 0);
-    laAssignNewKey(km, 0, "LA_managed_save", 0, LA_KEY_CTRL, LA_KEY_DOWN, 's', "quiet=true;");
-    laAssignNewKey(km, 0, "LA_managed_save", 0, LA_KEY_CTRL|LA_KEY_SHIFT, LA_KEY_DOWN, 's', 0);
-    laAssignNewKey(km, 0, "LA_manage_udf", 0, LA_KEY_SHIFT, LA_KEY_DOWN, 'r', 0);
-    laAssignNewKey(km, 0, "LA_switch_layout", 0, LA_KEY_CTRL, LA_KEY_DOWN, LA_KEY_ARRLEFT, "reverse=true;");
-    laAssignNewKey(km, 0, "LA_switch_layout", 0, LA_KEY_CTRL, LA_KEY_DOWN, LA_KEY_ARRRIGHT, 0);
+    laAssignNewKey(km, 0, "LA_udf_read", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_OPEN, 0);
+    laAssignNewKey(km, 0, "LA_managed_save", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_SAVE, "quiet=true;");
+    laAssignNewKey(km, 0, "LA_managed_save", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_SAVE_AS, 0);
+    laAssignNewKey(km, 0, "LA_switch_layout", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_LAYOUT_PREV, "reverse=true;");
+    laAssignNewKey(km, 0, "LA_switch_layout", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_LAYOUT_NEXT, 0);
+    laAssignNewKey(km, 0, "LA_undo", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_UNDO, 0);
+    laAssignNewKey(km, 0, "LA_redo", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_REDO, 0);
+    laAssignNewKey(km, 0, "LA_fullscreen", 0, 0, LA_SIGNAL_EVENT, LA_SIGNAL_FULLSCREEN, "toggle=true;");
+
     laAssignNewKey(km, 0, "LA_system_paste", 0, LA_KEY_CTRL, LA_KEY_DOWN, 'v', 0);
-    laAssignNewKey(km, 0, "LA_undo", 0, LA_KEY_CTRL, LA_KEY_DOWN, 'z', 0);
-    laAssignNewKey(km, 0, "LA_redo", 0, LA_KEY_CTRL|LA_KEY_SHIFT, LA_KEY_DOWN, 'z', 0);
-    laAssignNewKey(km, 0, "LA_fullscreen", 0, 0, LA_KEY_DOWN, LA_KEY_F11, "toggle=true;");
 }
 
 void la_RegisterMainThemes(){

+ 8 - 4
resources/la_operators.c

@@ -939,6 +939,7 @@ STRUCTURE(laKeyDetectorData){
     int pad;
     int IsController;
     int Key;
+    int SpecialKeyBit;
     int Button, Axis, Device;
     laSafeString* Str;
 };
@@ -958,9 +959,9 @@ int OPMOD_InputMappingEntrySelectKey(laOperator *a, laEvent *e){
     if(!a->This || !a->This->EndInstance) return LA_CANCELED; laInputMappingEntry* ime=a->This->EndInstance;
     laKeyDetectorData* kdd=a->CustomData; if(!kdd){ return LA_FINISHED; }
     char buf[64],*_next=buf;
-    if(e->type == LA_KEY_DOWN || e->type == LA_KEY_UP){
-        kdd->Key = e->key; laToUTF8(e->key,buf,&_next); *_next=0; strSafeSet(&kdd->Str,buf); kdd->IsController=0;
-        laNotifyInstanceUsers(kdd);
+    if(e->type == LA_KEY_DOWN){
+        kdd->Key = e->key; la_InputMappingGetKeyName(kdd->Key,e->SpecialKeyBit,buf); strSafeSet(&kdd->Str,buf); kdd->IsController=0;
+        laNotifyInstanceUsers(kdd); kdd->SpecialKeyBit=e->SpecialKeyBit;
         return LA_RUNNING;
     }elif(e->type == LA_EMPTY){
         if(MAIN.ControllerHasNewAxis){
@@ -975,7 +976,7 @@ int OPMOD_InputMappingEntrySelectKey(laOperator *a, laEvent *e){
         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; }
-            else{ ime->DeviceType = LA_INPUT_DEVICE_KEYBOARD; ime->KeyValue = kdd->Key; }
+            else{ ime->DeviceType = LA_INPUT_DEVICE_KEYBOARD; ime->KeyValue = kdd->Key; ime->SpecialKeyBits=kdd->SpecialKeyBit; }
             laNotifyInstanceUsers(ime);
         }
         return LA_FINISHED_PASS;
@@ -2128,6 +2129,9 @@ int OPMOD_ModalPanel(laOperator *a, laEvent *e){
     }
 
     if (!laIsInPanel(p, e->x, e->y) && !uid->TargetIndexVali){ 
+        if(e->type&LA_STATE_DOWN){
+            p->AnimationRatio=0; p->AnimationMode=LA_PANEL_ANIMATION_FLASH; laRedrawCurrentPanel();
+        }
         if(p->ShowCorner){ p->ShowCorner=0; laSetWindowCursor(LA_ARROW); laRefreshWindow(); } return LA_RUNNING; 
     }
 

+ 19 - 6
resources/la_properties.c

@@ -2106,10 +2106,23 @@ void la_RegisterDefaultSignals(){
     laNewCustomSignal("la.confirm",LA_SIGNAL_CONFIRM);
     laNewCustomSignal("la.undo",LA_SIGNAL_UNDO);
     laNewCustomSignal("la.redo",LA_SIGNAL_REDO);
-
-    laInputMapping* im = laNewInputMapping("Default");
-    laNewInputMappingEntry(im,LA_INPUT_DEVICE_KEYBOARD,0,"a",LA_KEY_SHIFT,"la.new");
-    laNewInputMappingEntry(im,LA_INPUT_DEVICE_KEYBOARD,0,"x",0,"la.delete");
-    laNewInputMappingEntry(im,LA_INPUT_DEVICE_KEYBOARD,0,"z",LA_KEY_CTRL,"la.undo");
-    laNewInputMappingEntry(im,LA_INPUT_DEVICE_KEYBOARD,0,"z",LA_KEY_CTRL|LA_KEY_SHIFT,"la.redo");
+    laNewCustomSignal("la.open",LA_SIGNAL_OPEN);
+    laNewCustomSignal("la.save",LA_SIGNAL_SAVE);
+    laNewCustomSignal("la.save_as",LA_SIGNAL_SAVE_AS);
+    laNewCustomSignal("la.layout_next",LA_SIGNAL_LAYOUT_NEXT);
+    laNewCustomSignal("la.layout_prev",LA_SIGNAL_LAYOUT_PREV);
+    laNewCustomSignal("la.fullscreen",LA_SIGNAL_FULLSCREEN);
+
+    laInputMapping* im=laNewInputMapping("Default");
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"z",LA_KEY_CTRL,LA_SIGNAL_UNDO);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"z",LA_KEY_CTRL|LA_KEY_SHIFT,LA_SIGNAL_REDO);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"o",LA_KEY_CTRL,LA_SIGNAL_OPEN);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"s",LA_KEY_CTRL,LA_SIGNAL_SAVE);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"s",LA_KEY_CTRL|LA_KEY_SHIFT,LA_SIGNAL_SAVE_AS);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"Right",LA_KEY_CTRL,LA_SIGNAL_LAYOUT_NEXT);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"Left",LA_KEY_CTRL,LA_SIGNAL_LAYOUT_PREV);
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"F11",0,LA_SIGNAL_FULLSCREEN);
+    
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"a",LA_KEY_SHIFT,"la.new");
+    laNewInputMappingEntryP(im,LA_INPUT_DEVICE_KEYBOARD,0,"x",0,"la.delete");
 }

+ 6 - 0
resources/la_templates.c

@@ -1630,8 +1630,14 @@ void laui_InputMapping(laUiList *uil, laPropPack *This, laPropPack *Extra, laCol
     laUiItem* b=laBeginRow(uil,c,0,0);
     laShowItem(uil,c,This,"new_entry");
     laEndRow(uil,b);
+    laShowSeparator(uil,c);
     
     laShowItemFull(uil,c,This,"entries",0,0,laui_InputMappingEntry,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
+
+    laShowSeparator(uil,c);
+    b=laBeginRow(uil,c,0,0);
+    laShowItem(uil,c,This,"new_entry");
+    laEndRow(uil,b);
 }
 void laui_InputMappingBundle(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil);

+ 17 - 2
resources/la_widgets_viewers.c

@@ -312,14 +312,22 @@ void la_RootObjectDrawOverlay(laUiItem *ui, int h){
 
     char* MaxIco=(MAIN.CurrentWindow->MaximizedUi!=ui)?"🡹":"🡻";
     tnsVector4d color; tnsVectorCopy4d(laThemeColor(bt,LA_BT_TEXT),color);
+    tnsVector4d colork; tnsVectorCopy4d(laThemeColor(bt,LA_BT_NORMAL),colork);
     color[3]=ui->State==LA_UI_NORMAL?0.0:(ui->State==LA_UI_ACTIVE?0.5:1.0);
+    colork[3]=ui->State==LA_UI_NORMAL?0.0:(ui->State==LA_UI_ACTIVE?0.5:1.0);
     int startx=(ui->R+ui->L)/2-LA_RH2*2;
+    int offs=LA_RH/12;
     
+    tnsDrawStringAuto("☰",colork,startx+offs, startx+LA_RH+offs, ui->B-bt->BM-LA_RH+offs, LA_TEXT_ALIGN_CENTER);
     tnsDrawStringAuto("☰",color,startx, startx+LA_RH, ui->B-bt->BM-LA_RH, LA_TEXT_ALIGN_CENTER);
+    tnsDrawStringAuto(MaxIco,colork,startx+LA_RH+offs, startx+LA_2RH+offs, ui->B-bt->BM-LA_RH+offs, LA_TEXT_ALIGN_CENTER);
     tnsDrawStringAuto(MaxIco,color,startx+LA_RH, startx+LA_2RH, ui->B-bt->BM-LA_RH, LA_TEXT_ALIGN_CENTER);
 
-    if(ui->Expand>=0 && ui!=MAIN.CurrentWindow->MaximizedUi)
+    if(ui->Expand>=0 && ui!=MAIN.CurrentWindow->MaximizedUi){
+        tnsDrawStringAuto("◿",colork,ui->R-LA_RH+offs, ui->R+offs, ui->B-bt->BM-LA_RH+offs, LA_TEXT_ALIGN_CENTER);
         tnsDrawStringAuto("◿",laThemeColor(bt,LA_BT_BORDER),ui->R-LA_RH, ui->R, ui->B-bt->BM-LA_RH, LA_TEXT_ALIGN_CENTER);
+    }
+    tnsFlush();
 }
 
 void la_CanvasDrawTexture(laBoxedTheme *bt, tnsTexture *t, laUiItem* ui){
@@ -502,14 +510,21 @@ void la_CanvasDefaultOverlay(laUiItem* ui, int h){
 
     char* MaxIco=(MAIN.CurrentWindow->MaximizedUi!=ui)?"🡹":"🡻";
     tnsVector4d color; tnsVectorCopy4d(laThemeColor(bt,LA_BT_TEXT),color);
+    tnsVector4d colork; tnsVectorCopy4d(laThemeColor(bt,LA_BT_NORMAL),colork);
     color[3]=ui->State==LA_UI_NORMAL?0.0:(ui->State==LA_UI_ACTIVE?0.5:1.0);
+    colork[3]=ui->State==LA_UI_NORMAL?0.0:(ui->State==LA_UI_ACTIVE?0.5:1.0);
     int startx=(ui->R+ui->L)/2-LA_RH2*2;
+    int offs=LA_RH/12;
     
+    tnsDrawStringAuto("☰",colork,startx+offs, startx+LA_RH+offs, ui->B-bt->BM-LA_RH+offs, LA_TEXT_ALIGN_CENTER);
     tnsDrawStringAuto("☰",color,startx, startx+LA_RH, ui->B-bt->BM-LA_RH, LA_TEXT_ALIGN_CENTER);
+    tnsDrawStringAuto(MaxIco,colork,startx+LA_RH+offs, startx+LA_2RH+offs, ui->B-bt->BM-LA_RH+offs, LA_TEXT_ALIGN_CENTER);
     tnsDrawStringAuto(MaxIco,color,startx+LA_RH, startx+LA_2RH, ui->B-bt->BM-LA_RH, LA_TEXT_ALIGN_CENTER);
 
-    if(ui->Expand>=0 && ui!=MAIN.CurrentWindow->MaximizedUi)
+    if(ui->Expand>=0 && ui!=MAIN.CurrentWindow->MaximizedUi){
+        tnsDrawStringAuto("◿",colork,ui->R-LA_RH+offs, ui->R+offs, ui->B-bt->BM-LA_RH+offs, LA_TEXT_ALIGN_CENTER);
         tnsDrawStringAuto("◿",laThemeColor(bt,LA_BT_BORDER),ui->R-LA_RH, ui->R, ui->B-bt->BM-LA_RH, LA_TEXT_ALIGN_CENTER);
+    }
 
     tnsFlush();
 }