From 548b2ac9eabe9fbce8dca4f69128ff9cf1403d7d Mon Sep 17 00:00:00 2001
From: DarkGod <darkgod@net-core.org>
Date: Mon, 16 Dec 2013 19:05:53 +0100
Subject: [PATCH] New video mode: borderless window

---
 game/engines/default/engine/Game.lua          | 16 +++++---
 .../engine/dialogs/DisplayResolution.lua      | 37 ++++++++++++++++---
 .../default/engine/dialogs/KeyBinder.lua      |  6 +--
 .../default/modules/boot/dialogs/LoadGame.lua |  2 +-
 game/modules/tome/init.lua                    |  2 +-
 src/core_lua.c                                |  9 +++--
 src/main.c                                    | 18 ++++++---
 src/main.h                                    |  2 +-
 8 files changed, 65 insertions(+), 27 deletions(-)

diff --git a/game/engines/default/engine/Game.lua b/game/engines/default/engine/Game.lua
index 17a491bd5c..2a292a2602 100644
--- a/game/engines/default/engine/Game.lua
+++ b/game/engines/default/engine/Game.lua
@@ -435,11 +435,15 @@ end
 function _M:setResolution(res, force)
 	local r = available_resolutions[res]
 	if force and not r then
+		local b = false
 		local _, _, w, h, f = res:find("([0-9][0-9][0-9]+)x([0-9][0-9][0-9]+)(.*)")
 		w = tonumber(w)
 		h = tonumber(h)
 		if f == " Fullscreen" then
 			f = true
+		elseif f == " Borderless" then
+			f = false
+			b = true
 		elseif f ~= " Windowed" then
 			-- If no windowed/fullscreen option sent, use the old value.
 			-- If no old value, opt for windowed mode.
@@ -447,14 +451,14 @@ function _M:setResolution(res, force)
 		else
 			f = false
 		end 
-		if w and h then r = {w, h, f} end
+		if w and h then r = {w, h, f, b} end
 	end
 	if not r then return false, "unknown resolution" end
 
 	-- Change the window size
-	print("setResolution: switching resolution to", res, r[1], r[2], r[3], force and "(forced)")
+	print("setResolution: switching resolution to", res, r[1], r[2], r[3], r[4], force and "(forced)")
 	local old_w, old_h, old_f = self.w, self.h, self.fullscreen
-	core.display.setWindowSize(r[1], r[2], r[3])
+	core.display.setWindowSize(r[1], r[2], r[3], r[4])
 	
 	-- Don't write self.w/h/fullscreen yet
 	local new_w, new_h, new_f = core.display.size()
@@ -472,7 +476,7 @@ end
 
 --- Called when screen resolution changes
 function _M:onResolutionChange()
-	local ow, oh, of = self.w, self.h, self.fullscreen
+	local ow, oh, of, ob = self.w, self.h, self.fullscreen, self.borderless
 
 	-- Save old values for a potential revert
 	if game and not self.change_res_dialog_oldw then
@@ -481,8 +485,8 @@ function _M:onResolutionChange()
 	end
 	
 	-- Get new resolution and save
-	self.w, self.h, self.fullscreen = core.display.size()
-	config.settings.window.size = ("%dx%d%s"):format(self.w, self.h, self.fullscreen and " Fullscreen" or " Windowed")
+	self.w, self.h, self.fullscreen, self.borderless = core.display.size()
+	config.settings.window.size = ("%dx%d%s"):format(self.w, self.h, self.fullscreen and " Fullscreen" or (self.borderless and " Borderless" or " Windowed"))
 	self:saveSettings("resolution", ("window.size = '%s'\n"):format(config.settings.window.size))
 	print("onResolutionChange: resolution changed to ", self.w, self.h, "from", ow, oh)
 
diff --git a/game/engines/default/engine/dialogs/DisplayResolution.lua b/game/engines/default/engine/dialogs/DisplayResolution.lua
index 0c24f42b77..65775f57ca 100644
--- a/game/engines/default/engine/dialogs/DisplayResolution.lua
+++ b/game/engines/default/engine/dialogs/DisplayResolution.lua
@@ -20,6 +20,7 @@
 require "engine.class"
 local Dialog = require "engine.ui.Dialog"
 local List = require "engine.ui.List"
+local Checkbox = require "engine.ui.Checkbox"
 
 module(..., package.seeall, class.inherit(Dialog))
 
