diff --git a/src/modules/window/Window.cpp b/src/modules/window/Window.cpp index 5ad2480ed..c79fb80c4 100644 --- a/src/modules/window/Window.cpp +++ b/src/modules/window/Window.cpp @@ -52,6 +52,9 @@ WindowSettings::WindowSettings() , highdpi(false) , sRGB(false) , refreshrate(0.0) + , useposition(false) + , x(0) + , y(0) { } @@ -101,6 +104,8 @@ StringMap::Entry Window::settingEntri {"highdpi", SETTING_HIGHDPI}, {"srgb", SETTING_SRGB}, {"refreshrate", SETTING_REFRESHRATE}, + {"x", SETTING_X}, + {"y", SETTING_Y}, }; StringMap Window::settings(Window::settingEntries, sizeof(Window::settingEntries)); diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index d1e8a1688..4ada807c9 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -60,6 +60,8 @@ public: SETTING_HIGHDPI, SETTING_SRGB, SETTING_REFRESHRATE, + SETTING_X, + SETTING_Y, SETTING_MAX_ENUM }; @@ -122,6 +124,9 @@ public: virtual void getDesktopDimensions(int displayindex, int &width, int &height) const = 0; + virtual void setPosition(int x, int y, int displayindex) = 0; + virtual void getPosition(int &x, int &y, int &displayindex) = 0; + virtual bool isCreated() const = 0; virtual void setWindowTitle(const std::string &title) = 0; @@ -205,6 +210,9 @@ struct WindowSettings bool highdpi; // false bool sRGB; // false double refreshrate; // 0.0 + bool useposition; // false + int x; // 0 + int y; // 0 }; // WindowSettings diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index 5a18cf6cb..ecee30208 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -124,6 +124,25 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) sdlflags |= SDL_WINDOW_ALLOW_HIGHDPI; #endif + int x = f.x; + int y = f.y; + + if (f.useposition) + { + // The position needs to be in the global coordinate space. + SDL_Rect displaybounds = {}; + SDL_GetDisplayBounds(f.display, &displaybounds); + x += displaybounds.x; + y += displaybounds.y; + } + else + { + if (f.centered) + x = y = SDL_WINDOWPOS_CENTERED_DISPLAY(f.display); + else + x = y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(f.display); + } + graphics::Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); if (gfx != nullptr) gfx->unSetMode(); @@ -156,9 +175,6 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) } } - int centeredpos = SDL_WINDOWPOS_CENTERED_DISPLAY(f.display); - int uncenteredpos = SDL_WINDOWPOS_UNDEFINED_DISPLAY(f.display); - if (!window) { created = false; @@ -167,9 +183,8 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) setWindowGLAttributes(f.msaa, f.sRGB); const char *title = windowTitle.c_str(); - int pos = f.centered ? centeredpos : uncenteredpos; - window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags); + window = SDL_CreateWindow(title, x, y, width, height, sdlflags); if (!window && f.msaa > 0) { @@ -177,7 +192,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags); + window = SDL_CreateWindow(title, x, y, width, height, sdlflags); f.msaa = 0; } @@ -195,8 +210,8 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) // Enforce minimum window dimensions. SDL_SetWindowMinimumSize(window, f.minwidth, f.minheight); - if (f.centered && !f.fullscreen) - SDL_SetWindowPosition(window, centeredpos, centeredpos); + if ((f.useposition || f.centered) && !f.fullscreen) + SDL_SetWindowPosition(window, x, y); SDL_RaiseWindow(window); @@ -374,7 +389,8 @@ void Window::updateSettings(const WindowSettings &newsettings) curMode.settings.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0; curMode.settings.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0; curMode.settings.centered = newsettings.centered; - curMode.settings.display = std::max(SDL_GetWindowDisplayIndex(window), 0); + + getPosition(curMode.settings.x, curMode.settings.y, curMode.settings.display); #if SDL_VERSION_ATLEAST(2,0,1) curMode.settings.highdpi = (wflags & SDL_WINDOW_ALLOW_HIGHDPI) != 0; @@ -543,6 +559,46 @@ void Window::getDesktopDimensions(int displayindex, int &width, int &height) con } } +void Window::setPosition(int x, int y, int displayindex) +{ + if (!window) + return; + + displayindex = std::min(std::max(displayindex, 0), getDisplayCount() - 1); + + SDL_Rect displaybounds = {}; + SDL_GetDisplayBounds(displayindex, &displaybounds); + + // The position needs to be in the global coordinate space. + x += displaybounds.x; + y += displaybounds.y; + + SDL_SetWindowPosition(window, x, y); + + curMode.settings.useposition = true; +} + +void Window::getPosition(int &x, int &y, int &displayindex) +{ + if (!window) + { + x = y = 0; + displayindex = 0; + return; + } + + displayindex = std::max(SDL_GetWindowDisplayIndex(window), 0); + + SDL_GetWindowPosition(window, &x, &y); + + SDL_Rect displaybounds = {}; + SDL_GetDisplayBounds(displayindex, &displaybounds); + + // The position needs to be in the monitor's coordinate space. + x -= displaybounds.x; + y -= displaybounds.y; +} + bool Window::isCreated() const { return created; diff --git a/src/modules/window/sdl/Window.h b/src/modules/window/sdl/Window.h index 3f3df0a05..8f1416f14 100644 --- a/src/modules/window/sdl/Window.h +++ b/src/modules/window/sdl/Window.h @@ -60,6 +60,9 @@ public: void getDesktopDimensions(int displayindex, int &width, int &height) const; + void setPosition(int x, int y, int displayindex); + void getPosition(int &x, int &y, int &displayindex); + bool isCreated() const; void setWindowTitle(const std::string &title); diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index 2e91c39c5..b8418591b 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -109,6 +109,16 @@ int w_setMode(lua_State *L) settings.highdpi = luax_boolflag(L, 3, settingName(Window::SETTING_HIGHDPI), false); settings.sRGB = luax_boolflag(L, 3, settingName(Window::SETTING_SRGB), false); + lua_getfield(L, 3, settingName(Window::SETTING_X)); + lua_getfield(L, 3, settingName(Window::SETTING_Y)); + settings.useposition = !(lua_isnoneornil(L, -2) && lua_isnoneornil(L, -1)); + if (settings.useposition) + { + settings.x = luaL_optint(L, -2, 0); + settings.y = luaL_optint(L, -1, 0); + } + lua_pop(L, 2); + // We don't explicitly set the refresh rate, it's "read-only". // For backward-compatibility. TODO: remove! @@ -178,6 +188,12 @@ int w_getMode(lua_State *L) lua_pushnumber(L, settings.refreshrate); lua_setfield(L, -2, settingName(Window::SETTING_REFRESHRATE)); + lua_pushinteger(L, settings.x); + lua_setfield(L, -2, settingName(Window::SETTING_X)); + + lua_pushinteger(L, settings.y); + lua_setfield(L, -2, settingName(Window::SETTING_Y)); + return 3; } @@ -279,6 +295,27 @@ int w_getDesktopDimensions(lua_State *L) return 2; } +int w_setPosition(lua_State *L) +{ + int x = luaL_checkint(L, 1); + int y = luaL_checkint(L, 2); + int displayindex = luaL_optint(L, 3, 1) - 1; + instance()->setPosition(x, y, displayindex); + return 0; +} + +int w_getPosition(lua_State *L) +{ + int x = 0; + int y = 0; + int displayindex = 0; + instance()->getPosition(x, y, displayindex); + lua_pushinteger(L, x); + lua_pushinteger(L, y); + lua_pushinteger(L, displayindex + 1); + return 3; +} + int w_setIcon(lua_State *L) { image::ImageData *i = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); @@ -455,6 +492,8 @@ static const luaL_Reg functions[] = { "getHeight", w_getHeight }, { "getDimensions", w_getDimensions }, { "getDesktopDimensions", w_getDesktopDimensions }, + { "setPosition", w_setPosition }, + { "getPosition", w_getPosition }, { "setIcon", w_setIcon }, { "getIcon", w_getIcon }, { "setTitle", w_setTitle }, diff --git a/src/modules/window/wrap_Window.h b/src/modules/window/wrap_Window.h index 1f784d09c..69e70189f 100644 --- a/src/modules/window/wrap_Window.h +++ b/src/modules/window/wrap_Window.h @@ -41,6 +41,8 @@ int w_getWidth(lua_State *L); int w_getHeight(lua_State *L); int w_getDimensions(lua_State *L); int w_getDesktopDimensions(lua_State *L); +int w_setPosition(lua_State *L); +int w_getPosition(lua_State *L); int w_setIcon(lua_State *L); int w_getIcon(lua_State *L); int w_setTitle(lua_State *L); diff --git a/src/scripts/boot.lua b/src/scripts/boot.lua index c27337796..c12dd58ed 100644 --- a/src/scripts/boot.lua +++ b/src/scripts/boot.lua @@ -300,6 +300,8 @@ function love.init() window = { width = 800, height = 600, + x = nil, + y = nil, minwidth = 1, minheight = 1, fullscreen = false, @@ -407,6 +409,8 @@ function love.init() display = c.window.display, highdpi = c.window.highdpi, srgb = c.window.srgb, + x = c.window.x, + y = c.window.y, }), "Could not set window mode") love.window.setTitle(c.window.title or c.title) if c.window.icon then diff --git a/src/scripts/boot.lua.h b/src/scripts/boot.lua.h index e9b29a1b6..c00a0f40a 100644 --- a/src/scripts/boot.lua.h +++ b/src/scripts/boot.lua.h @@ -546,6 +546,8 @@ const unsigned char boot_lua[] = 0x09, 0x09, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x38, 0x30, 0x30, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x36, 0x30, 0x30, 0x2c, 0x0a, + 0x09, 0x09, 0x09, 0x78, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x0a, + 0x09, 0x09, 0x09, 0x79, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x61, @@ -717,6 +719,8 @@ const unsigned char boot_lua[] = 0x64, 0x6f, 0x77, 0x2e, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x72, 0x67, 0x62, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2c, 0x0a, + 0x09, 0x09, 0x09, 0x78, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x78, 0x2c, 0x0a, + 0x09, 0x09, 0x09, 0x79, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x79, 0x2c, 0x0a, 0x09, 0x09, 0x7d, 0x29, 0x2c, 0x20, 0x22, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x54,