Skip to content

switch virtual keyboard default to false on hasKeyboard#15057

Merged
Frenzie merged 11 commits into
koreader:masterfrom
Commodore64user:vk-default
Mar 7, 2026
Merged

switch virtual keyboard default to false on hasKeyboard#15057
Frenzie merged 11 commits into
koreader:masterfrom
Commodore64user:vk-default

Conversation

@Commodore64user

@Commodore64user Commodore64user commented Mar 1, 2026

Copy link
Copy Markdown
Member

what's new

  • In reader.lua, the code now automatically disables the virtual keyboard on devices with physical keyboards, and enables it by default on devices with screen keyboards if the setting is not already set. This prevents the setting from being nil and ensures a sensible default for each device type.
  • In menu_keyboard_layout.lua, the logic for checking and toggling the virtual keyboard setting has been updated to use explicit boolean values (true or false) instead of possibly nil, and the toggle callback now directly saves the new value rather than flipping a nil-or-true state.
  • related to Switch virtual_keyboard_enabled default to false on hasKeyboard and hasScreenKB #15056

This change is Reviewable

@Commodore64user

Copy link
Copy Markdown
Member Author

how is this my fault?

Luacheck results
Checking frontend/ui/widget/bookstatuswidget.lua  1 warning

    frontend/ui/widget/bookstatuswidget.lua:15:7: unused variable InputContainer

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

No, it's macOS's fault for always failing which trains me not to pay attention to red crosses.

This PR in this form is too hacky for me I'm afraid. Plus as a result it only works in the reader.

@poire-z

poire-z commented Mar 2, 2026

Copy link
Copy Markdown
Contributor

This PR in this form is too hacky for me I'm afraid. Plus as a result it only works in the reader.

I also got confused :) it's the startup script reader.lua, not the frontend/apps/reader/readerui.lua.
There's a similar bit of code below about color rendering, but it might be there in reader.lua because there's some possible InfoMessage being displayed.
For this one, just setting a setting if absent, I don't know if one of our 2 modules dealing with migration isn't a better place - or if it's just right to have it here.

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

Yes, the color rendering is set there to avoid the need to track message shown separately. It doesn't strike me as comparable.

Migration doesn't make sense. There's nothing to be migrated.

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

I also got confused :) it's the startup script reader.lua, not the frontend/apps/reader/readerui.lua.

To be clear, the tangential remark does not relate to what I'm calling hacky. I do not intend to doom everyone to on or off as a quick hack to avoid changing code.

The behavior should act like a Device:shouldShowVirtualKeyboard(), regardless whether such an abstraction is added or not, which can then be sensibly used for an on/off/auto setting, where nil is auto.

@Commodore64user

Commodore64user commented Mar 2, 2026

Copy link
Copy Markdown
Member Author

On a new installation, the first thing we open is the quick start guide (reader), which is why it is set there.

No one is saying "doom every one to on off", to avoid changing code. I'm saying the default needs to change regardless. ;)

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

The default value of the setting needs to remain nil. It's the behavior that needs to change, and changing behavior through a setting is a hack.

@Commodore64user

Copy link
Copy Markdown
Member Author

The thing is, switching nil to falsy means i still need to "hack hasScreenKB to true" might as well force a strict true or false

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

It needs to deal properly with actions like plugging keyboards in and out and switching between gamepads and keyboards.[1] A strict true or false would "doom every one to on [or] off" and require manually setting it back to auto once that is implemented.

[1] In theory this applies on all of Kindle, Kobo, Android, and desktop Linux/Mac. In practice some of them might be harder than others, but that's all on a lower level.

"hack hasScreenKB to true"

That's not a hack. That is the only proper way to do it.

@Commodore64user

Copy link
Copy Markdown
Member Author

whether you connect or disconnect a keyboard won't matter, we always check both things hasKeyboard and isFalse, disconnected keyboard? well you are no longer hasKeyboard then. It already works automagically

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

