diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-11-21 15:07:49 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-11-21 15:07:49 +0200 |
commit | a6314e152b2d2f306bcbb880356d3890efbfc89e (patch) | |
tree | 574e5a78d63a5149213c0f9d68f4591af1e17e1f /src | |
parent | 6d24d800df86e11c5686d50437932a711af82915 (diff) |
Keyboard navigation mode for home row keys
Now there are keybindings for activating the keyboard navigation modes. The modifier-based mode remains as it was before, focusing on numbers, while the home row mode uses a separate activation key.
One can erase the bindings to disable the corresponding modes.
IssueID #34
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/bindingswidget.c | 6 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 158 | ||||
-rw-r--r-- | src/ui/keys.c | 38 | ||||
-rw-r--r-- | src/ui/util.c | 8 | ||||
-rw-r--r-- | src/ui/util.h | 1 |
5 files changed, 125 insertions, 86 deletions
diff --git a/src/ui/bindingswidget.c b/src/ui/bindingswidget.c index ff68ea7b..dee844db 100644 --- a/src/ui/bindingswidget.c +++ b/src/ui/bindingswidget.c | |||
@@ -195,6 +195,12 @@ static iBool processEvent_BindingsWidget_(iBindingsWidget *d, const SDL_Event *e | |||
195 | postCommand_App("bindings.changed"); | 195 | postCommand_App("bindings.changed"); |
196 | return iTrue; | 196 | return iTrue; |
197 | } | 197 | } |
198 | else if (ev->type == SDL_KEYUP && isMod_Sym(ev->key.keysym.sym)) { | ||
199 | setKey_BindingItem_(item_ListWidget(d->list, d->activePos), ev->key.keysym.sym, 0); | ||
200 | setActiveItem_BindingsWidget_(d, iInvalidPos); | ||
201 | postCommand_App("bindings.changed"); | ||
202 | return iTrue; | ||
203 | } | ||
198 | } | 204 | } |
199 | return processEvent_Widget(w, ev); | 205 | return processEvent_Widget(w, ev); |
200 | } | 206 | } |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index b1c166aa..3cf564ac 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -125,11 +125,17 @@ enum iDocumentWidgetFlag { | |||
125 | showLinkNumbers_DocumentWidgetFlag = iBit(3), | 125 | showLinkNumbers_DocumentWidgetFlag = iBit(3), |
126 | }; | 126 | }; |
127 | 127 | ||
128 | enum iDocumentLinkOrdinalMode { | ||
129 | numbersAndAlphabet_DocumentLinkOrdinalMode, | ||
130 | homeRow_DocumentLinkOrdinalMode, | ||
131 | }; | ||
132 | |||
128 | struct Impl_DocumentWidget { | 133 | struct Impl_DocumentWidget { |
129 | iWidget widget; | 134 | iWidget widget; |
130 | enum iRequestState state; | 135 | enum iRequestState state; |
131 | iPersistentDocumentState mod; | 136 | iPersistentDocumentState mod; |
132 | int flags; | 137 | int flags; |
138 | enum iDocumentLinkOrdinalMode ordinalMode; | ||
133 | iString * titleUser; | 139 | iString * titleUser; |
134 | iGmRequest * request; | 140 | iGmRequest * request; |
135 | iAtomicInt isRequestUpdated; /* request has new content, need to parse it */ | 141 | iAtomicInt isRequestUpdated; /* request has new content, need to parse it */ |
@@ -228,7 +234,6 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
228 | addAction_Widget(w, navigateForward_KeyShortcut, "navigate.forward"); | 234 | addAction_Widget(w, navigateForward_KeyShortcut, "navigate.forward"); |
229 | addAction_Widget(w, navigateParent_KeyShortcut, "navigate.parent"); | 235 | addAction_Widget(w, navigateParent_KeyShortcut, "navigate.parent"); |
230 | addAction_Widget(w, navigateRoot_KeyShortcut, "navigate.root"); | 236 | addAction_Widget(w, navigateRoot_KeyShortcut, "navigate.root"); |
231 | addAction_Widget(w, 'f', 0, "document.linkkeys"); | ||
232 | } | 237 | } |
233 | 238 | ||
234 | void deinit_DocumentWidget(iDocumentWidget *d) { | 239 | void deinit_DocumentWidget(iDocumentWidget *d) { |
@@ -371,6 +376,15 @@ static void invalidateLink_DocumentWidget_(iDocumentWidget *d, iGmLinkId id) { | |||
371 | } | 376 | } |
372 | } | 377 | } |
373 | 378 | ||
379 | static void invalidateVisibleLinks_DocumentWidget_(iDocumentWidget *d) { | ||
380 | iConstForEach(PtrArray, i, &d->visibleLinks) { | ||
381 | const iGmRun *run = i.ptr; | ||
382 | if (run->linkId) { | ||
383 | insert_PtrSet(d->invalidRuns, run); | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
374 | static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { | 388 | static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { |
375 | const iWidget *w = constAs_Widget(d); | 389 | const iWidget *w = constAs_Widget(d); |
376 | const iRect docBounds = documentBounds_DocumentWidget_(d); | 390 | const iRect docBounds = documentBounds_DocumentWidget_(d); |
@@ -969,7 +983,7 @@ static void smoothScroll_DocumentWidget_(iDocumentWidget *d, int offset, int dur | |||
969 | /* Get rid of link numbers when scrolling. */ | 983 | /* Get rid of link numbers when scrolling. */ |
970 | if (offset && d->flags & showLinkNumbers_DocumentWidgetFlag) { | 984 | if (offset && d->flags & showLinkNumbers_DocumentWidgetFlag) { |
971 | d->flags &= ~showLinkNumbers_DocumentWidgetFlag; | 985 | d->flags &= ~showLinkNumbers_DocumentWidgetFlag; |
972 | invalidate_DocumentWidget_(d); | 986 | invalidateVisibleLinks_DocumentWidget_(d); |
973 | } | 987 | } |
974 | if (!prefs_App()->smoothScrolling) { | 988 | if (!prefs_App()->smoothScrolling) { |
975 | duration = 0; /* always instant */ | 989 | duration = 0; /* always instant */ |
@@ -1542,8 +1556,14 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1542 | return iTrue; | 1556 | return iTrue; |
1543 | } | 1557 | } |
1544 | else if (equal_Command(cmd, "document.linkkeys") && document_App() == d) { | 1558 | else if (equal_Command(cmd, "document.linkkeys") && document_App() == d) { |
1545 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iTrue); | 1559 | if (argLabel_Command(cmd, "release")) { |
1546 | invalidate_DocumentWidget_(d); | 1560 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); |
1561 | } | ||
1562 | else { | ||
1563 | d->ordinalMode = arg_Command(cmd); | ||
1564 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iTrue); | ||
1565 | } | ||
1566 | invalidateVisibleLinks_DocumentWidget_(d); | ||
1547 | refresh_Widget(d); | 1567 | refresh_Widget(d); |
1548 | return iTrue; | 1568 | return iTrue; |
1549 | } | 1569 | } |
@@ -1815,45 +1835,75 @@ static iBool processPlayerEvents_DocumentWidget_(iDocumentWidget *d, const SDL_E | |||
1815 | return iFalse; | 1835 | return iFalse; |
1816 | } | 1836 | } |
1817 | 1837 | ||
1818 | static size_t linkOrdinalFromKey_(int key) { | 1838 | /* Sorted by proximity to F and J. */ |
1819 | if (key >= '1' && key <= '9') { | 1839 | static const int homeRowKeys_[] = { |
1820 | return key - '1'; | 1840 | 'f', 'd', 's', 'a', |
1821 | } | 1841 | 'j', 'k', 'l', |
1822 | if (key < 'a' || key > 'z') { | 1842 | 'r', 'e', 'w', 'q', |
1823 | return iInvalidPos; | 1843 | 'u', 'i', 'o', 'p', |
1824 | } | 1844 | 'v', 'c', 'x', 'z', |
1825 | int ord = key - 'a' + 9; | 1845 | 'm', 'n', |
1846 | 'g', 'h', | ||
1847 | 'b', | ||
1848 | 't', 'y', 'u', | ||
1849 | }; | ||
1850 | |||
1851 | static size_t linkOrdinalFromKey_DocumentWidget_(const iDocumentWidget *d, int key) { | ||
1852 | size_t ord = iInvalidPos; | ||
1853 | if (d->ordinalMode == numbersAndAlphabet_DocumentLinkOrdinalMode) { | ||
1854 | if (key >= '1' && key <= '9') { | ||
1855 | return key - '1'; | ||
1856 | } | ||
1857 | if (key < 'a' || key > 'z') { | ||
1858 | return iInvalidPos; | ||
1859 | } | ||
1860 | ord = key - 'a' + 9; | ||
1826 | #if defined (iPlatformApple) | 1861 | #if defined (iPlatformApple) |
1827 | /* Skip keys that would conflict with default system shortcuts: hide, minimize, quit, close. */ | 1862 | /* Skip keys that would conflict with default system shortcuts: hide, minimize, quit, close. */ |
1828 | if (key == 'h' || key == 'm' || key == 'q' || key == 'w') { | 1863 | if (key == 'h' || key == 'm' || key == 'q' || key == 'w') { |
1829 | return iInvalidPos; | 1864 | return iInvalidPos; |
1830 | } | 1865 | } |
1831 | if (key > 'h') ord--; | 1866 | if (key > 'h') ord--; |
1832 | if (key > 'm') ord--; | 1867 | if (key > 'm') ord--; |
1833 | if (key > 'q') ord--; | 1868 | if (key > 'q') ord--; |
1834 | if (key > 'w') ord--; | 1869 | if (key > 'w') ord--; |
1835 | #endif | 1870 | #endif |
1871 | } | ||
1872 | else { | ||
1873 | iForIndices(i, homeRowKeys_) { | ||
1874 | if (homeRowKeys_[i] == key) { | ||
1875 | return i; | ||
1876 | } | ||
1877 | } | ||
1878 | } | ||
1836 | return ord; | 1879 | return ord; |
1837 | } | 1880 | } |
1838 | 1881 | ||
1839 | static iChar linkOrdinalChar_(size_t ord) { | 1882 | static iChar linkOrdinalChar_DocumentWidget_(const iDocumentWidget *d, size_t ord) { |
1840 | if (ord < 9) { | 1883 | if (d->ordinalMode == numbersAndAlphabet_DocumentLinkOrdinalMode) { |
1841 | return 0x278a + ord; | 1884 | if (ord < 9) { |
1842 | } | 1885 | return 0x278a + ord; |
1886 | } | ||
1843 | #if defined (iPlatformApple) | 1887 | #if defined (iPlatformApple) |
1844 | if (ord < 9 + 22) { | 1888 | if (ord < 9 + 22) { |
1845 | int key = 'a' + ord - 9; | 1889 | int key = 'a' + ord - 9; |
1846 | if (key >= 'h') key++; | 1890 | if (key >= 'h') key++; |
1847 | if (key >= 'm') key++; | 1891 | if (key >= 'm') key++; |
1848 | if (key >= 'q') key++; | 1892 | if (key >= 'q') key++; |
1849 | if (key >= 'w') key++; | 1893 | if (key >= 'w') key++; |
1850 | return 0x24b6 + key - 'a'; | 1894 | return 0x24b6 + key - 'a'; |
1851 | } | 1895 | } |
1852 | #else | 1896 | #else |
1853 | if (ord < 9 + 26) { | 1897 | if (ord < 9 + 26) { |
1854 | return 0x24b6 + ord - 9; | 1898 | return 0x24b6 + ord - 9; |
1855 | } | 1899 | } |
1856 | #endif | 1900 | #endif |
1901 | } | ||
1902 | else { | ||
1903 | if (ord < iElemCount(homeRowKeys_)) { | ||
1904 | return 0x24b6 + homeRowKeys_[ord] - 'a'; | ||
1905 | } | ||
1906 | } | ||
1857 | return 0; | 1907 | return 0; |
1858 | } | 1908 | } |
1859 | 1909 | ||
@@ -1866,31 +1916,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
1866 | } | 1916 | } |
1867 | return iTrue; | 1917 | return iTrue; |
1868 | } | 1918 | } |
1869 | if (ev->type == SDL_KEYUP) { | ||
1870 | const int key = ev->key.keysym.sym; | ||
1871 | switch (key) { | ||
1872 | case SDLK_LALT: | ||
1873 | case SDLK_RALT: | ||
1874 | if (document_App() == d) { | ||
1875 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); | ||
1876 | invalidate_DocumentWidget_(d); | ||
1877 | refresh_Widget(w); | ||
1878 | } | ||
1879 | break; | ||
1880 | case SDLK_PAGEUP: | ||
1881 | case SDLK_PAGEDOWN: | ||
1882 | case SDLK_SPACE: | ||
1883 | case SDLK_UP: | ||
1884 | case SDLK_DOWN: | ||
1885 | // d->smoothContinue = iFalse; | ||
1886 | break; | ||
1887 | } | ||
1888 | } | ||
1889 | if (ev->type == SDL_KEYDOWN) { | 1919 | if (ev->type == SDL_KEYDOWN) { |
1890 | const int key = ev->key.keysym.sym; | 1920 | const int key = ev->key.keysym.sym; |
1891 | if ((d->flags & showLinkNumbers_DocumentWidgetFlag) && | 1921 | if ((d->flags & showLinkNumbers_DocumentWidgetFlag) && |
1892 | ((key >= '1' && key <= '9') || (key >= 'a' && key <= 'z'))) { | 1922 | ((key >= '1' && key <= '9') || (key >= 'a' && key <= 'z'))) { |
1893 | const size_t ord = linkOrdinalFromKey_(key); | 1923 | const size_t ord = linkOrdinalFromKey_DocumentWidget_(d, key); |
1894 | iConstForEach(PtrArray, i, &d->visibleLinks) { | 1924 | iConstForEach(PtrArray, i, &d->visibleLinks) { |
1895 | if (ord == iInvalidPos) break; | 1925 | if (ord == iInvalidPos) break; |
1896 | const iGmRun *run = i.ptr; | 1926 | const iGmRun *run = i.ptr; |
@@ -1904,6 +1934,8 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
1904 | cstr_String(absoluteUrl_String( | 1934 | cstr_String(absoluteUrl_String( |
1905 | d->mod.url, linkUrl_GmDocument(d->doc, run->linkId)))); | 1935 | d->mod.url, linkUrl_GmDocument(d->doc, run->linkId)))); |
1906 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); | 1936 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); |
1937 | invalidateVisibleLinks_DocumentWidget_(d); | ||
1938 | refresh_Widget(d); | ||
1907 | return iTrue; | 1939 | return iTrue; |
1908 | } | 1940 | } |
1909 | } | 1941 | } |
@@ -1912,19 +1944,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
1912 | case SDLK_ESCAPE: | 1944 | case SDLK_ESCAPE: |
1913 | if (d->flags & showLinkNumbers_DocumentWidgetFlag && document_App() == d) { | 1945 | if (d->flags & showLinkNumbers_DocumentWidgetFlag && document_App() == d) { |
1914 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); | 1946 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); |
1915 | invalidate_DocumentWidget_(d); | 1947 | invalidateVisibleLinks_DocumentWidget_(d); |
1916 | refresh_Widget(d); | 1948 | refresh_Widget(d); |
1917 | return iTrue; | 1949 | return iTrue; |
1918 | } | 1950 | } |
1919 | break; | 1951 | break; |
1920 | case SDLK_LALT: | ||
1921 | case SDLK_RALT: | ||
1922 | if (document_App() == d) { | ||
1923 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iTrue); | ||
1924 | invalidate_DocumentWidget_(d); | ||
1925 | refresh_Widget(w); | ||
1926 | } | ||
1927 | break; | ||
1928 | #if 1 | 1952 | #if 1 |
1929 | case SDLK_KP_1: | 1953 | case SDLK_KP_1: |
1930 | case '`': { | 1954 | case '`': { |
@@ -2374,11 +2398,11 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
2374 | else { | 2398 | else { |
2375 | if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { | 2399 | if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { |
2376 | const size_t ord = visibleLinkOrdinal_DocumentWidget_(d->widget, run->linkId); | 2400 | const size_t ord = visibleLinkOrdinal_DocumentWidget_(d->widget, run->linkId); |
2377 | const iChar ordChar = linkOrdinalChar_(ord); | 2401 | const iChar ordChar = linkOrdinalChar_DocumentWidget_(d->widget, ord); |
2378 | if (ordChar) { | 2402 | if (ordChar) { |
2379 | drawString_Text(run->font, | 2403 | drawString_Text(run->font, |
2380 | init_I2(d->viewPos.x - gap_UI / 3, visPos.y), | 2404 | init_I2(d->viewPos.x - gap_UI / 3, visPos.y), |
2381 | fg, | 2405 | tmQuote_ColorId, |
2382 | collect_String(newUnicodeN_String(&ordChar, 1))); | 2406 | collect_String(newUnicodeN_String(&ordChar, 1))); |
2383 | goto runDrawn; | 2407 | goto runDrawn; |
2384 | } | 2408 | } |
diff --git a/src/ui/keys.c b/src/ui/keys.c index ea874343..d42ecfba 100644 --- a/src/ui/keys.c +++ b/src/ui/keys.c | |||
@@ -57,7 +57,8 @@ static void clear_Keys_(iKeys *d) { | |||
57 | } | 57 | } |
58 | 58 | ||
59 | enum iBindFlag { | 59 | enum iBindFlag { |
60 | argRepeat_BindFlag = iBit(1), | 60 | argRepeat_BindFlag = iBit(1), |
61 | argRelease_BindFlag = iBit(2), | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | /* TODO: This indirection could be used for localization, although all UI strings | 64 | /* TODO: This indirection could be used for localization, although all UI strings |
@@ -73,7 +74,8 @@ static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] = | |||
73 | { 31, { "Go forward", navigateForward_KeyShortcut, "navigate.forward" }, 0 }, | 74 | { 31, { "Go forward", navigateForward_KeyShortcut, "navigate.forward" }, 0 }, |
74 | { 32, { "Go to parent directory", navigateParent_KeyShortcut, "navigate.parent" }, 0 }, | 75 | { 32, { "Go to parent directory", navigateParent_KeyShortcut, "navigate.parent" }, 0 }, |
75 | { 33, { "Go to site root", navigateRoot_KeyShortcut, "navigate.root" }, 0 }, | 76 | { 33, { "Go to site root", navigateRoot_KeyShortcut, "navigate.root" }, 0 }, |
76 | { 40, { "Open link via keyboard", 'f', 0, "document.linkkeys" }, 0 }, | 77 | { 40, { "Open link via home row keys", 'f', 0, "document.linkkeys arg:1" }, 0 }, |
78 | { 41, { "Open link via modifier key", SDLK_LALT, 0, "document.linkkeys arg:0" }, argRelease_BindFlag }, | ||
77 | /* The following cannot currently be changed (built-in duplicates). */ | 79 | /* The following cannot currently be changed (built-in duplicates). */ |
78 | { 1000, { NULL, SDLK_SPACE, KMOD_SHIFT, "scroll.page arg:-1" }, argRepeat_BindFlag }, | 80 | { 1000, { NULL, SDLK_SPACE, KMOD_SHIFT, "scroll.page arg:-1" }, argRepeat_BindFlag }, |
79 | { 1001, { NULL, SDLK_SPACE, 0, "scroll.page arg:1" }, argRepeat_BindFlag }, | 81 | { 1001, { NULL, SDLK_SPACE, 0, "scroll.page arg:1" }, argRepeat_BindFlag }, |
@@ -110,6 +112,11 @@ static void bindDefaults_(void) { | |||
110 | 112 | ||
111 | static iBinding *find_Keys_(iKeys *d, int key, int mods) { | 113 | static iBinding *find_Keys_(iKeys *d, int key, int mods) { |
112 | size_t pos; | 114 | size_t pos; |
115 | /* Do not differentiate between left and right modifier keys. */ | ||
116 | key = normalizedMod_Sym(key); | ||
117 | if (isMod_Sym(key)) { | ||
118 | mods = 0; | ||
119 | } | ||
113 | const iBinding elem = { .key = key, .mods = mods }; | 120 | const iBinding elem = { .key = key, .mods = mods }; |
114 | if (locate_PtrSet(&d->lookup, &elem, &pos)) { | 121 | if (locate_PtrSet(&d->lookup, &elem, &pos)) { |
115 | return at_PtrSet(&d->lookup, pos); | 122 | return at_PtrSet(&d->lookup, pos); |
@@ -138,8 +145,8 @@ static void updateLookup_Keys_(iKeys *d) { | |||
138 | void setKey_Binding(int id, int key, int mods) { | 145 | void setKey_Binding(int id, int key, int mods) { |
139 | iBinding *bind = findId_Keys_(&keys_, id); | 146 | iBinding *bind = findId_Keys_(&keys_, id); |
140 | if (bind) { | 147 | if (bind) { |
141 | bind->key = key; | 148 | bind->key = normalizedMod_Sym(key); |
142 | bind->mods = mods; | 149 | bind->mods = isMod_Sym(key) ? 0 : mods; |
143 | updateLookup_Keys_(&keys_); | 150 | updateLookup_Keys_(&keys_); |
144 | } | 151 | } |
145 | } | 152 | } |
@@ -252,25 +259,18 @@ void setLabel_Keys(int id, const char *label) { | |||
252 | } | 259 | } |
253 | } | 260 | } |
254 | 261 | ||
255 | #if 0 | ||
256 | const iString *label_Keys(const char *command) { | ||
257 | iKeys *d = &keys_; | ||
258 | /* TODO: A hash wouldn't hurt here. */ | ||
259 | iConstForEach(PtrSet, i, &d->bindings) { | ||
260 | const iBinding *bind = *i.value; | ||
261 | if (!cmp_String(&bind->command, command) && !isEmpty_String(&bind->label)) { | ||
262 | return &bind->label; | ||
263 | } | ||
264 | } | ||
265 | return collectNew_String(); | ||
266 | } | ||
267 | #endif | ||
268 | |||
269 | iBool processEvent_Keys(const SDL_Event *ev) { | 262 | iBool processEvent_Keys(const SDL_Event *ev) { |
270 | iKeys *d = &keys_; | 263 | iKeys *d = &keys_; |
271 | if (ev->type == SDL_KEYDOWN) { | 264 | if (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) { |
272 | const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod)); | 265 | const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod)); |
273 | if (bind) { | 266 | if (bind) { |
267 | if (ev->type == SDL_KEYUP) { | ||
268 | if (bind->flags & argRelease_BindFlag) { | ||
269 | postCommandf_App("%s release:1", cstr_String(&bind->command)); | ||
270 | return iTrue; | ||
271 | } | ||
272 | return iFalse; | ||
273 | } | ||
274 | if (ev->key.repeat && (bind->flags & argRepeat_BindFlag)) { | 274 | if (ev->key.repeat && (bind->flags & argRepeat_BindFlag)) { |
275 | postCommandf_App("%s repeat:1", cstr_String(&bind->command)); | 275 | postCommandf_App("%s repeat:1", cstr_String(&bind->command)); |
276 | } | 276 | } |
diff --git a/src/ui/util.c b/src/ui/util.c index 559c5381..c1312062 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -117,6 +117,14 @@ iBool isMod_Sym(int key) { | |||
117 | key == SDLK_LGUI || key == SDLK_RGUI || key == SDLK_LSHIFT || key == SDLK_RSHIFT; | 117 | key == SDLK_LGUI || key == SDLK_RGUI || key == SDLK_LSHIFT || key == SDLK_RSHIFT; |
118 | } | 118 | } |
119 | 119 | ||
120 | int normalizedMod_Sym(int key) { | ||
121 | if (key == SDLK_RSHIFT) key = SDLK_LSHIFT; | ||
122 | if (key == SDLK_RCTRL) key = SDLK_LCTRL; | ||
123 | if (key == SDLK_RALT) key = SDLK_LALT; | ||
124 | if (key == SDLK_RGUI) key = SDLK_LGUI; | ||
125 | return key; | ||
126 | } | ||
127 | |||
120 | int keyMods_Sym(int kmods) { | 128 | int keyMods_Sym(int kmods) { |
121 | kmods &= (KMOD_SHIFT | KMOD_ALT | KMOD_CTRL | KMOD_GUI); | 129 | kmods &= (KMOD_SHIFT | KMOD_ALT | KMOD_CTRL | KMOD_GUI); |
122 | /* Don't treat left/right modifiers differently. */ | 130 | /* Don't treat left/right modifiers differently. */ |
diff --git a/src/ui/util.h b/src/ui/util.h index c0e3a04c..f7a67f9a 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -49,6 +49,7 @@ iLocalDef iBool isResize_UserEvent(const SDL_Event *d) { | |||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | iBool isMod_Sym (int key); | 51 | iBool isMod_Sym (int key); |
52 | int normalizedMod_Sym (int key); | ||
52 | int keyMods_Sym (int kmods); /* shift, alt, control, or gui */ | 53 | int keyMods_Sym (int kmods); /* shift, alt, control, or gui */ |
53 | void toString_Sym (int key, int kmods, iString *str); | 54 | void toString_Sym (int key, int kmods, iString *str); |
54 | 55 | ||