move window creation and management to Lua (#1751)

* remove scaling logic from font code
for the time being its been hardcoded to 1 for the non SDL Renderer basewin setup, so nothing is lost for non MacOS users.
will be revisited in the future when scaling is improved with SDL3 and moved into scripts.

* remove unused window_renderer argument from font functions

* move window logic to lua, pass window via argument

* rename window creation functions `*_create`, `*_destroy`, add real init

* Set active window when processing frame

* get size directly from RenWindow, get active window size from renderer

* correct reverted draw calls

* fix window not reappearing on restart

* add simple logic to persist the core window

* fix style

* add renwindow documentation

* make windows hidden by default again

* reorder ren_update_rects execution, add comment to note future work
This commit is contained in:
Jan 2024-06-22 21:01:39 +02:00 committed by GitHub
parent dae74f01ae
commit 1a045e5e86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 424 additions and 185 deletions

View File

@ -560,7 +560,7 @@ function DocView:draw_overlay()
local T = config.blink_period local T = config.blink_period
for _, line1, col1, line2, col2 in self.doc:get_selections() do for _, line1, col1, line2, col2 in self.doc:get_selections() do
if line1 >= minline and line1 <= maxline if line1 >= minline and line1 <= maxline
and system.window_has_focus() then and system.window_has_focus(core.window) then
if ime.editing then if ime.editing then
self:draw_ime_decoration(line1, col1, line2, col2) self:draw_ime_decoration(line1, col1, line2, col2)
else else

View File

@ -1,3 +1,4 @@
local core = require "core"
local style = require "core.style" local style = require "core.style"
local keymap = require "core.keymap" local keymap = require "core.keymap"
local View = require "core.view" local View = require "core.view"

View File

@ -27,8 +27,8 @@ local function save_session()
local fp = io.open(USERDIR .. PATHSEP .. "session.lua", "w") local fp = io.open(USERDIR .. PATHSEP .. "session.lua", "w")
if fp then if fp then
fp:write("return {recents=", common.serialize(core.recent_projects), fp:write("return {recents=", common.serialize(core.recent_projects),
", window=", common.serialize(table.pack(system.get_window_size())), ", window=", common.serialize(table.pack(system.get_window_size(core.window))),
", window_mode=", common.serialize(system.get_window_mode()), ", window_mode=", common.serialize(system.get_window_mode(core.window)),
", previous_find=", common.serialize(core.previous_find), ", previous_find=", common.serialize(core.previous_find),
", previous_replace=", common.serialize(core.previous_replace), ", previous_replace=", common.serialize(core.previous_replace),
"}\n") "}\n")
@ -689,12 +689,16 @@ function core.init()
EXEDIR = common.normalize_volume(EXEDIR) EXEDIR = common.normalize_volume(EXEDIR)
end end
core.window = renwindow._restore()
if core.window == nil then
core.window = renwindow.create("")
end
do do
local session = load_session() local session = load_session()
if session.window_mode == "normal" then if session.window_mode == "normal" then
system.set_window_size(table.unpack(session.window)) system.set_window_size(core.window, table.unpack(session.window))
elseif session.window_mode == "maximized" then elseif session.window_mode == "maximized" then
system.set_window_mode("maximized") system.set_window_mode(core.window, "maximized")
end end
core.recent_projects = session.recents or {} core.recent_projects = session.recents or {}
core.previous_find = session.previous_find or {} core.previous_find = session.previous_find or {}
@ -922,7 +926,10 @@ end
function core.restart() function core.restart()
quit_with_function(function() core.restart_request = true end) quit_with_function(function()
core.restart_request = true
core.window:_persist()
end)
end end
@ -1309,7 +1316,7 @@ function core.on_event(type, ...)
elseif type == "touchmoved" then elseif type == "touchmoved" then
core.root_view:on_touch_moved(...) core.root_view:on_touch_moved(...)
elseif type == "resized" then elseif type == "resized" then
core.window_mode = system.get_window_mode() core.window_mode = system.get_window_mode(core.window)
elseif type == "minimized" or type == "maximized" or type == "restored" then elseif type == "minimized" or type == "maximized" or type == "restored" then
core.window_mode = type == "restored" and "normal" or type core.window_mode = type == "restored" and "normal" or type
elseif type == "filedropped" then elseif type == "filedropped" then
@ -1356,7 +1363,7 @@ function core.step()
core.redraw = true core.redraw = true
end end
local width, height = renderer.get_size() local width, height = core.window:get_size()
-- update -- update
core.root_view.size.x, core.root_view.size.y = width, height core.root_view.size.x, core.root_view.size.y = width, height
@ -1376,12 +1383,12 @@ function core.step()
-- update window title -- update window title
local current_title = get_title_filename(core.active_view) local current_title = get_title_filename(core.active_view)
if current_title ~= nil and current_title ~= core.window_title then if current_title ~= nil and current_title ~= core.window_title then
system.set_window_title(core.compose_window_title(current_title)) system.set_window_title(core.window, core.compose_window_title(current_title))
core.window_title = current_title core.window_title = current_title
end end
-- draw -- draw
renderer.begin_frame() renderer.begin_frame(core.window)
core.clip_rect_stack[1] = { 0, 0, width, height } core.clip_rect_stack[1] = { 0, 0, width, height }
renderer.set_clip_rect(table.unpack(core.clip_rect_stack[1])) renderer.set_clip_rect(table.unpack(core.clip_rect_stack[1]))
core.root_view:draw() core.root_view:draw()
@ -1453,7 +1460,7 @@ function core.run()
if core.restart_request or core.quit_request then break end if core.restart_request or core.quit_request then break end
if not did_redraw then if not did_redraw then
if system.window_has_focus() or not did_step or run_threads_full < 2 then if system.window_has_focus(core.window) or not did_step or run_threads_full < 2 then
local now = system.get_time() local now = system.get_time()
if not next_step then -- compute the time until the next blink if not next_step then -- compute the time until the next blink
local t = now - core.blink_start local t = now - core.blink_start

View File

@ -54,7 +54,7 @@ function NagView:get_target_height()
end end
function NagView:get_scrollable_size() function NagView:get_scrollable_size()
local w, h = system.get_window_size() local w, h = system.get_window_size(core.window)
if self.visible and self:get_target_height() > h then if self.visible and self:get_target_height() > h then
self.size.y = h self.size.y = h
return self:get_target_height() return self:get_target_height()

View File

@ -116,10 +116,13 @@ function renderer.get_size() end
--- ---
---Tell the rendering system that we want to build a new frame to render. ---Tell the rendering system that we want to build a new frame to render.
function renderer.begin_frame() end ---
---@param window renwindow
function renderer.begin_frame(window) end
--- ---
---Tell the rendering system that we finished building the frame. ---Tell the rendering system that we finished building the frame.
---
function renderer.end_frame() end function renderer.end_frame() end
--- ---

28
docs/api/renwindow.lua Normal file
View File

@ -0,0 +1,28 @@
---@meta
---
---Functionality to create and manage windows
---@class renwindow
renwindow = {}
---
---Create a new window
---
---
---
---@param x integer? if nil will be undefined
---@param y integer? if nil will be undefined
---@param width integer? if nil or less than 1 will be calculated from display
---@param height integer? if nil or less than 1 will be calculated from display
---
---@return renwindow
function renwindow.create(x, y, width, height) end
---
--- Get width and height of a window
---
---@param renwindow
---
---@return number width
---@return number height
function renwindow.get_size(window) end

View File

@ -76,8 +76,9 @@ function system.set_cursor(type) end
--- ---
---Change the window title. ---Change the window title.
--- ---
---@param window renwindow
---@param title string ---@param title string
function system.set_window_title(title) end function system.set_window_title(window, title) end
---@alias system.windowmode ---@alias system.windowmode
---| "normal" ---| "normal"
@ -88,14 +89,17 @@ function system.set_window_title(title) end
--- ---
---Change the window mode. ---Change the window mode.
--- ---
---@param window renwindow
---@param mode system.windowmode ---@param mode system.windowmode
function system.set_window_mode(mode) end function system.set_window_mode(window, mode) end
--- ---
---Retrieve the current window mode. ---Retrieve the window mode.
---
---@param window renwindow
--- ---
---@return system.windowmode mode ---@return system.windowmode mode
function system.get_window_mode() end function system.get_window_mode(window) end
--- ---
---Toggle between bordered and borderless. ---Toggle between bordered and borderless.
@ -118,32 +122,31 @@ function system.set_window_hit_test(title_height, controls_width, resize_border)
--- ---
---Get the size and coordinates of the window. ---Get the size and coordinates of the window.
--- ---
---@param window renwindow
---
---@return number width ---@return number width
---@return number height ---@return number height
---@return number x ---@return number x
---@return number y ---@return number y
function system.get_window_size() end function system.get_window_size(window) end
--- ---
---Sets the size and coordinates of the window. ---Sets the size and coordinates of the window.
--- ---
---@param window renwindow
---@param width number ---@param width number
---@param height number ---@param height number
---@param x number ---@param x number
---@param y number ---@param y number
function system.set_window_size(width, height, x, y) end function system.set_window_size(window, width, height, x, y) end
--- ---
---Check if the window currently has focus. ---Check if the window currently has focus.
--- ---
---@param window renwindow
---
---@return boolean ---@return boolean
function system.window_has_focus() end function system.window_has_focus(window) end
---
---Gets the mode of the window.
---
---@return system.windowmode
function system.get_window_mode() end
--- ---
---Sets the position of the IME composition window. ---Sets the position of the IME composition window.
@ -161,7 +164,9 @@ function system.clear_ime() end
--- ---
---Raise the main window and give it input focus. ---Raise the main window and give it input focus.
---Note: may not always be obeyed by the users window manager. ---Note: may not always be obeyed by the users window manager.
function system.raise_window() end --
---@param window renwindow
function system.raise_window(window) end
--- ---
---Opens a message box to display an error message. ---Opens a message box to display an error message.
@ -300,10 +305,12 @@ function system.fuzzy_match(haystack, needle, file) end
--- ---
---Change the opacity (also known as transparency) of the window. ---Change the opacity (also known as transparency) of the window.
--- ---
---@param window renwindow
---@param opacity number A value from 0.0 to 1.0, the lower the value ---@param opacity number A value from 0.0 to 1.0, the lower the value
---the less visible the window will be. ---the less visible the window will be.
---
---@return boolean success True if the operation suceeded. ---@return boolean success True if the operation suceeded.
function system.set_window_opacity(opacity) end function system.set_window_opacity(window, opacity) end
--- ---
---Loads a lua native module using the default Lua API or lite-xl native plugin API. ---Loads a lua native module using the default Lua API or lite-xl native plugin API.

View File

@ -2,6 +2,7 @@
int luaopen_system(lua_State *L); int luaopen_system(lua_State *L);
int luaopen_renderer(lua_State *L); int luaopen_renderer(lua_State *L);
int luaopen_renwindow(lua_State *L);
int luaopen_regex(lua_State *L); int luaopen_regex(lua_State *L);
int luaopen_process(lua_State *L); int luaopen_process(lua_State *L);
int luaopen_dirmonitor(lua_State* L); int luaopen_dirmonitor(lua_State* L);
@ -10,6 +11,7 @@ int luaopen_utf8extra(lua_State* L);
static const luaL_Reg libs[] = { static const luaL_Reg libs[] = {
{ "system", luaopen_system }, { "system", luaopen_system },
{ "renderer", luaopen_renderer }, { "renderer", luaopen_renderer },
{ "renwindow", luaopen_renwindow },
{ "regex", luaopen_regex }, { "regex", luaopen_regex },
{ "process", luaopen_process }, { "process", luaopen_process },
{ "dirmonitor", luaopen_dirmonitor }, { "dirmonitor", luaopen_dirmonitor },

View File

@ -9,6 +9,7 @@
#define API_TYPE_PROCESS "Process" #define API_TYPE_PROCESS "Process"
#define API_TYPE_DIRMONITOR "Dirmonitor" #define API_TYPE_DIRMONITOR "Dirmonitor"
#define API_TYPE_NATIVE_PLUGIN "NativePlugin" #define API_TYPE_NATIVE_PLUGIN "NativePlugin"
#define API_TYPE_RENWINDOW "RenWindow"
#define API_CONSTANT_DEFINE(L, idx, key, n) (lua_pushnumber(L, n), lua_setfield(L, idx - 1, key)) #define API_CONSTANT_DEFINE(L, idx, key, n) (lua_pushnumber(L, n), lua_setfield(L, idx - 1, key))

View File

@ -1,9 +1,12 @@
#include <string.h> #include <string.h>
#include <assert.h>
#include "api.h" #include "api.h"
#include "../renderer.h" #include "../renderer.h"
#include "../rencache.h" #include "../rencache.h"
#include "lua.h" #include "lua.h"
RenWindow *active_window_renderer = NULL;
// a reference index to a table that stores the fonts // a reference index to a table that stores the fonts
static int RENDERER_FONT_REF = LUA_NOREF; static int RENDERER_FONT_REF = LUA_NOREF;
@ -90,7 +93,7 @@ static int f_font_load(lua_State *L) {
return ret_code; return ret_code;
RenFont** font = lua_newuserdata(L, sizeof(RenFont*)); RenFont** font = lua_newuserdata(L, sizeof(RenFont*));
*font = ren_font_load(window_renderer, filename, size, antialiasing, hinting, style); *font = ren_font_load(filename, size, antialiasing, hinting, style);
if (!*font) if (!*font)
return luaL_error(L, "failed to load font"); return luaL_error(L, "failed to load font");
luaL_setmetatable(L, API_TYPE_FONT); luaL_setmetatable(L, API_TYPE_FONT);
@ -136,7 +139,7 @@ static int f_font_copy(lua_State *L) {
} }
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
RenFont** font = lua_newuserdata(L, sizeof(RenFont*)); RenFont** font = lua_newuserdata(L, sizeof(RenFont*));
*font = ren_font_copy(window_renderer, fonts[i], size, antialiasing, hinting, style); *font = ren_font_copy(fonts[i], size, antialiasing, hinting, style);
if (!*font) if (!*font)
return luaL_error(L, "failed to copy font"); return luaL_error(L, "failed to copy font");
luaL_setmetatable(L, API_TYPE_FONT); luaL_setmetatable(L, API_TYPE_FONT);
@ -204,7 +207,7 @@ static int f_font_get_width(lua_State *L) {
size_t len; size_t len;
const char *text = luaL_checklstring(L, 2, &len); const char *text = luaL_checklstring(L, 2, &len);
lua_pushnumber(L, ren_font_group_get_width(window_renderer, fonts, text, len, NULL)); lua_pushnumber(L, ren_font_group_get_width(fonts, text, len, NULL));
return 1; return 1;
} }
@ -223,7 +226,7 @@ static int f_font_get_size(lua_State *L) {
static int f_font_set_size(lua_State *L) { static int f_font_set_size(lua_State *L) {
RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1); RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1);
float size = luaL_checknumber(L, 2); float size = luaL_checknumber(L, 2);
ren_font_group_set_size(window_renderer, fonts, size); ren_font_group_set_size(fonts, size);
return 0; return 0;
} }
@ -281,8 +284,9 @@ static int f_show_debug(lua_State *L) {
static int f_get_size(lua_State *L) { static int f_get_size(lua_State *L) {
int w, h; int w = 0, h = 0;
ren_get_size(window_renderer, &w, &h); if (active_window_renderer)
ren_get_size(active_window_renderer, &w, &h);
lua_pushnumber(L, w); lua_pushnumber(L, w);
lua_pushnumber(L, h); lua_pushnumber(L, h);
return 2; return 2;
@ -290,13 +294,17 @@ static int f_get_size(lua_State *L) {
static int f_begin_frame(UNUSED lua_State *L) { static int f_begin_frame(UNUSED lua_State *L) {
rencache_begin_frame(window_renderer); assert(active_window_renderer == NULL);
active_window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
rencache_begin_frame(active_window_renderer);
return 0; return 0;
} }
static int f_end_frame(UNUSED lua_State *L) { static int f_end_frame(UNUSED lua_State *L) {
rencache_end_frame(window_renderer); assert(active_window_renderer != NULL);
rencache_end_frame(active_window_renderer);
active_window_renderer = NULL;
// clear the font reference table // clear the font reference table
lua_newtable(L); lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, RENDERER_FONT_REF); lua_rawseti(L, LUA_REGISTRYINDEX, RENDERER_FONT_REF);
@ -312,28 +320,31 @@ static RenRect rect_to_grid(lua_Number x, lua_Number y, lua_Number w, lua_Number
static int f_set_clip_rect(lua_State *L) { static int f_set_clip_rect(lua_State *L) {
assert(active_window_renderer != NULL);
lua_Number x = luaL_checknumber(L, 1); lua_Number x = luaL_checknumber(L, 1);
lua_Number y = luaL_checknumber(L, 2); lua_Number y = luaL_checknumber(L, 2);
lua_Number w = luaL_checknumber(L, 3); lua_Number w = luaL_checknumber(L, 3);
lua_Number h = luaL_checknumber(L, 4); lua_Number h = luaL_checknumber(L, 4);
RenRect rect = rect_to_grid(x, y, w, h); RenRect rect = rect_to_grid(x, y, w, h);
rencache_set_clip_rect(window_renderer, rect); rencache_set_clip_rect(active_window_renderer, rect);
return 0; return 0;
} }
static int f_draw_rect(lua_State *L) { static int f_draw_rect(lua_State *L) {
assert(active_window_renderer != NULL);
lua_Number x = luaL_checknumber(L, 1); lua_Number x = luaL_checknumber(L, 1);
lua_Number y = luaL_checknumber(L, 2); lua_Number y = luaL_checknumber(L, 2);
lua_Number w = luaL_checknumber(L, 3); lua_Number w = luaL_checknumber(L, 3);
lua_Number h = luaL_checknumber(L, 4); lua_Number h = luaL_checknumber(L, 4);
RenRect rect = rect_to_grid(x, y, w, h); RenRect rect = rect_to_grid(x, y, w, h);
RenColor color = checkcolor(L, 5, 255); RenColor color = checkcolor(L, 5, 255);
rencache_draw_rect(window_renderer, rect, color); rencache_draw_rect(active_window_renderer, rect, color);
return 0; return 0;
} }
static int f_draw_text(lua_State *L) { static int f_draw_text(lua_State *L) {
assert(active_window_renderer != NULL);
RenFont* fonts[FONT_FALLBACK_MAX]; RenFont* fonts[FONT_FALLBACK_MAX];
font_retrieve(L, fonts, 1); font_retrieve(L, fonts, 1);
@ -354,7 +365,7 @@ static int f_draw_text(lua_State *L) {
double x = luaL_checknumber(L, 3); double x = luaL_checknumber(L, 3);
int y = luaL_checknumber(L, 4); int y = luaL_checknumber(L, 4);
RenColor color = checkcolor(L, 5, 255); RenColor color = checkcolor(L, 5, 255);
x = rencache_draw_text(window_renderer, fonts, text, len, x, y, color); x = rencache_draw_text(active_window_renderer, fonts, text, len, x, y, color);
lua_pushnumber(L, x); lua_pushnumber(L, x);
return 1; return 1;
} }

113
src/api/renwindow.c Normal file
View File

@ -0,0 +1,113 @@
#include "api.h"
#include "../renwindow.h"
#include "lua.h"
#include <SDL.h>
static RenWindow *persistant_window = NULL;
static void init_window_icon(SDL_Window *window) {
#if !defined(_WIN32) && !defined(__APPLE__)
#include "../resources/icons/icon.inl"
(void) icon_rgba_len; /* unused */
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
icon_rgba, 64, 64,
32, 64 * 4,
0x000000ff,
0x0000ff00,
0x00ff0000,
0xff000000);
SDL_SetWindowIcon(window, surf);
SDL_FreeSurface(surf);
#endif
}
static int f_renwin_create(lua_State *L) {
const char *title = luaL_checkstring(L, 1);
const int x = luaL_optinteger(L, 2, SDL_WINDOWPOS_UNDEFINED);
const int y = luaL_optinteger(L, 3, SDL_WINDOWPOS_UNDEFINED);
float width = luaL_optnumber(L, 4, 0);
float height = luaL_optnumber(L, 5, 0);
if (width < 1 || height < 1) {
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
if (width < 1) {
width = dm.w * 0.8;
}
if (height < 1) {
height = dm.h * 0.8;
}
}
SDL_Window *window = SDL_CreateWindow(
title, x, y, width, height,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN
);
if (!window) {
return luaL_error(L, "Error creating lite-xl window: %s", SDL_GetError());
}
init_window_icon(window);
RenWindow **window_renderer = (RenWindow**)lua_newuserdata(L, sizeof(RenWindow*));
luaL_setmetatable(L, API_TYPE_RENWINDOW);
*window_renderer = ren_create(window);
return 1;
}
static int f_renwin_gc(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
if (window_renderer != persistant_window)
ren_destroy(window_renderer);
return 0;
}
static int f_renwin_get_size(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
int w, h;
ren_get_size(window_renderer, &w, &h);
lua_pushnumber(L, w);
lua_pushnumber(L, h);
return 2;
}
static int f_renwin_persist(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
persistant_window = window_renderer;
return 0;
}
static int f_renwin_restore(lua_State *L) {
if (!persistant_window) {
lua_pushnil(L);
}
else {
RenWindow **window_renderer = (RenWindow**)lua_newuserdata(L, sizeof(RenWindow*));
luaL_setmetatable(L, API_TYPE_RENWINDOW);
*window_renderer = persistant_window;
}
return 1;
}
static const luaL_Reg renwindow_lib[] = {
{ "create", f_renwin_create },
{ "__gc", f_renwin_gc },
{ "get_size", f_renwin_get_size },
{ "_persist", f_renwin_persist },
{ "_restore", f_renwin_restore },
{NULL, NULL}
};
int luaopen_renwindow(lua_State* L) {
luaL_newmetatable(L, API_TYPE_RENWINDOW);
luaL_setfuncs(L, renwindow_lib, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
return 1;
}

View File

@ -74,7 +74,7 @@ static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *p
const int controls_width = hit_info->controls_width; const int controls_width = hit_info->controls_width;
int w, h; int w, h;
SDL_GetWindowSize(window_renderer->window, &w, &h); SDL_GetWindowSize(window, &w, &h);
if (pt->y < hit_info->title_height && if (pt->y < hit_info->title_height &&
#if RESIZE_FROM_TOP #if RESIZE_FROM_TOP
@ -186,6 +186,7 @@ top:
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
if (e.window.event == SDL_WINDOWEVENT_RESIZED) { if (e.window.event == SDL_WINDOWEVENT_RESIZED) {
RenWindow* window_renderer = ren_find_window_from_id(e.window.windowID);
ren_resize_window(window_renderer); ren_resize_window(window_renderer);
lua_pushstring(L, "resized"); lua_pushstring(L, "resized");
/* The size below will be in points. */ /* The size below will be in points. */
@ -222,13 +223,16 @@ top:
goto top; goto top;
case SDL_DROPFILE: case SDL_DROPFILE:
SDL_GetMouseState(&mx, &my); {
lua_pushstring(L, "filedropped"); RenWindow* window_renderer = ren_find_window_from_id(e.drop.windowID);
lua_pushstring(L, e.drop.file); SDL_GetMouseState(&mx, &my);
lua_pushinteger(L, mx * window_renderer->scale_x); lua_pushstring(L, "filedropped");
lua_pushinteger(L, my * window_renderer->scale_y); lua_pushstring(L, e.drop.file);
SDL_free(e.drop.file); lua_pushinteger(L, mx * window_renderer->scale_x);
return 4; lua_pushinteger(L, my * window_renderer->scale_y);
SDL_free(e.drop.file);
return 4;
}
case SDL_KEYDOWN: case SDL_KEYDOWN:
#ifdef __APPLE__ #ifdef __APPLE__
@ -280,36 +284,45 @@ top:
#endif #endif
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
if (e.button.button == 1) { SDL_CaptureMouse(1); } {
lua_pushstring(L, "mousepressed"); if (e.button.button == 1) { SDL_CaptureMouse(1); }
lua_pushstring(L, button_name(e.button.button)); RenWindow* window_renderer = ren_find_window_from_id(e.button.windowID);
lua_pushinteger(L, e.button.x * window_renderer->scale_x); lua_pushstring(L, "mousepressed");
lua_pushinteger(L, e.button.y * window_renderer->scale_y); lua_pushstring(L, button_name(e.button.button));
lua_pushinteger(L, e.button.clicks); lua_pushinteger(L, e.button.x * window_renderer->scale_x);
return 5; lua_pushinteger(L, e.button.y * window_renderer->scale_y);
lua_pushinteger(L, e.button.clicks);
return 5;
}
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
if (e.button.button == 1) { SDL_CaptureMouse(0); } {
lua_pushstring(L, "mousereleased"); if (e.button.button == 1) { SDL_CaptureMouse(0); }
lua_pushstring(L, button_name(e.button.button)); RenWindow* window_renderer = ren_find_window_from_id(e.button.windowID);
lua_pushinteger(L, e.button.x * window_renderer->scale_x); lua_pushstring(L, "mousereleased");
lua_pushinteger(L, e.button.y * window_renderer->scale_y); lua_pushstring(L, button_name(e.button.button));
return 4; lua_pushinteger(L, e.button.x * window_renderer->scale_x);
lua_pushinteger(L, e.button.y * window_renderer->scale_y);
return 4;
}
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
SDL_PumpEvents(); {
while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) { SDL_PumpEvents();
e.motion.x = event_plus.motion.x; while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) {
e.motion.y = event_plus.motion.y; e.motion.x = event_plus.motion.x;
e.motion.xrel += event_plus.motion.xrel; e.motion.y = event_plus.motion.y;
e.motion.yrel += event_plus.motion.yrel; e.motion.xrel += event_plus.motion.xrel;
e.motion.yrel += event_plus.motion.yrel;
}
RenWindow* window_renderer = ren_find_window_from_id(e.motion.windowID);
lua_pushstring(L, "mousemoved");
lua_pushinteger(L, e.motion.x * window_renderer->scale_x);
lua_pushinteger(L, e.motion.y * window_renderer->scale_y);
lua_pushinteger(L, e.motion.xrel * window_renderer->scale_x);
lua_pushinteger(L, e.motion.yrel * window_renderer->scale_y);
return 5;
} }
lua_pushstring(L, "mousemoved");
lua_pushinteger(L, e.motion.x * window_renderer->scale_x);
lua_pushinteger(L, e.motion.y * window_renderer->scale_y);
lua_pushinteger(L, e.motion.xrel * window_renderer->scale_x);
lua_pushinteger(L, e.motion.yrel * window_renderer->scale_y);
return 5;
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
lua_pushstring(L, "mousewheel"); lua_pushstring(L, "mousewheel");
@ -324,49 +337,64 @@ top:
return 3; return 3;
case SDL_FINGERDOWN: case SDL_FINGERDOWN:
SDL_GetWindowSize(window_renderer->window, &w, &h); {
RenWindow* window_renderer = ren_find_window_from_id(e.tfinger.windowID);
SDL_GetWindowSize(window_renderer->window, &w, &h);
lua_pushstring(L, "touchpressed"); lua_pushstring(L, "touchpressed");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h)); lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, e.tfinger.fingerId); lua_pushinteger(L, e.tfinger.fingerId);
return 4; return 4;
}
case SDL_FINGERUP: case SDL_FINGERUP:
SDL_GetWindowSize(window_renderer->window, &w, &h); {
RenWindow* window_renderer = ren_find_window_from_id(e.tfinger.windowID);
SDL_GetWindowSize(window_renderer->window, &w, &h);
lua_pushstring(L, "touchreleased"); lua_pushstring(L, "touchreleased");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h)); lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, e.tfinger.fingerId); lua_pushinteger(L, e.tfinger.fingerId);
return 4; return 4;
}
case SDL_FINGERMOTION: case SDL_FINGERMOTION:
SDL_PumpEvents(); {
while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_FINGERMOTION, SDL_FINGERMOTION) > 0) { SDL_PumpEvents();
e.tfinger.x = event_plus.tfinger.x; while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_FINGERMOTION, SDL_FINGERMOTION) > 0) {
e.tfinger.y = event_plus.tfinger.y; e.tfinger.x = event_plus.tfinger.x;
e.tfinger.dx += event_plus.tfinger.dx; e.tfinger.y = event_plus.tfinger.y;
e.tfinger.dy += event_plus.tfinger.dy; e.tfinger.dx += event_plus.tfinger.dx;
} e.tfinger.dy += event_plus.tfinger.dy;
SDL_GetWindowSize(window_renderer->window, &w, &h); }
RenWindow* window_renderer = ren_find_window_from_id(e.tfinger.windowID);
SDL_GetWindowSize(window_renderer->window, &w, &h);
lua_pushstring(L, "touchmoved"); lua_pushstring(L, "touchmoved");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h)); lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, (lua_Integer)(e.tfinger.dx * w)); lua_pushinteger(L, (lua_Integer)(e.tfinger.dx * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.dy * h)); lua_pushinteger(L, (lua_Integer)(e.tfinger.dy * h));
lua_pushinteger(L, e.tfinger.fingerId); lua_pushinteger(L, e.tfinger.fingerId);
return 6; return 6;
}
case SDL_APP_WILLENTERFOREGROUND: case SDL_APP_WILLENTERFOREGROUND:
case SDL_APP_DIDENTERFOREGROUND: case SDL_APP_DIDENTERFOREGROUND:
#ifdef LITE_USE_SDL_RENDERER {
rencache_invalidate(); #ifdef LITE_USE_SDL_RENDERER
#else rencache_invalidate();
SDL_UpdateWindowSurface(window_renderer->window); #else
#endif RenWindow** window_list;
lua_pushstring(L, e.type == SDL_APP_WILLENTERFOREGROUND ? "enteringforeground" : "enteredforeground"); size_t window_count = ren_get_window_list(&window_list);
return 1; while (window_count) {
SDL_UpdateWindowSurface(window_list[--window_count]->window);
}
#endif
lua_pushstring(L, e.type == SDL_APP_WILLENTERFOREGROUND ? "enteringforeground" : "enteredforeground");
return 1;
}
case SDL_APP_WILLENTERBACKGROUND: case SDL_APP_WILLENTERBACKGROUND:
lua_pushstring(L, "enteringbackground"); lua_pushstring(L, "enteringbackground");
return 1; return 1;
@ -428,7 +456,8 @@ static int f_set_cursor(lua_State *L) {
static int f_set_window_title(lua_State *L) { static int f_set_window_title(lua_State *L) {
const char *title = luaL_checkstring(L, 1); RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
const char *title = luaL_checkstring(L, 2);
SDL_SetWindowTitle(window_renderer->window, title); SDL_SetWindowTitle(window_renderer->window, title);
return 0; return 0;
} }
@ -438,7 +467,8 @@ static const char *window_opts[] = { "normal", "minimized", "maximized", "fullsc
enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN }; enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN };
static int f_set_window_mode(lua_State *L) { static int f_set_window_mode(lua_State *L) {
int n = luaL_checkoption(L, 1, "normal", window_opts); RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
int n = luaL_checkoption(L, 2, "normal", window_opts);
SDL_SetWindowFullscreen(window_renderer->window, SDL_SetWindowFullscreen(window_renderer->window,
n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if (n == WIN_NORMAL) { SDL_RestoreWindow(window_renderer->window); } if (n == WIN_NORMAL) { SDL_RestoreWindow(window_renderer->window); }
@ -449,26 +479,38 @@ static int f_set_window_mode(lua_State *L) {
static int f_set_window_bordered(lua_State *L) { static int f_set_window_bordered(lua_State *L) {
RenWindow** window_list;
size_t window_count = ren_get_window_list(&window_list);
int bordered = lua_toboolean(L, 1); int bordered = lua_toboolean(L, 1);
SDL_SetWindowBordered(window_renderer->window, bordered); while (window_count) {
SDL_SetWindowBordered(window_list[--window_count]->window, bordered);
}
return 0; return 0;
} }
static int f_set_window_hit_test(lua_State *L) { static int f_set_window_hit_test(lua_State *L) {
RenWindow** window_list;
size_t window_count = ren_get_window_list(&window_list);
if (lua_gettop(L) == 0) { if (lua_gettop(L) == 0) {
SDL_SetWindowHitTest(window_renderer->window, NULL, NULL); while (window_count) {
SDL_SetWindowHitTest(window_list[--window_count]->window, NULL, NULL);
}
return 0; return 0;
} }
window_hit_info->title_height = luaL_checknumber(L, 1); window_hit_info->title_height = luaL_checknumber(L, 1);
window_hit_info->controls_width = luaL_checknumber(L, 2); window_hit_info->controls_width = luaL_checknumber(L, 2);
window_hit_info->resize_border = luaL_checknumber(L, 3); window_hit_info->resize_border = luaL_checknumber(L, 3);
SDL_SetWindowHitTest(window_renderer->window, hit_test, window_hit_info); while (window_count) {
SDL_SetWindowHitTest(window_list[--window_count]->window, hit_test, window_hit_info);
}
return 0; return 0;
} }
static int f_get_window_size(lua_State *L) { static int f_get_window_size(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
int x, y, w, h; int x, y, w, h;
SDL_GetWindowSize(window_renderer->window, &w, &h); SDL_GetWindowSize(window_renderer->window, &w, &h);
SDL_GetWindowPosition(window_renderer->window, &x, &y); SDL_GetWindowPosition(window_renderer->window, &x, &y);
@ -481,10 +523,11 @@ static int f_get_window_size(lua_State *L) {
static int f_set_window_size(lua_State *L) { static int f_set_window_size(lua_State *L) {
double w = luaL_checknumber(L, 1); RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
double h = luaL_checknumber(L, 2); double w = luaL_checknumber(L, 2);
double x = luaL_checknumber(L, 3); double h = luaL_checknumber(L, 3);
double y = luaL_checknumber(L, 4); double x = luaL_checknumber(L, 4);
double y = luaL_checknumber(L, 5);
SDL_SetWindowSize(window_renderer->window, w, h); SDL_SetWindowSize(window_renderer->window, w, h);
SDL_SetWindowPosition(window_renderer->window, x, y); SDL_SetWindowPosition(window_renderer->window, x, y);
ren_resize_window(window_renderer); ren_resize_window(window_renderer);
@ -493,6 +536,7 @@ static int f_set_window_size(lua_State *L) {
static int f_window_has_focus(lua_State *L) { static int f_window_has_focus(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
unsigned flags = SDL_GetWindowFlags(window_renderer->window); unsigned flags = SDL_GetWindowFlags(window_renderer->window);
lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS); lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS);
return 1; return 1;
@ -500,6 +544,7 @@ static int f_window_has_focus(lua_State *L) {
static int f_get_window_mode(lua_State *L) { static int f_get_window_mode(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
unsigned flags = SDL_GetWindowFlags(window_renderer->window); unsigned flags = SDL_GetWindowFlags(window_renderer->window);
if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) {
lua_pushstring(L, "fullscreen"); lua_pushstring(L, "fullscreen");
@ -532,6 +577,7 @@ static int f_clear_ime(lua_State *L) {
static int f_raise_window(lua_State *L) { static int f_raise_window(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
/* /*
SDL_RaiseWindow should be enough but on some window managers like the SDL_RaiseWindow should be enough but on some window managers like the
one used on Gnome the window needs to first have input focus in order one used on Gnome the window needs to first have input focus in order
@ -922,7 +968,8 @@ static int f_fuzzy_match(lua_State *L) {
} }
static int f_set_window_opacity(lua_State *L) { static int f_set_window_opacity(lua_State *L) {
double n = luaL_checknumber(L, 1); RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
double n = luaL_checknumber(L, 2);
int r = SDL_SetWindowOpacity(window_renderer->window, n); int r = SDL_SetWindowOpacity(window_renderer->window, n);
lua_pushboolean(L, r > -1); lua_pushboolean(L, r > -1);
return 1; return 1;

View File

@ -17,9 +17,6 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
static SDL_Window *window;
static void get_exe_filename(char *buf, int sz) { static void get_exe_filename(char *buf, int sz) {
#if _WIN32 #if _WIN32
int len; int len;
@ -56,23 +53,6 @@ static void get_exe_filename(char *buf, int sz) {
#endif #endif
} }
static void init_window_icon(void) {
#if !defined(_WIN32) && !defined(__APPLE__)
#include "../resources/icons/icon.inl"
(void) icon_rgba_len; /* unused */
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
icon_rgba, 64, 64,
32, 64 * 4,
0x000000ff,
0x0000ff00,
0x00ff0000,
0xff000000);
SDL_SetWindowIcon(window, surf);
SDL_FreeSurface(surf);
#endif
}
#ifdef _WIN32 #ifdef _WIN32
#define LITE_OS_HOME "USERPROFILE" #define LITE_OS_HOME "USERPROFILE"
#define LITE_PATHSEP_PATTERN "\\\\" #define LITE_PATHSEP_PATTERN "\\\\"
@ -165,18 +145,9 @@ int main(int argc, char **argv) {
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
SDL_DisplayMode dm; if ( ren_init() ) {
SDL_GetCurrentDisplayMode(0, &dm); fprintf(stderr, "internal font error when starting the application\n");
window = SDL_CreateWindow(
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
init_window_icon();
if (!window) {
fprintf(stderr, "Error creating lite-xl window: %s", SDL_GetError());
exit(1);
} }
window_renderer = ren_init(window);
lua_State *L; lua_State *L;
init_lua: init_lua:
@ -265,10 +236,9 @@ init_lua:
goto init_lua; goto init_lua;
} }
// This allows the window to be destroyed before lite-xl is done with
// reaping child processes
ren_free(window_renderer);
lua_close(L); lua_close(L);
ren_free();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -1,6 +1,7 @@
lite_sources = [ lite_sources = [
'api/api.c', 'api/api.c',
'api/renderer.c', 'api/renderer.c',
'api/renwindow.c',
'api/regex.c', 'api/regex.c',
'api/system.c', 'api/system.c',
'api/process.c', 'api/process.c',

View File

@ -192,7 +192,7 @@ void rencache_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color
double rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, double x, int y, RenColor color) double rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, double x, int y, RenColor color)
{ {
int x_offset; int x_offset;
double width = ren_font_group_get_width(window_renderer, fonts, text, len, &x_offset); double width = ren_font_group_get_width(fonts, text, len, &x_offset);
RenRect rect = { x + x_offset, y, (int)(width - x_offset), ren_font_group_get_height(fonts) }; RenRect rect = { x + x_offset, y, (int)(width - x_offset), ren_font_group_get_height(fonts) };
if (rects_overlap(last_clip_rect, rect)) { if (rects_overlap(last_clip_rect, rect)) {
int sz = len + 1; int sz = len + 1;

View File

@ -22,7 +22,8 @@
#define MAX_LOADABLE_GLYPHSETS (MAX_UNICODE / GLYPHSET_SIZE) #define MAX_LOADABLE_GLYPHSETS (MAX_UNICODE / GLYPHSET_SIZE)
#define SUBPIXEL_BITMAPS_CACHED 3 #define SUBPIXEL_BITMAPS_CACHED 3
RenWindow* window_renderer = NULL; static RenWindow **window_list = NULL;
static size_t window_count = 0;
static FT_Library library; static FT_Library library;
// draw_rect_surface is used as a 1x1 surface to simplify ren_draw_rect with blending // draw_rect_surface is used as a 1x1 surface to simplify ren_draw_rect with blending
@ -248,7 +249,7 @@ static void font_file_close(FT_Stream stream) {
} }
} }
RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) { RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) {
RenFont *font = NULL; RenFont *font = NULL;
FT_Face face = NULL; FT_Face face = NULL;
@ -267,8 +268,7 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size,
if (FT_Open_Face(library, &(FT_Open_Args){ .flags = FT_OPEN_STREAM, .stream = &font->stream }, 0, &face)) if (FT_Open_Face(library, &(FT_Open_Args){ .flags = FT_OPEN_STREAM, .stream = &font->stream }, 0, &face))
goto failure; goto failure;
const int surface_scale = renwin_get_surface(window_renderer).scale; if (FT_Set_Pixel_Sizes(face, 0, (int)(size)))
if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale)))
goto failure; goto failure;
strcpy(font->path, path); strcpy(font->path, path);
@ -305,12 +305,12 @@ rwops_failure:
return NULL; return NULL;
} }
RenFont* ren_font_copy(RenWindow *window_renderer, RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style) { RenFont* ren_font_copy(RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style) {
antialiasing = antialiasing == -1 ? font->antialiasing : antialiasing; antialiasing = antialiasing == -1 ? font->antialiasing : antialiasing;
hinting = hinting == -1 ? font->hinting : hinting; hinting = hinting == -1 ? font->hinting : hinting;
style = style == -1 ? font->style : style; style = style == -1 ? font->style : style;
return ren_font_load(window_renderer, font->path, size, antialiasing, hinting, style); return ren_font_load(font->path, size, antialiasing, hinting, style);
} }
const char* ren_font_get_path(RenFont *font) { const char* ren_font_get_path(RenFont *font) {
@ -344,12 +344,11 @@ float ren_font_group_get_size(RenFont **fonts) {
return fonts[0]->size; return fonts[0]->size;
} }
void ren_font_group_set_size(RenWindow *window_renderer, RenFont **fonts, float size) { void ren_font_group_set_size(RenFont **fonts, float size) {
const int surface_scale = renwin_get_surface(window_renderer).scale;
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
font_clear_glyph_cache(fonts[i]); font_clear_glyph_cache(fonts[i]);
FT_Face face = fonts[i]->face; FT_Face face = fonts[i]->face;
FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale)); FT_Set_Pixel_Sizes(face, 0, (int)(size));
fonts[i]->size = size; fonts[i]->size = size;
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
fonts[i]->scale = surface_scale; fonts[i]->scale = surface_scale;
@ -366,7 +365,7 @@ int ren_font_group_get_height(RenFont **fonts) {
return fonts[0]->height; return fonts[0]->height;
} }
double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, int *x_offset) { double ren_font_group_get_width(RenFont **fonts, const char *text, size_t len, int *x_offset) {
double width = 0; double width = 0;
const char* end = text + len; const char* end = text + len;
GlyphMetric* metric = NULL; GlyphSet* set = NULL; GlyphMetric* metric = NULL; GlyphSet* set = NULL;
@ -383,11 +382,10 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con
*x_offset = metric->bitmap_left; // TODO: should this be scaled by the surface scale? *x_offset = metric->bitmap_left; // TODO: should this be scaled by the surface scale?
} }
} }
const int surface_scale = renwin_get_surface(window_renderer).scale;
if (!set_x_offset) { if (!set_x_offset) {
*x_offset = 0; *x_offset = 0;
} }
return width / surface_scale; return width;
} }
double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) {
@ -519,29 +517,55 @@ void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) {
} }
/*************** Window Management ****************/ /*************** Window Management ****************/
RenWindow* ren_init(SDL_Window *win) { static void ren_add_window(RenWindow *window_renderer) {
assert(win); window_count += 1;
int error = FT_Init_FreeType( &library ); window_list = realloc(window_list, window_count);
if ( error ) { window_list[window_count-1] = window_renderer;
fprintf(stderr, "internal font error when starting the application\n"); }
return NULL;
static void ren_remove_window(RenWindow *window_renderer) {
for (size_t i = 0; i < window_count; ++i) {
if (window_list[i] == window_renderer) {
window_count -= 1;
memmove(&window_list[i], &window_list[i+1], window_count - i);
return;
}
} }
}
int ren_init(void) {
int err;
draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32,
0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
if ((err = FT_Init_FreeType( &library )))
return err;
return 0;
}
void ren_free(void) {
SDL_FreeSurface(draw_rect_surface);
}
RenWindow* ren_create(SDL_Window *win) {
assert(win);
RenWindow* window_renderer = calloc(1, sizeof(RenWindow)); RenWindow* window_renderer = calloc(1, sizeof(RenWindow));
window_renderer->window = win; window_renderer->window = win;
renwin_init_surface(window_renderer); renwin_init_surface(window_renderer);
renwin_init_command_buf(window_renderer); renwin_init_command_buf(window_renderer);
renwin_clip_to_surface(window_renderer); renwin_clip_to_surface(window_renderer);
draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32,
0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
ren_add_window(window_renderer);
return window_renderer; return window_renderer;
} }
void ren_free(RenWindow* window_renderer) { void ren_destroy(RenWindow* window_renderer) {
assert(window_renderer); assert(window_renderer);
ren_remove_window(window_renderer);
renwin_free(window_renderer); renwin_free(window_renderer);
SDL_FreeSurface(draw_rect_surface);
free(window_renderer->command_buf); free(window_renderer->command_buf);
window_renderer->command_buf = NULL; window_renderer->command_buf = NULL;
window_renderer->command_buf_size = 0; window_renderer->command_buf_size = 0;
@ -553,14 +577,14 @@ void ren_resize_window(RenWindow *window_renderer) {
renwin_update_scale(window_renderer); renwin_update_scale(window_renderer);
} }
// TODO: Does not work nicely with multiple windows
void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count) { void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count) {
static bool initial_frame = true; static bool initial_frame = true;
renwin_update_rects(window_renderer, rects, count);
if (initial_frame) { if (initial_frame) {
renwin_show_window(window_renderer); renwin_show_window(window_renderer);
initial_frame = false; initial_frame = false;
} }
renwin_update_rects(window_renderer, rects, count);
} }
@ -571,6 +595,27 @@ void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect) {
void ren_get_size(RenWindow *window_renderer, int *x, int *y) { void ren_get_size(RenWindow *window_renderer, int *x, int *y) {
RenSurface rs = renwin_get_surface(window_renderer); RenSurface rs = renwin_get_surface(window_renderer);
*x = rs.surface->w / rs.scale; *x = rs.surface->w;
*y = rs.surface->h / rs.scale; *y = rs.surface->h;
}
size_t ren_get_window_list(RenWindow ***window_list_dest) {
*window_list_dest = window_list;
return window_count;
}
RenWindow* ren_find_window(SDL_Window *window) {
for (size_t i = 0; i < window_count; ++i) {
RenWindow* window_renderer = window_list[i];
if (window_renderer->window == window) {
return window_renderer;
}
}
return NULL;
}
RenWindow* ren_find_window_from_id(uint32_t id) {
SDL_Window *window = SDL_GetWindowFromID(id);
return ren_find_window(window);
} }

View File

@ -23,31 +23,34 @@ typedef struct { SDL_Surface *surface; int scale; } RenSurface;
struct RenWindow; struct RenWindow;
typedef struct RenWindow RenWindow; typedef struct RenWindow RenWindow;
extern RenWindow* window_renderer;
RenFont* ren_font_load(RenWindow *window_renderer, const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style); RenFont* ren_font_load(const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style);
RenFont* ren_font_copy(RenWindow *window_renderer, RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style); RenFont* ren_font_copy(RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style);
const char* ren_font_get_path(RenFont *font); const char* ren_font_get_path(RenFont *font);
void ren_font_free(RenFont *font); void ren_font_free(RenFont *font);
int ren_font_group_get_tab_size(RenFont **font); int ren_font_group_get_tab_size(RenFont **font);
int ren_font_group_get_height(RenFont **font); int ren_font_group_get_height(RenFont **font);
float ren_font_group_get_size(RenFont **font); float ren_font_group_get_size(RenFont **font);
void ren_font_group_set_size(RenWindow *window_renderer, RenFont **font, float size); void ren_font_group_set_size(RenFont **font, float size);
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
void update_font_scale(RenWindow *window_renderer, RenFont **fonts); void update_font_scale(RenWindow *window_renderer, RenFont **fonts);
#endif #endif
void ren_font_group_set_tab_size(RenFont **font, int n); void ren_font_group_set_tab_size(RenFont **font, int n);
double ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, int *x_offset); double ren_font_group_get_width(RenFont **font, const char *text, size_t len, int *x_offset);
double ren_draw_text(RenSurface *rs, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); double ren_draw_text(RenSurface *rs, RenFont **font, const char *text, size_t len, float x, int y, RenColor color);
void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color); void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color);
RenWindow* ren_init(SDL_Window *win); int ren_init(void);
void ren_free(RenWindow* window_renderer); void ren_free(void);
RenWindow* ren_create(SDL_Window *win);
void ren_destroy(RenWindow* window_renderer);
void ren_resize_window(RenWindow *window_renderer); void ren_resize_window(RenWindow *window_renderer);
void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count); void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count);
void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect); void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect);
void ren_get_size(RenWindow *window_renderer, int *x, int *y); /* Reports the size in points. */ void ren_get_size(RenWindow *window_renderer, int *x, int *y); /* Reports the size in points. */
size_t ren_get_window_list(RenWindow ***window_list_dest);
RenWindow* ren_find_window(SDL_Window *window);
RenWindow* ren_find_window_from_id(uint32_t id);
#endif #endif