I don't much care what does or doesn't happen to work. I care that there are no surprise hacks in the code so that it is comprehensible and thereby maintainable.

whether you connect or disconnect a keyboard won't matter, we always check both things hasKeyboard and isFalse, disconnected keyboard? well you are no longer hasKeyboard then. It already works automagically

But fwiw, that's not true precisely because this is a hack applied on startup rather than a proper extensive code change.

  1. Start program without keyboard (hack doesn't activate)
  2. Plug in/connect keyboard
  3. See virtual keyboard

The setting should be left nil as default so that default can properly evolve.

This very change is a quick hack to allow for a release, but that doesn't mean it should be a literal hack.

@Commodore64user

Copy link
Copy Markdown
Member Author

there is still the making hasScreenKB true, which I don't know where the best place to do it is

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

Neat, thanks.

I'd be inclined to suggest to put an abstraction in VirtualKeyboard itself, but I see that won't do because of virtual vs physical.

@Commodore64user

Copy link
Copy Markdown
Member Author

I'll let you think about that, because it needs to happen once, and only once. I was also trying to avoid needing yet another boolean to track that single change.

@Commodore64user

Copy link
Copy Markdown
Member Author

Am i correct in thinking that the migration applies to new installs as well?

@Frenzie

Frenzie commented Mar 2, 2026

Copy link
Copy Markdown
Member

It would. I'm not the biggest fan of doing it that way but it is nicely self-contained. 🤔

@Commodore64user

Copy link
Copy Markdown
Member Author

well, if you have a better idea, feel free to change it, otherwise, that that that That's all Folks!

@Commodore64user

Copy link
Copy Markdown
Member Author

unsure about this?

on another note, it is a very lovely day today, so I thought I'd share the cheer by saying hello @poire-z and @Frenzie hope you are having a nice day too.

@Frenzie

Frenzie commented Mar 5, 2026

Copy link
Copy Markdown
Member

Bear with me because this is poc stuff with slightly excessive duplication, but what do you think about this concept?

diff --git a/frontend/ui/data/onetime_migration.lua b/frontend/ui/data/onetime_migration.lua
index 4b8e0fe5e..544425761 100644
--- a/frontend/ui/data/onetime_migration.lua
+++ b/frontend/ui/data/onetime_migration.lua
@@ -12,7 +12,7 @@ local util = require("util")
 local _ = require("gettext")
 
 -- Date at which the last migration snippet was added
-local CURRENT_MIGRATION_DATE = 20260302
+local CURRENT_MIGRATION_DATE = 20250929
 
 -- Retrieve the date of the previous migration, if any
 local last_migration_date = G_reader_settings:readSetting("last_migration_date", 0)
@@ -945,16 +945,5 @@ if last_migration_date < 20250929 then
     end
 end
 
--- 20260302, Enable virtual keyboard on kindle 4
--- https://github.com/koreader/koreader/pull/15057
-if last_migration_date < 20260302 then
-    logger.info("Performing one-time migration for 20260302")
-
-    local Device = require("device")
-    if Device:hasScreenKB() and G_reader_settings:hasNot("virtual_keyboard_enabled") then
-        G_reader_settings:makeTrue("virtual_keyboard_enabled")
-    end
-end
-
 -- We're done, store the current migration date
 G_reader_settings:saveSetting("last_migration_date", CURRENT_MIGRATION_DATE)
diff --git a/frontend/ui/elements/menu_keyboard_layout.lua b/frontend/ui/elements/menu_keyboard_layout.lua
index bee009d8b..e1ee7d020 100644
--- a/frontend/ui/elements/menu_keyboard_layout.lua
+++ b/frontend/ui/elements/menu_keyboard_layout.lua
@@ -16,6 +16,11 @@ local _ = require("gettext")
 
 local input_dialog, check_button_bold, check_button_border, check_button_compact
 
+local function isVirtualKeyboardEnabled()
+    return G_reader_settings:isTrue("virtual_keyboard_enabled")
+        or Device:hasScreenKB() and G_reader_settings:hasNot("virtual_keyboard_enabled")
+end
+
 local function getOrderedActivatedKeyboardLayouts()
     local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {})
     local activated_keyboards = {}
