Merged SDL2 changes from bartbes/love-experiments/SDL2 into default.

- Added love.system module, including clipboard functions.

- Added custom hardware cursors (love.mouse.newCursor, love.mouse.setCursor.)

- Revamped love.joystick:
-- added Joystick objects and moved love.joystick functions which operated on individual joysticks to methods on the Joystick objects.
-- Added love.joystick.getJoystick and love.joystick.getJoystickCount.
-- Added events for when joysticks are connected and disconnected.
-- Added 'Gamepad' methods to Joystick objects: Joystick:isGamepad, Joystick:getGamepadAxis, and Joystick:isGamepadDown. They're a common abstraction for xbox controller-like joystick across operating systems.

- Added monitor choosing support and "fullscreen desktop" mode to love.window.

- Moved unicode text input events to their own callback function (love.textinput), removed the key repeat functions from love.keyboard and made the second argument of love.keypressed a boolean saying whether the keypress was a repeat.

- liblove now works with love.window and love.graphics in OS X
This commit is contained in:
Alex Szpakowski
2013-08-25 16:51:42 -03:00
parent 035130533b
commit 113ed1cfe7
67 changed files with 4691 additions and 1665 deletions
+22
View File
@@ -40,13 +40,35 @@ void Window::swapBuffers()
WindowFlags::WindowFlags()
: fullscreen(false)
, fstype(Window::FULLSCREEN_TYPE_NORMAL)
, vsync(true)
, fsaa(0)
, resizable(false)
, minwidth(100)
, minheight(100)
, borderless(false)
, centered(true)
, display(0)
{
}
bool Window::getConstant(const char *in, Window::FullscreenType &out)
{
return fullscreenTypes.find(in, out);
}
bool Window::getConstant(Window::FullscreenType in, const char *&out)
{
return fullscreenTypes.find(in, out);
}
StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM>::Entry Window::fullscreenTypeEntries[] =
{
{"normal", Window::FULLSCREEN_TYPE_NORMAL},
{"desktop", Window::FULLSCREEN_TYPE_DESKTOP},
};
StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM> Window::fullscreenTypes(Window::fullscreenTypeEntries, sizeof(Window::fullscreenTypeEntries));
} // window
} // love
+61 -18
View File
@@ -21,32 +21,35 @@
#ifndef LOVE_WINDOW_WINDOW_H
#define LOVE_WINDOW_WINDOW_H
// STL
#include <string>
// LOVE
#include "common/Module.h"
#include "common/StringMap.h"
#include "image/ImageData.h"
// C++
#include <string>
#include <vector>
namespace love
{
namespace window
{
struct WindowFlags
{
WindowFlags();
bool fullscreen; // = false
bool vsync; // = true
int fsaa; // = 0
bool resizable; // = false
bool borderless; // = false
bool centered; // = true
}; // WindowFlags
// Forward-declared so it can be used in the class methods. We can't define the
// whole thing here because it uses the Window::Type enum.
struct WindowFlags;
class Window : public Module
{
public:
enum FullscreenType
{
FULLSCREEN_TYPE_NORMAL,
FULLSCREEN_TYPE_DESKTOP,
FULLSCREEN_TYPE_MAX_ENUM
};
struct WindowSize
{
int width;
@@ -56,18 +59,27 @@ public:
virtual ~Window();
virtual bool setWindow(int width = 800, int height = 600, WindowFlags *flags = 0) = 0;
virtual void getWindow(int &width, int &height, WindowFlags &flags) const = 0;
virtual void getWindow(int &width, int &height, WindowFlags &flags) = 0;
virtual bool checkWindowSize(int width, int height, bool fullscreen) const = 0;
virtual WindowSize *getFullscreenSizes(int &n) const = 0;
virtual bool setFullscreen(bool fullscreen, FullscreenType fstype) = 0;
virtual bool setFullscreen(bool fullscreen) = 0;
virtual bool onWindowResize(int width, int height) = 0;
virtual int getDisplayCount() const = 0;
virtual bool checkWindowSize(int width, int height, bool fullscreen, int displayindex) const = 0;
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 bool isCreated() const = 0;
virtual void setWindowTitle(const std::string &title) = 0;
virtual std::string getWindowTitle() const = 0;
virtual const std::string &getWindowTitle() const = 0;
virtual bool setIcon(love::image::ImageData *imgd) = 0;
virtual love::image::ImageData *getIcon() = 0;
@@ -83,13 +95,44 @@ public:
virtual void setMouseVisible(bool visible) = 0;
virtual bool getMouseVisible() const = 0;
virtual void setMouseGrab(bool grab) = 0;
virtual bool isMouseGrabbed() const = 0;
virtual const void *getHandle() const = 0;
//virtual static Window *createSingleton() = 0;
//virtual static Window *getSingleton() = 0;
// No virtual statics, of course, but you are supposed to implement this static.
// No virtual statics, of course, but you are supposed to implement these statics.
static bool getConstant(const char *in, FullscreenType &out);
static bool getConstant(FullscreenType in, const char *&out);
protected:
static Window *singleton;
private:
static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM>::Entry fullscreenTypeEntries[];
static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM> fullscreenTypes;
}; // Window
struct WindowFlags
{
WindowFlags();
bool fullscreen; // = false
Window::FullscreenType fstype; // = FULLSCREEN_TYPE_NORMAL
bool vsync; // = true
int fsaa; // = 0
bool resizable; // = false
int minwidth; // = 100
int minheight; // = 100
bool borderless; // = false
bool centered; // = true
int display; // = 0
}; // WindowFlags
} // window
} // love
+392 -155
View File
@@ -23,11 +23,10 @@
#include "graphics/Graphics.h"
#include "Window.h"
// SDL
#include <SDL.h>
// STL
// C++
#include <iostream>
#include <vector>
#include <algorithm>
namespace love
{
@@ -39,15 +38,30 @@ namespace sdl
Window::Window()
: windowTitle("")
, created(false)
, mouseGrabbed(false)
, window(0)
, context(0)
{
#ifdef LOVE_MACOSX
// SDL 2 minimizes the window at weird times on OSX if this isn't disabled.
// TODO: do Linux and/or Windows need this as well (multi-monitor)?
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
#endif
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
throw love::Exception(SDL_GetError());
throw love::Exception("%s", SDL_GetError());
}
Window::~Window()
{
if (currentMode.icon)
currentMode.icon->release();
if (curMode.icon)
curMode.icon->release();
if (window)
SDL_DestroyWindow(window);
if (context)
SDL_GL_DeleteContext(context);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
@@ -66,109 +80,181 @@ bool Window::setWindow(int width, int height, WindowFlags *flags)
if (gfx)
gfx->unSetMode();
bool fullscreen = false;
bool vsync = true;
int fsaa = 0;
bool resizable = false;
bool borderless = false;
bool centered = true;
WindowFlags f;
if (flags)
f = *flags;
f.minwidth = std::max(f.minwidth, 0);
f.minheight = std::max(f.minheight, 0);
f.display = std::min(std::max(f.display, 0), getDisplayCount());
// Use the desktop resolution if a width or height of 0 is specified.
if (width == 0 || height == 0)
{
fullscreen = flags->fullscreen;
vsync = flags->vsync;
fsaa = flags->fsaa;
resizable = flags->resizable;
borderless = flags->borderless;
centered = flags->centered;
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(f.display, &mode);
width = mode.w;
height = mode.h;
}
bool mouseVisible = getMouseVisible();
int keyrepeatDelay, keyrepeatInterval;
SDL_GetKeyRepeat(&keyrepeatDelay, &keyrepeatInterval);
Uint32 sdlflags = SDL_WINDOW_OPENGL;
// We need to restart the subsystem for two reasons:
// 1) Special case for fullscreen -> windowed. Windows XP did not
// work well with "normal" display mode change in this case.
// The application window does leave fullscreen, but the desktop
// resolution does not revert to the correct one. Restarting the
// SDL video subsystem does the trick, though.
// 2) Restart the event system (for whatever reason the event system
// started and stopped with SDL_INIT_VIDEO, see:
// http://sdl.beuc.net/sdl.wiki/Introduction_to_Events)
// because the mouse position will not be able to exceed
// the previous' video mode window size (i.e. alway
// love.mouse.getX() < 800 when switching from 800x600 to a
// higher resolution)
SDL_QuitSubSystem(SDL_INIT_VIDEO);
if (centered) // Window should be centered.
SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED=center"));
else
SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED="));
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
if (f.fullscreen)
{
std::cout << "Could not init SDL_VIDEO: " << SDL_GetError() << std::endl;
switch (f.fstype)
{
case FULLSCREEN_TYPE_NORMAL:
default:
sdlflags |= SDL_WINDOW_FULLSCREEN;
break;
case FULLSCREEN_TYPE_DESKTOP:
sdlflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
break;
}
}
if (f.resizable)
sdlflags |= SDL_WINDOW_RESIZABLE;
if (f.borderless)
sdlflags |= SDL_WINDOW_BORDERLESS;
// Destroy and recreate the window if the dimensions or flags have changed.
if (window)
{
int curdisplay = SDL_GetWindowDisplayIndex(window);
Uint32 wflags = SDL_GetWindowFlags(window);
wflags &= (SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS);
if (sdlflags != wflags || width != curMode.width || height != curMode.height
|| f.display != curdisplay || f.fsaa != curMode.flags.fsaa)
{
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);
}
}
int centeredpos = SDL_WINDOWPOS_CENTERED_DISPLAY(f.display);
int uncenteredpos = SDL_WINDOWPOS_UNDEFINED_DISPLAY(f.display);
if (!window)
{
// In Windows and Linux, some GL attributes are set on window creation.
setWindowGLAttributes(f.fsaa);
const char *title = windowTitle.c_str();
int pos = f.centered ? centeredpos : uncenteredpos;
window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags);
if (!window && f.fsaa > 0)
{
// FSAA 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, pos, pos, width, height, sdlflags);
f.fsaa = 0;
}
// Make sure the window keeps any previously set icon.
if (window && curMode.icon)
setIcon(curMode.icon);
}
if (!window)
{
std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
return false;
}
// Set caption.
setWindowTitle(windowTitle);
setMouseVisible(mouseVisible);
setIcon(currentMode.icon);
SDL_EnableKeyRepeat(keyrepeatDelay, keyrepeatInterval);
// Enforce minimum window dimensions.
SDL_SetWindowMinimumSize(window, f.minwidth, f.minheight);
// Set GL 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_SWAP_CONTROL, (vsync ? 1 : 0));
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
if (f.centered && !f.fullscreen)
SDL_SetWindowPosition(window, centeredpos, centeredpos);
// FSAA
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
SDL_RaiseWindow(window);
Uint32 sdlflags = SDL_OPENGL;
// Flags
if (fullscreen)
sdlflags |= SDL_FULLSCREEN;
if (resizable)
sdlflags |= SDL_RESIZABLE;
if (borderless)
sdlflags |= SDL_NOFRAME;
// Have SDL set the video mode.
SDL_Surface *surface;
if ((surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0)
{
bool failed = true;
if (fsaa > 0)
{
// FSAA might have caused the failure, disable it and try again
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
failed = (surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0;
}
if (failed)
{
std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
return false;
}
}
if (!setContext(f.fsaa, f.vsync))
return false;
created = true;
const SDL_VideoInfo *videoinfo = SDL_GetVideoInfo();
width = videoinfo->current_w;
height = videoinfo->current_h;
updateWindowFlags(f);
if (gfx)
gfx->setMode(curMode.width, curMode.height);
// Make sure the mouse keeps its previous grab setting.
setMouseGrab(mouseGrabbed);
return true;
}
bool Window::onWindowResize(int width, int height)
{
if (!window)
return false;
curMode.width = width;
curMode.height = height;
return true;
}
bool Window::setContext(int fsaa, bool vsync)
{
// We need to recreate the context if FSAA changes,
// or if the existing context has been invalidated.
if (context && (fsaa != curMode.flags.fsaa || SDL_GL_MakeCurrent(window, context) < 0))
{
SDL_GL_DeleteContext(context);
context = 0;
}
// Create a new OpenGL context.
if (!context)
{
setWindowGLAttributes(fsaa);
context = SDL_GL_CreateContext(window);
if (!context && fsaa > 0)
{
// FSAA 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)
{
std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
return false;
}
// Set vertical synchronization.
if (vsync)
{
// Prefer EXT_swap_control_tear (late swaps happen immediately),
// otherwise fall back to regular vsync.
if (SDL_GL_SetSwapInterval(-1) < 0 || SDL_GL_GetSwapInterval() != -1)
SDL_GL_SetSwapInterval(1);
}
else
SDL_GL_SetSwapInterval(0);
// Verify FSAA setting.
int buffers;
int samples;
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
@@ -179,65 +265,173 @@ bool Window::setWindow(int width, int height, WindowFlags *flags)
fsaa = (buffers > 0) ? samples : 0;
}
// Get the actual vsync status
int real_vsync;
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &real_vsync);
// Set the new display mode as the current display mode.
currentMode.width = width;
currentMode.height = height;
currentMode.flags.fsaa = fsaa;
currentMode.flags.fullscreen = fullscreen;
currentMode.flags.vsync = (real_vsync != 0);
currentMode.flags.resizable = ((surface->flags & SDL_RESIZABLE) != 0);
currentMode.flags.borderless = ((surface->flags & SDL_NOFRAME) != 0);
currentMode.flags.centered = centered;
if (gfx)
gfx->setMode(width, height);
curMode.flags.fsaa = fsaa;
curMode.flags.vsync = SDL_GL_GetSwapInterval() != 0;
return true;
}
void Window::getWindow(int &width, int &height, WindowFlags &flags) const
void Window::setWindowGLAttributes(int fsaa) const
{
width = currentMode.width;
height = currentMode.height;
flags = currentMode.flags;
// 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);
// FSAA.
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
}
bool Window::checkWindowSize(int width, int height, bool fullscreen) const
void Window::updateWindowFlags(const WindowFlags &newflags)
{
Uint32 sdlflags = fullscreen ? (SDL_OPENGL | SDL_FULLSCREEN) : SDL_OPENGL;
Uint32 wflags = SDL_GetWindowFlags(window);
// Check if mode is supported
int bpp = SDL_VideoModeOK(width, height, 32, sdlflags);
// Set the new display mode as the current display mode.
SDL_GetWindowSize(window, &curMode.width, &curMode.height);
return (bpp >= 16);
if ((wflags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
curMode.flags.fullscreen = true;
curMode.flags.fstype = FULLSCREEN_TYPE_DESKTOP;
}
else if ((wflags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)
{
curMode.flags.fullscreen = true;
curMode.flags.fstype = FULLSCREEN_TYPE_NORMAL;
}
else
{
curMode.flags.fullscreen = false;
curMode.flags.fstype = newflags.fstype;
}
// The min width/height is set to 0 internally in SDL when in fullscreen.
if (curMode.flags.fullscreen)
{
curMode.flags.minwidth = newflags.minwidth;
curMode.flags.minheight = newflags.minheight;
}
else
SDL_GetWindowMinimumSize(window, &curMode.flags.minwidth, &curMode.flags.minheight);
curMode.flags.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0;
curMode.flags.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0;
curMode.flags.centered = newflags.centered;
curMode.flags.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
}
void Window::getWindow(int &width, int &height, WindowFlags &flags)
{
// Window position may be different from creation - update display index.
if (window)
curMode.flags.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
width = curMode.width;
height = curMode.height;
flags = curMode.flags;
}
bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
{
if (!window)
return false;
WindowFlags newflags = curMode.flags;
newflags.fullscreen = fullscreen;
newflags.fstype = fstype;
Uint32 sdlflags = 0;
if (fullscreen)
{
if (fstype == FULLSCREEN_TYPE_DESKTOP)
sdlflags = SDL_WINDOW_FULLSCREEN_DESKTOP;
else
{
sdlflags = SDL_WINDOW_FULLSCREEN;
SDL_DisplayMode mode = {};
mode.w = curMode.width;
mode.h = curMode.height;
SDL_GetClosestDisplayMode(SDL_GetWindowDisplayIndex(window), &mode, &mode);
SDL_SetWindowDisplayMode(window, &mode);
}
}
if (SDL_SetWindowFullscreen(window, sdlflags) == 0)
{
SDL_GL_MakeCurrent(window, context);
updateWindowFlags(newflags);
return true;
}
return false;
}
bool Window::setFullscreen(bool fullscreen)
{
return setFullscreen(fullscreen, curMode.flags.fstype);
}
int Window::getDisplayCount() const
{
return SDL_GetNumVideoDisplays();
}
bool Window::checkWindowSize(int width, int height, bool fullscreen, int displayindex) const
{
if (fullscreen)
{
SDL_DisplayMode mode = {}, closest = {};
mode.w = width;
mode.h = height;
SDL_GetClosestDisplayMode(displayindex, &mode, &closest);
return (mode.w == closest.w && mode.h == closest.h);
}
else
{
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(displayindex, &mode);
return (width <= mode.w && height <= mode.h);
}
}
typedef Window::WindowSize WindowSize;
WindowSize *Window::getFullscreenSizes(int &n) const
std::vector<WindowSize> Window::getFullscreenSizes(int displayindex) const
{
SDL_Rect **modes = SDL_ListModes(0, SDL_OPENGL | SDL_FULLSCREEN);
std::vector<WindowSize> sizes;
if (modes == (SDL_Rect **)0 || modes == (SDL_Rect **)-1)
SDL_DisplayMode mode = {};
std::vector<WindowSize>::const_iterator it;
for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++)
{
n = 0;
return NULL;
}
SDL_GetDisplayMode(displayindex, i, &mode);
n = 0;
for (int i = 0; modes[i]; i++)
n++;
// SDL2's display mode list has multiple entries for modes of the same
// size with different bits per pixel, so we need to filter those out.
bool alreadyhassize = false;
for (it = sizes.begin(); it != sizes.end(); ++it)
{
if (it->width == mode.w && it->height == mode.h)
{
alreadyhassize = true;
break;
}
}
WindowSize *sizes = new WindowSize[n];
for (int i = 0; i < n; i++)
{
WindowSize w = {modes[i]->w, modes[i]->h};
sizes[i] = w;
if (!alreadyhassize)
{
WindowSize w = {mode.w, mode.h};
sizes.push_back(w);
}
}
return sizes;
@@ -245,12 +439,28 @@ WindowSize *Window::getFullscreenSizes(int &n) const
int Window::getWidth() const
{
return currentMode.width;
return curMode.width;
}
int Window::getHeight() const
{
return currentMode.height;
return curMode.height;
}
void Window::getDesktopDimensions(int displayindex, int &width, int &height) const
{
if (displayindex >= 0 && displayindex < getDisplayCount())
{
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(displayindex, &mode);
width = mode.w;
height = mode.h;
}
else
{
width = 0;
height = 0;
}
}
bool Window::isCreated() const
@@ -261,14 +471,13 @@ bool Window::isCreated() const
void Window::setWindowTitle(const std::string &title)
{
windowTitle = title;
SDL_WM_SetCaption(windowTitle.c_str(), 0);
if (window)
SDL_SetWindowTitle(window, title.c_str());
}
std::string Window::getWindowTitle() const
const std::string &Window::getWindowTitle() const
{
// not a reference
// because we want this untouched
// const std::string& might be an option
return windowTitle;
}
@@ -277,6 +486,14 @@ bool Window::setIcon(love::image::ImageData *imgd)
if (!imgd)
return false;
imgd->retain();
if (curMode.icon)
curMode.icon->release();
curMode.icon = imgd;
if (!window)
return false;
Uint32 rmask, gmask, bmask, amask;
#ifdef LOVE_BIG_ENDIAN
rmask = 0xFF000000;
@@ -294,51 +511,46 @@ bool Window::setIcon(love::image::ImageData *imgd)
int h = imgd->getHeight();
int pitch = imgd->getWidth() * 4;
SDL_Surface *icon = 0;
SDL_Surface *sdlicon = 0;
{
// We don't want another thread modifying the ImageData mid-copy.
love::thread::Lock lock(imgd->getMutex());
icon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
sdlicon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
}
if (!icon)
if (!sdlicon)
return false;
SDL_WM_SetIcon(icon, NULL);
SDL_FreeSurface(icon);
imgd->retain();
if (currentMode.icon)
currentMode.icon->release();
currentMode.icon = imgd;
SDL_SetWindowIcon(window, sdlicon);
SDL_FreeSurface(sdlicon);
return true;
}
love::image::ImageData *Window::getIcon()
{
return currentMode.icon;
return curMode.icon;
}
void Window::swapBuffers()
{
SDL_GL_SwapBuffers();
SDL_GL_SwapWindow(window);
}
bool Window::hasFocus() const
{
return (SDL_GetAppState() & SDL_APPINPUTFOCUS) != 0;
return (window && SDL_GetKeyboardFocus() == window);
}
bool Window::hasMouseFocus() const
{
return (SDL_GetAppState() & SDL_APPMOUSEFOCUS) != 0;
return (window && SDL_GetMouseFocus() == window);
}
bool Window::isVisible() const
{
return (SDL_GetAppState() & SDL_APPACTIVE) != 0;
return window && (SDL_GetWindowFlags(window) & SDL_WINDOW_SHOWN) != 0;
}
void Window::setMouseVisible(bool visible)
@@ -348,10 +560,30 @@ void Window::setMouseVisible(bool visible)
bool Window::getMouseVisible() const
{
return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) ? true : false;
return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE);
}
love::window::Window *Window::getSingleton()
void Window::setMouseGrab(bool grab)
{
mouseGrabbed = grab;
if (window)
SDL_SetWindowGrab(window, (SDL_bool) grab);
}
bool Window::isMouseGrabbed() const
{
if (window)
return (bool) SDL_GetWindowGrab(window);
else
return mouseGrabbed;
}
const void *Window::getHandle() const
{
return window;
}
love::window::Window *Window::createSingleton()
{
if (!singleton)
singleton = new Window();
@@ -361,6 +593,11 @@ love::window::Window *Window::getSingleton()
return singleton;
}
love::window::Window *Window::getSingleton()
{
return singleton;
}
const char *Window::getName() const
{
return "love.window.sdl";
+34 -5
View File
@@ -24,6 +24,9 @@
// LOVE
#include "window/Window.h"
// SDL
#include <SDL.h>
namespace love
{
namespace window
@@ -39,18 +42,27 @@ public:
~Window();
bool setWindow(int width = 800, int height = 600, WindowFlags *flags = 0);
void getWindow(int &width, int &height, WindowFlags &flags) const;
void getWindow(int &width, int &height, WindowFlags &flags);
bool checkWindowSize(int width, int height, bool fullscreen) const;
WindowSize *getFullscreenSizes(int &n) const;
bool setFullscreen(bool fullscreen, FullscreenType fstype);
bool setFullscreen(bool fullscreen);
bool onWindowResize(int width, int height);
int getDisplayCount() const;
bool checkWindowSize(int width, int height, bool fullscreen, int displayindex) const;
std::vector<WindowSize> getFullscreenSizes(int displayindex) const;
int getWidth() const;
int getHeight() const;
void getDesktopDimensions(int displayindex, int &width, int &height) const;
bool isCreated() const;
void setWindowTitle(const std::string &title);
std::string getWindowTitle() const;
const std::string &getWindowTitle() const;
bool setIcon(love::image::ImageData *imgd);
love::image::ImageData *getIcon();
@@ -65,12 +77,24 @@ public:
void setMouseVisible(bool visible);
bool getMouseVisible() const;
void setMouseGrab(bool grab);
bool isMouseGrabbed() const;
const void *getHandle() const;
static love::window::Window *createSingleton();
static love::window::Window *getSingleton();
const char *getName() const;
private:
bool setContext(int fsaa, bool vsync);
void setWindowGLAttributes(int fsaa) const;
// Update the window flags based on the window's actual state.
void updateWindowFlags(const WindowFlags &newflags);
std::string windowTitle;
struct _currentMode
@@ -82,10 +106,15 @@ private:
WindowFlags flags;
love::image::ImageData *icon;
} currentMode;
} curMode;
bool created;
bool mouseGrabbed;
SDL_Window *window;
SDL_GLContext context;
}; // Window
} // sdl
+104 -28
View File
@@ -28,23 +28,37 @@ namespace window
static Window *instance = 0;
int w_getDisplayCount(lua_State *L)
{
lua_pushinteger(L, instance->getDisplayCount());
return 1;
}
int w_checkMode(lua_State *L)
{
int w = luaL_checkint(L, 1);
int h = luaL_checkint(L, 2);
bool fs = false;
int displayindex = 0;
if (lua_istable(L, 3))
{
lua_getfield(L, 3, "fullscreen");
fs = luax_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 3, "display");
displayindex = luaL_optint(L, -1, 1) - 1;
lua_pop(L, 2);
}
else
{
fs = luax_toboolean(L, 3);
displayindex = luaL_optint(L, 4, 1) - 1;
}
luax_pushboolean(L, instance->checkWindowSize(w, h, fs));
luax_pushboolean(L, instance->checkWindowSize(w, h, fs, displayindex));
return 1;
}
@@ -63,12 +77,33 @@ int w_setMode(lua_State *L)
WindowFlags flags;
lua_getfield(L, 3, "fullscreentype");
if (!lua_isnoneornil(L, -1))
{
const char *typestr = luaL_checkstring(L, -1);
if (!Window::getConstant(typestr, flags.fstype))
return luaL_error(L, "Invalid fullscreen type: %s", typestr);
}
else
{
// Default to "normal" fullscreen.
flags.fstype = Window::FULLSCREEN_TYPE_NORMAL;
}
lua_pop(L, 1);
flags.fullscreen = luax_boolflag(L, 3, "fullscreen", false);
flags.vsync = luax_boolflag(L, 3, "vsync", true);
flags.fsaa = luax_intflag(L, 3, "fsaa", 0);
flags.resizable = luax_boolflag(L, 3, "resizable", false);
flags.minwidth = luax_intflag(L, 3, "minwidth", 100);
flags.minheight = luax_intflag(L, 3, "minheight", 100);
flags.borderless = luax_boolflag(L, 3, "borderless", false);
flags.centered = luax_boolflag(L, 3, "centered", true);
flags.display = luax_intflag(L, 3, "display", 1);
// Display index is 1-based in Lua and 0-based internally.
flags.display--;
try
{
@@ -92,38 +127,52 @@ int w_getMode(lua_State *L)
lua_newtable(L);
const char *fstypestr = "normal";
Window::getConstant(flags.fstype, fstypestr);
lua_pushstring(L, fstypestr);
lua_setfield(L, -2, "fullscreentype");
luax_pushboolean(L, flags.fullscreen);
lua_setfield(L, -2, "fullscreen");
luax_pushboolean(L, flags.vsync);
lua_setfield(L, -2, "vsync");
lua_pushnumber(L, flags.fsaa);
lua_pushinteger(L, flags.fsaa);
lua_setfield(L, -2, "fsaa");
luax_pushboolean(L, flags.resizable);
lua_setfield(L, -2, "resizable");
lua_pushinteger(L, flags.minwidth);
lua_setfield(L, -2, "minwidth");
lua_pushinteger(L, flags.minheight);
lua_setfield(L, -2, "minheight");
luax_pushboolean(L, flags.borderless);
lua_setfield(L, -2, "borderless");
luax_pushboolean(L, flags.centered);
lua_setfield(L, -2, "centered");
// Display index is 0-based internally and 1-based in Lua.
lua_pushinteger(L, flags.display + 1);
lua_setfield(L, -2, "display");
return 3;
}
int w_getModes(lua_State *L)
{
int n;
Window::WindowSize *modes = instance->getFullscreenSizes(n);
int displayindex = luaL_optint(L, 1, 1);
if (modes == 0)
return 0;
std::vector<Window::WindowSize> modes = instance->getFullscreenSizes(displayindex - 1);
lua_createtable(L, n, 0);
lua_createtable(L, modes.size(), 0);
for (int i = 0; i < n ; i++)
for (size_t i = 0; i < modes.size(); i++)
{
lua_pushinteger(L, i+1);
lua_createtable(L, 0, 2);
@@ -141,29 +190,43 @@ int w_getModes(lua_State *L)
lua_settable(L, -3);
}
delete[] modes;
return 1;
}
int w_toggleFullscreen(lua_State *L)
int w_setFullscreen(lua_State *L)
{
int width, height;
WindowFlags flags;
instance->getWindow(width, height, flags);
flags.fullscreen = !flags.fullscreen;
bool fullscreen = luax_toboolean(L, 1);
Window::FullscreenType fstype = Window::FULLSCREEN_TYPE_MAX_ENUM;
try
{
luax_pushboolean(L, instance->setWindow(width, height, &flags));
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
const char *typestr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(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)
success = instance->setFullscreen(fullscreen);
else
success = instance->setFullscreen(fullscreen, fstype);
luax_pushboolean(L, success);
return 1;
}
int w_isFullscreen(lua_State *L)
{
int w, h;
WindowFlags flags;
instance->getWindow(w, h, flags);
const char *typestr;
if (!Window::getConstant(flags.fstype, typestr))
luaL_error(L, "Unknown fullscreen type.");
luax_pushboolean(L, flags.fullscreen);
lua_pushstring(L, typestr);
return 2;
}
int w_isCreated(lua_State *L)
{
luax_pushboolean(L, instance->isCreated());
@@ -189,11 +252,21 @@ int w_getDimensions(lua_State *L)
return 2;
}
int w_getDesktopDimensions(lua_State *L)
{
int width = 0, height = 0;
int displayindex = luaL_optint(L, 1, 1) - 1;
instance->getDesktopDimensions(displayindex, width, height);
lua_pushinteger(L, width);
lua_pushinteger(L, height);
return 2;
}
int w_setIcon(lua_State *L)
{
image::ImageData *i = luax_checktype<image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
instance->setIcon(i);
return 0;
luax_pushboolean(L, instance->setIcon(i));
return 1;
}
int w_getIcon(lua_State *L)
@@ -242,15 +315,18 @@ int w_isVisible(lua_State *L)
static const luaL_Reg functions[] =
{
{ "getDisplayCount", w_getDisplayCount },
{ "checkMode", w_checkMode },
{ "setMode", w_setMode },
{ "getMode", w_getMode },
{ "getModes", w_getModes },
{ "toggleFullscreen", w_toggleFullscreen },
{ "setFullscreen", w_setFullscreen },
{ "isFullscreen", w_isFullscreen },
{ "isCreated", w_isCreated },
{ "getWidth", w_getWidth },
{ "getHeight", w_getHeight },
{ "getDimensions", w_getDimensions },
{ "getDesktopDimensions", w_getDesktopDimensions },
{ "setIcon", w_setIcon },
{ "getIcon", w_getIcon },
{ "setTitle", w_setTitle },
@@ -265,7 +341,7 @@ extern "C" int luaopen_love_window(lua_State *L)
{
try
{
instance = sdl::Window::getSingleton();
instance = sdl::Window::createSingleton();
}
catch (love::Exception &e)
{
+4 -1
View File
@@ -29,15 +29,18 @@ namespace love
namespace window
{
int w_getDisplayCount(lua_State *L);
int w_checkMode(lua_State *L);
int w_setMode(lua_State *L);
int w_getMode(lua_State *L);
int w_getModes(lua_State *L);
int w_toggleFullscreen(lua_State *L);
int w_setFullscreen(lua_State *L);
int w_isFullscreen(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_setIcon(lua_State *L);
int w_getIcon(lua_State *L);
int w_setTitle(lua_State *L);