@@ -27,15 +28,27 @@ function _M:init(on_change)
 	self.on_change = on_change
 	self:generateList()
 
+	local w, h, fullscreen, borderless = core.display.size()
+
 	Dialog.init(self, "Switch Resolution", 300, 20)
 
 	self.c_list = List.new{width=self.iw, nb_items=#self.list, list=self.list, fct=function(item) self:use(item) end}
+	self.c_fs = Checkbox.new{title="Fullscreen", default=fullscreen,
+		fct=function() end,
+		on_change=function(s) if s then self.c_bl.checked = false end end
+	}
+	self.c_bl = Checkbox.new{title="Borderless", default=borderless,
+		fct=function() end,
+		on_change=function(s) if s then self.c_fs.checked = false end end
+	}
 
 	self:loadUI{
-		{left=0, top=0, ui=self.c_list},
+		{left=0, top=0, ui=self.c_fs},
+		{left=self.c_fs.w + 5, top=0, ui=self.c_bl},
+		{left=0, top=self.c_fs.h, ui=self.c_list},
 	}
 	self:setFocus(self.c_list)
-	self:setupUI(false, true)
+	self:setupUI(true, true)
 
 	self.key:addBinds{
 		EXIT = function() game:unregisterDialog(self) end,
@@ -43,15 +56,25 @@ function _M:init(on_change)
 end
 
 function _M:use(item)
-	game:setResolution(item.r)
+	local mode = " Windowed"
+	if self.c_fs.checked then mode = " Fullscreen"
+	elseif self.c_bl.checked then mode = " Borderless"
+	end
+	local r = item.r..mode
+	game:setResolution(r, true)
 	game:unregisterDialog(self)
-	if self.on_change then self.on_change(item.r) end
+	if self.on_change then self.on_change(r) end
 end
 
 function _M:generateList()
 	local l = {}
-	for r, _ in pairs(game.available_resolutions) do
-		l[#l+1] = r
+	local seen = {}
+	for r, d in pairs(game.available_resolutions) do
+		seen[d[1]] = seen[d[1]] or {}
+		if not seen[d[1]][d[2]] then 
+			l[#l+1] = r
+			seen[d[1]][d[2]] = true
+		end
 	end
 	table.sort(l, function(a,b)
 		if game.available_resolutions[a][2] == game.available_resolutions[b][2] then
@@ -67,6 +90,8 @@ function _M:generateList()
 	local list = {}
 	local i = 0
 	for _, r in ipairs(l) do
+		local _, _, w, h = r:find("^([0-9]+)x([0-9]+)")
+		local r = w.."x"..h
 		list[#list+1] = { name=string.char(string.byte('a') + i)..")  "..r, r=r }
 		i = i + 1
 	end
diff --git a/game/engines/default/engine/dialogs/KeyBinder.lua b/game/engines/default/engine/dialogs/KeyBinder.lua
index b171050cf4..a47c34108d 100644
--- a/game/engines/default/engine/dialogs/KeyBinder.lua
+++ b/game/engines/default/engine/dialogs/KeyBinder.lua
@@ -77,10 +77,10 @@ function _M:use(item)
 	-- Make a dialog to ask for the key
 	--
 	if curcol == 1 or curcol == 2 then
-		local title = "Press a key (or escape) for: "..tostring(t.name)
+		local title = "      Press a key (escape to cancel, backspace to remove) for: "..tostring(t.name)
 		local font = self.font
-		local w, h = font:size(title)
-		local d = engine.Dialog.new(title, w + 8, h + 25, nil, nil, nil, font)
+		local w, h = font:size(title:removeColorCodes())
+		local d = engine.Dialog.new(title, w + 20, h + 25, nil, nil, nil, font)
 		d:keyCommands{__DEFAULT=function(sym, ctrl, shift, alt, meta, unicode)
 			-- Modifier keys are not treated
 			if not t.single_key and (sym == KeyBind._LCTRL or sym == KeyBind._RCTRL or
diff --git a/game/engines/default/modules/boot/dialogs/LoadGame.lua b/game/engines/default/modules/boot/dialogs/LoadGame.lua
index 39a356060e..22003757a9 100644
--- a/game/engines/default/modules/boot/dialogs/LoadGame.lua
+++ b/game/engines/default/modules/boot/dialogs/LoadGame.lua
@@ -32,7 +32,7 @@ module(..., package.seeall, class.inherit(Dialog))
 function _M:init()
 	Dialog.init(self, "Load Game", game.w * 0.8, game.h * 0.8)
 
-	self.c_compat = Checkbox.new{default=false, width=math.floor(self.iw / 3 - 40), title="Show incompatible", on_change=function() self:switch() end}
+	self.c_compat = Checkbox.new{default=false, width=math.floor(self.iw / 3 - 40), title="Show older versions", on_change=function() self:switch() end}
 	self.c_play = Button.new{text="  Play!  ", fct=function(text) self:playSave() end}
 	self.c_delete = Button.new{text="Delete", fct=function(text) self:deleteSave() end}
 	self.c_desc = Textzone.new{width=math.floor(self.iw / 3 * 2 - 10), height=self.ih - self.c_delete.h - 10, text=""}
diff --git a/game/modules/tome/init.lua b/game/modules/tome/init.lua
index a297a53e4f..ec9939370f 100644
--- a/game/modules/tome/init.lua
+++ b/game/modules/tome/init.lua
@@ -127,7 +127,7 @@ load_tips = {
 
 -- Define the fields that are sync'ed online, and how they are sync'ed
 profile_defs = {
-	allow_build = { {name="index:string:30"}, receive=function(data, save) save[data.name] = true end, export=function(env) for k, _ in pairs(env) do add{name=k} end end },
+	allow_build = { {name="index:string:50"}, receive=function(data, save) save[data.name] = true end, export=function(env) for k, _ in pairs(env) do add{name=k} end end },
 	lore = { {name="index:string:30"}, receive=function(data, save) save.lore = save.lore or {} save.lore[data.name] = true end, export=function(env) for k, v in pairs(env.lore or {}) do add{name=k} end end },
 	escorts = { {fate="index:enum(lost,betrayed,zigur,saved)"}, {nb="number"}, receive=function(data, save) inc_set(save, data.fate, data, "nb") end, export=function(env) for k, v in pairs(env) do add{fate=k, nb=v} end end },
 	artifacts = { {cid="index:string:50"}, {name="index:string:40"}, {nb="number"}, receive=function(data, save) save.artifacts = save.artifacts or {} save.artifacts[data.cid] = save.artifacts[data.cid] or {} inc_set(save.artifacts[data.cid], data.name, data, "nb") end, export=function(env) for cid, d in pairs(env.artifacts or {}) do for name, v in pairs(d) do add{cid=cid, name=name, nb=v} end end end },
diff --git a/src/core_lua.c b/src/core_lua.c
index 2e9e782230..6565850012 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -564,12 +564,14 @@ static const struct luaL_Reg gamelib[] =
 static bool no_text_aa = FALSE;
 
 extern bool is_fullscreen;
+extern bool is_borderless;
 static int sdl_screen_size(lua_State *L)
 {
 	lua_pushnumber(L, screen->w);
 	lua_pushnumber(L, screen->h);
 	lua_pushboolean(L, is_fullscreen);
-	return 3;
+	lua_pushboolean(L, is_borderless);
+	return 4;
 }
 
 static int sdl_new_font(lua_State *L)
@@ -2316,9 +2318,10 @@ static int sdl_set_window_size(lua_State *L)
 	int w = luaL_checknumber(L, 1);
 	int h = luaL_checknumber(L, 2);
 	bool fullscreen = lua_toboolean(L, 3);
+	bool borderless = lua_toboolean(L, 4);
 
-	printf("Setting resolution to %dx%d (%s)\n", w, h, fullscreen ? "fullscreen" : "windowed");
-	do_resize(w, h, fullscreen);
+	printf("Setting resolution to %dx%d (%s, %s)\n", w, h, fullscreen ? "fullscreen" : "windowed", borderless ? "borderless" : "with borders");
+	do_resize(w, h, fullscreen, borderless);
 
 	lua_pushboolean(L, TRUE);
 	return 1;
diff --git a/src/main.c b/src/main.c
index e5d7e69385..f309211206 100644
--- a/src/main.c
+++ b/src/main.c
@@ -58,6 +58,7 @@ char **g_argv;
 SDL_Window *window = NULL;
 SDL_GLContext maincontext; /* Our opengl context handle */
 bool is_fullscreen = FALSE;
+bool is_borderless = FALSE;
 static lua_State *L = NULL;
 int nb_cpus;
 bool no_debug = FALSE;
@@ -804,14 +805,14 @@ int resizeWindow(int width, int height)
 	return( TRUE );
 }
 
-void do_resize(int w, int h, bool fullscreen)
+void do_resize(int w, int h, bool fullscreen, bool borderless)
 {
 	/* Temporary width, height (since SDL might reject our resize) */
 	int aw, ah;
 	int mustPushEvent = 0;
 	SDL_Event fsEvent;
 
-	printf("[DO RESIZE] Requested: %dx%d (%d)\n", w, h, fullscreen);
+	printf("[DO RESIZE] Requested: %dx%d (%d, %d)\n", w, h, fullscreen, borderless);
 
 	/* If there is no current window, we have to make one and initialize */
 	if (!window) {
@@ -819,12 +820,15 @@ void do_resize(int w, int h, bool fullscreen)
 				(start_xpos == -1) ? SDL_WINDOWPOS_CENTERED : start_xpos,
 				(start_ypos == -1) ? SDL_WINDOWPOS_CENTERED : start_ypos, w, h,
 				SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
-						| (fullscreen ? SDL_WINDOW_FULLSCREEN : 0));
+				| (fullscreen ? SDL_WINDOW_FULLSCREEN : 0)
+				| (borderless ? SDL_WINDOW_BORDERLESS : 0)
+		);
 		if (window==NULL) {
 			printf("error opening screen: %s\n", SDL_GetError());
 			exit(1);
 		}
 		is_fullscreen = fullscreen;
+		is_borderless = borderless;
 		screen = SDL_GetWindowSurface(window);
 		maincontext = SDL_GL_CreateContext(window);
 		SDL_GL_MakeCurrent(window, maincontext);
@@ -842,6 +846,8 @@ void do_resize(int w, int h, bool fullscreen)
 
 		/* Update window size */
 		SDL_SetWindowSize(window, w, h);
+		SDL_SetWindowBordered(window, !borderless);
+		is_borderless = borderless;
 
 		/* Jump [back] into fullscreen if requested */
 		if (fullscreen) {
@@ -886,7 +892,7 @@ void do_resize(int w, int h, bool fullscreen)
 
 	/* Check and see if SDL honored our resize request */
 	SDL_GetWindowSize(window, &aw, &ah);
-	printf("[DO RESIZE] Got: %dx%d (%d)\n", aw, ah, is_fullscreen);
+	printf("[DO RESIZE] Got: %dx%d (%d, %d)\n", aw, ah, is_fullscreen, borderless);
 	SDL_GL_MakeCurrent(window, maincontext);
 	resizeWindow(aw, ah);
 
@@ -1195,7 +1201,7 @@ int main(int argc, char *argv[])
 
 	boot_lua(1, FALSE, argc, argv);
 
-	do_resize(WIDTH, HEIGHT, FALSE);
+	do_resize(WIDTH, HEIGHT, FALSE, FALSE);
 	if (screen==NULL) {
 		printf("error opening screen: %s\n", SDL_GetError());
 		return 3;
@@ -1251,7 +1257,7 @@ int main(int argc, char *argv[])
 					/* Note: SDL can't resize a fullscreen window, so don't bother! */
 					if (!is_fullscreen) {
 						printf("SDL_WINDOWEVENT_RESIZED: %d x %d\n", event.window.data1, event.window.data2);
-						do_resize(event.window.data1, event.window.data2, is_fullscreen);
+						do_resize(event.window.data1, event.window.data2, is_fullscreen, is_borderless);
 						if (current_game != LUA_NOREF)
 						{
 							lua_rawgeti(L, LUA_REGISTRYINDEX, current_game);
diff --git a/src/main.h b/src/main.h
index 2f2813f27c..65d19ca0f6 100644
--- a/src/main.h
+++ b/src/main.h
@@ -34,7 +34,7 @@
 #endif
 
 extern int resizeWindow(int width, int height);
-extern void do_resize(int w, int h, bool fullscreen);
+extern void do_resize(int w, int h, bool fullscreen, bool borderless);
 extern void setupRealtime(float freq);
 extern void setupDisplayTimer(int fps);
 extern int docall (lua_State *L, int narg, int nret);
-- 
GitLab