@@ -164,7 +169,7 @@ local sub_item_table = {
         text = _("Keyboard appearance settings"),
         keep_menu_open = true,
         enabled_func = function()
-            return G_reader_settings:isTrue("virtual_keyboard_enabled") or (Device:isTouchDevice() and not Device:hasKeyboard())
+            return isVirtualKeyboardEnabled() or (Device:isTouchDevice() and not Device:hasKeyboard())
         end,
         callback = function(touchmenu_instance)
             local InputDialog = require("ui/widget/inputdialog")
@@ -233,11 +238,15 @@ if Device:hasKeyboard() or Device:hasScreenKB() then
         text = _("Show virtual keyboard"),
         help_text = _("Enable this setting to always display the virtual keyboard within a text input field. When a field is selected (in focus), you can temporarily toggle the keyboard on/off by pressing 'Shift' (or 'ScreenKB') + 'Home'."),
         checked_func = function()
-            return G_reader_settings:isTrue("virtual_keyboard_enabled")
+            return isVirtualKeyboardEnabled()
         end,
         callback = function()
-            G_reader_settings:flipNilOrFalse("virtual_keyboard_enabled")
-            if G_reader_settings:nilOrFalse("virtual_keyboard_enabled") then
+            if Device:hasScreenKB() and G_reader_settings:hasNot("virtual_keyboard_enabled") then
+                G_reader_settings:makeFalse("virtual_keyboard_enabled")
+            else
+                G_reader_settings:flipNilOrFalse("virtual_keyboard_enabled")
+            end
+            if not isVirtualKeyboardEnabled() then
                 local keyboard_infomessage
                 if Device:hasScreenKB() then
                     keyboard_infomessage = _("When a text field is selected (in focus), you can temporarily bring up the virtual keyboard by pressing 'ScreenKB' + 'Home'.")
diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua
index fd5baa402..032f5697f 100644
--- a/frontend/ui/widget/inputdialog.lua
+++ b/frontend/ui/widget/inputdialog.lua
@@ -120,6 +120,11 @@ local T = require("ffi/util").template
 local util = require("util")
 local _ = require("gettext")
 
+local function isVirtualKeyboardEnabled()
+    return G_reader_settings:isTrue("virtual_keyboard_enabled")
+        or Device:hasScreenKB() and G_reader_settings:hasNot("virtual_keyboard_enabled")
+end
+
 local InputDialog = FocusManager:extend{
     is_always_active = true,
     title = "",
@@ -223,7 +228,7 @@ function InputDialog:init()
     if self.fullscreen or self.add_nav_bar then
         self.deny_keyboard_hiding = true
     end
-    if (Device:hasKeyboard() or Device:hasScreenKB()) and G_reader_settings:nilOrFalse("virtual_keyboard_enabled") then
+    if (Device:hasKeyboard() or Device:hasScreenKB()) and not isVirtualKeyboardEnabled() then
         self.keyboard_visible = false
         self.skip_first_show_keyboard = true
     end
@@ -642,7 +647,7 @@ function InputDialog:isKeyboardVisible()
 end
 
 function InputDialog:lockKeyboard(toggle)
-    if (Device:hasKeyboard() or Device:hasScreenKB()) and G_reader_settings:nilOrFalse("virtual_keyboard_enabled") then
+    if (Device:hasKeyboard() or Device:hasScreenKB()) and not isVirtualKeyboardEnabled() then
         -- do not lock the virtual keyboard when user is hiding it, we still *might* want to activate it via shortcuts ("Shift" + "Home") when in need of special characters or symbols
         return
     end
diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua
index 1557bcb8d..054a5fd5f 100644
--- a/frontend/ui/widget/inputtext.lua
+++ b/frontend/ui/widget/inputtext.lua
@@ -18,6 +18,11 @@ local util = require("util")
 local _ = require("gettext")
 local Screen = Device.screen
 
+local function isVirtualKeyboardEnabled()
+    return G_reader_settings:isTrue("virtual_keyboard_enabled")
+        or Device:hasScreenKB() and G_reader_settings:hasNot("virtual_keyboard_enabled")
+end
+
 local Keyboard -- Conditional instantiation
 local FocusManagerInstance -- Delayed instantiation
 
@@ -142,7 +147,7 @@ local function initTouchEvents()
             if self.parent.onSwitchFocus then
                 self.parent:onSwitchFocus(self)
             else
-                if not ((Device:hasKeyboard() or Device:hasScreenKB()) and G_reader_settings:nilOrFalse("virtual_keyboard_enabled")) then
+                if not ((Device:hasKeyboard() or Device:hasScreenKB()) and not isVirtualKeyboardEnabled()) then
                     self:onShowKeyboard()
                 end
                 Device:startTextInput()
@@ -209,7 +214,7 @@ local function initDPadEvents()
             -- Event sent by focusmanager
             if self.parent.onSwitchFocus then
                 self.parent:onSwitchFocus(self)
-            elseif (Device:hasKeyboard() or Device:hasScreenKB()) and G_reader_settings:nilOrFalse("virtual_keyboard_enabled") then
+            elseif (Device:hasKeyboard() or Device:hasScreenKB()) and not isVirtualKeyboardEnabled() then
                 do end -- luacheck: ignore 541
             else
                 if not self:isKeyboardVisible() then
diff --git a/frontend/ui/widget/multiinputdialog.lua b/frontend/ui/widget/multiinputdialog.lua
index 1460c19e8..ed818a381 100644
--- a/frontend/ui/widget/multiinputdialog.lua
+++ b/frontend/ui/widget/multiinputdialog.lua
@@ -91,6 +91,11 @@ local VerticalSpan = require("ui/widget/verticalspan")
 local _ = require("gettext")
 local Screen = Device.screen
 
+local function isVirtualKeyboardEnabled()
+    return G_reader_settings:isTrue("virtual_keyboard_enabled")
+        or Device:hasScreenKB() and G_reader_settings:hasNot("virtual_keyboard_enabled")
+end
+
 local MultiInputDialog = InputDialog:extend{
     fields = nil, -- array, mandatory
     input_fields = nil, -- array
@@ -112,7 +117,7 @@ function MultiInputDialog:init()
 
     -- Reset self.keyboard_visible because InputDialog:onCloseKeyboard sets it to false, which can lead to an incorrect keyboard
     -- visibility state since we still might want our very own virtual keyboard.
-    if (Device:hasKeyboard() or Device:hasScreenKB()) and G_reader_settings:nilOrFalse("virtual_keyboard_enabled") then
+    if (Device:hasKeyboard() or Device:hasScreenKB()) and not isVirtualKeyboardEnabled() then
         do end -- luacheck: ignore 541
     elseif self.readonly then
         do end -- luacheck: ignore 541
@@ -263,7 +268,7 @@ function MultiInputDialog:onSwitchFocus(inputbox)
     self._input_widget:focus()
     self.focused_field_idx = inputbox.idx
 
-    if (Device:hasKeyboard() or Device:hasScreenKB()) and G_reader_settings:nilOrFalse("virtual_keyboard_enabled") then
+    if (Device:hasKeyboard() or Device:hasScreenKB()) and not isVirtualKeyboardEnabled() then
         -- do not load virtual keyboard when user is hiding it.
         return
     end

@Commodore64user

Copy link
Copy Markdown
Member Author

what do you think about this concept?

but why? I sure hope you have some sort of master plan I fail to envision because otherwise why? Sure migrating K4 feels a bit naughty but this seems over the top, I'd keep the migration, makes code simpler elsewhere

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

The correct behavior would look something like this:

  • keyboard, gamepad, pen and touch are all available
  • press key on keyboard → no virtual keyboard
  • press button on gamepad, use pen, use touch → virtual keyboard, but all keyboard functionality should always remain working; this is nothing like unplugging all keyboards

It requires some kind of device/input abstraction that might look a little bit like the function in the above diff, because why do the logic on every bit of input when asking to show the virtual keyboard happens significantly less frequently.

Except of course on that particular device the logic would simply be return false, using the = no assignment in device definitions.

Maybe if you stick your original concept in InputText or something for the moment (instead of reader.lua) with an xxx/todo on it?

@Commodore64user

Copy link
Copy Markdown
Member Author

something like that?

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

I didn't mean revert everything and return to the problematic behavior of dooming everyone to a forced setting. :-/ I just meant the migration code as not a migration.

@Commodore64user

Copy link
Copy Markdown
Member Author

Maybe if you stick your original concept

that is literally what you said, and stop saying doom, no one is being doomed to anything.

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

I apologize for the confusion.

@Commodore64user

Copy link
Copy Markdown
Member Author

but wait a sec, this isn't going to work.

that switch needs to happen only once, not every time. If I then decide that I don't want the keyboard to pop up, that should be respected... migration seems still the correct path

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

You made it check for hasNot. That should be fine in the context of this PR.

@Commodore64user

Commodore64user commented Mar 6, 2026

Copy link
Copy Markdown
Member Author

You made it check for hasNot. That should be fine in the context of this PR.

but if I flip it, flipNilOrFalse("virtual_keyboard_enabled") makes it nil again. 'No bueno'. It will always be True no matter what

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

I see, thanks.

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

With some aid from the new GPT-5.4 chatbot to write things faster, please try this concept. (Built on your 0519f70.) It demonstrates my vision in a very practical manner.

https://github.com/Frenzie/koreader/tree/virtual-keyboard-input-tracking
Frenzie@253088b

@Commodore64user

Copy link
Copy Markdown
Member Author

okay I see what you mean now, the vision for the future. I do hate auto mode though ;), just because I click on something the next time I try to find something, the vk pops up? no thanks, #TeamNever

@Frenzie

Frenzie commented Mar 6, 2026

Copy link
Copy Markdown
Member

I'd prefer to combine it with the keyboard show/hide button prototype, and perhaps touch and click should be disambiguated, but this form suffices to show the principle and possibly (with some final tweaks) for the release. I'll have to sleep on it.

In the meantime @poire-z are you okay with the migration in this PR as is? It needs to be a migration to ensure it runs only once.

@Frenzie Frenzie added this to the 2026.02 milestone Mar 6, 2026
@poire-z

poire-z commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Nothing against. (I don't really know what Device:hasScreenKB() is on Kindle).

@Commodore64user

Copy link
Copy Markdown
Member Author

Is a euphemism for kindle 4 ;)

@Frenzie Frenzie merged commit bed8f55 into koreader:master Mar 7, 2026
4 checks passed
end
end

-- 20260306, Screensaver message position refactor: top/middle/bottom -> banner/box with custom positioning

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the description correct?

@Frenzie

Frenzie commented Mar 18, 2026

Copy link
Copy Markdown
Member

An interesting side effect. (I'm not mentioning this as a silent hint; I just figured you might get a laugh out of it.)
image

@Commodore64user Commodore64user deleted the vk-default branch March 18, 2026 22:00
@Commodore64user

Copy link
Copy Markdown
Member Author

That’s not our “ugly” keyboard… i suppose we should compare vk.x <= widget.x+h and reposition accordingly

0xstillb pushed a commit to 0xstillb/koreader-thai that referenced this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants