aboutsummaryrefslogtreecommitdiff
path: root/src/syslua/lx/gui.lua
blob: 9342025f1a99ddfb0fecfd0f48c557862897b9bf (plain) (blame)
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
local sys = require 'lx.sys'
local sysdef = require 'lx.sysdef'
local protodef = require 'lx.protodef'
local ioctl = require 'lx.ioctl'
local draw = require 'lx.draw'

local kbd = require 'lx.kbd'
local kbdcode = require 'lx.kbdcode'

local mainloop = require 'lx.mainloop'

local gui = {
	-- Keyboard info
	-- TODO
	-- Mouse info
	mouse_x = 0,
	mouse_y = 0,
	mouse_lbtn = false,
	mouse_rbtn = false,
	mouse_midbtn = false,
	cursor_visible = false,
}

function gui.open()
	if sys.stat('io:/display/vesa') and sys.stat('io:/input/pckbd') and sys.stat('io:/input/pcmouse') then
		gui.open_io()
	elseif sys.stat_open(sysdef.STD_FD_GIP) then
		gui.open_gip()
	else
		error("Could not open GUI!")
	end
end

function gui.open_io()
	-- Open display
	gui.vesa_fd = sys.open("io:/display/vesa", sysdef.FM_IOCTL | sysdef.FM_READ | sysdef.FM_WRITE | sysdef.FM_MMAP)
	assert(gui.vesa_fd ~= 0)

	gui.surface_geom = ioctl.fb_get_info(gui.vesa_fd)
	gui.surface = draw.surface_from_fd(gui.vesa_fd, gui.surface_geom)

	-- Open keyboard
	gui.pckbd_fd = sys.open("io:/input/pckbd", sysdef.FM_READ)
	assert(gui.pckbd_fd ~= 0)

	gui.pckbd_mainloop_fd = mainloop.add_fd(gui.pckbd_fd, function() error('pckbd fd error') end)
	local function pckbd_handler(ev)
		local scancode, ty = string.unpack(protodef.kbd_event.fmt, ev)
		gui.on_keyboard(scancode, ty)

		gui.pckbd_mainloop_fd:expect(protodef.kbd_event.len, pckbd_handler)
	end
	gui.pckbd_mainloop_fd:expect(protodef.kbd_event.len, pckbd_handler)

	gui.kbdlib = kbd.init()

	-- Open mouse
	gui.pcmouse_fd = sys.open("io:/input/pcmouse", sysdef.FM_READ)
	assert(gui.pcmouse_fd ~= 0)

	gui.pcmouse_mainloop_fd = mainloop.add_fd(gui.pcmouse_fd, function() error("pcmouse fd error") end)
	local function pcmouse_handler(ev)
		local dx, dy, dw, lb, rb, mb = string.unpack(protodef.mouse_event.fmt, ev)
		local change_but = false

		while not change_but do
			local bytes, n = sys.read(gui.pcmouse_fd, 1, protodef.mouse_event.len)
			if n == 8 then
				local dx2, dy2, dw2, lb2, rb2, mb2 = string.unpack(protodef.mouse_event.fmt, ev)
				change_but = change_but or (lb2 ~= lb) or (rb2 ~= rb) or (mb2 ~= mb)
				dx = dx + dx2
				dy = dy + dy2
				lb = lb2
				rb = rb2
				mb = mb2
			else
				break
			end
		end
		gui.on_mouse(dx, dy, dw, lb, rb, mb)

		gui.pcmouse_mainloop_fd:expect(protodef.mouse_event.len, pcmouse_handler)
	end
	gui.pcmouse_mainloop_fd:expect(protodef.mouse_event.len, pcmouse_handler)
end

function gui.open_gip()
	-- TODO
end

function gui.load_cursor(filename)
	gui.hide_cursor()
	gui.cursor = draw.load_image(filename)
	gui.cursor_backup = draw.new_surface(gui.cursor:width(),gui.cursor:height(), gui.surface_geom.bpp, false)
end

function gui.hide_cursor()
	if not gui.cursor_visible then return end

	gui.surface:blit(gui.mouse_x, gui.mouse_y, gui.cursor_backup)
	gui.cursor_visible = false
end

function gui.show_cursor()
	if gui.cursor_visible then return end
	if not gui.cursor then return end
	
	gui.cursor_backup:blit(0, 0, gui.surface:sub(gui.mouse_x, gui.mouse_y, gui.cursor:width(), gui.cursor:height()))
	gui.surface:blit(gui.mouse_x, gui.mouse_y, gui.cursor)
	gui.cursor_visible = true
end

function gui.on_keyboard(scancode, ty)
	if ty == kbdcode.event.KEYPRESS then
		local key = gui.kbdlib:press(scancode)
		gui.on_key_down(key)
		if key.chr then
			gui.on_text_input(string.char(key.chr))
		end
	elseif ty == kbdcode.event.KEYRELEASE then
		local key = gui.kbdlib:release(scancode)
		gui.on_key_up(key)
	end
end

function gui.on_key_down(key)
	-- Can be replaced :)
end

function gui.on_text_input(chr)
	-- Can be replaced :)
end

function gui.on_key_up(key)
	-- Can be replaced :)
end


function gui.on_mouse(dx, dy, dw, lb, rb, mb)
	if dx ~= 0 or dy ~= 0 then
		local prev_x, prev_y = gui.mouse_x, gui.mouse_y

		local csr = gui.cursor_visible
		if csr then gui.hide_cursor() end

		gui.mouse_x = gui.mouse_x + dx
		gui.mouse_y = gui.mouse_y - dy
		if gui.mouse_x < 0 then gui.mouse_x = 0 end
		if gui.mouse_y < 0 then gui.mouse_y = 0 end
		if gui.mouse_x >= gui.surface:width() then gui.mouse_x = gui.surface:width() - 1 end
		if gui.mouse_y >= gui.surface:height() then gui.mouse_y = gui.surface:height() - 1 end

		if csr then gui.show_cursor() end

		gui.on_mouse_move(prev_x, prev_y, gui.mouse_x, gui.mouse_y)
	end

	if lb == 1 and not gui.mouse_lbtn then
		gui.mouse_lbtn = true
		gui.on_mouse_down(true, false, false)
	elseif lb == 0 and gui.mouse_lbtn then
		gui.mouse_lbtn = false
		gui.on_mouse_up(true, false, false)
	end

	if rb == 1 and not gui.mouse_rbtn then
		gui.mouse_rbtn = true
		gui.on_mouse_down(false, true, false)
	elseif rb == 0 and gui.mouse_rbtn then
		gui.mouse_rbtn = false
		gui.on_mouse_up(false, true, false)
	end
end

function gui.on_mouse_move(prev_x, prev_y, x, y)
	-- Nothing, can be replaced :)
end

function gui.on_mouse_down(lb, rb, mb)
	-- Nothing, can be replaced :)
end

function gui.on_mouse_up(lb, rb, mb)
	-- Nothing, can be replaced :)
end

return gui