2018-03-18 20:32:39 +00:00
|
|
|
local Event = require("ui/event")
|
2023-05-18 21:13:43 +00:00
|
|
|
local Geom = require("ui/geometry")
|
2014-10-30 18:42:18 +00:00
|
|
|
local Generic = require("device/generic/device")
|
2023-05-18 21:13:43 +00:00
|
|
|
local UIManager
|
2020-07-20 22:52:50 +00:00
|
|
|
local SDL = require("ffi/SDL2_0")
|
2022-07-02 19:12:05 +00:00
|
|
|
local ffi = require("ffi")
|
2016-12-29 08:10:38 +00:00
|
|
|
local logger = require("logger")
|
2022-07-09 20:47:10 +00:00
|
|
|
local time = require("ui/time")
|
2014-10-30 18:42:18 +00:00
|
|
|
|
2022-07-02 19:12:05 +00:00
|
|
|
-- SDL computes WM_CLASS on X11/Wayland based on process's binary name.
|
|
|
|
-- Some desktop environments rely on WM_CLASS to name the app and/or to assign the proper icon.
|
|
|
|
if jit.os == "Linux" or jit.os == "BSD" or jit.os == "POSIX" then
|
|
|
|
if not os.getenv("SDL_VIDEO_WAYLAND_WMCLASS") then ffi.C.setenv("SDL_VIDEO_WAYLAND_WMCLASS", "KOReader", 1) end
|
|
|
|
if not os.getenv("SDL_VIDEO_X11_WMCLASS") then ffi.C.setenv("SDL_VIDEO_X11_WMCLASS", "KOReader", 1) end
|
|
|
|
end
|
|
|
|
|
2014-10-30 18:42:18 +00:00
|
|
|
local function yes() return true end
|
2015-09-27 01:25:47 +00:00
|
|
|
local function no() return false end
|
2020-08-04 22:17:09 +00:00
|
|
|
local function notOSX() return jit.os ~= "OSX" end
|
2014-10-30 18:42:18 +00:00
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
local function isUrl(s)
|
|
|
|
return type(s) == "string" and s:match("*?://")
|
2019-08-20 16:38:02 +00:00
|
|
|
end
|
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
local function isCommand(s)
|
2023-02-17 22:12:49 +00:00
|
|
|
return os.execute("command -v "..s.." >/dev/null") == 0
|
2019-08-20 16:38:02 +00:00
|
|
|
end
|
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
local function runCommand(command)
|
2023-07-16 01:51:57 +00:00
|
|
|
return os.execute(command) == 0
|
2019-08-20 16:38:02 +00:00
|
|
|
end
|
|
|
|
|
2020-08-27 19:41:16 +00:00
|
|
|
local function getDesktopDicts()
|
|
|
|
local t = {
|
|
|
|
{ "Goldendict", "Goldendict", false, "goldendict" },
|
|
|
|
}
|
|
|
|
-- apple dict is always present in osx
|
|
|
|
if jit.os == "OSX" then
|
|
|
|
table.insert(t, 1, { "Apple", "AppleDict", false, "dict://" })
|
|
|
|
end
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
local function getLinkOpener()
|
|
|
|
if jit.os == "Linux" and isCommand("xdg-open") then
|
|
|
|
return true, "xdg-open"
|
|
|
|
elseif jit.os == "OSX" and isCommand("open") then
|
|
|
|
return true, "open"
|
2020-05-22 15:38:16 +00:00
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2020-08-27 19:41:16 +00:00
|
|
|
-- thirdparty app support
|
|
|
|
local external = require("device/thirdparty"):new{
|
|
|
|
dicts = getDesktopDicts(),
|
|
|
|
check = function(self, app)
|
|
|
|
if (isUrl(app) and getLinkOpener()) or isCommand(app) then
|
|
|
|
return true
|
2020-05-22 15:38:16 +00:00
|
|
|
end
|
2020-08-27 19:41:16 +00:00
|
|
|
return false
|
|
|
|
end,
|
|
|
|
}
|
2020-05-22 15:38:16 +00:00
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local Device = Generic:extend{
|
2015-10-03 06:18:47 +00:00
|
|
|
model = "SDL",
|
|
|
|
isSDL = yes,
|
2021-01-07 19:38:10 +00:00
|
|
|
home_dir = os.getenv("XDG_DOCUMENTS_DIR") or os.getenv("HOME"),
|
2021-07-25 21:29:30 +00:00
|
|
|
hasBattery = SDL.getPowerInfo,
|
2014-10-30 18:42:18 +00:00
|
|
|
hasKeyboard = yes,
|
|
|
|
hasKeys = yes,
|
2015-09-27 01:05:37 +00:00
|
|
|
hasDPad = yes,
|
2019-02-06 14:51:50 +00:00
|
|
|
hasWifiToggle = no,
|
2014-10-30 18:42:18 +00:00
|
|
|
isTouchDevice = yes,
|
2022-06-24 21:19:38 +00:00
|
|
|
isDefaultFullscreen = no,
|
2015-09-27 01:25:47 +00:00
|
|
|
needsScreenRefreshAfterResume = no,
|
2017-10-01 17:23:06 +00:00
|
|
|
hasColorScreen = yes,
|
2019-02-01 08:18:27 +00:00
|
|
|
hasEinkScreen = no,
|
2021-04-19 07:04:31 +00:00
|
|
|
hasSystemFonts = yes,
|
2020-06-19 07:41:50 +00:00
|
|
|
canSuspend = no,
|
2022-07-02 18:20:35 +00:00
|
|
|
canStandby = no,
|
2020-12-30 21:26:40 +00:00
|
|
|
startTextInput = SDL.startTextInput,
|
|
|
|
stopTextInput = SDL.stopTextInput,
|
2019-08-20 16:38:02 +00:00
|
|
|
canOpenLink = getLinkOpener,
|
2019-03-20 15:58:32 +00:00
|
|
|
openLink = function(self, link)
|
2019-08-20 16:38:02 +00:00
|
|
|
local enabled, tool = getLinkOpener()
|
|
|
|
if not enabled or not tool or not link or type(link) ~= "string" then return end
|
2020-07-20 20:37:00 +00:00
|
|
|
return runCommand(tool .. " '" .. link .. "'")
|
2020-05-22 15:38:16 +00:00
|
|
|
end,
|
|
|
|
canExternalDictLookup = yes,
|
2020-08-27 19:41:16 +00:00
|
|
|
getExternalDictLookupList = function() return external.dicts end,
|
2020-05-22 15:38:16 +00:00
|
|
|
doExternalDictLookup = function(self, text, method, callback)
|
2020-08-27 19:41:16 +00:00
|
|
|
external.when_back_callback = callback
|
|
|
|
local ok, app = external:checkMethod("dict", method)
|
|
|
|
if app then
|
|
|
|
if isUrl(app) and getLinkOpener() then
|
|
|
|
ok = self:openLink(app..text)
|
|
|
|
elseif isCommand(app) then
|
|
|
|
ok = runCommand(app .. " " .. text .. " &")
|
2020-05-22 15:38:16 +00:00
|
|
|
end
|
|
|
|
end
|
2020-08-27 19:41:16 +00:00
|
|
|
if ok and external.when_back_callback then
|
|
|
|
external.when_back_callback()
|
|
|
|
external.when_back_callback = nil
|
2020-05-22 15:38:16 +00:00
|
|
|
end
|
2019-03-20 15:58:32 +00:00
|
|
|
end,
|
2021-03-06 21:44:18 +00:00
|
|
|
window = G_reader_settings:readSetting("sdl_window", {}),
|
2014-10-30 18:42:18 +00:00
|
|
|
}
|
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local AppImage = Device:extend{
|
2019-01-03 17:21:35 +00:00
|
|
|
model = "AppImage",
|
2019-03-19 19:18:38 +00:00
|
|
|
hasMultitouch = no,
|
2019-02-21 07:26:48 +00:00
|
|
|
hasOTAUpdates = yes,
|
2019-08-20 16:38:02 +00:00
|
|
|
isDesktop = yes,
|
2019-01-03 17:21:35 +00:00
|
|
|
}
|
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local Desktop = Device:extend{
|
2020-07-20 22:52:50 +00:00
|
|
|
model = SDL.getPlatform(),
|
|
|
|
isDesktop = yes,
|
2020-08-04 22:17:09 +00:00
|
|
|
canRestart = notOSX,
|
|
|
|
hasExitOptions = notOSX,
|
2020-07-20 22:52:50 +00:00
|
|
|
}
|
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local Emulator = Device:extend{
|
2019-01-03 17:21:35 +00:00
|
|
|
model = "Emulator",
|
|
|
|
isEmulator = yes,
|
2020-07-20 22:52:50 +00:00
|
|
|
hasBattery = yes,
|
2019-02-01 08:18:27 +00:00
|
|
|
hasEinkScreen = yes,
|
2019-01-03 17:21:35 +00:00
|
|
|
hasFrontlight = yes,
|
2020-08-19 20:41:10 +00:00
|
|
|
hasNaturalLight = yes,
|
|
|
|
hasNaturalLightApi = yes,
|
2019-02-06 14:51:50 +00:00
|
|
|
hasWifiToggle = yes,
|
2022-07-02 18:20:35 +00:00
|
|
|
-- Not really, Device:reboot & Device:powerOff are not implemented, so we just exit ;).
|
2020-06-19 07:41:50 +00:00
|
|
|
canPowerOff = yes,
|
|
|
|
canReboot = yes,
|
2022-07-02 18:20:35 +00:00
|
|
|
-- NOTE: Via simulateSuspend
|
2020-06-19 07:41:50 +00:00
|
|
|
canSuspend = yes,
|
2022-07-02 18:20:35 +00:00
|
|
|
canStandby = no,
|
2019-01-03 17:21:35 +00:00
|
|
|
}
|
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local UbuntuTouch = Device:extend{
|
2019-01-03 17:21:35 +00:00
|
|
|
model = "UbuntuTouch",
|
|
|
|
hasFrontlight = yes,
|
2022-06-24 21:19:38 +00:00
|
|
|
isDefaultFullscreen = yes,
|
2019-01-03 17:21:35 +00:00
|
|
|
}
|
2016-01-31 22:56:05 +00:00
|
|
|
|
2014-10-30 18:42:18 +00:00
|
|
|
function Device:init()
|
2014-11-27 10:15:44 +00:00
|
|
|
-- allows to set a viewport via environment variable
|
|
|
|
-- syntax is Lua table syntax, e.g. EMULATE_READER_VIEWPORT="{x=10,w=550,y=5,h=790}"
|
|
|
|
local viewport = os.getenv("EMULATE_READER_VIEWPORT")
|
2020-07-20 20:37:00 +00:00
|
|
|
if viewport then
|
2014-11-27 10:15:44 +00:00
|
|
|
self.viewport = require("ui/geometry"):new(loadstring("return " .. viewport)())
|
|
|
|
end
|
2019-01-03 17:21:35 +00:00
|
|
|
|
|
|
|
local touchless = os.getenv("DISABLE_TOUCH") == "1"
|
2020-07-20 20:37:00 +00:00
|
|
|
if touchless then
|
2019-01-03 17:21:35 +00:00
|
|
|
self.isTouchDevice = no
|
|
|
|
end
|
|
|
|
|
2014-11-27 15:33:48 +00:00
|
|
|
local portrait = os.getenv("EMULATE_READER_FORCE_PORTRAIT")
|
2020-07-20 20:37:00 +00:00
|
|
|
if portrait then
|
2014-11-27 15:33:48 +00:00
|
|
|
self.isAlwaysPortrait = yes
|
|
|
|
end
|
2014-11-27 10:15:44 +00:00
|
|
|
|
2019-09-05 21:30:13 +00:00
|
|
|
self.hasClipboard = yes
|
2020-08-13 11:20:49 +00:00
|
|
|
self.screen = require("ffi/framebuffer_SDL2_0"):new{
|
|
|
|
device = self,
|
|
|
|
debug = logger.dbg,
|
|
|
|
w = self.window.width,
|
|
|
|
h = self.window.height,
|
|
|
|
x = self.window.left,
|
|
|
|
y = self.window.top,
|
2020-09-25 11:20:02 +00:00
|
|
|
is_always_portrait = self.isAlwaysPortrait(),
|
2020-08-13 11:20:49 +00:00
|
|
|
}
|
2023-06-27 19:33:00 +00:00
|
|
|
-- Pickup the updated window sizes if they were enforced in S.open (we'll get the coordinates via the inital SDL_WINDOWEVENT_MOVED)...
|
|
|
|
self.window.width = self.screen.w
|
|
|
|
self.window.height = self.screen.h
|
2020-07-20 22:52:50 +00:00
|
|
|
self.powerd = require("device/sdl/powerd"):new{device = self}
|
2019-09-05 21:30:13 +00:00
|
|
|
|
|
|
|
local ok, re = pcall(self.screen.setWindowIcon, self.screen, "resources/koreader.png")
|
|
|
|
if not ok then logger.warn(re) end
|
|
|
|
|
|
|
|
local input = require("ffi/input")
|
|
|
|
self.input = require("device/input"):new{
|
|
|
|
device = self,
|
|
|
|
event_map = require("device/sdl/event_map_sdl2"),
|
|
|
|
handleSdlEv = function(device_input, ev)
|
2023-05-18 21:13:43 +00:00
|
|
|
|
2019-09-05 21:30:13 +00:00
|
|
|
|
|
|
|
-- SDL events can remain cdata but are almost completely transparent
|
2020-12-30 21:26:40 +00:00
|
|
|
local SDL_TEXTINPUT = 771
|
2019-09-05 21:30:13 +00:00
|
|
|
local SDL_MOUSEWHEEL = 1027
|
|
|
|
local SDL_MULTIGESTURE = 2050
|
|
|
|
local SDL_DROPFILE = 4096
|
2020-08-13 11:20:49 +00:00
|
|
|
local SDL_WINDOWEVENT_MOVED = 4
|
2019-09-05 21:30:13 +00:00
|
|
|
local SDL_WINDOWEVENT_RESIZED = 5
|
|
|
|
|
|
|
|
if ev.code == SDL_MOUSEWHEEL then
|
|
|
|
local scrolled_x = ev.value.x
|
|
|
|
local scrolled_y = ev.value.y
|
|
|
|
|
|
|
|
local up = 1
|
|
|
|
local down = -1
|
|
|
|
|
|
|
|
local pos = Geom:new{
|
|
|
|
x = 0,
|
|
|
|
y = 0,
|
|
|
|
w = 0, h = 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
local fake_ges = {
|
|
|
|
ges = "pan",
|
|
|
|
distance = 200,
|
|
|
|
relative = {
|
|
|
|
x = 50*scrolled_x,
|
|
|
|
y = 100*scrolled_y,
|
|
|
|
},
|
|
|
|
pos = pos,
|
2022-07-09 20:47:10 +00:00
|
|
|
time = time.timeval(ev.time),
|
2019-09-05 21:30:13 +00:00
|
|
|
mousewheel_direction = scrolled_y,
|
|
|
|
}
|
|
|
|
local fake_ges_release = {
|
|
|
|
ges = "pan_release",
|
|
|
|
distance = fake_ges.distance,
|
|
|
|
relative = fake_ges.relative,
|
|
|
|
pos = pos,
|
2022-07-09 20:47:10 +00:00
|
|
|
time = time.timeval(ev.time),
|
2021-05-19 20:57:54 +00:00
|
|
|
from_mousewheel = true,
|
2019-09-05 21:30:13 +00:00
|
|
|
}
|
|
|
|
local fake_pan_ev = Event:new("Pan", nil, fake_ges)
|
|
|
|
local fake_release_ev = Event:new("Gesture", fake_ges_release)
|
|
|
|
if scrolled_y == down then
|
|
|
|
fake_ges.direction = "north"
|
|
|
|
UIManager:broadcastEvent(fake_pan_ev)
|
|
|
|
UIManager:broadcastEvent(fake_release_ev)
|
|
|
|
elseif scrolled_y == up then
|
|
|
|
fake_ges.direction = "south"
|
|
|
|
UIManager:broadcastEvent(fake_pan_ev)
|
|
|
|
UIManager:broadcastEvent(fake_release_ev)
|
2018-03-18 20:32:39 +00:00
|
|
|
end
|
2019-09-05 21:30:13 +00:00
|
|
|
elseif ev.code == SDL_MULTIGESTURE then
|
|
|
|
-- no-op for now
|
|
|
|
do end -- luacheck: ignore 541
|
|
|
|
elseif ev.code == SDL_DROPFILE then
|
|
|
|
local dropped_file_path = ev.value
|
|
|
|
if dropped_file_path and dropped_file_path ~= "" then
|
|
|
|
local ReaderUI = require("apps/reader/readerui")
|
|
|
|
ReaderUI:doShowReader(dropped_file_path)
|
|
|
|
end
|
|
|
|
elseif ev.code == SDL_WINDOWEVENT_RESIZED then
|
|
|
|
device_input.device.screen.resize(device_input.device.screen, ev.value.data1, ev.value.data2)
|
2020-08-13 11:20:49 +00:00
|
|
|
self.window.width = ev.value.data1
|
|
|
|
self.window.height = ev.value.data2
|
2019-09-05 21:30:13 +00:00
|
|
|
|
|
|
|
local new_size = device_input.device.screen:getSize()
|
2023-05-12 16:12:11 +00:00
|
|
|
device_input.device.screen.screen_size.w = new_size.w
|
|
|
|
device_input.device.screen.screen_size.h = new_size.h
|
|
|
|
|
2019-09-05 21:30:13 +00:00
|
|
|
logger.dbg("Resizing screen to", new_size)
|
|
|
|
|
|
|
|
-- try to catch as many flies as we can
|
|
|
|
-- this means we can't just return one ScreenResize or SetDimensons event
|
|
|
|
UIManager:broadcastEvent(Event:new("SetDimensions", new_size))
|
|
|
|
UIManager:broadcastEvent(Event:new("ScreenResize", new_size))
|
|
|
|
--- @todo Toggle this elsewhere based on ScreenResize?
|
|
|
|
|
|
|
|
-- this triggers paged media like PDF and DjVu to redraw
|
|
|
|
-- CreDocument doesn't need it
|
|
|
|
UIManager:broadcastEvent(Event:new("RedrawCurrentPage"))
|
2020-11-14 20:15:05 +00:00
|
|
|
|
|
|
|
local FileManager = require("apps/filemanager/filemanager")
|
|
|
|
if FileManager.instance then
|
|
|
|
FileManager.instance:reinit(FileManager.instance.path,
|
|
|
|
FileManager.instance.focused_file)
|
|
|
|
end
|
2020-08-13 11:20:49 +00:00
|
|
|
elseif ev.code == SDL_WINDOWEVENT_MOVED then
|
|
|
|
self.window.left = ev.value.data1
|
|
|
|
self.window.top = ev.value.data2
|
2020-12-30 21:26:40 +00:00
|
|
|
elseif ev.code == SDL_TEXTINPUT then
|
2021-10-29 10:59:03 +00:00
|
|
|
UIManager:sendEvent(Event:new("TextInput", tostring(ev.value)))
|
2019-09-05 21:30:13 +00:00
|
|
|
end
|
|
|
|
end,
|
|
|
|
hasClipboardText = function()
|
|
|
|
return input.hasClipboardText()
|
|
|
|
end,
|
|
|
|
getClipboardText = function()
|
|
|
|
return input.getClipboardText()
|
|
|
|
end,
|
|
|
|
setClipboardText = function(text)
|
|
|
|
return input.setClipboardText(text)
|
|
|
|
end,
|
2019-09-29 13:42:05 +00:00
|
|
|
gameControllerRumble = function(left_intensity, right_intensity, duration)
|
|
|
|
return input.gameControllerRumble(left_intensity, right_intensity, duration)
|
|
|
|
end,
|
2019-09-05 21:30:13 +00:00
|
|
|
file_chooser = input.file_chooser,
|
|
|
|
}
|
2014-10-30 18:42:18 +00:00
|
|
|
|
2016-01-31 22:56:05 +00:00
|
|
|
self.keyboard_layout = require("device/sdl/keyboard_layout")
|
|
|
|
|
2019-09-29 13:42:05 +00:00
|
|
|
if self.input.gameControllerRumble(0, 0, 0) then
|
|
|
|
self.isHapticFeedbackEnabled = yes
|
|
|
|
self.performHapticFeedback = function(type)
|
|
|
|
self.input.gameControllerRumble()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
if portrait then
|
2014-11-27 15:33:48 +00:00
|
|
|
self.input:registerEventAdjustHook(
|
2022-12-21 14:50:39 +00:00
|
|
|
self.input.adjustTouchSwitchAxesAndMirrorX,
|
2022-09-04 21:38:13 +00:00
|
|
|
(self.screen:getScreenWidth() - 1)
|
2014-11-27 15:33:48 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2014-10-30 18:42:18 +00:00
|
|
|
Generic.init(self)
|
|
|
|
end
|
|
|
|
|
2017-09-18 17:04:36 +00:00
|
|
|
function Device:setDateTime(year, month, day, hour, min, sec)
|
2017-08-15 17:54:02 +00:00
|
|
|
if hour == nil or min == nil then return true end
|
2017-09-18 17:04:36 +00:00
|
|
|
local command
|
|
|
|
if year and month and day then
|
|
|
|
command = string.format("date -s '%d-%d-%d %d:%d:%d'", year, month, day, hour, min, sec)
|
|
|
|
else
|
|
|
|
command = string.format("date -s '%d:%d'",hour, min)
|
|
|
|
end
|
|
|
|
if os.execute(command) == 0 then
|
2017-08-15 17:54:02 +00:00
|
|
|
os.execute('hwclock -u -w')
|
|
|
|
return true
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-06-24 21:19:38 +00:00
|
|
|
function Device:isAlwaysFullscreen()
|
|
|
|
-- return true on embedded devices, which should default to fullscreen
|
|
|
|
return self:isDefaultFullscreen()
|
|
|
|
end
|
|
|
|
|
|
|
|
function Device:toggleFullscreen()
|
|
|
|
local current_mode = self.fullscreen or self:isDefaultFullscreen()
|
|
|
|
local new_mode = not current_mode
|
|
|
|
local ok, err = SDL.setWindowFullscreen(new_mode)
|
|
|
|
if not ok then
|
|
|
|
logger.warn("Unable to toggle fullscreen mode to", new_mode, "\n", err)
|
|
|
|
else
|
|
|
|
self.fullscreen = new_mode
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-05-18 21:13:43 +00:00
|
|
|
function Device:UIManagerReady(uimgr)
|
|
|
|
UIManager = uimgr
|
|
|
|
end
|
|
|
|
|
|
|
|
function Device:setEventHandlers(uimgr)
|
Assorted bag'o tweaks & fixes (#9569)
* UIManager: Support more specialized update modes for corner-cases:
* A2, which we'll use for the VirtualKeyboards keys (they'd... inadvertently switched to UI with the highlight refactor).
* NO_MERGE variants of ui & partial (for sunxi). Use `[ui]` in ReaderHighlight's popup, because of a Sage kernel bug that could otherwise make it translucent, sometimes completely so (*sigh*).
* UIManager: Assorted code cleanups & simplifications.
* Logger & dbg: Unify logging style, and code cleanups.
* SDL: Unbreak suspend/resume outside of the emulator (fix #9567).
* NetworkMgr: Cache the network status, and allow it to be queried. (Used by AutoSuspend to avoid repeatedly poking the system when computing the standby schedule delay).
* OneTimeMigration: Don't forget about `NETWORK_PROXY` & `STARDICT_DATA_DIR` when migrating `defaults.persistent.lua` (fix #9573)
* WakeupMgr: Workaround an apparent limitation of the RTC found on i.MX5 Kobo devices, where setting a wakealarm further than UINT16_MAX seconds in the future would apparently overflow and wraparound... (fix #8039, many thanks to @yfede for the extensive deep-dive and for actually accurately pinpointing the issue!).
* Kobo: Handle standby transitions at full CPU clock speeds, in order to limit the latency hit.
* UIManager: Properly quit on reboot & exit. This ensures our exit code is preserved, as we exit on our own terms (instead of being killed by the init system). This is important on platforms where exit codes are semantically meaningful (e.g., Kobo).
* UIManager: Speaking of reboot & exit, make sure the Screensaver shows in all circumstances (e.g., autoshutdown, re: #9542)), and that there aren't any extraneous refreshes triggered. (Additionally, fix a minor regression since #9448 about tracking this very transient state on Kobo & Cervantes).
* Kindle: ID the upcoming Scribe.
* Bump base (https://github.com/koreader/koreader-base/pull/1524)
2022-10-02 01:01:49 +00:00
|
|
|
if not self:canSuspend() then
|
2022-11-07 16:40:45 +00:00
|
|
|
-- If we can't suspend, we have no business even trying to, as we may not have overloaded `Device:simulateResume`.
|
|
|
|
-- Instead, rely on the Generic Suspend/Resume handlers.
|
Assorted bag'o tweaks & fixes (#9569)
* UIManager: Support more specialized update modes for corner-cases:
* A2, which we'll use for the VirtualKeyboards keys (they'd... inadvertently switched to UI with the highlight refactor).
* NO_MERGE variants of ui & partial (for sunxi). Use `[ui]` in ReaderHighlight's popup, because of a Sage kernel bug that could otherwise make it translucent, sometimes completely so (*sigh*).
* UIManager: Assorted code cleanups & simplifications.
* Logger & dbg: Unify logging style, and code cleanups.
* SDL: Unbreak suspend/resume outside of the emulator (fix #9567).
* NetworkMgr: Cache the network status, and allow it to be queried. (Used by AutoSuspend to avoid repeatedly poking the system when computing the standby schedule delay).
* OneTimeMigration: Don't forget about `NETWORK_PROXY` & `STARDICT_DATA_DIR` when migrating `defaults.persistent.lua` (fix #9573)
* WakeupMgr: Workaround an apparent limitation of the RTC found on i.MX5 Kobo devices, where setting a wakealarm further than UINT16_MAX seconds in the future would apparently overflow and wraparound... (fix #8039, many thanks to @yfede for the extensive deep-dive and for actually accurately pinpointing the issue!).
* Kobo: Handle standby transitions at full CPU clock speeds, in order to limit the latency hit.
* UIManager: Properly quit on reboot & exit. This ensures our exit code is preserved, as we exit on our own terms (instead of being killed by the init system). This is important on platforms where exit codes are semantically meaningful (e.g., Kobo).
* UIManager: Speaking of reboot & exit, make sure the Screensaver shows in all circumstances (e.g., autoshutdown, re: #9542)), and that there aren't any extraneous refreshes triggered. (Additionally, fix a minor regression since #9448 about tracking this very transient state on Kobo & Cervantes).
* Kindle: ID the upcoming Scribe.
* Bump base (https://github.com/koreader/koreader-base/pull/1524)
2022-10-02 01:01:49 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
UIManager.event_handlers.Suspend = function()
|
2022-09-10 11:45:31 +00:00
|
|
|
self:simulateSuspend()
|
|
|
|
end
|
Assorted bag'o tweaks & fixes (#9569)
* UIManager: Support more specialized update modes for corner-cases:
* A2, which we'll use for the VirtualKeyboards keys (they'd... inadvertently switched to UI with the highlight refactor).
* NO_MERGE variants of ui & partial (for sunxi). Use `[ui]` in ReaderHighlight's popup, because of a Sage kernel bug that could otherwise make it translucent, sometimes completely so (*sigh*).
* UIManager: Assorted code cleanups & simplifications.
* Logger & dbg: Unify logging style, and code cleanups.
* SDL: Unbreak suspend/resume outside of the emulator (fix #9567).
* NetworkMgr: Cache the network status, and allow it to be queried. (Used by AutoSuspend to avoid repeatedly poking the system when computing the standby schedule delay).
* OneTimeMigration: Don't forget about `NETWORK_PROXY` & `STARDICT_DATA_DIR` when migrating `defaults.persistent.lua` (fix #9573)
* WakeupMgr: Workaround an apparent limitation of the RTC found on i.MX5 Kobo devices, where setting a wakealarm further than UINT16_MAX seconds in the future would apparently overflow and wraparound... (fix #8039, many thanks to @yfede for the extensive deep-dive and for actually accurately pinpointing the issue!).
* Kobo: Handle standby transitions at full CPU clock speeds, in order to limit the latency hit.
* UIManager: Properly quit on reboot & exit. This ensures our exit code is preserved, as we exit on our own terms (instead of being killed by the init system). This is important on platforms where exit codes are semantically meaningful (e.g., Kobo).
* UIManager: Speaking of reboot & exit, make sure the Screensaver shows in all circumstances (e.g., autoshutdown, re: #9542)), and that there aren't any extraneous refreshes triggered. (Additionally, fix a minor regression since #9448 about tracking this very transient state on Kobo & Cervantes).
* Kindle: ID the upcoming Scribe.
* Bump base (https://github.com/koreader/koreader-base/pull/1524)
2022-10-02 01:01:49 +00:00
|
|
|
UIManager.event_handlers.Resume = function()
|
2022-09-10 11:45:31 +00:00
|
|
|
self:simulateResume()
|
|
|
|
end
|
Assorted bag'o tweaks & fixes (#9569)
* UIManager: Support more specialized update modes for corner-cases:
* A2, which we'll use for the VirtualKeyboards keys (they'd... inadvertently switched to UI with the highlight refactor).
* NO_MERGE variants of ui & partial (for sunxi). Use `[ui]` in ReaderHighlight's popup, because of a Sage kernel bug that could otherwise make it translucent, sometimes completely so (*sigh*).
* UIManager: Assorted code cleanups & simplifications.
* Logger & dbg: Unify logging style, and code cleanups.
* SDL: Unbreak suspend/resume outside of the emulator (fix #9567).
* NetworkMgr: Cache the network status, and allow it to be queried. (Used by AutoSuspend to avoid repeatedly poking the system when computing the standby schedule delay).
* OneTimeMigration: Don't forget about `NETWORK_PROXY` & `STARDICT_DATA_DIR` when migrating `defaults.persistent.lua` (fix #9573)
* WakeupMgr: Workaround an apparent limitation of the RTC found on i.MX5 Kobo devices, where setting a wakealarm further than UINT16_MAX seconds in the future would apparently overflow and wraparound... (fix #8039, many thanks to @yfede for the extensive deep-dive and for actually accurately pinpointing the issue!).
* Kobo: Handle standby transitions at full CPU clock speeds, in order to limit the latency hit.
* UIManager: Properly quit on reboot & exit. This ensures our exit code is preserved, as we exit on our own terms (instead of being killed by the init system). This is important on platforms where exit codes are semantically meaningful (e.g., Kobo).
* UIManager: Speaking of reboot & exit, make sure the Screensaver shows in all circumstances (e.g., autoshutdown, re: #9542)), and that there aren't any extraneous refreshes triggered. (Additionally, fix a minor regression since #9448 about tracking this very transient state on Kobo & Cervantes).
* Kindle: ID the upcoming Scribe.
* Bump base (https://github.com/koreader/koreader-base/pull/1524)
2022-10-02 01:01:49 +00:00
|
|
|
UIManager.event_handlers.PowerRelease = function()
|
2022-09-10 11:45:31 +00:00
|
|
|
-- Resume if we were suspended
|
|
|
|
if self.screen_saver_mode then
|
2023-05-18 21:13:43 +00:00
|
|
|
if self.screen_saver_lock then
|
|
|
|
UIManager.event_handlers.Suspend()
|
|
|
|
else
|
|
|
|
UIManager.event_handlers.Resume()
|
|
|
|
end
|
2022-09-10 11:45:31 +00:00
|
|
|
else
|
Assorted bag'o tweaks & fixes (#9569)
* UIManager: Support more specialized update modes for corner-cases:
* A2, which we'll use for the VirtualKeyboards keys (they'd... inadvertently switched to UI with the highlight refactor).
* NO_MERGE variants of ui & partial (for sunxi). Use `[ui]` in ReaderHighlight's popup, because of a Sage kernel bug that could otherwise make it translucent, sometimes completely so (*sigh*).
* UIManager: Assorted code cleanups & simplifications.
* Logger & dbg: Unify logging style, and code cleanups.
* SDL: Unbreak suspend/resume outside of the emulator (fix #9567).
* NetworkMgr: Cache the network status, and allow it to be queried. (Used by AutoSuspend to avoid repeatedly poking the system when computing the standby schedule delay).
* OneTimeMigration: Don't forget about `NETWORK_PROXY` & `STARDICT_DATA_DIR` when migrating `defaults.persistent.lua` (fix #9573)
* WakeupMgr: Workaround an apparent limitation of the RTC found on i.MX5 Kobo devices, where setting a wakealarm further than UINT16_MAX seconds in the future would apparently overflow and wraparound... (fix #8039, many thanks to @yfede for the extensive deep-dive and for actually accurately pinpointing the issue!).
* Kobo: Handle standby transitions at full CPU clock speeds, in order to limit the latency hit.
* UIManager: Properly quit on reboot & exit. This ensures our exit code is preserved, as we exit on our own terms (instead of being killed by the init system). This is important on platforms where exit codes are semantically meaningful (e.g., Kobo).
* UIManager: Speaking of reboot & exit, make sure the Screensaver shows in all circumstances (e.g., autoshutdown, re: #9542)), and that there aren't any extraneous refreshes triggered. (Additionally, fix a minor regression since #9448 about tracking this very transient state on Kobo & Cervantes).
* Kindle: ID the upcoming Scribe.
* Bump base (https://github.com/koreader/koreader-base/pull/1524)
2022-10-02 01:01:49 +00:00
|
|
|
UIManager.event_handlers.Suspend()
|
2022-09-10 11:45:31 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-01-31 20:28:32 +00:00
|
|
|
function Device:initNetworkManager(NetworkMgr)
|
|
|
|
function NetworkMgr:isWifiOn() return true end
|
|
|
|
function NetworkMgr:isConnected()
|
|
|
|
-- Pull the default gateway first, so we don't even try to ping anything if there isn't one...
|
2023-02-20 23:46:19 +00:00
|
|
|
local default_gw = Device:getDefaultRoute()
|
|
|
|
if not default_gw then
|
|
|
|
return false
|
2023-01-31 20:28:32 +00:00
|
|
|
end
|
2023-02-17 22:12:49 +00:00
|
|
|
return 0 == os.execute("ping -c1 -w2 " .. default_gw .. " > /dev/null")
|
2023-01-31 20:28:32 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-01-02 22:13:19 +00:00
|
|
|
function Emulator:supportsScreensaver() return true end
|
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
function Emulator:simulateSuspend()
|
2022-01-02 22:13:19 +00:00
|
|
|
local Screensaver = require("ui/screensaver")
|
|
|
|
Screensaver:setup()
|
|
|
|
Screensaver:show()
|
2023-05-18 21:13:43 +00:00
|
|
|
|
|
|
|
self.powerd:beforeSuspend()
|
2017-06-23 17:04:11 +00:00
|
|
|
end
|
|
|
|
|
2020-07-20 20:37:00 +00:00
|
|
|
function Emulator:simulateResume()
|
2022-01-02 22:13:19 +00:00
|
|
|
local Screensaver = require("ui/screensaver")
|
|
|
|
Screensaver:close()
|
2023-05-18 21:13:43 +00:00
|
|
|
|
|
|
|
self.powerd:afterResume()
|
2017-06-23 17:04:11 +00:00
|
|
|
end
|
|
|
|
|
2020-06-26 18:47:09 +00:00
|
|
|
-- fake network manager for the emulator
|
|
|
|
function Emulator:initNetworkManager(NetworkMgr)
|
|
|
|
local connectionChangedEvent = function()
|
|
|
|
if G_reader_settings:nilOrTrue("emulator_fake_wifi_connected") then
|
|
|
|
UIManager:broadcastEvent(Event:new("NetworkConnected"))
|
|
|
|
else
|
|
|
|
UIManager:broadcastEvent(Event:new("NetworkDisconnected"))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function NetworkMgr:turnOffWifi(complete_callback)
|
|
|
|
G_reader_settings:flipNilOrTrue("emulator_fake_wifi_connected")
|
|
|
|
UIManager:scheduleIn(2, connectionChangedEvent)
|
|
|
|
end
|
|
|
|
function NetworkMgr:turnOnWifi(complete_callback)
|
|
|
|
G_reader_settings:flipNilOrTrue("emulator_fake_wifi_connected")
|
|
|
|
UIManager:scheduleIn(2, connectionChangedEvent)
|
|
|
|
end
|
|
|
|
function NetworkMgr:isWifiOn()
|
|
|
|
return G_reader_settings:nilOrTrue("emulator_fake_wifi_connected")
|
|
|
|
end
|
2023-01-31 20:28:32 +00:00
|
|
|
NetworkMgr.isConnected = NetworkMgr.isWifiOn
|
2020-06-26 18:47:09 +00:00
|
|
|
end
|
|
|
|
|
2020-07-20 22:52:50 +00:00
|
|
|
io.write("Starting SDL in " .. SDL.getBasePath() .. "\n")
|
|
|
|
|
2019-01-03 17:21:35 +00:00
|
|
|
-------------- device probe ------------
|
|
|
|
if os.getenv("APPIMAGE") then
|
|
|
|
return AppImage
|
|
|
|
elseif os.getenv("KO_MULTIUSER") then
|
2020-07-20 22:52:50 +00:00
|
|
|
return Desktop
|
2019-01-03 17:21:35 +00:00
|
|
|
elseif os.getenv("UBUNTU_APPLICATION_ISOLATION") then
|
|
|
|
return UbuntuTouch
|
|
|
|
else
|
|
|
|
return Emulator
|
|
|
|
end
|