summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-03 11:57:40 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-03 11:58:51 +0200
commit5b1b19d6d0e07103cdeb8df2dcd838fe67a923cd (patch)
tree6509e3f70c9fb23f6575cbcf5a35754635e5d27c
parent12630f504b022b0718655a615d2fbb1d045ded18 (diff)
Load keyboard modifier mapping from modmap.txt
IssueID #87
-rw-r--r--src/app.c9
-rw-r--r--src/ui/keys.c68
-rw-r--r--src/ui/window.c7
3 files changed, 77 insertions, 7 deletions
diff --git a/src/app.c b/src/app.c
index 5c04fd92..b1036ffe 100644
--- a/src/app.c
+++ b/src/app.c
@@ -896,6 +896,15 @@ void processEvents_App(enum iAppEventMode eventMode) {
896 d->isIdling = iFalse; 896 d->isIdling = iFalse;
897#endif 897#endif
898 gotEvents = iTrue; 898 gotEvents = iTrue;
899 /* Keyboard modifier mapping. */ {
900 if (ev.type == SDL_KEYDOWN || ev.type == SDL_KEYUP) {
901 /* Track Caps Lock state as a modifier. */
902 if (ev.key.keysym.sym == SDLK_CAPSLOCK) {
903 setCapsLockDown_Keys(ev.key.state == SDL_PRESSED);
904 }
905 ev.key.keysym.mod = mapMods_Keys(ev.key.keysym.mod & ~KMOD_CAPS);
906 }
907 }
899 iBool wasUsed = processEvent_Window(d->window, &ev); 908 iBool wasUsed = processEvent_Window(d->window, &ev);
900 if (!wasUsed) { 909 if (!wasUsed) {
901 /* There may be a key bindings for this. */ 910 /* There may be a key bindings for this. */
diff --git a/src/ui/keys.c b/src/ui/keys.c
index ce80d9f0..60f06f77 100644
--- a/src/ui/keys.c
+++ b/src/ui/keys.c
@@ -43,6 +43,29 @@ enum iModMap {
43 max_ModMap 43 max_ModMap
44}; 44};
45 45
46static const char *modToStr_[max_ModMap] = {
47 "none",
48 "Lshift",
49 "Lctrl",
50 "Lalt",
51 "Lgui",
52 "Rshift",
53 "Rctrl",
54 "Ralt",
55 "Rgui",
56 "caps",
57};
58
59static int strToMod_(iRangecc str) {
60 trim_Rangecc(&str);
61 for (int i = 0; i < max_ModMap; i++) {
62 if (equalCase_Rangecc(str, modToStr_[i])) {
63 return i;
64 }
65 }
66 return none_ModMap;
67}
68
46static int modMap_[max_ModMap]; 69static int modMap_[max_ModMap];
47static iBool capsLockDown_; 70static iBool capsLockDown_;
48 71
@@ -87,6 +110,50 @@ void setCapsLockDown_Keys(iBool isDown) {
87 capsLockDown_ = isDown; 110 capsLockDown_ = isDown;
88} 111}
89 112
113static void loadModMap_Keys_(const char *saveDir) {
114 iFile *f = iClob(newCStr_File(concatPath_CStr(saveDir, "modmap.txt")));
115 if (open_File(f, readOnly_FileMode | text_FileMode)) {
116 const iString *text = collect_String(readString_File(f));
117 iRangecc textLine = iNullRange;
118 while (nextSplit_Rangecc(range_String(text), "\n", &textLine)) {
119 iRangecc line = textLine;
120 trim_Rangecc(&line);
121 if (isEmpty_Range(&line) || startsWith_Rangecc(line, "#")) {
122 continue; /* comment */
123 }
124 iRangecc seg = iNullRange;
125 if (nextSplit_Rangecc(line, "->", &seg)) {
126 const int fromMod = strToMod_(seg);
127 if (fromMod && nextSplit_Rangecc(line, "->", &seg)) {
128 const int toMod = strToMod_(seg);
129 modMap_[fromMod] = toMod;
130 }
131 }
132 }
133 close_File(f);
134 }
135 else {
136 open_File(f, writeOnly_FileMode | text_FileMode);
137 printf_Stream(stream_File(f),
138 "# This is a translation table for keyboard modifiers. The syntax is:\n"
139 "#\n"
140 "# (hardware key) -> (effective modifier)\n"
141 "#\n"
142 "# A modifier can be mapped to \"none\" to disable it. For example:\n"
143 "#\n"
144 "# Lalt -> none\n"
145 "#\n"
146 "# When using CapsLock as a modifier key, its toggled state will still affect\n"
147 "# text entry. You may need to remap or disable CapsLock in your window system.\n"
148 "#\n"
149 "# You may delete this file and it will be recreated with the default mapping.\n\n");
150 for (int i = 1; i < max_ModMap; i++) {
151 printf_Stream(stream_File(f), "%s -> %s\n", modToStr_[i], modToStr_[i]);
152 }
153 close_File(f);
154 }
155}
156
90/*----------------------------------------------------------------------------------------------*/ 157/*----------------------------------------------------------------------------------------------*/
91 158
92iDeclareType(Keys) 159iDeclareType(Keys)
@@ -270,6 +337,7 @@ void deinit_Keys(void) {
270 337
271void load_Keys(const char *saveDir) { 338void load_Keys(const char *saveDir) {
272 iKeys *d = &keys_; 339 iKeys *d = &keys_;
340 loadModMap_Keys_(saveDir);
273 iFile *f = iClob(newCStr_File(concatPath_CStr(saveDir, filename_Keys_))); 341 iFile *f = iClob(newCStr_File(concatPath_CStr(saveDir, filename_Keys_)));
274 if (open_File(f, readOnly_FileMode | text_FileMode)) { 342 if (open_File(f, readOnly_FileMode | text_FileMode)) {
275 iBlock * src = collect_Block(readAll_File(f)); 343 iBlock * src = collect_Block(readAll_File(f));
diff --git a/src/ui/window.c b/src/ui/window.c
index bfa95f90..fb5daa80 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1596,13 +1596,6 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
1596 As a workaround, ignore these events. */ 1596 As a workaround, ignore these events. */
1597 return iTrue; /* won't go to bindings, either */ 1597 return iTrue; /* won't go to bindings, either */
1598 } 1598 }
1599 /* Apply keyboard modifier mapping. */
1600 if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
1601 if (event.key.keysym.sym == SDLK_CAPSLOCK) {
1602 setCapsLockDown_Keys(event.key.state == SDL_PRESSED);
1603 }
1604 event.key.keysym.mod = mapMods_Keys(event.key.keysym.mod & ~KMOD_CAPS);
1605 }
1606 if (event.type == SDL_MOUSEBUTTONDOWN && d->ignoreClick) { 1599 if (event.type == SDL_MOUSEBUTTONDOWN && d->ignoreClick) {
1607 d->ignoreClick = iFalse; 1600 d->ignoreClick = iFalse;
1608 return iTrue; 1601 return iTrue;