forked from koreader/koreader
/
device.lua
229 lines (201 loc) · 7.83 KB
/
device.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
local Event = require("ui/event")
local Generic = require("device/generic/device")
local util = require("ffi/util")
local logger = require("logger")
local function yes() return true end
local function no() return false end
local Device = Generic:new{
model = "SDL",
isSDL = yes,
hasKeyboard = yes,
hasKeys = yes,
hasDPad = yes,
isTouchDevice = yes,
needsScreenRefreshAfterResume = no,
hasColorScreen = yes,
}
local AppImage = Device:new{
model = "AppImage",
}
local Emulator = Device:new{
model = "Emulator",
isEmulator = yes,
hasFrontlight = yes,
}
local Linux = Device:new{
model = "Linux",
}
local UbuntuTouch = Device:new{
model = "UbuntuTouch",
hasFrontlight = yes,
}
function Device:init()
local emulator = self.isEmulator
-- 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")
if emulator and viewport then
self.viewport = require("ui/geometry"):new(loadstring("return " .. viewport)())
end
local touchless = os.getenv("DISABLE_TOUCH") == "1"
if emulator and touchless then
self.isTouchDevice = no
end
local portrait = os.getenv("EMULATE_READER_FORCE_PORTRAIT")
if emulator and portrait then
self.isAlwaysPortrait = yes
end
if util.haveSDL2() then
self.hasClipboard = yes
self.screen = require("ffi/framebuffer_SDL2_0"):new{device = self, debug = logger.dbg}
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)
local Geom = require("ui/geometry")
local TimeVal = require("ui/timeval")
local UIManager = require("ui/uimanager")
-- SDL events can remain cdata but are almost completely transparent
local SDL_MOUSEWHEEL = 1027
local SDL_MULTIGESTURE = 2050
local SDL_DROPFILE = 4096
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 timev = TimeVal:new(ev.time)
local fake_ges = {
ges = "pan",
distance = 200,
relative = {
x = 50*scrolled_x,
y = 100*scrolled_y,
},
pos = pos,
time = timev,
}
local fake_ges_release = {
ges = "pan_release",
distance = 200,
relative = {
x = 50*scrolled_x,
y = 100*scrolled_y,
},
pos = pos,
time = timev,
}
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)
end
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.screen_size.w = ev.value.data1
device_input.device.screen.screen_size.h = ev.value.data2
device_input.device.screen.resize(device_input.device.screen, ev.value.data1, ev.value.data2)
local new_size = device_input.device.screen:getSize()
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"))
end
end,
hasClipboardText = function()
return input.hasClipboardText()
end,
getClipboardText = function()
return input.getClipboardText()
end,
setClipboardText = function(text)
return input.setClipboardText(text)
end,
file_chooser = input.file_chooser,
}
else
self.screen = require("ffi/framebuffer_SDL1_2"):new{device = self, debug = logger.dbg}
self.input = require("device/input"):new{
device = self,
event_map = require("device/sdl/event_map_sdl"),
}
end
self.keyboard_layout = require("device/sdl/keyboard_layout")
if emulator and portrait then
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY)
self.input:registerEventAdjustHook(
self.input.adjustTouchMirrorX,
self.screen:getScreenWidth()
)
end
Generic.init(self)
end
function Device:setDateTime(year, month, day, hour, min, sec)
if hour == nil or min == nil then return true end
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
os.execute('hwclock -u -w')
return true
else
return false
end
end
function Device:simulateSuspend()
local InfoMessage = require("ui/widget/infomessage")
local UIManager = require("ui/uimanager")
local _ = require("gettext")
UIManager:show(InfoMessage:new{
text = _("Suspend")
})
end
function Device:simulateResume()
local InfoMessage = require("ui/widget/infomessage")
local UIManager = require("ui/uimanager")
local _ = require("gettext")
UIManager:show(InfoMessage:new{
text = _("Resume")
})
end
-------------- device probe ------------
if os.getenv("APPIMAGE") then
return AppImage
elseif os.getenv("KO_MULTIUSER") then
return Linux
elseif os.getenv("UBUNTU_APPLICATION_ISOLATION") then
return UbuntuTouch
else
return Emulator
end