mirror of
https://github.com/love2d/love-android.git
synced 2026-08-20 04:31:26 +02:00
Using latest android branch of LÖVE (6d14516b05c9) that now syncs with default (woooo!)
This commit is contained in:
@@ -38,26 +38,6 @@ void Window::swapBuffers()
|
||||
{
|
||||
}
|
||||
|
||||
WindowSettings::WindowSettings()
|
||||
: fullscreen(false)
|
||||
, fstype(Window::FULLSCREEN_TYPE_NORMAL)
|
||||
, vsync(true)
|
||||
, msaa(0)
|
||||
, resizable(false)
|
||||
, minwidth(1)
|
||||
, minheight(1)
|
||||
, borderless(false)
|
||||
, centered(true)
|
||||
, display(0)
|
||||
, highdpi(false)
|
||||
, sRGB(false)
|
||||
, refreshrate(0.0)
|
||||
, useposition(false)
|
||||
, x(0)
|
||||
, y(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool Window::getConstant(const char *in, Window::FullscreenType &out)
|
||||
{
|
||||
return fullscreenTypes.find(in, out);
|
||||
@@ -93,7 +73,6 @@ StringMap<Window::Setting, Window::SETTING_MAX_ENUM>::Entry Window::settingEntri
|
||||
{"fullscreen", SETTING_FULLSCREEN},
|
||||
{"fullscreentype", SETTING_FULLSCREEN_TYPE},
|
||||
{"vsync", SETTING_VSYNC},
|
||||
{"fsaa", SETTING_FSAA},
|
||||
{"msaa", SETTING_MSAA},
|
||||
{"resizable", SETTING_RESIZABLE},
|
||||
{"minwidth", SETTING_MIN_WIDTH},
|
||||
@@ -110,19 +89,19 @@ StringMap<Window::Setting, Window::SETTING_MAX_ENUM>::Entry Window::settingEntri
|
||||
|
||||
StringMap<Window::Setting, Window::SETTING_MAX_ENUM> Window::settings(Window::settingEntries, sizeof(Window::settingEntries));
|
||||
|
||||
StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM>::Entry Window::fullscreenTypeEntries[] =
|
||||
StringMap<Window::FullscreenType, Window::FULLSCREEN_MAX_ENUM>::Entry Window::fullscreenTypeEntries[] =
|
||||
{
|
||||
{"normal", Window::FULLSCREEN_TYPE_NORMAL},
|
||||
{"desktop", Window::FULLSCREEN_TYPE_DESKTOP},
|
||||
{"exclusive", FULLSCREEN_EXCLUSIVE},
|
||||
{"desktop", FULLSCREEN_DESKTOP},
|
||||
};
|
||||
|
||||
StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM> Window::fullscreenTypes(Window::fullscreenTypeEntries, sizeof(Window::fullscreenTypeEntries));
|
||||
StringMap<Window::FullscreenType, Window::FULLSCREEN_MAX_ENUM> Window::fullscreenTypes(Window::fullscreenTypeEntries, sizeof(Window::fullscreenTypeEntries));
|
||||
|
||||
StringMap<Window::MessageBoxType, Window::MESSAGEBOX_MAX_ENUM>::Entry Window::messageBoxTypeEntries[] =
|
||||
{
|
||||
{"error", Window::MESSAGEBOX_ERROR},
|
||||
{"warning", Window::MESSAGEBOX_WARNING},
|
||||
{"info", Window::MESSAGEBOX_INFO},
|
||||
{"error", MESSAGEBOX_ERROR},
|
||||
{"warning", MESSAGEBOX_WARNING},
|
||||
{"info", MESSAGEBOX_INFO},
|
||||
};
|
||||
|
||||
StringMap<Window::MessageBoxType, Window::MESSAGEBOX_MAX_ENUM> Window::messageBoxTypes(Window::messageBoxTypeEntries, sizeof(Window::messageBoxTypeEntries));
|
||||
|
||||
@@ -49,7 +49,6 @@ public:
|
||||
SETTING_FULLSCREEN,
|
||||
SETTING_FULLSCREEN_TYPE,
|
||||
SETTING_VSYNC,
|
||||
SETTING_FSAA, // For backward-compatibility. TODO: remove!
|
||||
SETTING_MSAA,
|
||||
SETTING_RESIZABLE,
|
||||
SETTING_MIN_WIDTH,
|
||||
@@ -67,9 +66,9 @@ public:
|
||||
|
||||
enum FullscreenType
|
||||
{
|
||||
FULLSCREEN_TYPE_NORMAL,
|
||||
FULLSCREEN_TYPE_DESKTOP,
|
||||
FULLSCREEN_TYPE_MAX_ENUM
|
||||
FULLSCREEN_EXCLUSIVE,
|
||||
FULLSCREEN_DESKTOP,
|
||||
FULLSCREEN_MAX_ENUM
|
||||
};
|
||||
|
||||
enum MessageBoxType
|
||||
@@ -116,7 +115,7 @@ public:
|
||||
virtual bool setFullscreen(bool fullscreen, FullscreenType fstype) = 0;
|
||||
virtual bool setFullscreen(bool fullscreen) = 0;
|
||||
|
||||
virtual bool onWindowResize(int width, int height) = 0;
|
||||
virtual bool onSizeChanged(int width, int height) = 0;
|
||||
|
||||
virtual int getDisplayCount() const = 0;
|
||||
|
||||
@@ -124,9 +123,6 @@ public:
|
||||
|
||||
virtual std::vector<WindowSize> getFullscreenSizes(int displayindex) const = 0;
|
||||
|
||||
virtual int getWidth() const = 0;
|
||||
virtual int getHeight() const = 0;
|
||||
|
||||
virtual void getDesktopDimensions(int displayindex, int &width, int &height) const = 0;
|
||||
|
||||
virtual void setPosition(int x, int y, int displayindex) = 0;
|
||||
@@ -157,9 +153,13 @@ public:
|
||||
virtual void setMouseGrab(bool grab) = 0;
|
||||
virtual bool isMouseGrabbed() const = 0;
|
||||
|
||||
virtual double getPixelScale() const = 0;
|
||||
virtual void getPixelDimensions(int &w, int &h) const = 0;
|
||||
// Note: window-space coordinates are not necessarily the same as
|
||||
// density-independent units (which toPixels and fromPixels use.)
|
||||
virtual void windowToPixelCoords(double *x, double *y) const = 0;
|
||||
virtual void pixelToWindowCoords(double *x, double *y) const = 0;
|
||||
|
||||
virtual bool isTouchScreen(int displayindex) const = 0;
|
||||
virtual double getPixelScale() const = 0;
|
||||
|
||||
virtual double toPixels(double x) const = 0;
|
||||
virtual void toPixels(double wx, double wy, double &px, double &py) const = 0;
|
||||
@@ -171,9 +171,10 @@ public:
|
||||
virtual bool showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow) = 0;
|
||||
virtual int showMessageBox(const MessageBoxData &data) = 0;
|
||||
|
||||
virtual void requestAttention(bool continuous) = 0;
|
||||
|
||||
//virtual static Window *createSingleton() = 0;
|
||||
//virtual static Window *getSingleton() = 0;
|
||||
// No virtual statics, of course, but you are supposed to implement these statics.
|
||||
// No virtual statics, of course, but you are supposed to implement this static.
|
||||
|
||||
static bool getConstant(const char *in, Setting &out);
|
||||
static bool getConstant(Setting in, const char *&out);
|
||||
@@ -193,8 +194,8 @@ private:
|
||||
static StringMap<Setting, SETTING_MAX_ENUM>::Entry settingEntries[];
|
||||
static StringMap<Setting, SETTING_MAX_ENUM> settings;
|
||||
|
||||
static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM>::Entry fullscreenTypeEntries[];
|
||||
static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM> fullscreenTypes;
|
||||
static StringMap<FullscreenType, FULLSCREEN_MAX_ENUM>::Entry fullscreenTypeEntries[];
|
||||
static StringMap<FullscreenType, FULLSCREEN_MAX_ENUM> fullscreenTypes;
|
||||
|
||||
static StringMap<MessageBoxType, MESSAGEBOX_MAX_ENUM>::Entry messageBoxTypeEntries[];
|
||||
static StringMap<MessageBoxType, MESSAGEBOX_MAX_ENUM> messageBoxTypes;
|
||||
@@ -203,26 +204,23 @@ private:
|
||||
|
||||
struct WindowSettings
|
||||
{
|
||||
WindowSettings();
|
||||
|
||||
bool fullscreen; // = false
|
||||
Window::FullscreenType fstype; // = FULLSCREEN_TYPE_NORMAL
|
||||
bool vsync; // = true
|
||||
int msaa; // = 0
|
||||
bool resizable; // = false
|
||||
int minwidth; // = 1
|
||||
int minheight; // = 1
|
||||
bool borderless; // = false
|
||||
bool centered; // = true
|
||||
int display; // = 0
|
||||
bool highdpi; // false
|
||||
bool sRGB; // false
|
||||
double refreshrate; // 0.0
|
||||
bool useposition; // false
|
||||
int x; // 0
|
||||
int y; // 0
|
||||
|
||||
}; // WindowSettings
|
||||
bool fullscreen = false;
|
||||
Window::FullscreenType fstype = Window::FULLSCREEN_DESKTOP;
|
||||
bool vsync = true;
|
||||
int msaa = 0;
|
||||
bool resizable = false;
|
||||
int minwidth = 1;
|
||||
int minheight = 1;
|
||||
bool borderless = false;
|
||||
bool centered = true;
|
||||
int display = 0;
|
||||
bool highdpi = false;
|
||||
bool sRGB = false;
|
||||
double refreshrate = 0.0;
|
||||
bool useposition = false;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
|
||||
} // window
|
||||
} // love
|
||||
|
||||
@@ -33,7 +33,20 @@
|
||||
#include <algorithm>
|
||||
|
||||
// C
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
// SDL
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#if defined(LOVE_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(LOVE_MACOSX)
|
||||
#include "common/OSX.h"
|
||||
#endif
|
||||
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -43,14 +56,15 @@ namespace sdl
|
||||
{
|
||||
|
||||
Window::Window()
|
||||
: windowTitle("")
|
||||
, created(false)
|
||||
: created(false)
|
||||
, mouseGrabbed(false)
|
||||
, window(0)
|
||||
, context(0)
|
||||
, window(nullptr)
|
||||
, context(nullptr)
|
||||
, displayedWindowError(false)
|
||||
, displayedContextError(false)
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
|
||||
throw love::Exception("%s", SDL_GetError());
|
||||
throw love::Exception("Could not initialize SDL video subsystem (%s)", SDL_GetError());
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
@@ -70,12 +84,288 @@ Window::~Window()
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
}
|
||||
|
||||
Window::_currentMode::_currentMode()
|
||||
: width(800)
|
||||
, height(600)
|
||||
, settings()
|
||||
, icon(0)
|
||||
void Window::setGLFramebufferAttributes(int msaa, bool sRGB)
|
||||
{
|
||||
// Set GL window / framebuffer attributes.
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (msaa > 0) ? 1 : 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (msaa > 0) ? msaa : 0);
|
||||
|
||||
// SDL or GLX may have bugs with this: https://bugzilla.libsdl.org/show_bug.cgi?id=2897
|
||||
// It's fine to leave the attribute disabled on desktops though, because in
|
||||
// practice the framebuffer will be sRGB-capable even if it's not requested.
|
||||
#if !defined(LOVE_LINUX)
|
||||
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, sRGB ? 1 : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Window::setGLContextAttributes(const ContextAttribs &attribs)
|
||||
{
|
||||
int profilemask = 0;
|
||||
int contextflags = 0;
|
||||
|
||||
if (attribs.gles)
|
||||
profilemask |= SDL_GL_CONTEXT_PROFILE_ES;
|
||||
else if (attribs.debug)
|
||||
profilemask |= SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
|
||||
if (attribs.debug)
|
||||
contextflags |= SDL_GL_CONTEXT_DEBUG_FLAG;
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, attribs.versionMajor);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, attribs.versionMinor);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profilemask);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, contextflags);
|
||||
}
|
||||
|
||||
bool Window::checkGLVersion(const ContextAttribs &attribs)
|
||||
{
|
||||
typedef unsigned char GLubyte;
|
||||
typedef unsigned int GLenum;
|
||||
typedef const GLubyte *(APIENTRY *glGetStringPtr)(GLenum name);
|
||||
const GLenum GL_VERSION_ENUM = 0x1F02;
|
||||
|
||||
// We don't have OpenGL headers or an automatic OpenGL function loader in
|
||||
// this module, so we have to get the glGetString function pointer ourselves.
|
||||
glGetStringPtr glGetStringFunc = (glGetStringPtr) SDL_GL_GetProcAddress("glGetString");
|
||||
if (!glGetStringFunc)
|
||||
return false;
|
||||
|
||||
const char *glversion = (const char *) glGetStringFunc(GL_VERSION_ENUM);
|
||||
if (!glversion)
|
||||
return false;
|
||||
|
||||
int glmajor = 0;
|
||||
int glminor = 0;
|
||||
|
||||
// glGetString(GL_VERSION) returns a string with the format "major.minor",
|
||||
// or "OpenGL ES major.minor" in GLES contexts.
|
||||
const char *format = "%d.%d";
|
||||
if (attribs.gles)
|
||||
format = "OpenGL ES %d.%d";
|
||||
|
||||
if (sscanf(glversion, format, &glmajor, &glminor) != 2)
|
||||
return false;
|
||||
|
||||
if (glmajor < attribs.versionMajor
|
||||
|| (glmajor == attribs.versionMajor && glminor < attribs.versionMinor))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, int msaa, bool sRGB)
|
||||
{
|
||||
bool preferGLES = false;
|
||||
|
||||
#ifdef LOVE_GRAPHICS_USE_OPENGLES
|
||||
preferGLES = true;
|
||||
#endif
|
||||
|
||||
const char *curdriver = SDL_GetCurrentVideoDriver();
|
||||
const char *glesdrivers[] = {"RPI", "Android", "uikit", "winrt", "emscripten"};
|
||||
|
||||
// We always want to try OpenGL ES first on certain video backends.
|
||||
for (const char *glesdriver : glesdrivers)
|
||||
{
|
||||
if (curdriver && strstr(curdriver, glesdriver) == curdriver)
|
||||
{
|
||||
preferGLES = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!preferGLES)
|
||||
{
|
||||
const char *gleshint = SDL_GetHint("LOVE_GRAPHICS_USE_OPENGLES");
|
||||
preferGLES = (gleshint != nullptr && gleshint[0] != '0');
|
||||
}
|
||||
|
||||
// Do we want a debug context?
|
||||
const char *debughint = SDL_GetHint("LOVE_GRAPHICS_DEBUG");
|
||||
bool debug = (debughint != nullptr && debughint[0] != '0');
|
||||
|
||||
// Different context attribute profiles to try.
|
||||
std::vector<ContextAttribs> attribslist = {
|
||||
{2, 1, false, debug}, // OpenGL 2.1.
|
||||
{3, 0, true, debug}, // OpenGL ES 3.
|
||||
{2, 0, true, debug}, // OpenGL ES 2.
|
||||
};
|
||||
|
||||
SDL_version sdlversion = {};
|
||||
SDL_GetVersion(&sdlversion);
|
||||
|
||||
// OpenGL ES 3+ contexts are only properly supported in SDL 2.0.4+.
|
||||
if (sdlversion.major == 2 && sdlversion.minor == 0 && sdlversion.patch <= 3)
|
||||
attribslist.erase(attribslist.begin() + 1);
|
||||
|
||||
// Move OpenGL ES to the front of the list if we should prefer GLES.
|
||||
if (preferGLES)
|
||||
std::rotate(attribslist.begin(), attribslist.begin() + 1, attribslist.end());
|
||||
|
||||
if (context)
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
std::string windowerror;
|
||||
|
||||
// Try each context profile in order.
|
||||
for (ContextAttribs attribs : attribslist)
|
||||
{
|
||||
// Unfortunately some OpenGL context settings are part of the internal
|
||||
// window state in the Windows and Linux SDL backends, so we have to
|
||||
// recreate the window when we want to change those settings...
|
||||
if (window)
|
||||
{
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_FlushEvent(SDL_WINDOWEVENT);
|
||||
window = nullptr;
|
||||
}
|
||||
|
||||
int curMSAA = msaa;
|
||||
bool curSRGB = sRGB;
|
||||
|
||||
setGLFramebufferAttributes(curMSAA, curSRGB);
|
||||
setGLContextAttributes(attribs);
|
||||
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
|
||||
if (!window && curMSAA > 0)
|
||||
{
|
||||
// The MSAA setting could have caused the failure.
|
||||
setGLFramebufferAttributes(0, curSRGB);
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
if (window)
|
||||
curMSAA = 0;
|
||||
}
|
||||
|
||||
if (!window && curSRGB)
|
||||
{
|
||||
// same with sRGB.
|
||||
setGLFramebufferAttributes(curMSAA, false);
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
if (window)
|
||||
curSRGB = false;
|
||||
}
|
||||
|
||||
if (!window && curMSAA > 0 && curSRGB)
|
||||
{
|
||||
// Or both!
|
||||
setGLFramebufferAttributes(0, false);
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
if (window)
|
||||
{
|
||||
curMSAA = 0;
|
||||
curSRGB = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Immediately try the next context profile if window creation failed.
|
||||
if (!window)
|
||||
{
|
||||
windowerror = std::string(SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
windowerror.clear();
|
||||
|
||||
context = SDL_GL_CreateContext(window);
|
||||
|
||||
if (!context && curMSAA > 0)
|
||||
{
|
||||
// MSAA and sRGB settings can also cause CreateContext to fail, on
|
||||
// certain SDL backends.
|
||||
setGLFramebufferAttributes(0, curSRGB);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context && curSRGB)
|
||||
{
|
||||
setGLFramebufferAttributes(curMSAA, false);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context && curMSAA > 0 && curSRGB)
|
||||
{
|
||||
setGLFramebufferAttributes(0, false);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context && attribs.debug)
|
||||
{
|
||||
attribs.debug = false;
|
||||
setGLContextAttributes(attribs);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
// Make sure the context's version is at least what we requested.
|
||||
if (context && !checkGLVersion(attribs))
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
if (context)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context || !window)
|
||||
{
|
||||
if (!windowerror.empty())
|
||||
{
|
||||
std::string title = "Unable to create window";
|
||||
std::string message = "SDL error: " + windowerror;
|
||||
|
||||
std::cerr << title << std::endl << message << std::endl;
|
||||
|
||||
// Display a message box with the error, but only once.
|
||||
if (!displayedWindowError)
|
||||
{
|
||||
showMessageBox(title, message, MESSAGEBOX_ERROR, false);
|
||||
displayedWindowError = true;
|
||||
}
|
||||
}
|
||||
else if (!context)
|
||||
{
|
||||
std::string title = "Unable to initialize OpenGL";
|
||||
std::string message = "This program requires a graphics card and video drivers which support OpenGL 2.1 or OpenGL ES 2.";
|
||||
|
||||
std::cerr << title << std::endl << message << std::endl;
|
||||
|
||||
// Display a message box with the error, but only once.
|
||||
if (!displayedContextError)
|
||||
{
|
||||
showMessageBox(title, message, MESSAGEBOX_ERROR, true);
|
||||
displayedContextError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (context)
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_FlushEvent(SDL_WINDOWEVENT);
|
||||
window = nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
@@ -103,12 +393,12 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
|
||||
// On Android we always must have fullscreen type FULLSCREEN_TYPE_DESKTOP
|
||||
#ifdef LOVE_ANDROID
|
||||
f.fstype = FULLSCREEN_TYPE_DESKTOP;
|
||||
f.fstype = FULLSCREEN_DESKTOP;
|
||||
#endif
|
||||
|
||||
if (f.fullscreen)
|
||||
{
|
||||
if (f.fstype == FULLSCREEN_TYPE_DESKTOP)
|
||||
if (f.fstype == FULLSCREEN_DESKTOP)
|
||||
sdlflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
else
|
||||
{
|
||||
@@ -136,11 +426,8 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
if (f.borderless)
|
||||
sdlflags |= SDL_WINDOW_BORDERLESS;
|
||||
|
||||
// FIXME: disabled in Linux for runtime SDL 2.0.0 compatibility.
|
||||
#if SDL_VERSION_ATLEAST(2,0,1) && !defined(LOVE_LINUX)
|
||||
if (f.highdpi)
|
||||
sdlflags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
#endif
|
||||
|
||||
int x = f.x;
|
||||
int y = f.y;
|
||||
@@ -165,65 +452,34 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
if (gfx != nullptr)
|
||||
gfx->unSetMode();
|
||||
|
||||
// Destroy and recreate the window if the dimensions or flags have changed.
|
||||
if (context)
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
int curdisplay = SDL_GetWindowDisplayIndex(window);
|
||||
Uint32 wflags = SDL_GetWindowFlags(window);
|
||||
SDL_DestroyWindow(window);
|
||||
window = nullptr;
|
||||
|
||||
Uint32 testflags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP
|
||||
| SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS;
|
||||
|
||||
// FIXME: disabled in Linux for runtime SDL 2.0.0 compatibility.
|
||||
#if SDL_VERSION_ATLEAST(2,0,1) && !defined(LOVE_LINUX)
|
||||
testflags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
#endif
|
||||
|
||||
wflags &= testflags;
|
||||
|
||||
if (sdlflags != wflags || width != curMode.width || height != curMode.height
|
||||
|| f.display != curdisplay || f.msaa != curMode.settings.msaa)
|
||||
{
|
||||
SDL_DestroyWindow(window);
|
||||
window = 0;
|
||||
|
||||
// The old window may have generated pending events which are no
|
||||
// longer relevant. Destroy them all!
|
||||
SDL_FlushEvent(SDL_WINDOWEVENT);
|
||||
}
|
||||
// The old window may have generated pending events which are no longer
|
||||
// relevant. Destroy them all!
|
||||
SDL_FlushEvent(SDL_WINDOWEVENT);
|
||||
}
|
||||
|
||||
if (!window)
|
||||
{
|
||||
created = false;
|
||||
created = false;
|
||||
|
||||
// In Windows and Linux, some GL attributes are set on window creation.
|
||||
setWindowGLAttributes(f.msaa, f.sRGB);
|
||||
|
||||
const char *title = windowTitle.c_str();
|
||||
|
||||
window = SDL_CreateWindow(title, x, y, width, height, sdlflags);
|
||||
|
||||
if (!window && f.msaa > 0)
|
||||
{
|
||||
// MSAA might have caused the failure, disable it and try again.
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
|
||||
|
||||
window = SDL_CreateWindow(title, x, y, width, height, sdlflags);
|
||||
f.msaa = 0;
|
||||
}
|
||||
|
||||
// Make sure the window keeps any previously set icon.
|
||||
if (window && curMode.icon.get())
|
||||
setIcon(curMode.icon.get());
|
||||
}
|
||||
|
||||
if (!window)
|
||||
{
|
||||
showMessageBox("Could not create window", SDL_GetError(), MESSAGEBOX_ERROR, false);
|
||||
if (!createWindowAndContext(x, y, width, height, sdlflags, f.msaa, f.sRGB))
|
||||
return false;
|
||||
}
|
||||
|
||||
created = true;
|
||||
|
||||
// Make sure the window keeps any previously set icon.
|
||||
setIcon(curMode.icon.get());
|
||||
|
||||
// Make sure the mouse keeps its previous grab setting.
|
||||
setMouseGrab(mouseGrabbed);
|
||||
|
||||
// Enforce minimum window dimensions.
|
||||
SDL_SetWindowMinimumSize(window, f.minwidth, f.minheight);
|
||||
@@ -233,41 +489,21 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
|
||||
SDL_RaiseWindow(window);
|
||||
|
||||
if (!setContext(f.msaa, f.vsync, f.sRGB))
|
||||
{
|
||||
created = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
created = true;
|
||||
SDL_GL_SetSwapInterval(f.vsync ? 1 : 0);
|
||||
|
||||
updateSettings(f);
|
||||
|
||||
if (gfx != nullptr)
|
||||
{
|
||||
int width = curMode.width;
|
||||
int height = curMode.height;
|
||||
|
||||
// FIXME: disabled in Linux for runtime SDL 2.0.0 compatibility.
|
||||
#if SDL_VERSION_ATLEAST(2,0,1) && !defined(LOVE_LINUX)
|
||||
SDL_GL_GetDrawableSize(window, &width, &height);
|
||||
#endif
|
||||
|
||||
if (!gfx->setMode(width, height, curMode.settings.sRGB))
|
||||
showMessageBox("Could not set graphics mode", "Unsupported OpenGL version?", MESSAGEBOX_ERROR, true);
|
||||
gfx->setMode(curMode.pixelwidth, curMode.pixelheight, curMode.settings.sRGB);
|
||||
|
||||
#ifdef LOVE_ANDROID
|
||||
love::android::setImmersive(f.fullscreen);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Make sure the mouse keeps its previous grab setting.
|
||||
setMouseGrab(mouseGrabbed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Window::onWindowResize(int width, int height)
|
||||
bool Window::onSizeChanged(int width, int height)
|
||||
{
|
||||
if (!window)
|
||||
return false;
|
||||
@@ -275,166 +511,32 @@ bool Window::onWindowResize(int width, int height)
|
||||
curMode.width = width;
|
||||
curMode.height = height;
|
||||
|
||||
return true;
|
||||
}
|
||||
SDL_GL_GetDrawableSize(window, &curMode.pixelwidth, &curMode.pixelheight);
|
||||
|
||||
bool Window::setContext(int msaa, bool vsync, bool sRGB)
|
||||
{
|
||||
// We would normally only need to recreate the context if MSAA changes or
|
||||
// SDL_GL_MakeCurrent is unsuccessful, but in Windows MakeCurrent can
|
||||
// sometimes claim success but the context will actually be trashed.
|
||||
if (context)
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = 0;
|
||||
}
|
||||
|
||||
// Make sure the proper attributes are set.
|
||||
setWindowGLAttributes(msaa, sRGB);
|
||||
|
||||
context = SDL_GL_CreateContext(window);
|
||||
|
||||
if (!context && msaa > 0)
|
||||
{
|
||||
// MSAA might have caused the failure, disable it and try again.
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context)
|
||||
{
|
||||
int flags = 0;
|
||||
int profilemask = 0;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &flags);
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profilemask);
|
||||
if (flags & SDL_GL_CONTEXT_DEBUG_FLAG)
|
||||
{
|
||||
profilemask &= ~SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profilemask);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context)
|
||||
{
|
||||
showMessageBox("Could not create OpenGL context", SDL_GetError(), MESSAGEBOX_ERROR, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set vertical synchronization.
|
||||
SDL_GL_SetSwapInterval(vsync ? 1 : 0);
|
||||
|
||||
// Verify MSAA setting.
|
||||
int buffers;
|
||||
int samples;
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
|
||||
|
||||
// Don't fail because of this, but issue a warning.
|
||||
if ((!buffers && msaa) || (samples != msaa))
|
||||
{
|
||||
std::cerr << "Warning, MSAA setting failed! (Result: buffers: " << buffers << ", samples: " << samples << ")" << std::endl;
|
||||
msaa = (buffers > 0) ? samples : 0;
|
||||
}
|
||||
|
||||
curMode.settings.msaa = msaa;
|
||||
curMode.settings.vsync = SDL_GL_GetSwapInterval() != 0;
|
||||
graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
gfx->setViewportSize(curMode.pixelwidth, curMode.pixelheight);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Window::setWindowGLAttributes(int msaa, bool /* sRGB */) const
|
||||
{
|
||||
// Set GL window attributes.
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
||||
|
||||
// MSAA.
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (msaa > 0) ? 1 : 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (msaa > 0) ? msaa : 0);
|
||||
|
||||
/* FIXME: Enable this code but make sure to try to re-create the window and
|
||||
* context with this disabled, if creation fails with it enabled.
|
||||
* We can leave this out for now because in practice the framebuffer will
|
||||
* already be sRGB-capable (on desktops at least.)
|
||||
#if SDL_VERSION_ATLEAST(2,0,1)
|
||||
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, sRGB ? 1 : 0);
|
||||
#endif
|
||||
*/
|
||||
|
||||
int contextprofile = 0;
|
||||
|
||||
bool tryGLES = false;
|
||||
|
||||
const char *driver = SDL_GetCurrentVideoDriver();
|
||||
const char *glesdrivers[] = {"RPI", "Android", "uikit", "winrt"};
|
||||
|
||||
// We always want to use OpenGL ES on certain video backends.
|
||||
for (size_t i = 0; i < sizeof(glesdrivers) / sizeof(glesdrivers[0]); i++)
|
||||
{
|
||||
if (driver && strstr(driver, glesdrivers[i]))
|
||||
{
|
||||
tryGLES = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *hint = SDL_GetHint("LOVE_GRAPHICS_USE_OPENGLES");
|
||||
if (hint)
|
||||
tryGLES = (*hint) != '0';
|
||||
|
||||
if (tryGLES)
|
||||
{
|
||||
// Use OpenGL ES 2+.
|
||||
contextprofile = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use desktop OpenGL.
|
||||
contextprofile = 0;
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // default
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
}
|
||||
|
||||
// Do we want a debug context?
|
||||
const char *debugenv = SDL_GetHint("LOVE_GRAPHICS_DEBUG");
|
||||
if (debugenv && *debugenv == '1')
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
if (!tryGLES)
|
||||
contextprofile |= SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
}
|
||||
else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, contextprofile);
|
||||
}
|
||||
|
||||
void Window::updateSettings(const WindowSettings &newsettings)
|
||||
{
|
||||
Uint32 wflags = SDL_GetWindowFlags(window);
|
||||
|
||||
// Set the new display mode as the current display mode.
|
||||
SDL_GetWindowSize(window, &curMode.width, &curMode.height);
|
||||
SDL_GL_GetDrawableSize(window, &curMode.pixelwidth, &curMode.pixelheight);
|
||||
|
||||
if ((wflags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
|
||||
{
|
||||
curMode.settings.fullscreen = true;
|
||||
curMode.settings.fstype = FULLSCREEN_TYPE_DESKTOP;
|
||||
curMode.settings.fstype = FULLSCREEN_DESKTOP;
|
||||
}
|
||||
else if ((wflags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)
|
||||
{
|
||||
curMode.settings.fullscreen = true;
|
||||
curMode.settings.fstype = FULLSCREEN_TYPE_NORMAL;
|
||||
curMode.settings.fstype = FULLSCREEN_EXCLUSIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -461,21 +563,26 @@ void Window::updateSettings(const WindowSettings &newsettings)
|
||||
|
||||
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;
|
||||
#else
|
||||
curMode.settings.highdpi = false;
|
||||
#endif
|
||||
|
||||
// Only minimize on focus loss if the window is in exclusive-fullscreen
|
||||
// mode.
|
||||
if (curMode.settings.fullscreen && curMode.settings.fstype == FULLSCREEN_TYPE_NORMAL)
|
||||
if (curMode.settings.fullscreen && curMode.settings.fstype == FULLSCREEN_EXCLUSIVE)
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1");
|
||||
else
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||
|
||||
curMode.settings.sRGB = newsettings.sRGB;
|
||||
|
||||
// Verify MSAA setting.
|
||||
int buffers = 0;
|
||||
int samples = 0;
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
|
||||
|
||||
curMode.settings.msaa = (buffers > 0 ? samples : 0);
|
||||
curMode.settings.vsync = SDL_GL_GetSwapInterval() != 0;
|
||||
|
||||
SDL_DisplayMode dmode = {};
|
||||
SDL_GetCurrentDisplayMode(curMode.settings.display, &dmode);
|
||||
|
||||
@@ -507,7 +614,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
if (fstype == FULLSCREEN_TYPE_DESKTOP)
|
||||
if (fstype == FULLSCREEN_DESKTOP)
|
||||
sdlflags = SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
else
|
||||
{
|
||||
@@ -534,17 +641,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
|
||||
// Update the viewport size now instead of waiting for event polling.
|
||||
graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
{
|
||||
int width = curMode.width;
|
||||
int height = curMode.height;
|
||||
|
||||
// FIXME: disabled in Linux for runtime SDL 2.0.0 compatibility.
|
||||
#if SDL_VERSION_ATLEAST(2,0,1) && !defined(LOVE_LINUX)
|
||||
SDL_GL_GetDrawableSize(window, &width, &height);
|
||||
#endif
|
||||
|
||||
gfx->setViewportSize(width, height);
|
||||
}
|
||||
gfx->setViewportSize(curMode.pixelwidth, curMode.pixelheight);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -594,16 +691,6 @@ std::vector<WindowSize> Window::getFullscreenSizes(int displayindex) const
|
||||
return sizes;
|
||||
}
|
||||
|
||||
int Window::getWidth() const
|
||||
{
|
||||
return curMode.width;
|
||||
}
|
||||
|
||||
int Window::getHeight() const
|
||||
{
|
||||
return curMode.height;
|
||||
}
|
||||
|
||||
void Window::getDesktopDimensions(int displayindex, int &width, int &height) const
|
||||
{
|
||||
if (displayindex >= 0 && displayindex < getDisplayCount())
|
||||
@@ -671,7 +758,7 @@ bool Window::isCreated() const
|
||||
|
||||
void Window::setWindowTitle(const std::string &title)
|
||||
{
|
||||
windowTitle = title;
|
||||
this->title = title;
|
||||
|
||||
if (window)
|
||||
SDL_SetWindowTitle(window, title.c_str());
|
||||
@@ -679,7 +766,7 @@ void Window::setWindowTitle(const std::string &title)
|
||||
|
||||
const std::string &Window::getWindowTitle() const
|
||||
{
|
||||
return windowTitle;
|
||||
return title;
|
||||
}
|
||||
|
||||
bool Window::setIcon(love::image::ImageData *imgd)
|
||||
@@ -783,43 +870,39 @@ void Window::setMouseGrab(bool grab)
|
||||
bool Window::isMouseGrabbed() const
|
||||
{
|
||||
if (window)
|
||||
return (bool) SDL_GetWindowGrab(window);
|
||||
return SDL_GetWindowGrab(window) != SDL_FALSE;
|
||||
else
|
||||
return mouseGrabbed;
|
||||
}
|
||||
|
||||
double Window::getPixelScale() const
|
||||
void Window::getPixelDimensions(int &w, int &h) const
|
||||
{
|
||||
double scale = 1.0;
|
||||
|
||||
#ifdef LOVE_ANDROID
|
||||
scale = love::android::getScreenScale();
|
||||
// FIXME: disabled in Linux for runtime SDL 2.0.0 compatibility.
|
||||
#elif SDL_VERSION_ATLEAST(2,0,1) && !defined(LOVE_LINUX)
|
||||
if (window)
|
||||
{
|
||||
int wheight;
|
||||
SDL_GetWindowSize(window, nullptr, &wheight);
|
||||
|
||||
int dheight = wheight;
|
||||
SDL_GL_GetDrawableSize(window, nullptr, &dheight);
|
||||
|
||||
scale = (double) dheight / wheight;
|
||||
}
|
||||
#endif
|
||||
|
||||
return scale;
|
||||
w = curMode.pixelwidth;
|
||||
h = curMode.pixelheight;
|
||||
}
|
||||
|
||||
bool Window::isTouchScreen(int displayindex) const
|
||||
void Window::windowToPixelCoords(double *x, double *y) const
|
||||
{
|
||||
#if defined(LOVE_ANDROID) || defined(LOVE_IOS)
|
||||
// Display 0 is always a touch screen on Android and iOS.
|
||||
return displayindex == 0;
|
||||
if (x != nullptr)
|
||||
*x = (*x) * ((double) curMode.pixelwidth / (double) curMode.width);
|
||||
if (y != nullptr)
|
||||
*y = (*y) * ((double) curMode.pixelheight / (double) curMode.height);
|
||||
}
|
||||
|
||||
void Window::pixelToWindowCoords(double *x, double *y) const
|
||||
{
|
||||
if (x != nullptr)
|
||||
*x = (*x) * ((double) curMode.width / (double) curMode.pixelwidth);
|
||||
if (y != nullptr)
|
||||
*y = (*y) * ((double) curMode.height / (double) curMode.pixelheight);
|
||||
}
|
||||
|
||||
double Window::getPixelScale() const
|
||||
{
|
||||
#ifdef LOVE_ANDROID
|
||||
return love::android::getScreenScale();
|
||||
#else
|
||||
// TODO: implement for Windows and Linux.
|
||||
LOVE_UNUSED(displayindex);
|
||||
return false;
|
||||
return (double) curMode.pixelheight / (double) curMode.height;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -887,17 +970,17 @@ int Window::showMessageBox(const MessageBoxData &data)
|
||||
|
||||
std::vector<SDL_MessageBoxButtonData> sdlbuttons;
|
||||
|
||||
for (size_t i = 0; i < data.buttons.size(); i++)
|
||||
for (int i = 0; i < (int) data.buttons.size(); i++)
|
||||
{
|
||||
SDL_MessageBoxButtonData sdlbutton = {};
|
||||
|
||||
sdlbutton.buttonid = (int) i;
|
||||
sdlbutton.buttonid = i;
|
||||
sdlbutton.text = data.buttons[i].c_str();
|
||||
|
||||
if ((int) i == data.enterButtonIndex)
|
||||
if (i == data.enterButtonIndex)
|
||||
sdlbutton.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
|
||||
|
||||
if ((int) i == data.escapeButtonIndex)
|
||||
if (i == data.escapeButtonIndex)
|
||||
sdlbutton.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
|
||||
|
||||
sdlbuttons.push_back(sdlbutton);
|
||||
@@ -911,6 +994,46 @@ int Window::showMessageBox(const MessageBoxData &data)
|
||||
return pressedbutton;
|
||||
}
|
||||
|
||||
void Window::requestAttention(bool continuous)
|
||||
{
|
||||
#if defined(LOVE_WINDOWS)
|
||||
|
||||
if (hasFocus())
|
||||
return;
|
||||
|
||||
SDL_SysWMinfo wminfo = {};
|
||||
SDL_VERSION(&wminfo.version);
|
||||
|
||||
if (SDL_GetWindowWMInfo(window, &wminfo))
|
||||
{
|
||||
FLASHWINFO flashinfo = {};
|
||||
flashinfo.cbSize = sizeof(FLASHWINFO);
|
||||
flashinfo.hwnd = wminfo.info.win.window;
|
||||
flashinfo.uCount = 1;
|
||||
flashinfo.dwFlags = FLASHW_ALL;
|
||||
|
||||
if (continuous)
|
||||
{
|
||||
flashinfo.uCount = 0;
|
||||
flashinfo.dwFlags |= FLASHW_TIMERNOFG;
|
||||
}
|
||||
|
||||
FlashWindowEx(&flashinfo);
|
||||
}
|
||||
|
||||
#elif defined(LOVE_MACOSX)
|
||||
|
||||
love::osx::requestAttention(continuous);
|
||||
|
||||
#else
|
||||
|
||||
LOVE_UNUSED(continuous);
|
||||
|
||||
#endif
|
||||
|
||||
// TODO: Linux?
|
||||
}
|
||||
|
||||
love::window::Window *Window::createSingleton()
|
||||
{
|
||||
if (!singleton)
|
||||
@@ -921,11 +1044,6 @@ love::window::Window *Window::createSingleton()
|
||||
return singleton;
|
||||
}
|
||||
|
||||
love::window::Window *Window::getSingleton()
|
||||
{
|
||||
return singleton;
|
||||
}
|
||||
|
||||
const char *Window::getName() const
|
||||
{
|
||||
return "love.window.sdl";
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
bool setFullscreen(bool fullscreen, FullscreenType fstype);
|
||||
bool setFullscreen(bool fullscreen);
|
||||
|
||||
bool onWindowResize(int width, int height);
|
||||
bool onSizeChanged(int width, int height);
|
||||
|
||||
int getDisplayCount() const;
|
||||
|
||||
@@ -55,9 +55,6 @@ public:
|
||||
|
||||
std::vector<WindowSize> getFullscreenSizes(int displayindex) const;
|
||||
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
|
||||
void getDesktopDimensions(int displayindex, int &width, int &height) const;
|
||||
|
||||
void setPosition(int x, int y, int displayindex);
|
||||
@@ -87,9 +84,11 @@ public:
|
||||
void setMouseGrab(bool grab);
|
||||
bool isMouseGrabbed() const;
|
||||
|
||||
double getPixelScale() const;
|
||||
void getPixelDimensions(int &w, int &h) const;
|
||||
void windowToPixelCoords(double *x, double *y) const;
|
||||
void pixelToWindowCoords(double *x, double *y) const;
|
||||
|
||||
bool isTouchScreen(int displayindex) const;
|
||||
double getPixelScale() const;
|
||||
|
||||
double toPixels(double x) const;
|
||||
void toPixels(double wx, double wy, double &px, double &py) const;
|
||||
@@ -101,29 +100,40 @@ public:
|
||||
bool showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow);
|
||||
int showMessageBox(const MessageBoxData &data);
|
||||
|
||||
void requestAttention(bool continuous);
|
||||
|
||||
static love::window::Window *createSingleton();
|
||||
static love::window::Window *getSingleton();
|
||||
|
||||
const char *getName() const;
|
||||
|
||||
private:
|
||||
|
||||
bool setContext(int msaa, bool vsync, bool sRGB);
|
||||
void setWindowGLAttributes(int msaa, bool sRGB) const;
|
||||
struct ContextAttribs
|
||||
{
|
||||
int versionMajor;
|
||||
int versionMinor;
|
||||
bool gles;
|
||||
bool debug;
|
||||
};
|
||||
|
||||
void setGLFramebufferAttributes(int msaa, bool sRGB);
|
||||
void setGLContextAttributes(const ContextAttribs &attribs);
|
||||
bool checkGLVersion(const ContextAttribs &attribs);
|
||||
bool createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, int msaa, bool sRGB);
|
||||
|
||||
// Update the saved window settings based on the window's actual state.
|
||||
void updateSettings(const WindowSettings &newsettings);
|
||||
|
||||
SDL_MessageBoxFlags convertMessageBoxType(MessageBoxType type) const;
|
||||
|
||||
std::string windowTitle;
|
||||
std::string title;
|
||||
|
||||
struct _currentMode
|
||||
{
|
||||
_currentMode();
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int width = 800;
|
||||
int height = 600;
|
||||
int pixelwidth = 800;
|
||||
int pixelheight = 600;
|
||||
WindowSettings settings;
|
||||
StrongRef<love::image::ImageData> icon;
|
||||
|
||||
@@ -136,6 +146,9 @@ private:
|
||||
SDL_Window *window;
|
||||
SDL_GLContext context;
|
||||
|
||||
bool displayedWindowError;
|
||||
bool displayedContextError;
|
||||
|
||||
}; // Window
|
||||
|
||||
} // sdl
|
||||
|
||||
@@ -36,7 +36,7 @@ int w_getDisplayCount(lua_State *L)
|
||||
|
||||
int w_getDisplayName(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
int index = (int) luaL_checknumber(L, 1) - 1;
|
||||
|
||||
const char *name = nullptr;
|
||||
luax_catchexcept(L, [&](){ name = instance()->getDisplayName(index); });
|
||||
@@ -54,12 +54,12 @@ static const char *settingName(Window::Setting setting)
|
||||
|
||||
int w_setMode(lua_State *L)
|
||||
{
|
||||
int w = luaL_checkint(L, 1);
|
||||
int h = luaL_checkint(L, 2);
|
||||
int w = (int) luaL_checknumber(L, 1);
|
||||
int h = (int) luaL_checknumber(L, 2);
|
||||
|
||||
if (lua_isnoneornil(L, 3))
|
||||
{
|
||||
luax_pushboolean(L, instance()->setWindow(w, h, 0));
|
||||
luax_pushboolean(L, instance()->setWindow(w, h, nullptr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@ int w_setMode(lua_State *L)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to "normal" fullscreen.
|
||||
settings.fstype = Window::FULLSCREEN_TYPE_NORMAL;
|
||||
// Default to desktop fullscreen mode.
|
||||
settings.fstype = Window::FULLSCREEN_DESKTOP;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
@@ -114,17 +114,13 @@ int w_setMode(lua_State *L)
|
||||
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);
|
||||
settings.x = (int) luaL_optnumber(L, -2, 0);
|
||||
settings.y = (int) luaL_optnumber(L, -1, 0);
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
|
||||
// We don't explicitly set the refresh rate, it's "read-only".
|
||||
|
||||
// For backward-compatibility. TODO: remove!
|
||||
int fsaa = luax_intflag(L, 3, settingName(Window::SETTING_FSAA), 0);
|
||||
if (fsaa > settings.msaa) settings.msaa = fsaa;
|
||||
|
||||
luax_catchexcept(L,
|
||||
[&](){ luax_pushboolean(L, instance()->setWindow(w, h, &settings)); }
|
||||
);
|
||||
@@ -142,7 +138,7 @@ int w_getMode(lua_State *L)
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
const char *fstypestr = "normal";
|
||||
const char *fstypestr = "desktop";
|
||||
Window::getConstant(settings.fstype, fstypestr);
|
||||
|
||||
lua_pushstring(L, fstypestr);
|
||||
@@ -157,9 +153,6 @@ int w_getMode(lua_State *L)
|
||||
lua_pushinteger(L, settings.msaa);
|
||||
lua_setfield(L, -2, settingName(Window::SETTING_MSAA));
|
||||
|
||||
lua_pushinteger(L, settings.msaa);
|
||||
lua_setfield(L, -2, settingName(Window::SETTING_FSAA)); // For backward-compatibility. TODO: remove!
|
||||
|
||||
luax_pushboolean(L, settings.resizable);
|
||||
lua_setfield(L, -2, settingName(Window::SETTING_RESIZABLE));
|
||||
|
||||
@@ -199,15 +192,22 @@ int w_getMode(lua_State *L)
|
||||
|
||||
int w_getFullscreenModes(lua_State *L)
|
||||
{
|
||||
int displayindex = luaL_optint(L, 1, 1) - 1;
|
||||
int displayindex = 0;
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
displayindex = (int) luaL_checknumber(L, 1);
|
||||
else
|
||||
{
|
||||
int x, y;
|
||||
instance()->getPosition(x, y, displayindex);
|
||||
}
|
||||
|
||||
std::vector<Window::WindowSize> modes = instance()->getFullscreenSizes(displayindex);
|
||||
|
||||
lua_createtable(L, modes.size(), 0);
|
||||
lua_createtable(L, (int) modes.size(), 0);
|
||||
|
||||
for (size_t i = 0; i < modes.size(); i++)
|
||||
{
|
||||
lua_pushinteger(L, i+1);
|
||||
lua_pushinteger(L, i + 1);
|
||||
lua_createtable(L, 0, 2);
|
||||
|
||||
// Inner table attribs.
|
||||
@@ -229,14 +229,14 @@ int w_getFullscreenModes(lua_State *L)
|
||||
int w_setFullscreen(lua_State *L)
|
||||
{
|
||||
bool fullscreen = luax_toboolean(L, 1);
|
||||
Window::FullscreenType fstype = Window::FULLSCREEN_TYPE_MAX_ENUM;
|
||||
Window::FullscreenType fstype = Window::FULLSCREEN_MAX_ENUM;
|
||||
|
||||
const char *typestr = lua_isnoneornil(L, 2) ? 0 : luaL_checkstring(L, 2);
|
||||
if (typestr && !Window::getConstant(typestr, fstype))
|
||||
return luaL_error(L, "Invalid fullscreen type: %s", typestr);
|
||||
|
||||
bool success = false;
|
||||
if (fstype == Window::FULLSCREEN_TYPE_MAX_ENUM)
|
||||
if (fstype == Window::FULLSCREEN_MAX_ENUM)
|
||||
success = instance()->setFullscreen(fullscreen);
|
||||
else
|
||||
success = instance()->setFullscreen(fullscreen, fstype);
|
||||
@@ -266,29 +266,17 @@ int w_isCreated(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getWidth(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance()->getWidth());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getHeight(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance()->getHeight());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getDimensions(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance()->getWidth());
|
||||
lua_pushinteger(L, instance()->getHeight());
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_getDesktopDimensions(lua_State *L)
|
||||
{
|
||||
int width = 0, height = 0;
|
||||
int displayindex = luaL_optint(L, 1, 1) - 1;
|
||||
int displayindex = 0;
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
displayindex = (int) luaL_checknumber(L, 1);
|
||||
else
|
||||
{
|
||||
int x, y;
|
||||
instance()->getPosition(x, y, displayindex);
|
||||
}
|
||||
instance()->getDesktopDimensions(displayindex, width, height);
|
||||
lua_pushinteger(L, width);
|
||||
lua_pushinteger(L, height);
|
||||
@@ -297,9 +285,18 @@ int w_getDesktopDimensions(lua_State *L)
|
||||
|
||||
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;
|
||||
int x = (int) luaL_checknumber(L, 1);
|
||||
int y = (int) luaL_checknumber(L, 2);
|
||||
|
||||
int displayindex = 0;
|
||||
if (!lua_isnoneornil(L, 3))
|
||||
displayindex = (int) luaL_checknumber(L, 3);
|
||||
else
|
||||
{
|
||||
int x_unused, y_unused;
|
||||
instance()->getPosition(x_unused, y_unused, displayindex);
|
||||
}
|
||||
|
||||
instance()->setPosition(x, y, displayindex);
|
||||
return 0;
|
||||
}
|
||||
@@ -318,7 +315,7 @@ int w_getPosition(lua_State *L)
|
||||
|
||||
int w_setIcon(lua_State *L)
|
||||
{
|
||||
image::ImageData *i = luax_checktype<image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
|
||||
image::ImageData *i = luax_checktype<image::ImageData>(L, 1, IMAGE_IMAGE_DATA_ID);
|
||||
luax_pushboolean(L, instance()->setIcon(i));
|
||||
return 1;
|
||||
}
|
||||
@@ -326,10 +323,7 @@ int w_setIcon(lua_State *L)
|
||||
int w_getIcon(lua_State *L)
|
||||
{
|
||||
image::ImageData *i = instance()->getIcon();
|
||||
if (i)
|
||||
luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
luax_pushtype(L, IMAGE_IMAGE_DATA_ID, i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -370,13 +364,6 @@ int w_getPixelScale(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_isTouchScreen(lua_State *L)
|
||||
{
|
||||
int index = luaL_optint(L, 1, 1) - 1;
|
||||
luax_pushboolean(L, instance()->isTouchScreen(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_toPixels(lua_State *L)
|
||||
{
|
||||
double wx = luaL_checknumber(L, 1);
|
||||
@@ -443,14 +430,14 @@ int w_showMessageBox(lua_State *L)
|
||||
// means we should use the more complex message box API.
|
||||
if (lua_istable(L, 3))
|
||||
{
|
||||
size_t numbuttons = lua_objlen(L, 3);
|
||||
size_t numbuttons = luax_objlen(L, 3);
|
||||
if (numbuttons == 0)
|
||||
return luaL_error(L, "Must have at least one messagebox button.");
|
||||
|
||||
// Array of button names.
|
||||
for (size_t i = 0; i < numbuttons; i++)
|
||||
{
|
||||
lua_rawgeti(L, 3, i + 1);
|
||||
lua_rawgeti(L, 3, (int) i + 1);
|
||||
data.buttons.push_back(luax_checkstring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
@@ -458,7 +445,7 @@ int w_showMessageBox(lua_State *L)
|
||||
// Optional table entry specifying the button to use when enter is pressed.
|
||||
lua_getfield(L, 3, "enterbutton");
|
||||
if (!lua_isnoneornil(L, -1))
|
||||
data.enterButtonIndex = luaL_checkint(L, -1) - 1;
|
||||
data.enterButtonIndex = (int) luaL_checknumber(L, -1) - 1;
|
||||
else
|
||||
data.enterButtonIndex = 0;
|
||||
lua_pop(L, 1);
|
||||
@@ -466,7 +453,7 @@ int w_showMessageBox(lua_State *L)
|
||||
// Optional table entry specifying the button to use when esc is pressed.
|
||||
lua_getfield(L, 3, "escapebutton");
|
||||
if (!lua_isnoneornil(L, -1))
|
||||
data.escapeButtonIndex = luaL_checkint(L, -1) - 1;
|
||||
data.escapeButtonIndex = (int) luaL_checknumber(L, -1) - 1;
|
||||
else
|
||||
data.escapeButtonIndex = (int) data.buttons.size() - 1;
|
||||
lua_pop(L, 1);
|
||||
@@ -496,6 +483,13 @@ int w_showMessageBox(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_requestAttention(lua_State *L)
|
||||
{
|
||||
bool continuous = luax_optboolean(L, 1, false);
|
||||
instance()->requestAttention(continuous);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "getDisplayCount", w_getDisplayCount },
|
||||
@@ -506,9 +500,6 @@ static const luaL_Reg functions[] =
|
||||
{ "setFullscreen", w_setFullscreen },
|
||||
{ "getFullscreen", w_getFullscreen },
|
||||
{ "isCreated", w_isCreated },
|
||||
{ "getWidth", w_getWidth },
|
||||
{ "getHeight", w_getHeight },
|
||||
{ "getDimensions", w_getDimensions },
|
||||
{ "getDesktopDimensions", w_getDesktopDimensions },
|
||||
{ "setPosition", w_setPosition },
|
||||
{ "getPosition", w_getPosition },
|
||||
@@ -520,12 +511,12 @@ static const luaL_Reg functions[] =
|
||||
{ "hasMouseFocus", w_hasMouseFocus },
|
||||
{ "isVisible", w_isVisible },
|
||||
{ "getPixelScale", w_getPixelScale },
|
||||
{ "isTouchScreen", w_isTouchScreen },
|
||||
{ "toPixels", w_toPixels },
|
||||
{ "fromPixels", w_fromPixels },
|
||||
{ "minimize", w_minimize },
|
||||
{ "maximize", w_maximize },
|
||||
{ "showMessageBox", w_showMessageBox },
|
||||
{ "requestAttention", w_requestAttention },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -537,7 +528,7 @@ extern "C" int luaopen_love_window(lua_State *L)
|
||||
WrappedModule w;
|
||||
w.module = instance;
|
||||
w.name = "window";
|
||||
w.flags = MODULE_T;
|
||||
w.type = MODULE_ID;
|
||||
w.functions = functions;
|
||||
w.types = 0;
|
||||
|
||||
|
||||
@@ -37,9 +37,6 @@ int w_getFullscreenModes(lua_State *L);
|
||||
int w_setFullscreen(lua_State *L);
|
||||
int w_getFullscreen(lua_State *L);
|
||||
int w_isCreated(lua_State *L);
|
||||
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);
|
||||
@@ -51,12 +48,12 @@ int w_hasFocus(lua_State *L);
|
||||
int w_hasMouseFocus(lua_State *L);
|
||||
int w_isVisible(lua_State *L);
|
||||
int w_getPixelScale(lua_State *L);
|
||||
int w_isTouchScreen(lua_State *L);
|
||||
int w_toPixels(lua_State *L);
|
||||
int w_fromPixels(lua_State *L);
|
||||
int w_minimize(lua_State *L);
|
||||
int w_maximize(lua_State *L);
|
||||
int w_showMessageBox(lua_State *L);
|
||||
int w_requestAttention(lua_State *L);
|
||||
extern "C" LOVE_EXPORT int luaopen_love_window(lua_State *L);
|
||||
|
||||
} // window
|
||||
|
||||
Reference in New Issue
Block a user