Make windows control buttons active

This commit is contained in:
Francesco Abbate 2021-04-11 23:52:31 +02:00
parent 8ad87d77da
commit 67dc16ad26
2 changed files with 95 additions and 25 deletions

View File

@ -1,44 +1,109 @@
local core = require "core"
local common = require "core.common"
local style = require "core.style"
local StatusView = require "core.statusview"
local View = require "core.view"
local title_commands = {
{symbol = "_", action = function() system.set_window_mode("minimized") end},
{symbol = "w", action = function() system.set_window_mode("maximized") end},
{symbol = "W", action = function() core.quit() end},
}
local TitleView = StatusView:extend()
local TitleView = View:extend()
TitleView.separator = " "
local function title_view_height()
return style.font:get_height() + style.padding.y * 2
end
function TitleView:new()
TitleView.super.new(self)
-- FIXME: decide if visible is actually needed
self.visible = true
end
function TitleView:on_mouse_pressed()
core.set_active_view(core.last_active_view)
end
function TitleView:on_mouse_moved(px, py, ...)
end
function TitleView:update()
if self.visible then
self.size.y = title_view_height()
else
self.size.y = 0
end
TitleView.super.update(self)
local title_height = self.size.y
if core.window_borderless and title_height ~= core.hit_test_title_height then
local resize_border = title_height / 2
system.set_window_hit_test(title_height, resize_border)
local icon_w = style.icon_font:get_width("_")
local icon_spacing = icon_w
local controls_width = (icon_w + icon_spacing) * #title_commands + icon_spacing
system.set_window_hit_test(title_height, controls_width, icon_spacing)
core.hit_test_title_height = title_height
end
end
function TitleView:get_items()
function TitleView:draw_window_title()
local h = style.font:get_height()
local ox, oy = self:get_content_offset()
local color = style.text
local x, y = ox + style.padding.x, oy + style.padding.y
x = common.draw_text(style.icon_font, color, "M ", nil, x, y, 0, h)
local title = core.compose_window_title(core.window_title)
return {
style.text, style.icon_font, "M ", style.font, title,
}, {
style.text, style.icon_font, "_", TitleView.separator, "w", TitleView.separator, "W",
}
common.draw_text(style.font, color, title, nil, x, y, 0, h)
end
function TitleView:each_control_item()
local icon_h, icon_w = style.icon_font:get_height(), style.icon_font:get_width("_")
local icon_spacing = icon_w
local ox, oy = self:get_content_offset()
ox = ox + self.size.x
local i, n = 0, #title_commands
local iter = function()
i = i + 1
if i <= n then
local dx = - (icon_w + icon_spacing) * (n - i + 1)
local dy = style.padding.y
return title_commands[i], ox + dx, oy + dy, icon_w, icon_h
end
end
return iter
end
function TitleView:draw_window_controls()
for item, x, y, w, h in self:each_control_item() do
local color = item == self.hovered_item and style.text or style.dim
common.draw_text(style.icon_font, color, item.symbol, nil, x, y, 0, h)
end
end
function TitleView:on_mouse_pressed(button, x, y, clicks)
local caught = TitleView.super.on_mouse_pressed(self, button, x, y, clicks)
if caught then return end
core.set_active_view(core.last_active_view)
if self.hovered_item then
self.hovered_item.action()
end
end
function TitleView:on_mouse_moved(px, py, ...)
TitleView.super.on_mouse_moved(self, px, py, ...)
self.hovered_item = nil
local x_min, x_max, y_min, y_max = self.size.x, 0, self.size.y, 0
for item, x, y, w, h in self:each_control_item() do
x_min, x_max = math.min(x, x_min), math.max(x + w, x_max)
y_min, y_max = y, y + h
if px > x and py > y and px <= x + w and py <= y + h then
self.hovered_item = item
return
end
end
end
function TitleView:draw()
self:draw_background(style.background2)
self:draw_window_title()
self:draw_window_controls()
end
return TitleView

View File

@ -37,6 +37,7 @@ static char* key_name(char *dst, int sym) {
struct HitTestInfo {
int title_height;
int controls_width;
int resize_border;
};
typedef struct HitTestInfo HitTestInfo;
@ -46,11 +47,13 @@ static HitTestInfo window_hit_info[1] = {{0, 0}};
static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *pt, void *data) {
const HitTestInfo *hit_info = (HitTestInfo *) data;
const int resize_border = hit_info->resize_border;
const int controls_width = hit_info->controls_width;
int w, h;
SDL_GetWindowSize(window, &w, &h);
if (pt->y < hit_info->title_height && pt->x > resize_border && pt->x < w - resize_border) {
if (pt->y < hit_info->title_height && pt->y > hit_info->resize_border &&
pt->x > resize_border && pt->x < w - controls_width) {
return SDL_HITTEST_DRAGGABLE;
}
@ -60,7 +63,7 @@ static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *p
if (pt->x < resize_border && pt->y < resize_border) {
REPORT_RESIZE_HIT(TOPLEFT);
} else if (pt->x > resize_border && pt->x < w - resize_border && pt->y < resize_border) {
} else if (pt->x > resize_border && pt->x < w - controls_width && pt->y < resize_border) {
REPORT_RESIZE_HIT(TOP);
} else if (pt->x > w - resize_border && pt->y < resize_border) {
REPORT_RESIZE_HIT(TOPRIGHT);
@ -231,8 +234,8 @@ static int f_set_window_title(lua_State *L) {
}
static const char *window_opts[] = { "normal", "maximized", "fullscreen", 0 };
enum { WIN_NORMAL, WIN_MAXIMIZED, WIN_FULLSCREEN };
static const char *window_opts[] = { "normal", "minimized", "maximized", "fullscreen", 0 };
enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN };
static int f_set_window_mode(lua_State *L) {
int n = luaL_checkoption(L, 1, "normal", window_opts);
@ -240,6 +243,7 @@ static int f_set_window_mode(lua_State *L) {
n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if (n == WIN_NORMAL) { SDL_RestoreWindow(window); }
if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window); }
if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window); }
return 0;
}
@ -253,7 +257,8 @@ static int f_set_window_bordered(lua_State *L) {
static int f_set_window_hit_test(lua_State *L) {
window_hit_info->title_height = luaL_checknumber(L, 1);
window_hit_info->resize_border = luaL_checknumber(L, 2);
window_hit_info->controls_width = luaL_checknumber(L, 2);
window_hit_info->resize_border = luaL_checknumber(L, 3);
if (SDL_SetWindowHitTest(window, hit_test, window_hit_info) == -1) {
lua_pushboolean(L, 0);
} else {