From 67dc16ad2645ad0282860bdd7efc9d8452fdc7aa Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Sun, 11 Apr 2021 23:52:31 +0200 Subject: [PATCH] Make windows control buttons active --- data/core/titleview.lua | 105 ++++++++++++++++++++++++++++++++-------- src/api/system.c | 15 ++++-- 2 files changed, 95 insertions(+), 25 deletions(-) diff --git a/data/core/titleview.lua b/data/core/titleview.lua index e4487a55..c53c5371 100644 --- a/data/core/titleview.lua +++ b/data/core/titleview.lua @@ -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 diff --git a/src/api/system.c b/src/api/system.c index 7d316d58..024b04f0 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -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 {