summaryrefslogtreecommitdiff
path: root/osd.lua
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-01-21 12:52:15 -0800
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-01-21 12:52:15 -0800
commit15198eb77727b4277d5b5d80fb3ae4b25b3c8ef8 (patch)
treef16471159acb70601dc90d83147a1596c9b5a983 /osd.lua
parent9b863cad505d01017ee980e16d072fb7cffcd029 (diff)
downloadmpv-iptv-menu-15198eb77727b4277d5b5d80fb3ae4b25b3c8ef8.tar.gz
mpv-iptv-menu-15198eb77727b4277d5b5d80fb3ae4b25b3c8ef8.tar.xz
move mouse state to osd; add scrollbar hover
Diffstat (limited to 'osd.lua')
-rw-r--r--osd.lua160
1 files changed, 114 insertions, 46 deletions
diff --git a/osd.lua b/osd.lua
index 35115a1..981d824 100644
--- a/osd.lua
+++ b/osd.lua
@@ -43,7 +43,7 @@ function osd.new(init)
local t = setmetatable({
fg = mp.create_osd_overlay('ass-events'),
bg = mp.create_osd_overlay('ass-events'),
- menu_button = mp.create_osd_overlay('ass-events'),
+ menu_btn = mp.create_osd_overlay('ass-events'),
width = 0,
height = 0,
scale = 1,
@@ -51,8 +51,8 @@ function osd.new(init)
padding = math.floor((720 - (lines * config.font_size)) / 2),
}, mt)
t.bg.z = -1
- t.menu_button.z = 1
- t.menu_button.hidden = true
+ t.menu_btn.z = 1
+ t.menu_btn.hidden = true
for k, v in pairs(init or {}) do
t[k] = v
@@ -93,15 +93,15 @@ function mt:resize(w, h)
}
coords.x2 = coords.x1 + sz
coords.y2 = coords.y1 + sz
- self.menu_button_coords = coords
- self.menu_button.data =
+ self.menu_btn_coords = coords
+ self.menu_btn.data =
'{\\pos(' .. coords.x1 .. ',' .. coords.y1 .. ')}' ..
- colours.menu_button_bg .. draw_rect(0, 0, sz, sz) .. '\n' ..
+ colours.menu_btn_bg .. draw_rect(0, 0, sz, sz) .. '\n' ..
'{\\q2\\fs' .. sz .. '\\bord0\\an5\\pos(' ..
coords.x1 + sz/2 .. ',' .. coords.y1 + sz/2 ..')}' ..
- colours.menu_button_fg .. '≡'
- self.menu_button:update()
+ colours.menu_btn_fg .. '≡'
+ self.menu_btn:update()
end
function mt:set_status(msg, level, no_dirty)
@@ -414,12 +414,11 @@ function mt:set_img(path, menu_res)
return true, true
end
-function mt:draw_scrollbar(state)
+function mt:calc_scrollbar(state)
local menu = state:menu()
local opts = #menu.options
local lines = self:menu_lines(state)
if opts <= lines then
- self.scrollbar_coords = nil
return
end
@@ -428,20 +427,45 @@ function mt:draw_scrollbar(state)
local w = self.padding - 4
local hh = math.max(config.font_size / 2, h * lines / opts)
local pos = (h - hh) * (menu.view_top - 1) / (opts - lines)
- self.scrollbar_coords = {
+
+ return {
x1 = 2,
y1 = top,
x2 = 2 + w,
y2 = top + h,
+ w = w,
+ h = h,
+ pos = pos,
+ hh = hh,
}
- return (
- -- bg
- colours.scrollbar_bg ..
- '{\\pos(2,' .. top .. ')}' .. draw_rect(0, 0, w, h) .. '\n' ..
- -- fg
- colours.scrollbar_fg .. '{\\bord0}' ..
- '{\\pos(2,' .. top + pos .. ')}' .. draw_rect(0, 0, w, hh))
+end
+
+function mt:render_bg()
+ self.bg.data =
+ '{\\pos(0,0)\\alpha&H' .. config.bg_alpha .. '&\\c&H&}' ..
+ draw_rect(0, 0, 7680, 720)
+
+ local sb = self.out.scrollbar
+ if sb then
+ local hover = self.mstate and self.mstate.target == 'scrollbar'
+ local fg = hover and colours.scrollbar_fg_hover or
+ colours.scrollbar_fg
+ local bg = hover and colours.scrollbar_bg_hover or
+ colours.scrollbar_bg
+
+ self.bg.data = self.bg.data .. '\n' ..
+ -- bg
+ bg ..
+ '{\\pos(2,' .. sb.y1 .. ')}' ..
+ draw_rect(0, 0, sb.w, sb.h) .. '\n' ..
+ -- fg
+ fg .. '{\\bord0}' ..
+ '{\\pos(2,' .. sb.y1 + sb.pos .. ')}' ..
+ draw_rect(0, 0, sb.w, sb.hh)
+ end
+
+ self.bg:update()
end
-- this takes the data generated by redraw() and related functions, prepares it
@@ -486,7 +510,7 @@ function mt:render()
-- need it when update() is called to toggle visibility of the last
-- rendered data.
self.fg.compute_bounds = false
- self.bg:update()
+ self:render_bg()
if self.out.img_path then
local upd, new = self:set_img(self.out.img_path, res)
if upd then
@@ -565,18 +589,9 @@ function mt:redraw(state)
titles = out_titles,
options = out_options,
max = out_max,
+ scrollbar = self:calc_scrollbar(state),
}
- -- we can draw this directly from here since any changes handled by
- -- render() will not modify this.
- self.bg.data =
- '{\\pos(0,0)\\alpha&H' .. config.bg_alpha .. '&\\c&H&}' ..
- draw_rect(0, 0, 7680, 720)
- local sb = self:draw_scrollbar(state)
- if sb then
- self.bg.data = self.bg.data .. '\n' .. sb
- end
-
if img and self.img_path_func then
self.out.img_path = self.img_path_func(img, function(path)
-- these are set by render(), which we always call
@@ -587,6 +602,9 @@ function mt:redraw(state)
end)
end
+ -- menu changes could result in hover changes
+ self:update_mstate()
+
self:render()
self.is_dirty = false
end
@@ -628,7 +646,7 @@ end
function mt:mouse_scrollbar_ratio(mpos)
local x = mpos.x / self.scale
local y = mpos.y / self.scale
- local coords = self.scrollbar_coords
+ local coords = self.out.scrollbar
if not coords or x < coords.x1 or x > coords.x2 or
y < coords.y1 or y > coords.y2 then
@@ -639,39 +657,89 @@ function mt:mouse_scrollbar_ratio(mpos)
return math.max(0, math.min(1, ratio))
end
-function mt:mouse_over_button_area(mpos)
- if not mpos.hover then
- return false
- end
-
+function mt:mouse_over_btn_area(mpos)
local y = mpos.y / self.scale
return y < self.padding + (2 * config.font_size)
end
-function mt:mouse_over_menu_button(mpos)
- if not mpos.hover then
- return false
- end
-
+function mt:mouse_over_menu_btn(mpos)
local x = mpos.x / self.scale
local y = mpos.y / self.scale
- local coords = self.menu_button_coords
+ local coords = self.menu_btn_coords
return coords and
x > coords.x1 and x < coords.x2 and
y > coords.y1 and y < coords.y2
end
-function mt:show_menu_button(bool)
- if self.menu_button.hidden ~= bool then
+function mt:update_mstate()
+ local t = {}
+ local val
+
+ if not self.mpos or not self.mpos.hover then
+ goto update
+ end
+
+ val = self:mouse_over_menu_btn(self.mpos)
+ if val then
+ t.target = 'menu_btn'
+ goto common
+ end
+
+ val = self:mouse_scrollbar_ratio(self.mpos)
+ if val then
+ t.target = 'scrollbar'
+ t.ratio = val
+ goto common
+ end
+
+ val = self:mouse_menu_line(self.mpos)
+ if val then
+ t.target = 'menu'
+ t.line = val
+ t.option_line = val - #self.out.titles - 1
+ goto common
+ end
+
+ ::common::
+
+ t.over_btn_area = self:mouse_over_btn_area(self.mpos)
+
+ ::update::
+
+ local ms = self.mstate or {}
+ self.mstate = t
+
+ if (t.target == 'scrollbar') ~= (ms.target == 'scrollbar') then
+ self:render_bg()
+ end
+
+ return t
+end
+
+function mt:set_mpos(mpos)
+ -- mpv sends (0, 0) on startup if the mouse hasn't moved yet. don't
+ -- trigger display of the button until the mouse has actually moved.
+ if not self.mpos and mpos and mpos.x == 0 and mpos.y == 0 then
+ return
+ end
+
+ self.mpos = mpos
+ self.mpos_time = mp.get_time()
+
+ return self:update_mstate()
+end
+
+function mt:show_menu_btn(bool)
+ if not self.menu_btn.hidden ~= not bool then
return
end
- self.menu_button.hidden = not bool
- self.menu_button:update()
+ self.menu_btn.hidden = not bool
+ self.menu_btn:update()
end
function mt:measure_width(str)
- local e = self.menu_button
+ local e = self.menu_btn
local data = e.data
local hidden = e.hidden
e.hidden = true