mirror of
https://github.com/encounter/SDL.git
synced 2025-12-09 21:47:44 +00:00
WinRT: merged with SDL 2.0.0 codebase (aka. SDL hg rev d4ce48ff30d1)
This commit is contained in:
@@ -37,8 +37,10 @@
|
||||
#else /* fprintf, _exit(), etc. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if ! defined(__WINRT__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static SDL_assert_state
|
||||
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
#include "core/windows/SDL_windows.h"
|
||||
#elif defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
@@ -315,7 +315,7 @@ static void
|
||||
SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
||||
const char *message)
|
||||
{
|
||||
#if defined(__WIN32__)
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
/* Way too many allocations here, urgh */
|
||||
/* Note: One can't call SDL_SetError here, since that function itself logs. */
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "SDL_timer.h"
|
||||
|
||||
/* Don't do the check for Visual Studio 2005, it's safe here */
|
||||
#ifdef __WIN32__
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
#include "../core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
69
src/audio/xaudio2/SDL_xaudio2_winrthelpers.cpp
Normal file
69
src/audio/xaudio2/SDL_xaudio2_winrthelpers.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
#include <xaudio2.h>
|
||||
#include "SDL_xaudio2_winrthelpers.h"
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
using Windows::Devices::Enumeration::DeviceClass;
|
||||
using Windows::Devices::Enumeration::DeviceInformation;
|
||||
using Windows::Devices::Enumeration::DeviceInformationCollection;
|
||||
#endif
|
||||
|
||||
HRESULT IXAudio2_GetDeviceCount(IXAudio2 * ixa2, UINT32 * devcount)
|
||||
{
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// There doesn't seem to be any audio device enumeration on Windows Phone.
|
||||
// In lieu of this, just treat things as if there is one and only one
|
||||
// audio device.
|
||||
*devcount = 1;
|
||||
return S_OK;
|
||||
#else
|
||||
// TODO, WinRT: make xaudio2 device enumeration only happen once, and in the background
|
||||
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
|
||||
while (operation->Status != Windows::Foundation::AsyncStatus::Completed)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceInformationCollection^ devices = operation->GetResults();
|
||||
*devcount = devices->Size;
|
||||
return S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT IXAudio2_GetDeviceDetails(IXAudio2 * unused, UINT32 index, XAUDIO2_DEVICE_DETAILS * details)
|
||||
{
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// Windows Phone doesn't seem to have the same device enumeration APIs that
|
||||
// Windows 8/RT has, or it doesn't have them at all. In lieu of this,
|
||||
// just treat things as if there is one, and only one, default device.
|
||||
if (index != 0)
|
||||
{
|
||||
return XAUDIO2_E_INVALID_CALL;
|
||||
}
|
||||
|
||||
if (details)
|
||||
{
|
||||
wcsncpy_s(details->DeviceID, ARRAYSIZE(details->DeviceID), L"default", _TRUNCATE);
|
||||
wcsncpy_s(details->DisplayName, ARRAYSIZE(details->DisplayName), L"default", _TRUNCATE);
|
||||
}
|
||||
return S_OK;
|
||||
#else
|
||||
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
|
||||
while (operation->Status != Windows::Foundation::AsyncStatus::Completed)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceInformationCollection^ devices = operation->GetResults();
|
||||
if (index >= devices->Size)
|
||||
{
|
||||
return XAUDIO2_E_INVALID_CALL;
|
||||
}
|
||||
|
||||
DeviceInformation^ d = devices->GetAt(index);
|
||||
if (details)
|
||||
{
|
||||
wcsncpy_s(details->DeviceID, ARRAYSIZE(details->DeviceID), d->Id->Data(), _TRUNCATE);
|
||||
wcsncpy_s(details->DisplayName, ARRAYSIZE(details->DisplayName), d->Name->Data(), _TRUNCATE);
|
||||
}
|
||||
return S_OK;
|
||||
#endif
|
||||
}
|
||||
40
src/audio/xaudio2/SDL_xaudio2_winrthelpers.h
Normal file
40
src/audio/xaudio2/SDL_xaudio2_winrthelpers.h
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Re-implementation of methods removed from XAudio2 (in Windows RT):
|
||||
//
|
||||
|
||||
typedef struct XAUDIO2_DEVICE_DETAILS
|
||||
{
|
||||
WCHAR DeviceID[256];
|
||||
WCHAR DisplayName[256];
|
||||
/* Other fields exist in the pre-Windows 8 version of this struct, however
|
||||
they weren't used by SDL, so they weren't added.
|
||||
*/
|
||||
} XAUDIO2_DEVICE_DETAILS;
|
||||
|
||||
HRESULT IXAudio2_GetDeviceCount(IXAudio2 * unused, UINT32 * devcount);
|
||||
HRESULT IXAudio2_GetDeviceDetails(IXAudio2 * unused, UINT32 index, XAUDIO2_DEVICE_DETAILS * details);
|
||||
|
||||
|
||||
//
|
||||
// C-style macros to call XAudio2's methods in C++:
|
||||
//
|
||||
|
||||
#define IXAudio2_CreateMasteringVoice(A, B, C, D, E, F, G) (A)->CreateMasteringVoice((B), (C), (D), (E), (F), (G))
|
||||
#define IXAudio2_CreateSourceVoice(A, B, C, D, E, F, G, H) (A)->CreateSourceVoice((B), (C), (D), (E), (F), (G), (H))
|
||||
#define IXAudio2_QueryInterface(A, B, C) (A)->QueryInterface((B), (C))
|
||||
#define IXAudio2_Release(A) (A)->Release()
|
||||
#define IXAudio2_StartEngine(A) (A)->StartEngine()
|
||||
#define IXAudio2_StopEngine(A) (A)->StopEngine()
|
||||
|
||||
#define IXAudio2MasteringVoice_DestroyVoice(A) (A)->DestroyVoice()
|
||||
|
||||
#define IXAudio2SourceVoice_DestroyVoice(A) (A)->DestroyVoice()
|
||||
#define IXAudio2SourceVoice_Discontinuity(A) (A)->Discontinuity()
|
||||
#define IXAudio2SourceVoice_FlushSourceBuffers(A) (A)->FlushSourceBuffers()
|
||||
#define IXAudio2SourceVoice_GetState(A, B) (A)->GetState((B))
|
||||
#define IXAudio2SourceVoice_Start(A, B, C) (A)->Start((B), (C))
|
||||
#define IXAudio2SourceVoice_Stop(A, B, C) (A)->Stop((B), (C))
|
||||
#define IXAudio2SourceVoice_SubmitSourceBuffer(A, B, C) (A)->SubmitSourceBuffer((B), (C))
|
||||
@@ -20,21 +20,21 @@
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_windows.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include <objbase.h> /* for CoInitialize/CoUninitialize */
|
||||
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
|
||||
|
||||
/* Sets an error message based on GetLastError() */
|
||||
int
|
||||
WIN_SetError(const char *prefix)
|
||||
WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
|
||||
{
|
||||
TCHAR buffer[1024];
|
||||
char *message;
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0,
|
||||
buffer, SDL_arraysize(buffer), NULL);
|
||||
message = WIN_StringToUTF8(buffer);
|
||||
SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
|
||||
@@ -42,9 +42,24 @@ WIN_SetError(const char *prefix)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Sets an error message based on GetLastError() */
|
||||
int
|
||||
WIN_SetError(const char *prefix)
|
||||
{
|
||||
return WIN_SetErrorFromHRESULT(prefix, GetLastError());
|
||||
}
|
||||
|
||||
HRESULT
|
||||
WIN_CoInitialize(void)
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
/* DLudwig: On WinRT, it is assumed that COM was initialized in main().
|
||||
CoInitializeEx is available (not CoInitialize though), however
|
||||
on WinRT, main() is typically declared with the [MTAThread]
|
||||
attribute, which, AFAIK, should initialize COM.
|
||||
*/
|
||||
return S_OK;
|
||||
#else
|
||||
const HRESULT hr = CoInitialize(NULL);
|
||||
|
||||
/* S_FALSE means success, but someone else already initialized. */
|
||||
@@ -54,12 +69,15 @@ WIN_CoInitialize(void)
|
||||
}
|
||||
|
||||
return hr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WIN_CoUninitialize(void)
|
||||
{
|
||||
#ifndef __WINRT__
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef _INCLUDED_WINDOWS_H
|
||||
#define _INCLUDED_WINDOWS_H
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define STRICT
|
||||
#ifndef UNICODE
|
||||
@@ -31,6 +32,7 @@
|
||||
#endif
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x501 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input */
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -43,6 +45,9 @@
|
||||
#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1)
|
||||
#endif
|
||||
|
||||
/* Sets an error message based on a given HRESULT */
|
||||
extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);
|
||||
|
||||
/* Sets an error message based on GetLastError(). Always return -1. */
|
||||
extern int WIN_SetError(const char *prefix);
|
||||
|
||||
|
||||
94
src/core/windowsrt/SDL_winrtpaths.cpp
Normal file
94
src/core/windowsrt/SDL_winrtpaths.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/* TODO, WinRT: include copyright info in SDL_winrtpaths.cpp
|
||||
TODO, WinRT: add note to SDL_winrtpaths.cpp mentioning that /ZW must be used when compiling the file
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef __WINRT__
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_system.h"
|
||||
#include "../windows/SDL_windows.h"
|
||||
}
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
using namespace Windows::Storage;
|
||||
|
||||
extern "C" const wchar_t *
|
||||
SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType)
|
||||
{
|
||||
switch (pathType) {
|
||||
case SDL_WINRT_PATH_INSTALLED_LOCATION:
|
||||
{
|
||||
static wstring path;
|
||||
if (path.empty()) {
|
||||
path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();
|
||||
}
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
case SDL_WINRT_PATH_LOCAL_FOLDER:
|
||||
{
|
||||
static wstring path;
|
||||
if (path.empty()) {
|
||||
path = ApplicationData::Current->LocalFolder->Path->Data();
|
||||
}
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
case SDL_WINRT_PATH_ROAMING_FOLDER:
|
||||
{
|
||||
static wstring path;
|
||||
if (path.empty()) {
|
||||
path = ApplicationData::Current->RoamingFolder->Path->Data();
|
||||
}
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
case SDL_WINRT_PATH_TEMP_FOLDER:
|
||||
{
|
||||
static wstring path;
|
||||
if (path.empty()) {
|
||||
path = ApplicationData::Current->TemporaryFolder->Path->Data();
|
||||
}
|
||||
return path.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" const char *
|
||||
SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType)
|
||||
{
|
||||
typedef unordered_map<SDL_WinRT_Path, string> UTF8PathMap;
|
||||
static UTF8PathMap utf8Paths;
|
||||
|
||||
UTF8PathMap::iterator searchResult = utf8Paths.find(pathType);
|
||||
if (searchResult != utf8Paths.end()) {
|
||||
return searchResult->second.c_str();
|
||||
}
|
||||
|
||||
const wchar_t * ucs2Path = SDL_WinRTGetFSPathUNICODE(pathType);
|
||||
if (!ucs2Path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * utf8Path = WIN_StringToUTF8(ucs2Path);
|
||||
utf8Paths[pathType] = utf8Path;
|
||||
SDL_free(utf8Path);
|
||||
return utf8Paths[pathType].c_str();
|
||||
}
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
1521
src/file/SDL_rwops.c
1521
src/file/SDL_rwops.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -108,7 +108,7 @@ extern SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index);
|
||||
/* Function to return the stable GUID for a opened joystick */
|
||||
extern SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick);
|
||||
|
||||
#ifdef SDL_JOYSTICK_DINPUT
|
||||
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
||||
/* Function to get the current instance id of the joystick located at device_index */
|
||||
extern SDL_bool SDL_SYS_IsXInputDeviceIndex( int device_index );
|
||||
#endif
|
||||
|
||||
435
src/joystick/windowsrt/SDL_xinputjoystick.c
Normal file
435
src/joystick/windowsrt/SDL_xinputjoystick.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
|
||||
/* SDL_xinputjoystick.c implements an XInput-only joystick and game controller
|
||||
backend that is suitable for use on WinRT. SDL's DirectInput backend, also
|
||||
XInput-capable, was not used as DirectInput is not available on WinRT (or,
|
||||
at least, it isn't a public API). Some portions of this XInput backend
|
||||
may copy parts of the XInput-using code from the DirectInput backend.
|
||||
Refactoring the common parts into one location may be good to-do at some
|
||||
point.
|
||||
|
||||
TODO, WinRT: add hotplug support for XInput based game controllers
|
||||
*/
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "SDL_events.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Xinput.h>
|
||||
|
||||
struct joystick_hwdata {
|
||||
//Uint8 bXInputHaptic; // Supports force feedback via XInput.
|
||||
DWORD userIndex; // The XInput device index, in the range [0, XUSER_MAX_COUNT-1] (probably [0,3]).
|
||||
XINPUT_STATE XInputState; // the last-read in XInputState, kept around to compare old and new values
|
||||
SDL_bool isDeviceConnected; // was the device connected (on the last polling, or during backend-initialization)?
|
||||
SDL_bool isDeviceRemovalEventPending; // was the device removed, and is the associated removal event pending?
|
||||
};
|
||||
|
||||
/* Keep track of data on all XInput devices, regardless of whether or not
|
||||
they've been opened (via SDL_JoystickOpen).
|
||||
*/
|
||||
static struct joystick_hwdata g_XInputData[XUSER_MAX_COUNT];
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
XINPUT_STATE tempXInputState;
|
||||
int i;
|
||||
|
||||
SDL_zero(g_XInputData);
|
||||
|
||||
/* Make initial notes on whether or not devices are connected (or not).
|
||||
*/
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
result = XInputGetState(i, &tempXInputState);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
g_XInputData[i].isDeviceConnected = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
int joystickCount = 0;
|
||||
DWORD i;
|
||||
|
||||
/* Iterate through each possible XInput device and see if something
|
||||
was connected (at joystick init, or during the last polling).
|
||||
*/
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
if (g_XInputData[i].isDeviceConnected) {
|
||||
++joystickCount;
|
||||
}
|
||||
}
|
||||
|
||||
return joystickCount;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
DWORD i;
|
||||
XINPUT_STATE tempXInputState;
|
||||
HRESULT result;
|
||||
SDL_Event event;
|
||||
|
||||
/* Iterate through each possible XInput device, seeing if any devices
|
||||
have been connected, or if they were removed.
|
||||
*/
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
/* See if any new devices are connected. */
|
||||
if (!g_XInputData[i].isDeviceConnected && !g_XInputData[i].isDeviceRemovalEventPending) {
|
||||
result = XInputGetState(i, &tempXInputState);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
/* Yup, a device is connected. Mark the device as connected,
|
||||
then tell others about it (via an SDL_JOYDEVICEADDED event.)
|
||||
*/
|
||||
g_XInputData[i].isDeviceConnected = SDL_TRUE;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = i;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (g_XInputData[i].isDeviceRemovalEventPending) {
|
||||
/* A device was previously marked as removed (by
|
||||
SDL_SYS_JoystickUpdate). Tell others about the device removal.
|
||||
*/
|
||||
|
||||
g_XInputData[i].isDeviceRemovalEventPending = SDL_FALSE;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = i; //joystick->hwdata->userIndex;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
/* Since XInput, or WinRT, provides any events to indicate when a game
|
||||
controller gets connected, and instead indicates device availability
|
||||
solely through polling, we'll poll (for new devices).
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Internal function to retreive device capabilities.
|
||||
This function will return an SDL-standard value of 0 on success
|
||||
(a device is connected, and data on it was retrieved), or -1
|
||||
on failure (no device was connected, or some other error
|
||||
occurred. SDL_SetError() will be invoked to set an appropriate
|
||||
error message.
|
||||
*/
|
||||
static int
|
||||
SDL_XInput_GetDeviceCapabilities(int device_index, XINPUT_CAPABILITIES * pDeviceCaps)
|
||||
{
|
||||
HRESULT dwResult;
|
||||
|
||||
/* Make sure that the device index is a valid one. If not, return to the
|
||||
caller with an error.
|
||||
*/
|
||||
if (device_index < 0 || device_index >= XUSER_MAX_COUNT) {
|
||||
return SDL_SetError("invalid/unavailable device index");
|
||||
}
|
||||
|
||||
/* See if a device exists, and if so, what its capabilities are. If a
|
||||
device is not available, return to the caller with an error.
|
||||
*/
|
||||
switch ((dwResult = XInputGetCapabilities(device_index, 0, pDeviceCaps))) {
|
||||
case ERROR_SUCCESS:
|
||||
/* A device is available, and its capabilities were retrieved! */
|
||||
return 0;
|
||||
case ERROR_DEVICE_NOT_CONNECTED:
|
||||
return SDL_SetError("no device is connected at joystick index, %d", device_index);
|
||||
default:
|
||||
return SDL_SetError("an unknown error occurred when retrieving info on a device at joystick index, %d", device_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
XINPUT_CAPABILITIES deviceCaps;
|
||||
|
||||
if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
|
||||
/* Uh oh. Device capabilities couldn't be retrieved. Return to the
|
||||
caller. SDL_SetError() has already been invoked (with relevant
|
||||
information).
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (deviceCaps.SubType) {
|
||||
default:
|
||||
if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return "Undefined game controller";
|
||||
} else {
|
||||
return "Undefined controller";
|
||||
}
|
||||
case XINPUT_DEVSUBTYPE_UNKNOWN:
|
||||
if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return "Unknown game controller";
|
||||
} else {
|
||||
return "Unknown controller";
|
||||
}
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||
return "Gamepad controller";
|
||||
case XINPUT_DEVSUBTYPE_WHEEL:
|
||||
return "Racing wheel controller";
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
||||
return "Arcade stick controller";
|
||||
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
||||
return "Flight stick controller";
|
||||
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
||||
return "Dance pad controller";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR:
|
||||
return "Guitar controller";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
|
||||
return "Guitar controller, Alternate";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_BASS:
|
||||
return "Guitar controller, Bass";
|
||||
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
||||
return "Drum controller";
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_PAD:
|
||||
return "Arcade pad controller";
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
XINPUT_CAPABILITIES deviceCaps;
|
||||
|
||||
if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
|
||||
/* Uh oh. Device capabilities couldn't be retrieved. Return to the
|
||||
caller. SDL_SetError() has already been invoked (with relevant
|
||||
information).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* For now, only game pads are supported. If the device is something other
|
||||
than that, return an error to the caller.
|
||||
*/
|
||||
if (deviceCaps.Type != XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return SDL_SetError("a device is connected (at joystick index, %d), but it is of an unknown device type (deviceCaps.Flags=%ul)",
|
||||
device_index, (unsigned int)deviceCaps.Flags);
|
||||
}
|
||||
|
||||
/* Create the joystick data structure */
|
||||
joystick->instance_id = device_index;
|
||||
joystick->hwdata = &g_XInputData[device_index];
|
||||
|
||||
// The XInput API has a hard coded button/axis mapping, so we just match it
|
||||
joystick->naxes = 6;
|
||||
joystick->nbuttons = 15;
|
||||
joystick->nballs = 0;
|
||||
joystick->nhats = 0;
|
||||
|
||||
/* We're done! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return joystick->hwdata->isDeviceConnected;
|
||||
}
|
||||
|
||||
/* Function to return > 0 if a bit array of buttons differs after applying a mask
|
||||
*/
|
||||
static int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
|
||||
{
|
||||
return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
/* Before polling for new data, make note of the old data */
|
||||
XINPUT_STATE prevXInputState = joystick->hwdata->XInputState;
|
||||
|
||||
/* Poll for new data */
|
||||
result = XInputGetState(joystick->hwdata->userIndex, &joystick->hwdata->XInputState);
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED) {
|
||||
if (joystick->hwdata->isDeviceConnected) {
|
||||
joystick->hwdata->isDeviceConnected = SDL_FALSE;
|
||||
joystick->hwdata->isDeviceRemovalEventPending = SDL_TRUE;
|
||||
/* TODO, WinRT: make sure isDeviceRemovalEventPending gets cleared as appropriate, and that quick re-plugs don't cause trouble */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure the device is marked as connected */
|
||||
joystick->hwdata->isDeviceConnected = SDL_TRUE;
|
||||
|
||||
// only fire events if the data changed from last time
|
||||
if ( joystick->hwdata->XInputState.dwPacketNumber != 0
|
||||
&& joystick->hwdata->XInputState.dwPacketNumber != prevXInputState.dwPacketNumber )
|
||||
{
|
||||
XINPUT_STATE *pXInputState = &joystick->hwdata->XInputState;
|
||||
XINPUT_STATE *pXInputStatePrev = &prevXInputState;
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-1*pXInputState->Gamepad.sThumbLY-1) );
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-1*pXInputState->Gamepad.sThumbRY-1) );
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)((int)pXInputState->Gamepad.bLeftTrigger*32767/255) );
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)((int)pXInputState->Gamepad.bRightTrigger*32767/255) );
|
||||
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
|
||||
SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
|
||||
SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
|
||||
SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
|
||||
SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
|
||||
SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
|
||||
SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
|
||||
SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
|
||||
SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
|
||||
SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
|
||||
SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
|
||||
SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
|
||||
SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
|
||||
SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
|
||||
SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, 0x400 ) )
|
||||
SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED : SDL_RELEASED ); // 0x400 is the undocumented code for the guide button
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
/* Clear cached button data on the joystick */
|
||||
SDL_zero(joystick->hwdata->XInputState);
|
||||
|
||||
/* There's need to free 'hwdata', as it's a pointer to a global array.
|
||||
The field will be cleared anyways, just to indicate that it's not
|
||||
currently needed.
|
||||
*/
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
// the GUID is just the first 16 chars of the name for now
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
// the GUID is just the first 16 chars of the name for now
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_IsXInputDeviceIndex(int device_index)
|
||||
{
|
||||
/* The XInput-capable DirectInput joystick backend implements the same
|
||||
function (SDL_SYS_IsXInputDeviceIndex), however in that case, not all
|
||||
joystick devices are XInput devices. In this case, with the
|
||||
WinRT-enabled XInput-only backend, all "joystick" devices are XInput
|
||||
devices.
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -33,7 +33,15 @@ void *
|
||||
SDL_LoadObject(const char *sofile)
|
||||
{
|
||||
LPTSTR tstr = WIN_UTF8ToString(sofile);
|
||||
#ifdef __WINRT__
|
||||
/* WinRT only publically supports LoadPackagedLibrary() for loading .dll
|
||||
files. LoadLibrary() is a private API, and not available for apps
|
||||
(that can be published to MS' Windows Store.)
|
||||
*/
|
||||
void *handle = (void *) LoadPackagedLibrary(tstr, 0);
|
||||
#else
|
||||
void *handle = (void *) LoadLibrary(tstr);
|
||||
#endif
|
||||
SDL_free(tstr);
|
||||
|
||||
/* Generate an error message if all loads failed */
|
||||
|
||||
14
src/main/windowsrt/SDL_winrt_main.cpp
Normal file
14
src/main/windowsrt/SDL_winrt_main.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
//#include "pch.h"
|
||||
|
||||
// The app's C-style main will be passed into SDL.dll as a function
|
||||
// pointer, and called at the appropriate time.
|
||||
typedef int (*SDLmain_MainFunction)(int, char **);
|
||||
extern __declspec(dllimport) int SDL_WinRT_RunApplication(SDLmain_MainFunction mainFunction);
|
||||
extern "C" int SDL_main(int, char **);
|
||||
|
||||
[Platform::MTAThread]
|
||||
int main(Platform::Array<Platform::String^>^)
|
||||
{
|
||||
return SDL_WinRT_RunApplication(SDL_main);
|
||||
}
|
||||
@@ -166,6 +166,9 @@ struct SDL_RenderDriver
|
||||
#if SDL_VIDEO_RENDER_D3D
|
||||
extern SDL_RenderDriver D3D_RenderDriver;
|
||||
#endif
|
||||
#if SDL_VIDEO_RENDER_D3D11
|
||||
extern SDL_RenderDriver D3D11_RenderDriver;
|
||||
#endif
|
||||
#if SDL_VIDEO_RENDER_OGL
|
||||
extern SDL_RenderDriver GL_RenderDriver;
|
||||
#endif
|
||||
|
||||
12
src/render/direct3d11/SDL_D3D11_PixelShader_FixedColor.hlsl
Normal file
12
src/render/direct3d11/SDL_D3D11_PixelShader_FixedColor.hlsl
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
struct PixelShaderInput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 tex : TEXCOORD0;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
|
||||
float4 main(PixelShaderInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
Texture2D theTexture : register(t0);
|
||||
SamplerState theSampler : register(s0);
|
||||
|
||||
struct PixelShaderInput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 tex : TEXCOORD0;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
|
||||
float4 main(PixelShaderInput input) : SV_TARGET
|
||||
{
|
||||
return theTexture.Sample(theSampler, input.tex) * input.color;
|
||||
}
|
||||
41
src/render/direct3d11/SDL_D3D11_VertexShader_Default.hlsl
Normal file
41
src/render/direct3d11/SDL_D3D11_VertexShader_Default.hlsl
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
#pragma pack_matrix( row_major )
|
||||
|
||||
cbuffer SDL_VertexShaderConstants : register(b0)
|
||||
{
|
||||
matrix model;
|
||||
matrix view;
|
||||
matrix projection;
|
||||
};
|
||||
|
||||
struct VertexShaderInput
|
||||
{
|
||||
float3 pos : POSITION;
|
||||
float2 tex : TEXCOORD0;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
|
||||
struct VertexShaderOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 tex : TEXCOORD0;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
|
||||
VertexShaderOutput main(VertexShaderInput input)
|
||||
{
|
||||
VertexShaderOutput output;
|
||||
float4 pos = float4(input.pos, 1.0f);
|
||||
|
||||
// Transform the vertex position into projected space.
|
||||
pos = mul(pos, model);
|
||||
pos = mul(pos, view);
|
||||
pos = mul(pos, projection);
|
||||
output.pos = pos;
|
||||
|
||||
// Pass through texture coordinates and color values without transformation
|
||||
output.tex = input.tex;
|
||||
output.color = input.color;
|
||||
|
||||
return output;
|
||||
}
|
||||
1807
src/render/direct3d11/SDL_render_d3d11.cpp
Normal file
1807
src/render/direct3d11/SDL_render_d3d11.cpp
Normal file
File diff suppressed because it is too large
Load Diff
84
src/render/direct3d11/SDL_render_d3d11_cpp.h
Normal file
84
src/render/direct3d11/SDL_render_d3d11_cpp.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <D3D11_1.h>
|
||||
#include <DirectXMath.h>
|
||||
#include <wrl/client.h>
|
||||
#include <vector>
|
||||
|
||||
struct SDL_VertexShaderConstants
|
||||
{
|
||||
DirectX::XMFLOAT4X4 model;
|
||||
DirectX::XMFLOAT4X4 view;
|
||||
DirectX::XMFLOAT4X4 projection;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> d3dContext;
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
|
||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainRenderTargetView;
|
||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> currentOffscreenRenderTargetView;
|
||||
Microsoft::WRL::ComPtr<ID3D11InputLayout> inputLayout;
|
||||
Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
|
||||
Microsoft::WRL::ComPtr<ID3D11VertexShader> vertexShader;
|
||||
Microsoft::WRL::ComPtr<ID3D11PixelShader> texturePixelShader;
|
||||
Microsoft::WRL::ComPtr<ID3D11PixelShader> colorPixelShader;
|
||||
Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeBlend;
|
||||
Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeAdd;
|
||||
Microsoft::WRL::ComPtr<ID3D11BlendState> blendModeMod;
|
||||
Microsoft::WRL::ComPtr<ID3D11SamplerState> mainSampler;
|
||||
Microsoft::WRL::ComPtr<ID3D11RasterizerState> mainRasterizer;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
|
||||
// Vertex buffer constants:
|
||||
SDL_VertexShaderConstants vertexShaderConstantsData;
|
||||
Microsoft::WRL::ComPtr<ID3D11Buffer> vertexShaderConstants;
|
||||
|
||||
// Cached renderer properties.
|
||||
DirectX::XMFLOAT2 windowSizeInDIPs;
|
||||
DirectX::XMFLOAT2 renderTargetSize;
|
||||
Windows::Graphics::Display::DisplayOrientations orientation;
|
||||
|
||||
// Transform used for display orientation.
|
||||
DirectX::XMFLOAT4X4 orientationTransform3D;
|
||||
} D3D11_RenderData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> mainTexture;
|
||||
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> mainTextureResourceView;
|
||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainTextureRenderTargetView;
|
||||
SDL_PixelFormat * pixelFormat;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
|
||||
DirectX::XMINT2 lockedTexturePosition;
|
||||
} D3D11_TextureData;
|
||||
|
||||
struct VertexPositionColor
|
||||
{
|
||||
DirectX::XMFLOAT3 pos;
|
||||
DirectX::XMFLOAT2 tex;
|
||||
DirectX::XMFLOAT4 color;
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "windows/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_PSP
|
||||
#include "psp/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_STDCPP
|
||||
#include "stdcpp/SDL_systhread_c.h"
|
||||
#else
|
||||
#error Need thread implementation for this platform
|
||||
#include "generic/SDL_systhread_c.h"
|
||||
|
||||
183
src/thread/stdcpp/SDL_syscond.cpp
Normal file
183
src/thread/stdcpp/SDL_syscond.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_thread.h"
|
||||
}
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <ratio>
|
||||
|
||||
#include "SDL_sysmutex_c.h"
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
std::condition_variable_any cpp_cond;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
extern "C"
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
/* Allocate and initialize the condition variable */
|
||||
try {
|
||||
SDL_cond * cond = new SDL_cond;
|
||||
return cond;
|
||||
} catch (std::exception & ex) {
|
||||
SDL_SetError("unable to create C++ condition variable: %s", ex.what());
|
||||
return NULL;
|
||||
} catch (...) {
|
||||
SDL_SetError("unable to create C++ condition variable due to an unknown exception");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Destroy a condition variable */
|
||||
extern "C"
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if (cond) {
|
||||
try {
|
||||
delete cond;
|
||||
} catch (...) {
|
||||
// catch any and all exceptions, just in case something happens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart one of the threads that are waiting on the condition variable */
|
||||
extern "C"
|
||||
int
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
cond->cpp_cond.notify_one();
|
||||
return 0;
|
||||
} catch (...) {
|
||||
// catch any and all exceptions, just in case something happens
|
||||
SDL_SetError("unable to signal C++ condition variable due to an unknown exception");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
extern "C"
|
||||
int
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
cond->cpp_cond.notify_all();
|
||||
return 0;
|
||||
} catch (...) {
|
||||
// catch any and all exceptions, just in case something happens
|
||||
SDL_SetError("unable to broadcast C++ condition variable due to an unknown exception");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
The mutex must be locked before entering this function!
|
||||
The mutex is unlocked during the wait, and locked again after the wait.
|
||||
|
||||
Typical use:
|
||||
|
||||
Thread A:
|
||||
SDL_LockMutex(lock);
|
||||
while ( ! condition ) {
|
||||
SDL_CondWait(cond, lock);
|
||||
}
|
||||
SDL_UnlockMutex(lock);
|
||||
|
||||
Thread B:
|
||||
SDL_LockMutex(lock);
|
||||
...
|
||||
condition = true;
|
||||
...
|
||||
SDL_CondSignal(cond);
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
extern "C"
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mutex) {
|
||||
SDL_SetError("Passed a NULL mutex variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::defer_lock_t());
|
||||
if (ms == SDL_MUTEX_MAXWAIT) {
|
||||
cond->cpp_cond.wait(
|
||||
cpp_lock
|
||||
);
|
||||
cpp_lock.release();
|
||||
return 0;
|
||||
} else {
|
||||
auto wait_result = cond->cpp_cond.wait_for(
|
||||
cpp_lock,
|
||||
std::chrono::duration<Uint32, std::milli>(ms)
|
||||
);
|
||||
cpp_lock.release();
|
||||
if (wait_result == std::cv_status::timeout) {
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} catch (std::exception & ex) {
|
||||
SDL_SetError("unable to wait on C++ condition variable: %s", ex.what());
|
||||
return -1;
|
||||
} catch (...) {
|
||||
SDL_SetError("unable to lock wait on C++ condition variable due to an unknown exception");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
extern "C"
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
113
src/thread/stdcpp/SDL_sysmutex.cpp
Normal file
113
src/thread/stdcpp/SDL_sysmutex.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
#include "SDL_log.h"
|
||||
}
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include "SDL_sysmutex_c.h"
|
||||
#include <Windows.h>
|
||||
|
||||
|
||||
/* Create a mutex */
|
||||
extern "C"
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
/* Allocate and initialize the mutex */
|
||||
try {
|
||||
SDL_mutex * mutex = new SDL_mutex;
|
||||
return mutex;
|
||||
} catch (std::exception & ex) {
|
||||
SDL_SetError("unable to create C++ mutex: %s", ex.what());
|
||||
return NULL;
|
||||
} catch (...) {
|
||||
SDL_SetError("unable to create C++ mutex due to an unknown exception");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
extern "C"
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex) {
|
||||
try {
|
||||
delete mutex;
|
||||
} catch (...) {
|
||||
// catch any and all exceptions, just in case something happens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the semaphore */
|
||||
extern "C"
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
SDL_threadID threadID = SDL_ThreadID();
|
||||
DWORD realThreadID = GetCurrentThreadId();
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
mutex->cpp_mutex.lock();
|
||||
return 0;
|
||||
} catch (std::exception & ex) {
|
||||
SDL_SetError("unable to lock C++ mutex: %s", ex.what());
|
||||
return -1;
|
||||
} catch (...) {
|
||||
SDL_SetError("unable to lock C++ mutex due to an unknown exception");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
extern "C"
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
SDL_threadID threadID = SDL_ThreadID();
|
||||
DWORD realThreadID = GetCurrentThreadId();
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
mutex->cpp_mutex.unlock();
|
||||
return 0;
|
||||
} catch (...) {
|
||||
// catch any and all exceptions, just in case something happens.
|
||||
SDL_SetError("unable to unlock C++ mutex due to an unknown exception");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
30
src/thread/stdcpp/SDL_sysmutex_c.h
Normal file
30
src/thread/stdcpp/SDL_sysmutex_c.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
std::recursive_mutex cpp_mutex;
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
124
src/thread/stdcpp/SDL_systhread.cpp
Normal file
124
src/thread/stdcpp/SDL_systhread.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Thread management routines for SDL */
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_systhread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "SDL_log.h"
|
||||
}
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
// HACK: Mimic C++11's thread_local keyword on Visual C++ 2012 (aka. VC++ 11)
|
||||
// TODO: make sure this hack doesn't get used if and when Visual C++ supports
|
||||
// the official, 'thread_local' keyword.
|
||||
#ifdef _MSC_VER
|
||||
#define thread_local __declspec(thread)
|
||||
// Documentation for __declspec(thread) can be found online at:
|
||||
// http://msdn.microsoft.com/en-us/library/2s9wt68x.aspx
|
||||
#endif
|
||||
|
||||
static void
|
||||
RunThread(void *args)
|
||||
{
|
||||
SDL_RunThread(args);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
try {
|
||||
std::thread cpp_thread(RunThread, args);
|
||||
thread->handle = (void *) new std::thread(std::move(cpp_thread));
|
||||
return 0;
|
||||
} catch (std::exception & ex) {
|
||||
SDL_SetError("unable to create a C++ thread: %s", ex.what());
|
||||
return -1;
|
||||
} catch (...) {
|
||||
SDL_SetError("unable to create a C++ thread due to an unknown exception");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void
|
||||
SDL_SYS_SetupThread(const char *name)
|
||||
{
|
||||
// Make sure a thread ID gets assigned ASAP, for debugging purposes:
|
||||
SDL_ThreadID();
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
static thread_local SDL_threadID current_thread_id = 0;
|
||||
static SDL_threadID next_thread_id = 1;
|
||||
static std::mutex next_thread_id_mutex;
|
||||
|
||||
if (current_thread_id == 0) {
|
||||
std::lock_guard<std::mutex> lock(next_thread_id_mutex);
|
||||
current_thread_id = next_thread_id;
|
||||
++next_thread_id;
|
||||
}
|
||||
|
||||
return current_thread_id;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
// Thread priorities do not look to be settable via C++11's thread
|
||||
// interface, at least as of this writing (Nov 2012). std::thread does
|
||||
// provide access to the OS' native handle, however, and some form of
|
||||
// priority-setting could, in theory, be done through this interface.
|
||||
return (0);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
if ( ! thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
std::thread * cpp_thread = (std::thread *) thread->handle;
|
||||
if (cpp_thread->joinable()) {
|
||||
cpp_thread->join();
|
||||
}
|
||||
} catch (...) {
|
||||
// Catch any exceptions, just in case.
|
||||
// Report nothing, as SDL_WaitThread does not seem to offer a means
|
||||
// to report errors to its callers.
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
26
src/thread/stdcpp/SDL_systhread_c.h
Normal file
26
src/thread/stdcpp/SDL_systhread_c.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* For a thread handle, use a void pointer to a std::thread */
|
||||
typedef void * SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -343,6 +343,9 @@ extern VideoBootStrap DirectFB_bootstrap;
|
||||
#if SDL_VIDEO_DRIVER_WINDOWS
|
||||
extern VideoBootStrap WINDOWS_bootstrap;
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WINRT
|
||||
extern VideoBootStrap WINRT_bootstrap;
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_BWINDOW
|
||||
extern VideoBootStrap BWINDOW_bootstrap;
|
||||
#endif
|
||||
|
||||
@@ -64,6 +64,9 @@ static VideoBootStrap *bootstrap[] = {
|
||||
#if SDL_VIDEO_DRIVER_WINDOWS
|
||||
&WINDOWS_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WINRT
|
||||
&WINRT_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_BWINDOW
|
||||
&BWINDOW_bootstrap,
|
||||
#endif
|
||||
|
||||
@@ -202,7 +202,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
||||
if (external) {
|
||||
[uiwindow setScreen:data->uiscreen];
|
||||
}
|
||||
|
||||
|
||||
if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
||||
[uiwindow release];
|
||||
return -1;
|
||||
@@ -301,10 +301,12 @@ SDL_bool
|
||||
UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||
{
|
||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
||||
UIViewController *uiviewcontroller = ((SDL_WindowData *) window->driverdata)->viewcontroller;
|
||||
|
||||
if (info->version.major <= SDL_MAJOR_VERSION) {
|
||||
info->subsystem = SDL_SYSWM_UIKIT;
|
||||
info->info.uikit.window = uiwindow;
|
||||
info->info.uikit.viewcontroller = uiviewcontroller;
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
||||
|
||||
978
src/video/windowsrt/SDL_WinRTApp.cpp
Normal file
978
src/video/windowsrt/SDL_WinRTApp.cpp
Normal file
@@ -0,0 +1,978 @@
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
|
||||
#include "ppltasks.h"
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_render.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../SDL_hints_c.h"
|
||||
#include "../../events/scancodes_windows.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "../../render/SDL_sysrender.h"
|
||||
}
|
||||
|
||||
#include "SDL_winrtvideo.h"
|
||||
#include "SDL_WinRTApp.h"
|
||||
|
||||
using namespace concurrency;
|
||||
using namespace std;
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::ApplicationModel::Activation;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Input;
|
||||
|
||||
// Compile-time debugging options:
|
||||
// To enable, uncomment; to disable, comment them out.
|
||||
//#define LOG_POINTER_EVENTS 1
|
||||
//#define LOG_WINDOW_EVENTS 1
|
||||
//#define LOG_ORIENTATION_EVENTS 1
|
||||
|
||||
|
||||
// HACK, DLudwig: The C-style main() will get loaded via the app's
|
||||
// WinRT-styled main(), which is part of SDLmain_for_WinRT.cpp.
|
||||
// This seems wrong on some level, but does seem to work.
|
||||
typedef int (*SDL_WinRT_MainFunction)(int, char **);
|
||||
static SDL_WinRT_MainFunction SDL_WinRT_main = nullptr;
|
||||
|
||||
// HACK, DLudwig: record a reference to the global, Windows RT 'app'/view.
|
||||
// SDL/WinRT will use this throughout its code.
|
||||
//
|
||||
// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something
|
||||
// non-global, such as something created inside
|
||||
// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside
|
||||
// SDL_CreateWindow().
|
||||
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
|
||||
|
||||
ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
|
||||
{
|
||||
public:
|
||||
virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
|
||||
};
|
||||
|
||||
IFrameworkView^ SDLApplicationSource::CreateView()
|
||||
{
|
||||
// TODO, WinRT: see if this function (CreateView) can ever get called
|
||||
// more than once. For now, just prevent it from ever assigning
|
||||
// SDL_WinRTGlobalApp more than once.
|
||||
SDL_assert(!SDL_WinRTGlobalApp);
|
||||
SDL_WinRTApp ^ app = ref new SDL_WinRTApp();
|
||||
if (!SDL_WinRTGlobalApp)
|
||||
{
|
||||
SDL_WinRTGlobalApp = app;
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
__declspec(dllexport) int SDL_WinRT_RunApplication(SDL_WinRT_MainFunction mainFunction)
|
||||
{
|
||||
SDL_WinRT_main = mainFunction;
|
||||
auto direct3DApplicationSource = ref new SDLApplicationSource();
|
||||
CoreApplication::Run(direct3DApplicationSource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WINRT_SetDisplayOrientationsPreference(const char *name, const char *oldValue, const char *newValue)
|
||||
{
|
||||
SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
|
||||
|
||||
// Start with no orientation flags, then add each in as they're parsed
|
||||
// from newValue.
|
||||
unsigned int orientationFlags = 0;
|
||||
std::istringstream tokenizer(newValue);
|
||||
while (!tokenizer.eof()) {
|
||||
std::string orientationName;
|
||||
std::getline(tokenizer, orientationName, ' ');
|
||||
if (orientationName == "LandscapeLeft") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::LandscapeFlipped;
|
||||
} else if (orientationName == "LandscapeRight") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::Landscape;
|
||||
} else if (orientationName == "Portrait") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::Portrait;
|
||||
} else if (orientationName == "PortraitUpsideDown") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::PortraitFlipped;
|
||||
}
|
||||
}
|
||||
|
||||
// If no valid orientation flags were specified, use a reasonable set of defaults:
|
||||
if (!orientationFlags) {
|
||||
// TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
|
||||
orientationFlags = (unsigned int) ( \
|
||||
DisplayOrientations::Landscape |
|
||||
DisplayOrientations::LandscapeFlipped |
|
||||
DisplayOrientations::Portrait |
|
||||
DisplayOrientations::PortraitFlipped);
|
||||
}
|
||||
|
||||
// Set the orientation/rotation preferences. Please note that this does
|
||||
// not constitute a 100%-certain lock of a given set of possible
|
||||
// orientations. According to Microsoft's documentation on Windows RT [1]
|
||||
// when a device is not capable of being rotated, Windows may ignore
|
||||
// the orientation preferences, and stick to what the device is capable of
|
||||
// displaying.
|
||||
//
|
||||
// [1] Documentation on the 'InitialRotationPreference' setting for a
|
||||
// Windows app's manifest file describes how some orientation/rotation
|
||||
// preferences may be ignored. See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
|
||||
// for details. Microsoft's "Display orientation sample" also gives an
|
||||
// outline of how Windows treats device rotation
|
||||
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
|
||||
DisplayProperties::AutoRotationPreferences = (DisplayOrientations) orientationFlags;
|
||||
}
|
||||
|
||||
SDL_WinRTApp::SDL_WinRTApp() :
|
||||
m_windowClosed(false),
|
||||
m_windowVisible(true),
|
||||
m_sdlWindowData(NULL),
|
||||
m_sdlVideoDevice(NULL),
|
||||
m_useRelativeMouseMode(false)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
|
||||
{
|
||||
applicationView->Activated +=
|
||||
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnActivated);
|
||||
|
||||
CoreApplication::Suspending +=
|
||||
ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
|
||||
|
||||
CoreApplication::Resuming +=
|
||||
ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnResuming);
|
||||
|
||||
DisplayProperties::OrientationChanged +=
|
||||
ref new DisplayPropertiesEventHandler(this, &SDL_WinRTApp::OnOrientationChanged);
|
||||
|
||||
// Register the hint, SDL_HINT_ORIENTATIONS, with SDL. This needs to be
|
||||
// done before the hint's callback is registered (as of Feb 22, 2013),
|
||||
// otherwise the hint callback won't get registered.
|
||||
//
|
||||
// WinRT, TODO: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
|
||||
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight Portrait PortraitUpsideDown");
|
||||
SDL_RegisterHintChangedCb(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
|
||||
{
|
||||
#if LOG_ORIENTATION_EVENTS==1
|
||||
CoreWindow^ window = CoreWindow::GetForCurrentThread();
|
||||
if (window) {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
|
||||
__FUNCTION__,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences,
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
} else {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
|
||||
__FUNCTION__,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window Size={%f,%f}\n",
|
||||
__FUNCTION__,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences,
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
#endif
|
||||
|
||||
window->SizeChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &SDL_WinRTApp::OnWindowSizeChanged);
|
||||
|
||||
window->VisibilityChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
|
||||
|
||||
window->Closed +=
|
||||
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
|
||||
#endif
|
||||
|
||||
window->PointerPressed +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerPressed);
|
||||
|
||||
window->PointerReleased +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
|
||||
|
||||
window->PointerWheelChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
|
||||
|
||||
window->PointerMoved +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerMoved);
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
// Retrieves relative-only mouse movements:
|
||||
Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
|
||||
ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &SDL_WinRTApp::OnMouseMoved);
|
||||
#endif
|
||||
|
||||
window->KeyDown +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyDown);
|
||||
|
||||
window->KeyUp +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyUp);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Load(Platform::String^ entryPoint)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Run()
|
||||
{
|
||||
if (SDL_WinRT_main)
|
||||
{
|
||||
// TODO, WinRT: pass the C-style main() a reasonably realistic
|
||||
// representation of command line arguments.
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
SDL_WinRT_main(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::PumpEvents()
|
||||
{
|
||||
if (!m_windowClosed)
|
||||
{
|
||||
if (m_windowVisible)
|
||||
{
|
||||
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Uninitialize()
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, m_sdlWindowData?=%s\n",
|
||||
__FUNCTION__,
|
||||
args->Size.Width, args->Size.Height,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences,
|
||||
(m_sdlWindowData ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
if (m_sdlWindowData) {
|
||||
// Make the new window size be the one true fullscreen mode.
|
||||
// This change was done, in part, to allow the Direct3D 11.1 renderer
|
||||
// to receive window-resize events as a device rotates.
|
||||
// Before, rotating a device from landscape, to portrait, and then
|
||||
// back to landscape would cause the Direct3D 11.1 swap buffer to
|
||||
// not get resized appropriately. SDL would, on the rotation from
|
||||
// landscape to portrait, re-resize the SDL window to it's initial
|
||||
// size (landscape). On the subsequent rotation, SDL would drop the
|
||||
// window-resize event as it appeared the SDL window didn't change
|
||||
// size, and the Direct3D 11.1 renderer wouldn't resize its swap
|
||||
// chain.
|
||||
//
|
||||
// TODO, WinRT: consider dropping old display modes after the fullscreen window changes size (from rotations, etc.)
|
||||
m_sdlWindowData->sdlWindow->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
|
||||
SDL_AddDisplayMode(&m_sdlVideoDevice->displays[0], &m_sdlWindowData->sdlWindow->fullscreen_mode);
|
||||
|
||||
// HACK, Feb 19, 2013: SDL_WINDOWEVENT_RESIZED events, when sent,
|
||||
// will attempt to fix the values of the main window's renderer's
|
||||
// viewport. While this can be good, it does appear to be buggy,
|
||||
// and can cause a fullscreen viewport to become corrupted. This
|
||||
// behavior was noticed on a Surface RT while rotating the device
|
||||
// from landscape to portrait. Oddly enough, this did not occur
|
||||
// in the Windows Simulator.
|
||||
//
|
||||
// Backing up, then restoring, the main renderer's 'resized' flag
|
||||
// seems to fix fullscreen viewport problems when rotating a
|
||||
// Windows device.
|
||||
//
|
||||
// Commencing hack in 3... 2... 1...
|
||||
SDL_Renderer * rendererForMainWindow = SDL_GetRenderer(m_sdlWindowData->sdlWindow);
|
||||
// For now, limit the hack to when the Direct3D 11.1 is getting used:
|
||||
const bool usingD3D11Renderer = \
|
||||
(rendererForMainWindow != NULL) &&
|
||||
(SDL_strcmp(rendererForMainWindow->info.name, "direct3d 11.1") == 0);
|
||||
SDL_bool wasD3D11RendererResized = SDL_FALSE;
|
||||
if (usingD3D11Renderer) {
|
||||
wasD3D11RendererResized = rendererForMainWindow->resized;
|
||||
}
|
||||
|
||||
// Send the window-resize event to the rest of SDL, and to apps:
|
||||
const int windowWidth = (int) ceil(args->Size.Width);
|
||||
const int windowHeight = (int) ceil(args->Size.Height);
|
||||
SDL_SendWindowEvent(
|
||||
m_sdlWindowData->sdlWindow,
|
||||
SDL_WINDOWEVENT_RESIZED,
|
||||
windowWidth,
|
||||
windowHeight);
|
||||
|
||||
// Viewport hack, part two:
|
||||
if (usingD3D11Renderer) {
|
||||
rendererForMainWindow->resized = wasD3D11RendererResized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, visible?=%s, m_sdlWindowData?=%s\n",
|
||||
__FUNCTION__,
|
||||
(args->Visible ? "yes" : "no"),
|
||||
(m_sdlWindowData ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
m_windowVisible = args->Visible;
|
||||
if (m_sdlWindowData) {
|
||||
SDL_bool wasSDLWindowSurfaceValid = m_sdlWindowData->sdlWindow->surface_valid;
|
||||
|
||||
if (args->Visible) {
|
||||
SDL_SendWindowEvent(m_sdlWindowData->sdlWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
} else {
|
||||
SDL_SendWindowEvent(m_sdlWindowData->sdlWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
|
||||
}
|
||||
|
||||
// HACK: Prevent SDL's window-hide handling code, which currently
|
||||
// triggers a fake window resize (possibly erronously), from
|
||||
// marking the SDL window's surface as invalid.
|
||||
//
|
||||
// A better solution to this probably involves figuring out if the
|
||||
// fake window resize can be prevented.
|
||||
m_sdlWindowData->sdlWindow->surface_valid = wasSDLWindowSurfaceValid;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s\n", __FUNCTION__);
|
||||
#endif
|
||||
m_windowClosed = true;
|
||||
}
|
||||
|
||||
static Uint8
|
||||
WINRT_GetSDLButtonForPointerPoint(PointerPoint ^ pt)
|
||||
{
|
||||
switch (pt->Properties->PointerUpdateKind)
|
||||
{
|
||||
case PointerUpdateKind::LeftButtonPressed:
|
||||
case PointerUpdateKind::LeftButtonReleased:
|
||||
return SDL_BUTTON_LEFT;
|
||||
|
||||
case PointerUpdateKind::RightButtonPressed:
|
||||
case PointerUpdateKind::RightButtonReleased:
|
||||
return SDL_BUTTON_RIGHT;
|
||||
|
||||
case PointerUpdateKind::MiddleButtonPressed:
|
||||
case PointerUpdateKind::MiddleButtonReleased:
|
||||
return SDL_BUTTON_MIDDLE;
|
||||
|
||||
case PointerUpdateKind::XButton1Pressed:
|
||||
case PointerUpdateKind::XButton1Released:
|
||||
return SDL_BUTTON_X1;
|
||||
|
||||
case PointerUpdateKind::XButton2Pressed:
|
||||
case PointerUpdateKind::XButton2Released:
|
||||
return SDL_BUTTON_X2;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
WINRT_ConvertPointerUpdateKindToString(PointerUpdateKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case PointerUpdateKind::Other:
|
||||
return "Other";
|
||||
case PointerUpdateKind::LeftButtonPressed:
|
||||
return "LeftButtonPressed";
|
||||
case PointerUpdateKind::LeftButtonReleased:
|
||||
return "LeftButtonReleased";
|
||||
case PointerUpdateKind::RightButtonPressed:
|
||||
return "RightButtonPressed";
|
||||
case PointerUpdateKind::RightButtonReleased:
|
||||
return "RightButtonReleased";
|
||||
case PointerUpdateKind::MiddleButtonPressed:
|
||||
return "MiddleButtonPressed";
|
||||
case PointerUpdateKind::MiddleButtonReleased:
|
||||
return "MiddleButtonReleased";
|
||||
case PointerUpdateKind::XButton1Pressed:
|
||||
return "XButton1Pressed";
|
||||
case PointerUpdateKind::XButton1Released:
|
||||
return "XButton1Released";
|
||||
case PointerUpdateKind::XButton2Pressed:
|
||||
return "XButton2Pressed";
|
||||
case PointerUpdateKind::XButton2Released:
|
||||
return "XButton2Released";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_LogPointerEvent(const string & header, PointerEventArgs ^ args, Point transformedPoint)
|
||||
{
|
||||
PointerPoint ^ pt = args->CurrentPoint;
|
||||
SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, PointerUpdateKind=%s\n",
|
||||
header.c_str(),
|
||||
pt->Position.X, pt->Position.Y,
|
||||
transformedPoint.X, transformedPoint.Y,
|
||||
pt->Properties->MouseWheelDelta,
|
||||
pt->FrameId,
|
||||
pt->PointerId,
|
||||
WINRT_ConvertPointerUpdateKindToString(args->CurrentPoint->Properties->PointerUpdateKind));
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("mouse down", args, TransformCursor(args->CurrentPoint->Position));
|
||||
#endif
|
||||
|
||||
if (m_sdlWindowData) {
|
||||
Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
|
||||
if (button) {
|
||||
SDL_SendMouseButton(m_sdlWindowData->sdlWindow, 0, SDL_PRESSED, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("mouse up", args, TransformCursor(args->CurrentPoint->Position));
|
||||
#endif
|
||||
|
||||
if (m_sdlWindowData) {
|
||||
Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
|
||||
if (button) {
|
||||
SDL_SendMouseButton(m_sdlWindowData->sdlWindow, 0, SDL_RELEASED, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("wheel changed", args, TransformCursor(args->CurrentPoint->Position));
|
||||
#endif
|
||||
|
||||
if (m_sdlWindowData) {
|
||||
// FIXME: This may need to accumulate deltas up to WHEEL_DELTA
|
||||
short motion = args->CurrentPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
|
||||
SDL_SendMouseWheel(m_sdlWindowData->sdlWindow, 0, 0, motion);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int _lround(float arg) {
|
||||
if (arg >= 0.0f) {
|
||||
return (int)floor(arg + 0.5f);
|
||||
} else {
|
||||
return (int)ceil(arg - 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
|
||||
{
|
||||
if (m_sdlWindowData && m_useRelativeMouseMode) {
|
||||
// DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
|
||||
// Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
|
||||
// MouseDelta field often reports very large values. More information
|
||||
// on this can be found at the following pages on MSDN:
|
||||
// - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
|
||||
// - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
|
||||
//
|
||||
// The values do not appear to be as large when running on some systems,
|
||||
// most notably a Surface RT. Furthermore, the values returned by
|
||||
// CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
|
||||
// method, do not ever appear to be large, even when MouseEventArgs'
|
||||
// MouseDelta is reporting to the contrary.
|
||||
//
|
||||
// On systems with the large-values behavior, it appears that the values
|
||||
// get reported as if the screen's size is 65536 units in both the X and Y
|
||||
// dimensions. This can be viewed by using Windows' now-private, "Raw Input"
|
||||
// APIs. (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
|
||||
//
|
||||
// MSDN's documentation on MouseEventArgs' MouseDelta field (at
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
|
||||
// does not seem to indicate (to me) that its values should be so large. It
|
||||
// says that its values should be a "change in screen location". I could
|
||||
// be misinterpreting this, however a post on MSDN from a Microsoft engineer (see:
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
|
||||
// indicates that these values are in DIPs, which is the same unit used
|
||||
// by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
|
||||
// property. See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
|
||||
// for details.)
|
||||
//
|
||||
// To note, PointerMoved events are sent a 'RawPosition' value (via the
|
||||
// CurrentPoint property in MouseEventArgs), however these do not seem
|
||||
// to exhibit the same large-value behavior.
|
||||
//
|
||||
// The values passed via PointerMoved events can't always be used for relative
|
||||
// mouse motion, unfortunately. Its values are bound to the cursor's position,
|
||||
// which stops when it hits one of the screen's edges. This can be a problem in
|
||||
// first person shooters, whereby it is normal for mouse motion to travel far
|
||||
// along any one axis for a period of time. MouseMoved events do not have the
|
||||
// screen-bounding limitation, and can be used regardless of where the system's
|
||||
// cursor is.
|
||||
//
|
||||
// One possible workaround would be to programmatically set the cursor's
|
||||
// position to the screen's center (when SDL's relative mouse mode is enabled),
|
||||
// however Windows RT does not yet seem to have the ability to set the cursor's
|
||||
// position via a public API. Win32 did this via an API call, SetCursorPos,
|
||||
// however WinRT makes this function be private. Apps that use it won't get
|
||||
// approved for distribution in the Windows Store. I've yet to be able to find
|
||||
// a suitable, store-friendly counterpart for WinRT.
|
||||
//
|
||||
// There may be some room for a workaround whereby OnPointerMoved's values
|
||||
// are compared to the values from OnMouseMoved in order to detect
|
||||
// when this bug is active. A suitable transformation could then be made to
|
||||
// OnMouseMoved's values. For now, however, the system-reported values are sent
|
||||
// to SDL with minimal transformation: from native screen coordinates (in DIPs)
|
||||
// to SDL window coordinates.
|
||||
//
|
||||
const Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
|
||||
const Point mouseDeltaInSDLWindowCoords = TransformCursor(mouseDeltaInDIPs);
|
||||
SDL_SendMouseMotion(
|
||||
m_sdlWindowData->sdlWindow,
|
||||
0,
|
||||
1,
|
||||
_lround(mouseDeltaInSDLWindowCoords.X),
|
||||
_lround(mouseDeltaInSDLWindowCoords.Y));
|
||||
}
|
||||
}
|
||||
|
||||
// Applies necessary geometric transformations to raw cursor positions:
|
||||
Point SDL_WinRTApp::TransformCursor(Point rawPosition)
|
||||
{
|
||||
if ( ! m_sdlWindowData || ! m_sdlWindowData->sdlWindow ) {
|
||||
return rawPosition;
|
||||
}
|
||||
CoreWindow ^ nativeWindow = CoreWindow::GetForCurrentThread();
|
||||
Point outputPosition;
|
||||
outputPosition.X = rawPosition.X * (((float32)m_sdlWindowData->sdlWindow->w) / nativeWindow->Bounds.Width);
|
||||
outputPosition.Y = rawPosition.Y * (((float32)m_sdlWindowData->sdlWindow->h) / nativeWindow->Bounds.Height);
|
||||
return outputPosition;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer moved", args, TransformCursor(args->CurrentPoint->Position));
|
||||
#endif
|
||||
|
||||
if (m_sdlWindowData && ! m_useRelativeMouseMode)
|
||||
{
|
||||
Point transformedPoint = TransformCursor(args->CurrentPoint->Position);
|
||||
SDL_SendMouseMotion(m_sdlWindowData->sdlWindow, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Scancode WinRT_Official_Keycodes[] = {
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.None -- 0
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftButton -- 1
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.RightButton -- 2
|
||||
SDL_SCANCODE_CANCEL, // VirtualKey.Cancel -- 3
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.MiddleButton -- 4
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton1 -- 5
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton2 -- 6
|
||||
SDL_SCANCODE_UNKNOWN, // -- 7
|
||||
SDL_SCANCODE_BACKSPACE, // VirtualKey.Back -- 8
|
||||
SDL_SCANCODE_TAB, // VirtualKey.Tab -- 9
|
||||
SDL_SCANCODE_UNKNOWN, // -- 10
|
||||
SDL_SCANCODE_UNKNOWN, // -- 11
|
||||
SDL_SCANCODE_CLEAR, // VirtualKey.Clear -- 12
|
||||
SDL_SCANCODE_RETURN, // VirtualKey.Enter -- 13
|
||||
SDL_SCANCODE_UNKNOWN, // -- 14
|
||||
SDL_SCANCODE_UNKNOWN, // -- 15
|
||||
SDL_SCANCODE_LSHIFT, // VirtualKey.Shift -- 16
|
||||
SDL_SCANCODE_LCTRL, // VirtualKey.Control -- 17
|
||||
SDL_SCANCODE_MENU, // VirtualKey.Menu -- 18
|
||||
SDL_SCANCODE_PAUSE, // VirtualKey.Pause -- 19
|
||||
SDL_SCANCODE_CAPSLOCK, // VirtualKey.CapitalLock -- 20
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Kana or VirtualKey.Hangul -- 21
|
||||
SDL_SCANCODE_UNKNOWN, // -- 22
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Junja -- 23
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Final -- 24
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Hanja or VirtualKey.Kanji -- 25
|
||||
SDL_SCANCODE_UNKNOWN, // -- 26
|
||||
SDL_SCANCODE_ESCAPE, // VirtualKey.Escape -- 27
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Convert -- 28
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.NonConvert -- 29
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Accept -- 30
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.ModeChange -- 31 (maybe SDL_SCANCODE_MODE ?)
|
||||
SDL_SCANCODE_SPACE, // VirtualKey.Space -- 32
|
||||
SDL_SCANCODE_PAGEUP, // VirtualKey.PageUp -- 33
|
||||
SDL_SCANCODE_PAGEDOWN, // VirtualKey.PageDown -- 34
|
||||
SDL_SCANCODE_END, // VirtualKey.End -- 35
|
||||
SDL_SCANCODE_HOME, // VirtualKey.Home -- 36
|
||||
SDL_SCANCODE_LEFT, // VirtualKey.Left -- 37
|
||||
SDL_SCANCODE_UP, // VirtualKey.Up -- 38
|
||||
SDL_SCANCODE_RIGHT, // VirtualKey.Right -- 39
|
||||
SDL_SCANCODE_DOWN, // VirtualKey.Down -- 40
|
||||
SDL_SCANCODE_SELECT, // VirtualKey.Select -- 41
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Print -- 42 (maybe SDL_SCANCODE_PRINTSCREEN ?)
|
||||
SDL_SCANCODE_EXECUTE, // VirtualKey.Execute -- 43
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Snapshot -- 44
|
||||
SDL_SCANCODE_INSERT, // VirtualKey.Insert -- 45
|
||||
SDL_SCANCODE_DELETE, // VirtualKey.Delete -- 46
|
||||
SDL_SCANCODE_HELP, // VirtualKey.Help -- 47
|
||||
SDL_SCANCODE_0, // VirtualKey.Number0 -- 48
|
||||
SDL_SCANCODE_1, // VirtualKey.Number1 -- 49
|
||||
SDL_SCANCODE_2, // VirtualKey.Number2 -- 50
|
||||
SDL_SCANCODE_3, // VirtualKey.Number3 -- 51
|
||||
SDL_SCANCODE_4, // VirtualKey.Number4 -- 52
|
||||
SDL_SCANCODE_5, // VirtualKey.Number5 -- 53
|
||||
SDL_SCANCODE_6, // VirtualKey.Number6 -- 54
|
||||
SDL_SCANCODE_7, // VirtualKey.Number7 -- 55
|
||||
SDL_SCANCODE_8, // VirtualKey.Number8 -- 56
|
||||
SDL_SCANCODE_9, // VirtualKey.Number9 -- 57
|
||||
SDL_SCANCODE_UNKNOWN, // -- 58
|
||||
SDL_SCANCODE_UNKNOWN, // -- 59
|
||||
SDL_SCANCODE_UNKNOWN, // -- 60
|
||||
SDL_SCANCODE_UNKNOWN, // -- 61
|
||||
SDL_SCANCODE_UNKNOWN, // -- 62
|
||||
SDL_SCANCODE_UNKNOWN, // -- 63
|
||||
SDL_SCANCODE_UNKNOWN, // -- 64
|
||||
SDL_SCANCODE_A, // VirtualKey.A -- 65
|
||||
SDL_SCANCODE_B, // VirtualKey.B -- 66
|
||||
SDL_SCANCODE_C, // VirtualKey.C -- 67
|
||||
SDL_SCANCODE_D, // VirtualKey.D -- 68
|
||||
SDL_SCANCODE_E, // VirtualKey.E -- 69
|
||||
SDL_SCANCODE_F, // VirtualKey.F -- 70
|
||||
SDL_SCANCODE_G, // VirtualKey.G -- 71
|
||||
SDL_SCANCODE_H, // VirtualKey.H -- 72
|
||||
SDL_SCANCODE_I, // VirtualKey.I -- 73
|
||||
SDL_SCANCODE_J, // VirtualKey.J -- 74
|
||||
SDL_SCANCODE_K, // VirtualKey.K -- 75
|
||||
SDL_SCANCODE_L, // VirtualKey.L -- 76
|
||||
SDL_SCANCODE_M, // VirtualKey.M -- 77
|
||||
SDL_SCANCODE_N, // VirtualKey.N -- 78
|
||||
SDL_SCANCODE_O, // VirtualKey.O -- 79
|
||||
SDL_SCANCODE_P, // VirtualKey.P -- 80
|
||||
SDL_SCANCODE_Q, // VirtualKey.Q -- 81
|
||||
SDL_SCANCODE_R, // VirtualKey.R -- 82
|
||||
SDL_SCANCODE_S, // VirtualKey.S -- 83
|
||||
SDL_SCANCODE_T, // VirtualKey.T -- 84
|
||||
SDL_SCANCODE_U, // VirtualKey.U -- 85
|
||||
SDL_SCANCODE_V, // VirtualKey.V -- 86
|
||||
SDL_SCANCODE_W, // VirtualKey.W -- 87
|
||||
SDL_SCANCODE_X, // VirtualKey.X -- 88
|
||||
SDL_SCANCODE_Y, // VirtualKey.Y -- 89
|
||||
SDL_SCANCODE_Z, // VirtualKey.Z -- 90
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftWindows -- 91 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?)
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.RightWindows -- 92 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?)
|
||||
SDL_SCANCODE_APPLICATION, // VirtualKey.Application -- 93
|
||||
SDL_SCANCODE_UNKNOWN, // -- 94
|
||||
SDL_SCANCODE_SLEEP, // VirtualKey.Sleep -- 95
|
||||
SDL_SCANCODE_KP_0, // VirtualKey.NumberPad0 -- 96
|
||||
SDL_SCANCODE_KP_1, // VirtualKey.NumberPad1 -- 97
|
||||
SDL_SCANCODE_KP_2, // VirtualKey.NumberPad2 -- 98
|
||||
SDL_SCANCODE_KP_3, // VirtualKey.NumberPad3 -- 99
|
||||
SDL_SCANCODE_KP_4, // VirtualKey.NumberPad4 -- 100
|
||||
SDL_SCANCODE_KP_5, // VirtualKey.NumberPad5 -- 101
|
||||
SDL_SCANCODE_KP_6, // VirtualKey.NumberPad6 -- 102
|
||||
SDL_SCANCODE_KP_7, // VirtualKey.NumberPad7 -- 103
|
||||
SDL_SCANCODE_KP_8, // VirtualKey.NumberPad8 -- 104
|
||||
SDL_SCANCODE_KP_9, // VirtualKey.NumberPad9 -- 105
|
||||
SDL_SCANCODE_KP_MULTIPLY, // VirtualKey.Multiply -- 106
|
||||
SDL_SCANCODE_KP_PLUS, // VirtualKey.Add -- 107
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Separator -- 108
|
||||
SDL_SCANCODE_KP_MINUS, // VirtualKey.Subtract -- 109
|
||||
SDL_SCANCODE_UNKNOWN, // VirtualKey.Decimal -- 110 (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?)
|
||||
SDL_SCANCODE_KP_DIVIDE, // VirtualKey.Divide -- 111
|
||||
SDL_SCANCODE_F1, // VirtualKey.F1 -- 112
|
||||
SDL_SCANCODE_F2, // VirtualKey.F2 -- 113
|
||||
SDL_SCANCODE_F3, // VirtualKey.F3 -- 114
|
||||
SDL_SCANCODE_F4, // VirtualKey.F4 -- 115
|
||||
SDL_SCANCODE_F5, // VirtualKey.F5 -- 116
|
||||
SDL_SCANCODE_F6, // VirtualKey.F6 -- 117
|
||||
SDL_SCANCODE_F7, // VirtualKey.F7 -- 118
|
||||
SDL_SCANCODE_F8, // VirtualKey.F8 -- 119
|
||||
SDL_SCANCODE_F9, // VirtualKey.F9 -- 120
|
||||
SDL_SCANCODE_F10, // VirtualKey.F10 -- 121
|
||||
SDL_SCANCODE_F11, // VirtualKey.F11 -- 122
|
||||
SDL_SCANCODE_F12, // VirtualKey.F12 -- 123
|
||||
SDL_SCANCODE_F13, // VirtualKey.F13 -- 124
|
||||
SDL_SCANCODE_F14, // VirtualKey.F14 -- 125
|
||||
SDL_SCANCODE_F15, // VirtualKey.F15 -- 126
|
||||
SDL_SCANCODE_F16, // VirtualKey.F16 -- 127
|
||||
SDL_SCANCODE_F17, // VirtualKey.F17 -- 128
|
||||
SDL_SCANCODE_F18, // VirtualKey.F18 -- 129
|
||||
SDL_SCANCODE_F19, // VirtualKey.F19 -- 130
|
||||
SDL_SCANCODE_F20, // VirtualKey.F20 -- 131
|
||||
SDL_SCANCODE_F21, // VirtualKey.F21 -- 132
|
||||
SDL_SCANCODE_F22, // VirtualKey.F22 -- 133
|
||||
SDL_SCANCODE_F23, // VirtualKey.F23 -- 134
|
||||
SDL_SCANCODE_F24, // VirtualKey.F24 -- 135
|
||||
SDL_SCANCODE_UNKNOWN, // -- 136
|
||||
SDL_SCANCODE_UNKNOWN, // -- 137
|
||||
SDL_SCANCODE_UNKNOWN, // -- 138
|
||||
SDL_SCANCODE_UNKNOWN, // -- 139
|
||||
SDL_SCANCODE_UNKNOWN, // -- 140
|
||||
SDL_SCANCODE_UNKNOWN, // -- 141
|
||||
SDL_SCANCODE_UNKNOWN, // -- 142
|
||||
SDL_SCANCODE_UNKNOWN, // -- 143
|
||||
SDL_SCANCODE_NUMLOCKCLEAR, // VirtualKey.NumberKeyLock -- 144
|
||||
SDL_SCANCODE_SCROLLLOCK, // VirtualKey.Scroll -- 145
|
||||
SDL_SCANCODE_UNKNOWN, // -- 146
|
||||
SDL_SCANCODE_UNKNOWN, // -- 147
|
||||
SDL_SCANCODE_UNKNOWN, // -- 148
|
||||
SDL_SCANCODE_UNKNOWN, // -- 149
|
||||
SDL_SCANCODE_UNKNOWN, // -- 150
|
||||
SDL_SCANCODE_UNKNOWN, // -- 151
|
||||
SDL_SCANCODE_UNKNOWN, // -- 152
|
||||
SDL_SCANCODE_UNKNOWN, // -- 153
|
||||
SDL_SCANCODE_UNKNOWN, // -- 154
|
||||
SDL_SCANCODE_UNKNOWN, // -- 155
|
||||
SDL_SCANCODE_UNKNOWN, // -- 156
|
||||
SDL_SCANCODE_UNKNOWN, // -- 157
|
||||
SDL_SCANCODE_UNKNOWN, // -- 158
|
||||
SDL_SCANCODE_UNKNOWN, // -- 159
|
||||
SDL_SCANCODE_LSHIFT, // VirtualKey.LeftShift -- 160
|
||||
SDL_SCANCODE_RSHIFT, // VirtualKey.RightShift -- 161
|
||||
SDL_SCANCODE_LCTRL, // VirtualKey.LeftControl -- 162
|
||||
SDL_SCANCODE_RCTRL, // VirtualKey.RightControl -- 163
|
||||
SDL_SCANCODE_MENU, // VirtualKey.LeftMenu -- 164
|
||||
SDL_SCANCODE_MENU, // VirtualKey.RightMenu -- 165
|
||||
};
|
||||
|
||||
static std::unordered_map<int, SDL_Scancode> WinRT_Unofficial_Keycodes;
|
||||
|
||||
static SDL_Scancode
|
||||
TranslateKeycode(int keycode)
|
||||
{
|
||||
if (WinRT_Unofficial_Keycodes.empty()) {
|
||||
/* Set up a table of undocumented (by Microsoft), WinRT-specific,
|
||||
key codes: */
|
||||
// TODO, WinRT: move content declarations of WinRT_Unofficial_Keycodes into a C++11 initializer list, when possible
|
||||
WinRT_Unofficial_Keycodes[220] = SDL_SCANCODE_GRAVE;
|
||||
WinRT_Unofficial_Keycodes[222] = SDL_SCANCODE_BACKSLASH;
|
||||
}
|
||||
|
||||
/* Try to get a documented, WinRT, 'VirtualKey' first (as documented at
|
||||
http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ).
|
||||
If that fails, fall back to a Win32 virtual key.
|
||||
*/
|
||||
// TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints
|
||||
//SDL_Log("WinRT TranslateKeycode, keycode=%d\n", (int)keycode);
|
||||
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
||||
if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) {
|
||||
scancode = WinRT_Official_Keycodes[keycode];
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
if (WinRT_Unofficial_Keycodes.find(keycode) != WinRT_Unofficial_Keycodes.end()) {
|
||||
scancode = WinRT_Unofficial_Keycodes[keycode];
|
||||
}
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
if (keycode < SDL_arraysize(windows_scancode_table)) {
|
||||
scancode = windows_scancode_table[keycode];
|
||||
}
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode);
|
||||
}
|
||||
return scancode;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
|
||||
{
|
||||
SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey);
|
||||
#if 0
|
||||
SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
|
||||
SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, repeat count=%d, native scan code=%d, was down?=%s, vkey=%d, sdl scan code=%d (%s), sdl key code=%d (%s)\n",
|
||||
(args->Handled ? "1" : "0"),
|
||||
(args->KeyStatus.IsExtendedKey ? "1" : "0"),
|
||||
(args->KeyStatus.IsKeyReleased ? "1" : "0"),
|
||||
(args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
|
||||
args->KeyStatus.RepeatCount,
|
||||
args->KeyStatus.ScanCode,
|
||||
(args->KeyStatus.WasKeyDown ? "1" : "0"),
|
||||
args->VirtualKey,
|
||||
sdlScancode,
|
||||
SDL_GetScancodeName(sdlScancode),
|
||||
keycode,
|
||||
SDL_GetKeyName(keycode));
|
||||
//args->Handled = true;
|
||||
//VirtualKey vkey = args->VirtualKey;
|
||||
#endif
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, sdlScancode);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
|
||||
{
|
||||
SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey);
|
||||
#if 0
|
||||
SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
|
||||
SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, repeat count=%d, native scan code=%d, was down?=%s, vkey=%d, sdl scan code=%d (%s), sdl key code=%d (%s)\n",
|
||||
(args->Handled ? "1" : "0"),
|
||||
(args->KeyStatus.IsExtendedKey ? "1" : "0"),
|
||||
(args->KeyStatus.IsKeyReleased ? "1" : "0"),
|
||||
(args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
|
||||
args->KeyStatus.RepeatCount,
|
||||
args->KeyStatus.ScanCode,
|
||||
(args->KeyStatus.WasKeyDown ? "1" : "0"),
|
||||
args->VirtualKey,
|
||||
sdlScancode,
|
||||
SDL_GetScancodeName(sdlScancode),
|
||||
keycode,
|
||||
SDL_GetKeyName(keycode));
|
||||
//args->Handled = true;
|
||||
#endif
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, sdlScancode);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
{
|
||||
CoreWindow::GetForCurrentThread()->Activate();
|
||||
}
|
||||
|
||||
static int SDLCALL RemoveAppSuspendAndResumeEvents(void * userdata, SDL_Event * event)
|
||||
{
|
||||
if (event->type == SDL_WINDOWEVENT)
|
||||
{
|
||||
switch (event->window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
// Return 0 to indicate that the event should be removed from the
|
||||
// event queue:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return 1 to indicate that the event should stay in the event queue:
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
|
||||
{
|
||||
// Save app state asynchronously after requesting a deferral. Holding a deferral
|
||||
// indicates that the application is busy performing suspending operations. Be
|
||||
// aware that a deferral may not be held indefinitely. After about five seconds,
|
||||
// the app will be forced to exit.
|
||||
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
|
||||
create_task([this, deferral]()
|
||||
{
|
||||
// Send a window-minimized event immediately to observers.
|
||||
// CoreDispatcher::ProcessEvents, which is the backbone on which
|
||||
// SDL_WinRTApp::PumpEvents is built, will not return to its caller
|
||||
// once it sends out a suspend event. Any events posted to SDL's
|
||||
// event queue won't get received until the WinRT app is resumed.
|
||||
// SDL_AddEventWatch() may be used to receive app-suspend events on
|
||||
// WinRT.
|
||||
//
|
||||
// In order to prevent app-suspend events from being received twice:
|
||||
// first via a callback passed to SDL_AddEventWatch, and second via
|
||||
// SDL's event queue, the event will be sent to SDL, then immediately
|
||||
// removed from the queue.
|
||||
if (m_sdlWindowData)
|
||||
{
|
||||
SDL_SendWindowEvent(m_sdlWindowData->sdlWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0); // TODO: see if SDL_WINDOWEVENT_SIZE_CHANGED should be getting triggered here (it is, currently)
|
||||
SDL_FilterEvents(RemoveAppSuspendAndResumeEvents, 0);
|
||||
}
|
||||
deferral->Complete();
|
||||
});
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnResuming(Platform::Object^ sender, Platform::Object^ args)
|
||||
{
|
||||
// Restore any data or state that was unloaded on suspend. By default, data
|
||||
// and state are persisted when resuming from suspend. Note that this event
|
||||
// does not occur if the app was previously terminated.
|
||||
if (m_sdlWindowData)
|
||||
{
|
||||
SDL_SendWindowEvent(m_sdlWindowData->sdlWindow, SDL_WINDOWEVENT_RESTORED, 0, 0); // TODO: see if SDL_WINDOWEVENT_SIZE_CHANGED should be getting triggered here (it is, currently)
|
||||
|
||||
// Remove the app-resume event from the queue, as is done with the
|
||||
// app-suspend event.
|
||||
//
|
||||
// TODO, WinRT: consider posting this event to the queue even though
|
||||
// its counterpart, the app-suspend event, effectively has to be
|
||||
// processed immediately.
|
||||
SDL_FilterEvents(RemoveAppSuspendAndResumeEvents, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_DisplayMode SDL_WinRTApp::GetMainDisplayMode()
|
||||
{
|
||||
// Create an empty, zeroed-out display mode:
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
|
||||
// Fill in most fields:
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
mode.refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
|
||||
mode.driverdata = NULL;
|
||||
|
||||
// Calculate the display size given the window size, taking into account
|
||||
// the current display's DPI:
|
||||
const float currentDPI = Windows::Graphics::Display::DisplayProperties::LogicalDpi;
|
||||
const float dipsPerInch = 96.0f;
|
||||
mode.w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
|
||||
mode.h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
const SDL_WindowData * SDL_WinRTApp::GetSDLWindowData() const
|
||||
{
|
||||
return m_sdlWindowData;
|
||||
}
|
||||
|
||||
bool SDL_WinRTApp::HasSDLWindowData() const
|
||||
{
|
||||
return (m_sdlWindowData != NULL);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::SetRelativeMouseMode(bool enable)
|
||||
{
|
||||
m_useRelativeMouseMode = enable;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::SetSDLWindowData(const SDL_WindowData * windowData)
|
||||
{
|
||||
m_sdlWindowData = windowData;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::SetSDLVideoDevice(const SDL_VideoDevice * videoDevice)
|
||||
{
|
||||
m_sdlVideoDevice = videoDevice;
|
||||
}
|
||||
52
src/video/windowsrt/SDL_WinRTApp.h
Normal file
52
src/video/windowsrt/SDL_WinRTApp.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
struct SDL_WindowData;
|
||||
|
||||
ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFrameworkView
|
||||
{
|
||||
public:
|
||||
SDL_WinRTApp();
|
||||
|
||||
// IFrameworkView Methods.
|
||||
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
|
||||
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
|
||||
virtual void Load(Platform::String^ entryPoint);
|
||||
virtual void Run();
|
||||
virtual void Uninitialize();
|
||||
|
||||
internal:
|
||||
// SDL-specific methods
|
||||
SDL_DisplayMode GetMainDisplayMode();
|
||||
void PumpEvents();
|
||||
const SDL_WindowData * GetSDLWindowData() const;
|
||||
bool HasSDLWindowData() const;
|
||||
void SetRelativeMouseMode(bool enable);
|
||||
void SetSDLWindowData(const SDL_WindowData * windowData);
|
||||
void SetSDLVideoDevice(const SDL_VideoDevice * videoDevice);
|
||||
Windows::Foundation::Point TransformCursor(Windows::Foundation::Point rawPosition);
|
||||
|
||||
protected:
|
||||
// Event Handlers.
|
||||
void OnOrientationChanged(Platform::Object^ sender);
|
||||
void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
|
||||
void OnLogicalDpiChanged(Platform::Object^ sender);
|
||||
void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
|
||||
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
|
||||
void OnResuming(Platform::Object^ sender, Platform::Object^ args);
|
||||
void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
|
||||
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
|
||||
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
|
||||
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
|
||||
private:
|
||||
bool m_windowClosed;
|
||||
bool m_windowVisible;
|
||||
const SDL_WindowData* m_sdlWindowData;
|
||||
const SDL_VideoDevice* m_sdlVideoDevice;
|
||||
bool m_useRelativeMouseMode;
|
||||
};
|
||||
41
src/video/windowsrt/SDL_winrtevents.cpp
Normal file
41
src/video/windowsrt/SDL_winrtevents.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_winrtvideo.h"
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "SDL_WinRTApp.h"
|
||||
|
||||
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
|
||||
|
||||
void
|
||||
WINRT_PumpEvents(_THIS)
|
||||
{
|
||||
SDL_WinRTGlobalApp->PumpEvents();
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
27
src/video/windowsrt/SDL_winrtevents_c.h
Normal file
27
src/video/windowsrt/SDL_winrtevents_c.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_winrtvideo.h"
|
||||
|
||||
extern void WINRT_PumpEvents(_THIS);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
149
src/video/windowsrt/SDL_winrtmouse.cpp
Normal file
149
src/video/windowsrt/SDL_winrtmouse.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_assert.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
}
|
||||
|
||||
#include "SDL_WinRTApp.h"
|
||||
#include "SDL_winrtmouse.h"
|
||||
|
||||
using namespace Windows::UI::Core;
|
||||
using Windows::UI::Core::CoreCursor;
|
||||
|
||||
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
|
||||
|
||||
|
||||
static SDL_Cursor *
|
||||
WINRT_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
CoreCursorType cursorType = CoreCursorType::Arrow;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
default:
|
||||
SDL_assert(0);
|
||||
return NULL;
|
||||
case SDL_SYSTEM_CURSOR_ARROW: cursorType = CoreCursorType::Arrow; break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM: cursorType = CoreCursorType::IBeam; break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT: cursorType = CoreCursorType::Wait; break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR: cursorType = CoreCursorType::Cross; break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW: cursorType = CoreCursorType::Wait; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE: cursorType = CoreCursorType::SizeNorthwestSoutheast; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW: cursorType = CoreCursorType::SizeNortheastSouthwest; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE: cursorType = CoreCursorType::SizeWestEast; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS: cursorType = CoreCursorType::SizeNorthSouth; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL: cursorType = CoreCursorType::SizeAll; break;
|
||||
case SDL_SYSTEM_CURSOR_NO: cursorType = CoreCursorType::UniversalNo; break;
|
||||
case SDL_SYSTEM_CURSOR_HAND: cursorType = CoreCursorType::Hand; break;
|
||||
}
|
||||
|
||||
cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
/* Create a pointer to a COM reference to a cursor. The extra
|
||||
pointer is used (on top of the COM reference) to allow the cursor
|
||||
to be referenced by the SDL_cursor's driverdata field, which is
|
||||
a void pointer.
|
||||
*/
|
||||
CoreCursor ^* theCursor = new CoreCursor^(nullptr);
|
||||
*theCursor = ref new CoreCursor(cursorType, 0);
|
||||
cursor->driverdata = (void *) theCursor;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *
|
||||
WINRT_CreateDefaultCursor()
|
||||
{
|
||||
return WINRT_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_FreeCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
if (cursor->driverdata) {
|
||||
CoreCursor ^* theCursor = (CoreCursor ^*) cursor->driverdata;
|
||||
*theCursor = nullptr; // Release the COM reference to the CoreCursor
|
||||
delete theCursor; // Delete the pointer to the COM reference
|
||||
}
|
||||
SDL_free(cursor);
|
||||
}
|
||||
|
||||
static int
|
||||
WINRT_ShowCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
if (cursor) {
|
||||
CoreCursor ^* theCursor = (CoreCursor ^*) cursor->driverdata;
|
||||
CoreWindow::GetForCurrentThread()->PointerCursor = *theCursor;
|
||||
} else {
|
||||
CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
WINRT_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
SDL_WinRTGlobalApp->SetRelativeMouseMode(enabled ? true : false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_InitMouse(_THIS)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
/* DLudwig, Dec 3, 2012: Windows RT does not currently provide APIs for
|
||||
the following features, AFAIK:
|
||||
- custom cursors (multiple system cursors are, however, available)
|
||||
- programmatically moveable cursors
|
||||
*/
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
//mouse->CreateCursor = WINRT_CreateCursor;
|
||||
mouse->CreateSystemCursor = WINRT_CreateSystemCursor;
|
||||
mouse->ShowCursor = WINRT_ShowCursor;
|
||||
mouse->FreeCursor = WINRT_FreeCursor;
|
||||
//mouse->WarpMouse = WINRT_WarpMouse;
|
||||
mouse->SetRelativeMouseMode = WINRT_SetRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(WINRT_CreateDefaultCursor());
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_QuitMouse(_THIS)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
31
src/video/windowsrt/SDL_winrtmouse.h
Normal file
31
src/video/windowsrt/SDL_winrtmouse.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_windowsmouse_h
|
||||
#define _SDL_windowsmouse_h
|
||||
|
||||
extern void WINRT_InitMouse(_THIS);
|
||||
extern void WINRT_QuitMouse(_THIS);
|
||||
|
||||
#endif /* _SDL_windowsmouse_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
262
src/video/windowsrt/SDL_winrtvideo.cpp
Normal file
262
src/video/windowsrt/SDL_winrtvideo.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/* WinRT SDL video driver implementation
|
||||
|
||||
Initial work on this was done by David Ludwig (dludwig@pobox.com), and
|
||||
was based off of SDL's "dummy" video driver.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../render/SDL_sysrender.h"
|
||||
#include "SDL_syswm.h"
|
||||
}
|
||||
|
||||
#include "SDL_WinRTApp.h"
|
||||
#include "SDL_winrtvideo.h"
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "SDL_winrtmouse.h"
|
||||
|
||||
using namespace Windows::UI::Core;
|
||||
|
||||
/* On Windows, windows.h defines CreateWindow */
|
||||
#ifdef CreateWindow
|
||||
#undef CreateWindow
|
||||
#endif
|
||||
|
||||
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
|
||||
|
||||
#define WINRTVID_DRIVER_NAME "winrt"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int WINRT_VideoInit(_THIS);
|
||||
static int WINRT_InitModes(_THIS);
|
||||
static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
|
||||
static void WINRT_VideoQuit(_THIS);
|
||||
|
||||
/* Window functions */
|
||||
static int WINRT_CreateWindow(_THIS, SDL_Window * window);
|
||||
static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
|
||||
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
|
||||
|
||||
/* WinRT driver bootstrap functions */
|
||||
|
||||
static int
|
||||
WINRT_Available(void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_DeleteDevice(SDL_VideoDevice * device)
|
||||
{
|
||||
SDL_WinRTGlobalApp->SetSDLVideoDevice(NULL);
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *
|
||||
WINRT_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (!device) {
|
||||
SDL_OutOfMemory();
|
||||
if (device) {
|
||||
SDL_free(device);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = WINRT_VideoInit;
|
||||
device->VideoQuit = WINRT_VideoQuit;
|
||||
device->CreateWindow = WINRT_CreateWindow;
|
||||
device->DestroyWindow = WINRT_DestroyWindow;
|
||||
device->SetDisplayMode = WINRT_SetDisplayMode;
|
||||
device->PumpEvents = WINRT_PumpEvents;
|
||||
//device->CreateWindowFramebuffer = SDL_WINRT_CreateWindowFramebuffer;
|
||||
//device->UpdateWindowFramebuffer = SDL_WINRT_UpdateWindowFramebuffer;
|
||||
//device->DestroyWindowFramebuffer = SDL_WINRT_DestroyWindowFramebuffer;
|
||||
device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
|
||||
device->free = WINRT_DeleteDevice;
|
||||
|
||||
SDL_WinRTGlobalApp->SetSDLVideoDevice(device);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
VideoBootStrap WINRT_bootstrap = {
|
||||
WINRTVID_DRIVER_NAME, "SDL Windows RT video driver",
|
||||
WINRT_Available, WINRT_CreateDevice
|
||||
};
|
||||
|
||||
int
|
||||
WINRT_VideoInit(_THIS)
|
||||
{
|
||||
// TODO, WinRT: consider adding a hack to wait (here) for the app's orientation to finish getting set (before the initial display mode is set up)
|
||||
|
||||
if (WINRT_InitModes(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
WINRT_InitMouse(_this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
WINRT_InitModes(_THIS)
|
||||
{
|
||||
SDL_DisplayMode mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
|
||||
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_AddDisplayMode(&_this->displays[0], &mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_VideoQuit(_THIS)
|
||||
{
|
||||
WINRT_QuitMouse(_this);
|
||||
}
|
||||
|
||||
int
|
||||
WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
// Make sure that only one window gets created, at least until multimonitor
|
||||
// support is added.
|
||||
if (SDL_WinRTGlobalApp->HasSDLWindowData())
|
||||
{
|
||||
SDL_SetError("WinRT only supports one window");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_WindowData *data = new SDL_WindowData;
|
||||
if (!data) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
window->driverdata = data;
|
||||
data->sdlWindow = window;
|
||||
data->coreWindow = CoreWindow::GetForCurrentThread();
|
||||
|
||||
/* Make sure the window is considered to be positioned at {0,0},
|
||||
and is considered fullscreen, shown, and the like.
|
||||
*/
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
window->flags =
|
||||
SDL_WINDOW_FULLSCREEN |
|
||||
SDL_WINDOW_SHOWN |
|
||||
SDL_WINDOW_BORDERLESS |
|
||||
SDL_WINDOW_MAXIMIZED |
|
||||
SDL_WINDOW_INPUT_GRABBED;
|
||||
|
||||
/* HACK from DLudwig: The following line of code prevents
|
||||
SDL_CreateWindow and SDL_UpdateFullscreenMode from trying to resize
|
||||
the window after the call to WINRT_CreateWindow returns.
|
||||
|
||||
This hack should allow a window to be created in virtually any size,
|
||||
and more importantly, it allows a window's framebuffer, as created and
|
||||
retrieved via SDL_GetWindowSurface, to be in any size. This can be
|
||||
utilized by apps centered around software rendering, such as ports
|
||||
of older apps. The app can have SDL create a framebuffer in any size
|
||||
it chooses. SDL will scale the framebuffer to the native
|
||||
screen size on the GPU (via SDL_UpdateWindowSurface).
|
||||
*/
|
||||
_this->displays[0].fullscreen_window = window;
|
||||
|
||||
/* Further prevent any display resizing, and make sure SDL_GetWindowDisplayMode
|
||||
can report the correct size of windows, by creating a new display
|
||||
mode in the requested size. To note, if the window is being created in
|
||||
the device's native screen size, SDL_AddDisplayMode will do nothing.
|
||||
*/
|
||||
window->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
|
||||
window->fullscreen_mode.w = window->w;
|
||||
window->fullscreen_mode.h = window->h;
|
||||
SDL_AddDisplayMode(&_this->displays[0], &window->fullscreen_mode);
|
||||
|
||||
/* TODO: Consider removing custom display modes in WINRT_DestroyWindow. */
|
||||
|
||||
/* Make sure the WinRT app's IFramworkView can post events on
|
||||
behalf of SDL:
|
||||
*/
|
||||
SDL_WinRTGlobalApp->SetSDLWindowData(data);
|
||||
|
||||
/* All done! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_DestroyWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (SDL_WinRTGlobalApp->HasSDLWindowData() &&
|
||||
SDL_WinRTGlobalApp->GetSDLWindowData()->sdlWindow == window)
|
||||
{
|
||||
SDL_WinRTGlobalApp->SetSDLWindowData(NULL);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
// Delete the internal window data:
|
||||
delete data;
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||
{
|
||||
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (info->version.major <= SDL_MAJOR_VERSION) {
|
||||
info->subsystem = SDL_SYSWM_WINDOWSRT;
|
||||
info->info.winrt.window = reinterpret_cast<IUnknown *>(data->coreWindow.Get());
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
40
src/video/windowsrt/SDL_winrtvideo.h
Normal file
40
src/video/windowsrt/SDL_winrtvideo.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_winrtvideo_h
|
||||
#define _SDL_winrtvideo_h
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
}
|
||||
|
||||
#include <agile.h>
|
||||
|
||||
struct SDL_WindowData
|
||||
{
|
||||
SDL_Window *sdlWindow;
|
||||
Platform::Agile<Windows::UI::Core::CoreWindow> coreWindow;
|
||||
};
|
||||
|
||||
#endif /* _SDL_winrtvideo_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user