mirror of
https://github.com/love2d/megasource.git
synced 2026-08-18 19:54:37 +02:00
Update SDL2 to the latest hg revision of 2.0.4.
This commit is contained in:
@@ -58,8 +58,13 @@
|
||||
/* The configure script already did any necessary checking */
|
||||
# define SDL_XAUDIO2_HAS_SDK 1
|
||||
#elif defined(__WINRT__)
|
||||
/* WinRT always has access to the XAudio 2 SDK */
|
||||
/* WinRT always has access to the XAudio 2 SDK (albeit with a header file
|
||||
that doesn't compile as C code).
|
||||
*/
|
||||
# define SDL_XAUDIO2_HAS_SDK
|
||||
#include "SDL_xaudio2.h" /* ... compiles as C code, in contrast to XAudio2 headers
|
||||
in the Windows SDK, v.10.0.10240.0 (Win 10's initial SDK)
|
||||
*/
|
||||
#else
|
||||
/* XAudio2 exists as of the March 2008 DirectX SDK
|
||||
The XAudio2 implementation available in the Windows 8 SDK targets Windows 8 and newer.
|
||||
@@ -88,17 +93,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The XAudio header file, when #include'd on WinRT, will only compile in C++
|
||||
files, but not C. A few preprocessor-based hacks are defined below in order
|
||||
to get xaudio2.h to compile in the C/non-C++ file, SDL_xaudio2.c.
|
||||
*/
|
||||
#ifdef __WINRT__
|
||||
#define uuid(x)
|
||||
#define DX_BUILD
|
||||
#endif
|
||||
|
||||
#if !defined(_SDL_XAUDIO2_H)
|
||||
#define INITGUID 1
|
||||
#include <xaudio2.h>
|
||||
#endif
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 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.
|
||||
*/
|
||||
|
||||
#ifndef _SDL_XAUDIO2_H
|
||||
#define _SDL_XAUDIO2_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmreg.h>
|
||||
#include <objbase.h>
|
||||
|
||||
/* XAudio2 packs its structure members together as tightly as possible.
|
||||
This pragma is needed to ensure compatibility with XAudio2 on 64-bit
|
||||
platforms.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef interface IXAudio2 IXAudio2;
|
||||
typedef interface IXAudio2SourceVoice IXAudio2SourceVoice;
|
||||
typedef interface IXAudio2MasteringVoice IXAudio2MasteringVoice;
|
||||
typedef interface IXAudio2EngineCallback IXAudio2EngineCallback;
|
||||
typedef interface IXAudio2VoiceCallback IXAudio2VoiceCallback;
|
||||
typedef interface IXAudio2Voice IXAudio2Voice;
|
||||
typedef interface IXAudio2SubmixVoice IXAudio2SubmixVoice;
|
||||
|
||||
typedef enum _AUDIO_STREAM_CATEGORY {
|
||||
AudioCategory_Other = 0,
|
||||
AudioCategory_ForegroundOnlyMedia,
|
||||
AudioCategory_BackgroundCapableMedia,
|
||||
AudioCategory_Communications,
|
||||
AudioCategory_Alerts,
|
||||
AudioCategory_SoundEffects,
|
||||
AudioCategory_GameEffects,
|
||||
AudioCategory_GameMedia,
|
||||
AudioCategory_GameChat,
|
||||
AudioCategory_Movie,
|
||||
AudioCategory_Media
|
||||
} AUDIO_STREAM_CATEGORY;
|
||||
|
||||
typedef struct XAUDIO2_BUFFER {
|
||||
UINT32 Flags;
|
||||
UINT32 AudioBytes;
|
||||
const BYTE *pAudioData;
|
||||
UINT32 PlayBegin;
|
||||
UINT32 PlayLength;
|
||||
UINT32 LoopBegin;
|
||||
UINT32 LoopLength;
|
||||
UINT32 LoopCount;
|
||||
void *pContext;
|
||||
} XAUDIO2_BUFFER;
|
||||
|
||||
typedef struct XAUDIO2_BUFFER_WMA {
|
||||
const UINT32 *pDecodedPacketCumulativeBytes;
|
||||
UINT32 PacketCount;
|
||||
} XAUDIO2_BUFFER_WMA;
|
||||
|
||||
typedef struct XAUDIO2_SEND_DESCRIPTOR {
|
||||
UINT32 Flags;
|
||||
IXAudio2Voice *pOutputVoice;
|
||||
} XAUDIO2_SEND_DESCRIPTOR;
|
||||
|
||||
typedef struct XAUDIO2_VOICE_SENDS {
|
||||
UINT32 SendCount;
|
||||
XAUDIO2_SEND_DESCRIPTOR *pSends;
|
||||
} XAUDIO2_VOICE_SENDS;
|
||||
|
||||
typedef struct XAUDIO2_EFFECT_DESCRIPTOR {
|
||||
IUnknown *pEffect;
|
||||
BOOL InitialState;
|
||||
UINT32 OutputChannels;
|
||||
} XAUDIO2_EFFECT_DESCRIPTOR;
|
||||
|
||||
typedef struct XAUDIO2_EFFECT_CHAIN {
|
||||
UINT32 EffectCount;
|
||||
XAUDIO2_EFFECT_DESCRIPTOR *pEffectDescriptors;
|
||||
} XAUDIO2_EFFECT_CHAIN;
|
||||
|
||||
typedef struct XAUDIO2_PERFORMANCE_DATA {
|
||||
UINT64 AudioCyclesSinceLastQuery;
|
||||
UINT64 TotalCyclesSinceLastQuery;
|
||||
UINT32 MinimumCyclesPerQuantum;
|
||||
UINT32 MaximumCyclesPerQuantum;
|
||||
UINT32 MemoryUsageInBytes;
|
||||
UINT32 CurrentLatencyInSamples;
|
||||
UINT32 GlitchesSinceEngineStarted;
|
||||
UINT32 ActiveSourceVoiceCount;
|
||||
UINT32 TotalSourceVoiceCount;
|
||||
UINT32 ActiveSubmixVoiceCount;
|
||||
UINT32 ActiveResamplerCount;
|
||||
UINT32 ActiveMatrixMixCount;
|
||||
UINT32 ActiveXmaSourceVoices;
|
||||
UINT32 ActiveXmaStreams;
|
||||
} XAUDIO2_PERFORMANCE_DATA;
|
||||
|
||||
typedef struct XAUDIO2_DEBUG_CONFIGURATION {
|
||||
UINT32 TraceMask;
|
||||
UINT32 BreakMask;
|
||||
BOOL LogThreadID;
|
||||
BOOL LogFileline;
|
||||
BOOL LogFunctionName;
|
||||
BOOL LogTiming;
|
||||
} XAUDIO2_DEBUG_CONFIGURATION;
|
||||
|
||||
typedef struct XAUDIO2_VOICE_DETAILS {
|
||||
UINT32 CreationFlags;
|
||||
UINT32 ActiveFlags;
|
||||
UINT32 InputChannels;
|
||||
UINT32 InputSampleRate;
|
||||
} XAUDIO2_VOICE_DETAILS;
|
||||
|
||||
typedef enum XAUDIO2_FILTER_TYPE {
|
||||
LowPassFilter = 0,
|
||||
BandPassFilter = 1,
|
||||
HighPassFilter = 2,
|
||||
NotchFilter = 3,
|
||||
LowPassOnePoleFilter = 4,
|
||||
HighPassOnePoleFilter = 5
|
||||
} XAUDIO2_FILTER_TYPE;
|
||||
|
||||
typedef struct XAUDIO2_FILTER_PARAMETERS {
|
||||
XAUDIO2_FILTER_TYPE Type;
|
||||
float Frequency;
|
||||
float OneOverQ;
|
||||
} XAUDIO2_FILTER_PARAMETERS;
|
||||
|
||||
typedef struct XAUDIO2_VOICE_STATE {
|
||||
void *pCurrentBufferContext;
|
||||
UINT32 BuffersQueued;
|
||||
UINT64 SamplesPlayed;
|
||||
} XAUDIO2_VOICE_STATE;
|
||||
|
||||
|
||||
typedef UINT32 XAUDIO2_PROCESSOR;
|
||||
#define Processor1 0x00000001
|
||||
#define XAUDIO2_DEFAULT_PROCESSOR Processor1
|
||||
|
||||
#define XAUDIO2_E_DEVICE_INVALIDATED 0x88960004
|
||||
#define XAUDIO2_COMMIT_NOW 0
|
||||
#define XAUDIO2_VOICE_NOSAMPLESPLAYED 0x0100
|
||||
#define XAUDIO2_DEFAULT_CHANNELS 0
|
||||
|
||||
extern HRESULT __stdcall XAudio2Create(
|
||||
_Out_ IXAudio2 **ppXAudio2,
|
||||
_In_ UINT32 Flags,
|
||||
_In_ XAUDIO2_PROCESSOR XAudio2Processor
|
||||
);
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IXAudio2
|
||||
typedef interface IXAudio2 {
|
||||
const struct IXAudio2Vtbl FAR* lpVtbl;
|
||||
} IXAudio2;
|
||||
typedef const struct IXAudio2Vtbl IXAudio2Vtbl;
|
||||
const struct IXAudio2Vtbl
|
||||
{
|
||||
/* IUnknown */
|
||||
STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
|
||||
STDMETHOD_(ULONG, AddRef)(THIS) PURE;
|
||||
STDMETHOD_(ULONG, Release)(THIS) PURE;
|
||||
|
||||
/* IXAudio2 */
|
||||
STDMETHOD_(HRESULT, RegisterForCallbacks)(THIS, IXAudio2EngineCallback *pCallback) PURE;
|
||||
STDMETHOD_(VOID, UnregisterForCallbacks)(THIS, IXAudio2EngineCallback *pCallback) PURE;
|
||||
STDMETHOD_(HRESULT, CreateSourceVoice)(THIS, IXAudio2SourceVoice **ppSourceVoice,
|
||||
const WAVEFORMATEX *pSourceFormat,
|
||||
UINT32 Flags,
|
||||
float MaxFrequencyRatio,
|
||||
IXAudio2VoiceCallback *pCallback,
|
||||
const XAUDIO2_VOICE_SENDS *pSendList,
|
||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain) PURE;
|
||||
STDMETHOD_(HRESULT, CreateSubmixVoice)(THIS, IXAudio2SubmixVoice **ppSubmixVoice,
|
||||
UINT32 InputChannels,
|
||||
UINT32 InputSampleRate,
|
||||
UINT32 Flags,
|
||||
UINT32 ProcessingStage,
|
||||
const XAUDIO2_VOICE_SENDS *pSendList,
|
||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain) PURE;
|
||||
STDMETHOD_(HRESULT, CreateMasteringVoice)(THIS, IXAudio2MasteringVoice **ppMasteringVoice,
|
||||
UINT32 InputChannels,
|
||||
UINT32 InputSampleRate,
|
||||
UINT32 Flags,
|
||||
LPCWSTR szDeviceId,
|
||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain,
|
||||
AUDIO_STREAM_CATEGORY StreamCategory) PURE;
|
||||
STDMETHOD_(HRESULT, StartEngine)(THIS) PURE;
|
||||
STDMETHOD_(VOID, StopEngine)(THIS) PURE;
|
||||
STDMETHOD_(HRESULT, CommitChanges)(THIS, UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(HRESULT, GetPerformanceData)(THIS, XAUDIO2_PERFORMANCE_DATA *pPerfData) PURE;
|
||||
STDMETHOD_(HRESULT, SetDebugConfiguration)(THIS, XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
|
||||
VOID *pReserved) PURE;
|
||||
};
|
||||
|
||||
#define IXAudio2_Release(A) ((A)->lpVtbl->Release(A))
|
||||
#define IXAudio2_CreateSourceVoice(A,B,C,D,E,F,G,H) ((A)->lpVtbl->CreateSourceVoice(A,B,C,D,E,F,G,H))
|
||||
#define IXAudio2_CreateMasteringVoice(A,B,C,D,E,F,G,H) ((A)->lpVtbl->CreateMasteringVoice(A,B,C,D,E,F,G,H))
|
||||
#define IXAudio2_StartEngine(A) ((A)->lpVtbl->StartEngine(A))
|
||||
#define IXAudio2_StopEngine(A) ((A)->lpVtbl->StopEngine(A))
|
||||
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IXAudio2SourceVoice
|
||||
typedef interface IXAudio2SourceVoice {
|
||||
const struct IXAudio2SourceVoiceVtbl FAR* lpVtbl;
|
||||
} IXAudio2SourceVoice;
|
||||
typedef const struct IXAudio2SourceVoiceVtbl IXAudio2SourceVoiceVtbl;
|
||||
const struct IXAudio2SourceVoiceVtbl
|
||||
{
|
||||
/* MSDN says that IXAudio2Voice inherits from IXAudio2, but MSVC's debugger
|
||||
* says otherwise, and that IXAudio2Voice doesn't inherit from any other
|
||||
* interface!
|
||||
*/
|
||||
|
||||
/* IXAudio2Voice */
|
||||
STDMETHOD_(VOID, GetVoiceDetails)(THIS, XAUDIO2_VOICE_DETAILS *pVoiceDetails) PURE;
|
||||
STDMETHOD_(HRESULT, SetOutputVoices)(THIS, const XAUDIO2_VOICE_SENDS *pSendList) PURE;
|
||||
STDMETHOD_(HRESULT, SetEffectChain)(THIS, const XAUDIO2_EFFECT_CHAIN *pEffectChain) PURE;
|
||||
STDMETHOD_(HRESULT, EnableEffect)(THIS, UINT32 EffectIndex, UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(HRESULT, DisableEffect)(THIS, UINT32 EffectIndex, UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetEffectState)(THIS, UINT32 EffectIndex, BOOL *pEnabled) PURE;
|
||||
STDMETHOD_(HRESULT, SetEffectParameters)(THIS, UINT32 EffectIndex,
|
||||
const void *pParameters,
|
||||
UINT32 ParametersByteSize,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetEffectParameters)(THIS, UINT32 EffectIndex,
|
||||
void *pParameters,
|
||||
UINT32 ParametersByteSize) PURE;
|
||||
STDMETHOD_(HRESULT, SetFilterParameters)(THIS, const XAUDIO2_FILTER_PARAMETERS *pParameters,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetFilterParameters)(THIS, XAUDIO2_FILTER_PARAMETERS *pParameters) PURE;
|
||||
STDMETHOD_(HRESULT, SetOutputFilterParameters)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
XAUDIO2_FILTER_PARAMETERS *pParameters,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetOutputFilterParameters)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
XAUDIO2_FILTER_PARAMETERS *pParameters) PURE;
|
||||
STDMETHOD_(HRESULT, SetVolume)(THIS, float Volume,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetVolume)(THIS, float *pVolume) PURE;
|
||||
STDMETHOD_(HRESULT, SetChannelVolumes)(THIS, UINT32 Channels,
|
||||
const float *pVolumes,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetChannelVolumes)(THIS, UINT32 Channels,
|
||||
float *pVolumes) PURE;
|
||||
STDMETHOD_(HRESULT, SetOutputMatrix)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
UINT32 SourceChannels,
|
||||
UINT32 DestinationChannels,
|
||||
const float *pLevelMatrix,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetOutputMatrix)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
UINT32 SourceChannels,
|
||||
UINT32 DestinationChannels,
|
||||
float *pLevelMatrix) PURE;
|
||||
STDMETHOD_(VOID, DestroyVoice)(THIS) PURE;
|
||||
|
||||
/* IXAudio2SourceVoice */
|
||||
STDMETHOD_(HRESULT, Start)(THIS, UINT32 Flags,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(HRESULT, Stop)(THIS, UINT32 Flags,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(HRESULT, SubmitSourceBuffer)(THIS, const XAUDIO2_BUFFER *pBuffer,
|
||||
const XAUDIO2_BUFFER_WMA *pBufferWMA) PURE;
|
||||
STDMETHOD_(HRESULT, FlushSourceBuffers)(THIS) PURE;
|
||||
STDMETHOD_(HRESULT, Discontinuity)(THIS) PURE;
|
||||
STDMETHOD_(HRESULT, ExitLoop)(THIS, UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetState)(THIS, XAUDIO2_VOICE_STATE *pVoiceState,
|
||||
UINT32 Flags) PURE;
|
||||
STDMETHOD_(HRESULT, SetFrequencyRatio)(THIS, float Ratio,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetFrequencyRatio)(THIS, float *pRatio) PURE;
|
||||
STDMETHOD_(HRESULT, SetSourceSampleRate)(THIS, UINT32 NewSourceSampleRate) PURE;
|
||||
};
|
||||
|
||||
#define IXAudio2SourceVoice_DestroyVoice(A) ((A)->lpVtbl->DestroyVoice(A))
|
||||
#define IXAudio2SourceVoice_Start(A,B,C) ((A)->lpVtbl->Start(A,B,C))
|
||||
#define IXAudio2SourceVoice_Stop(A,B,C) ((A)->lpVtbl->Stop(A,B,C))
|
||||
#define IXAudio2SourceVoice_SubmitSourceBuffer(A,B,C) ((A)->lpVtbl->SubmitSourceBuffer(A,B,C))
|
||||
#define IXAudio2SourceVoice_FlushSourceBuffers(A) ((A)->lpVtbl->FlushSourceBuffers(A))
|
||||
#define IXAudio2SourceVoice_Discontinuity(A) ((A)->lpVtbl->Discontinuity(A))
|
||||
#define IXAudio2SourceVoice_GetState(A,B,C) ((A)->lpVtbl->GetState(A,B,C))
|
||||
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IXAudio2MasteringVoice
|
||||
typedef interface IXAudio2MasteringVoice {
|
||||
const struct IXAudio2MasteringVoiceVtbl FAR* lpVtbl;
|
||||
} IXAudio2MasteringVoice;
|
||||
typedef const struct IXAudio2MasteringVoiceVtbl IXAudio2MasteringVoiceVtbl;
|
||||
const struct IXAudio2MasteringVoiceVtbl
|
||||
{
|
||||
/* MSDN says that IXAudio2Voice inherits from IXAudio2, but MSVC's debugger
|
||||
* says otherwise, and that IXAudio2Voice doesn't inherit from any other
|
||||
* interface!
|
||||
*/
|
||||
|
||||
/* IXAudio2Voice */
|
||||
STDMETHOD_(VOID, GetVoiceDetails)(THIS, XAUDIO2_VOICE_DETAILS *pVoiceDetails) PURE;
|
||||
STDMETHOD_(HRESULT, SetOutputVoices)(THIS, const XAUDIO2_VOICE_SENDS *pSendList) PURE;
|
||||
STDMETHOD_(HRESULT, SetEffectChain)(THIS, const XAUDIO2_EFFECT_CHAIN *pEffectChain) PURE;
|
||||
STDMETHOD_(HRESULT, EnableEffect)(THIS, UINT32 EffectIndex, UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(HRESULT, DisableEffect)(THIS, UINT32 EffectIndex, UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetEffectState)(THIS, UINT32 EffectIndex, BOOL *pEnabled) PURE;
|
||||
STDMETHOD_(HRESULT, SetEffectParameters)(THIS, UINT32 EffectIndex,
|
||||
const void *pParameters,
|
||||
UINT32 ParametersByteSize,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetEffectParameters)(THIS, UINT32 EffectIndex,
|
||||
void *pParameters,
|
||||
UINT32 ParametersByteSize) PURE;
|
||||
STDMETHOD_(HRESULT, SetFilterParameters)(THIS, const XAUDIO2_FILTER_PARAMETERS *pParameters,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetFilterParameters)(THIS, XAUDIO2_FILTER_PARAMETERS *pParameters) PURE;
|
||||
STDMETHOD_(HRESULT, SetOutputFilterParameters)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
XAUDIO2_FILTER_PARAMETERS *pParameters,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetOutputFilterParameters)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
XAUDIO2_FILTER_PARAMETERS *pParameters) PURE;
|
||||
STDMETHOD_(HRESULT, SetVolume)(THIS, float Volume,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetVolume)(THIS, float *pVolume) PURE;
|
||||
STDMETHOD_(HRESULT, SetChannelVolumes)(THIS, UINT32 Channels,
|
||||
const float *pVolumes,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetChannelVolumes)(THIS, UINT32 Channels,
|
||||
float *pVolumes) PURE;
|
||||
STDMETHOD_(HRESULT, SetOutputMatrix)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
UINT32 SourceChannels,
|
||||
UINT32 DestinationChannels,
|
||||
const float *pLevelMatrix,
|
||||
UINT32 OperationSet) PURE;
|
||||
STDMETHOD_(VOID, GetOutputMatrix)(THIS, IXAudio2Voice *pDestinationVoice,
|
||||
UINT32 SourceChannels,
|
||||
UINT32 DestinationChannels,
|
||||
float *pLevelMatrix) PURE;
|
||||
STDMETHOD_(VOID, DestroyVoice)(THIS) PURE;
|
||||
|
||||
/* IXAudio2SourceVoice */
|
||||
STDMETHOD_(VOID, GetChannelMask)(THIS, DWORD *pChannelMask) PURE;
|
||||
};
|
||||
|
||||
#define IXAudio2MasteringVoice_DestroyVoice(A) ((A)->lpVtbl->DestroyVoice(A))
|
||||
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IXAudio2VoiceCallback
|
||||
typedef interface IXAudio2VoiceCallback {
|
||||
const struct IXAudio2VoiceCallbackVtbl FAR* lpVtbl;
|
||||
} IXAudio2VoiceCallback;
|
||||
typedef const struct IXAudio2VoiceCallbackVtbl IXAudio2VoiceCallbackVtbl;
|
||||
const struct IXAudio2VoiceCallbackVtbl
|
||||
{
|
||||
/* MSDN says that IXAudio2VoiceCallback inherits from IXAudio2, but SDL's
|
||||
* own code says otherwise, and that IXAudio2VoiceCallback doesn't inherit
|
||||
* from any other interface!
|
||||
*/
|
||||
|
||||
/* IXAudio2VoiceCallback */
|
||||
STDMETHOD_(VOID, OnVoiceProcessingPassStart)(THIS, UINT32 BytesRequired) PURE;
|
||||
STDMETHOD_(VOID, OnVoiceProcessingPassEnd)(THIS) PURE;
|
||||
STDMETHOD_(VOID, OnStreamEnd)(THIS) PURE;
|
||||
STDMETHOD_(VOID, OnBufferStart)(THIS, void *pBufferContext) PURE;
|
||||
STDMETHOD_(VOID, OnBufferEnd)(THIS, void *pBufferContext) PURE;
|
||||
STDMETHOD_(VOID, OnLoopEnd)(THIS, void *pBufferContext) PURE;
|
||||
STDMETHOD_(VOID, OnVoiceError)(THIS, void *pBufferContext, HRESULT Error) PURE;
|
||||
};
|
||||
|
||||
#pragma pack(pop) /* Undo pragma push */
|
||||
|
||||
#endif /* _SDL_XAUDIO2_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -71,7 +71,6 @@ static jclass mActivityClass;
|
||||
|
||||
/* method signatures */
|
||||
static jmethodID midGetNativeSurface;
|
||||
static jmethodID midFlipBuffers;
|
||||
static jmethodID midAudioInit;
|
||||
static jmethodID midAudioWriteShortBuffer;
|
||||
static jmethodID midAudioWriteByteBuffer;
|
||||
@@ -119,8 +118,6 @@ JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
|
||||
|
||||
midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"getNativeSurface","()Landroid/view/Surface;");
|
||||
midFlipBuffers = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"flipBuffers","()V");
|
||||
midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"audioInit", "(IZZI)I");
|
||||
midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
@@ -134,7 +131,7 @@ JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
|
||||
|
||||
bHasNewData = SDL_FALSE;
|
||||
|
||||
if(!midGetNativeSurface || !midFlipBuffers || !midAudioInit ||
|
||||
if (!midGetNativeSurface || !midAudioInit ||
|
||||
!midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit || !midPollInputDevices) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
|
||||
}
|
||||
@@ -160,7 +157,7 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeResize(
|
||||
}
|
||||
|
||||
/* Paddown */
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_onNativePadDown(
|
||||
JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_onNativePadDown(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
{
|
||||
@@ -168,7 +165,7 @@ JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_onNativePadDown(
|
||||
}
|
||||
|
||||
/* Padup */
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_onNativePadUp(
|
||||
JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_onNativePadUp(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
{
|
||||
@@ -192,7 +189,7 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeHat(
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
|
||||
JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name, jint is_accelerometer,
|
||||
jint nbuttons, jint naxes, jint nhats, jint nballs)
|
||||
@@ -207,7 +204,7 @@ JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
|
||||
return retval;
|
||||
}
|
||||
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
|
||||
JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
|
||||
JNIEnv* env, jclass jcls, jint device_id)
|
||||
{
|
||||
return Android_RemoveJoystick(device_id);
|
||||
@@ -267,11 +264,6 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_nativeFlipBuffers(JNIEnv* env, jclass jcls)
|
||||
{
|
||||
SDL_GL_SwapWindow(Android_Window);
|
||||
}
|
||||
|
||||
/* Keydown */
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
|
||||
JNIEnv* env, jclass jcls, jint keycode)
|
||||
@@ -478,12 +470,6 @@ ANativeWindow* Android_JNI_GetNativeWindow(void)
|
||||
return anw;
|
||||
}
|
||||
|
||||
void Android_JNI_SwapWindow(void)
|
||||
{
|
||||
JNIEnv *mEnv = Android_JNI_GetEnv();
|
||||
(*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midFlipBuffers);
|
||||
}
|
||||
|
||||
void Android_JNI_SetActivityTitle(const char *title)
|
||||
{
|
||||
jmethodID mid;
|
||||
@@ -785,12 +771,19 @@ fallback:
|
||||
"open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
|
||||
inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /* ACCESS_RANDOM */);
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
// Try fallback to APK Extension files
|
||||
/* Try fallback to APK expansion files */
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
|
||||
"openAPKExtensionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
|
||||
"openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
|
||||
if (!mid) {
|
||||
SDL_SetError("No openAPKExpansionInputStream() in Java class");
|
||||
goto failure; /* Java class is missing the required method */
|
||||
}
|
||||
inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
|
||||
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
/* Exception is checked first because it always needs to be cleared.
|
||||
* If no exception occurred then the last SDL error message is kept.
|
||||
*/
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE) || !inputStream) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,6 @@ extern "C" {
|
||||
#include "SDL_rect.h"
|
||||
|
||||
/* Interface from the SDL library into the Android Java activity */
|
||||
/* extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion, int red, int green, int blue, int alpha, int buffer, int depth, int stencil, int buffers, int samples);
|
||||
extern SDL_bool Android_JNI_DeleteContext(void); */
|
||||
extern void Android_JNI_SwapWindow(void);
|
||||
extern void Android_JNI_SetActivityTitle(const char *title);
|
||||
extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
|
||||
extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
|
||||
@@ -64,7 +61,7 @@ SDL_bool Android_JNI_HasClipboardText(void);
|
||||
|
||||
/* Power support */
|
||||
int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
|
||||
|
||||
|
||||
/* Joystick support */
|
||||
void Android_JNI_PollInputDevices(void);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
XInputGetState_t SDL_XInputGetState = NULL;
|
||||
XInputSetState_t SDL_XInputSetState = NULL;
|
||||
XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
|
||||
XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation = NULL;
|
||||
DWORD SDL_XInputVersion = 0;
|
||||
|
||||
static HANDLE s_pXInputDLL = 0;
|
||||
@@ -55,6 +56,7 @@ WIN_LoadXInputDLL(void)
|
||||
SDL_XInputGetState = (XInputGetState_t)XInputGetState;
|
||||
SDL_XInputSetState = (XInputSetState_t)XInputSetState;
|
||||
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)XInputGetCapabilities;
|
||||
SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)XInputGetBatteryInformation;
|
||||
|
||||
/* XInput 1.4 ships with Windows 8 and 8.1: */
|
||||
SDL_XInputVersion = (1 << 16) | 4;
|
||||
@@ -84,11 +86,15 @@ WIN_LoadXInputDLL(void)
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_4.dll"); /* 1.4 Ships with Windows 8. */
|
||||
if (!s_pXInputDLL) {
|
||||
version = (1 << 16) | 3;
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_3.dll"); /* 1.3 Ships with Vista and Win7, can be installed as a redistributable component. */
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_3.dll"); /* 1.3 can be installed as a redistributable component. */
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
s_pXInputDLL = LoadLibrary(L"bin\\XInput1_3.dll");
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
/* "9.1.0" Ships with Vista and Win7, and is more limited than 1.3+ (e.g. XInputGetStateEx is not available.) */
|
||||
s_pXInputDLL = LoadLibrary(L"XInput9_1_0.dll");
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -99,8 +105,12 @@ WIN_LoadXInputDLL(void)
|
||||
|
||||
/* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
|
||||
SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, (LPCSTR)100);
|
||||
if (!SDL_XInputGetState) {
|
||||
SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetState");
|
||||
}
|
||||
SDL_XInputSetState = (XInputSetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputSetState");
|
||||
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetCapabilities");
|
||||
SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetBatteryInformation" );
|
||||
if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
|
||||
WIN_UnloadXInputDLL();
|
||||
return -1;
|
||||
|
||||
@@ -76,6 +76,29 @@
|
||||
#define XINPUT_GAMEPAD_GUIDE 0x0400
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_DEVTYPE_GAMEPAD
|
||||
#define BATTERY_DEVTYPE_GAMEPAD 0x00
|
||||
#endif
|
||||
#ifndef BATTERY_TYPE_WIRED
|
||||
#define BATTERY_TYPE_WIRED 0x01
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_TYPE_UNKNOWN
|
||||
#define BATTERY_TYPE_UNKNOWN 0xFF
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_EMPTY
|
||||
#define BATTERY_LEVEL_EMPTY 0x00
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_LOW
|
||||
#define BATTERY_LEVEL_LOW 0x01
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_MEDIUM
|
||||
#define BATTERY_LEVEL_MEDIUM 0x02
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_FULL
|
||||
#define BATTERY_LEVEL_FULL 0x03
|
||||
#endif
|
||||
|
||||
/* typedef's for XInput structs we use */
|
||||
typedef struct
|
||||
{
|
||||
@@ -95,6 +118,12 @@ typedef struct
|
||||
XINPUT_GAMEPAD_EX Gamepad;
|
||||
} XINPUT_STATE_EX;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE BatteryType;
|
||||
BYTE BatteryLevel;
|
||||
} XINPUT_BATTERY_INFORMATION_EX;
|
||||
|
||||
/* Forward decl's for XInput API's we load dynamically and use if available */
|
||||
typedef DWORD (WINAPI *XInputGetState_t)
|
||||
(
|
||||
@@ -115,17 +144,26 @@ typedef DWORD (WINAPI *XInputGetCapabilities_t)
|
||||
XINPUT_CAPABILITIES* pCapabilities /* [out] Receives the capabilities */
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *XInputGetBatteryInformation_t)
|
||||
(
|
||||
DWORD dwUserIndex,
|
||||
BYTE devType,
|
||||
XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation
|
||||
);
|
||||
|
||||
extern int WIN_LoadXInputDLL(void);
|
||||
extern void WIN_UnloadXInputDLL(void);
|
||||
|
||||
extern XInputGetState_t SDL_XInputGetState;
|
||||
extern XInputSetState_t SDL_XInputSetState;
|
||||
extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
|
||||
extern XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation;
|
||||
extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
|
||||
|
||||
#define XINPUTGETSTATE SDL_XInputGetState
|
||||
#define XINPUTSETSTATE SDL_XInputSetState
|
||||
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
|
||||
#define XINPUTGETBATTERYINFORMATION SDL_XInputGetBatteryInformation
|
||||
|
||||
#endif /* HAVE_XINPUT_H */
|
||||
|
||||
|
||||
@@ -184,97 +184,48 @@ static void WINRT_SetDisplayOrientationsPreference(void *userdata, const char *n
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_ProcessWindowSizeChange()
|
||||
WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
|
||||
if (coreWindow) {
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
SDL_Window * window = WINRT_GlobalSDLWindow;
|
||||
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
// Make the new window size be the one true fullscreen mode.
|
||||
// This change was initially 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.
|
||||
SDL_DisplayMode newDisplayMode;
|
||||
if (WINRT_CalcDisplayModeUsingNativeWindow(&newDisplayMode) != 0) {
|
||||
return;
|
||||
}
|
||||
int x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
|
||||
int y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
|
||||
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
|
||||
// Make note of the old display mode, and it's old driverdata.
|
||||
SDL_DisplayMode oldDisplayMode;
|
||||
SDL_zero(oldDisplayMode);
|
||||
if (_this) {
|
||||
oldDisplayMode = _this->displays[0].desktop_mode;
|
||||
}
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
|
||||
/* WinPhone 8.0 always keeps its native window size in portrait,
|
||||
regardless of orientation. This changes in WinPhone 8.1,
|
||||
in which the native window's size changes along with
|
||||
orientation.
|
||||
|
||||
// Setup the new display mode in the appropriate spots.
|
||||
if (_this) {
|
||||
// Make a full copy of the display mode for display_modes[0],
|
||||
// one with with a separately malloced 'driverdata' field.
|
||||
// SDL_VideoQuit(), if called, will attempt to free the driverdata
|
||||
// fields in 'desktop_mode' and each entry in the 'display_modes'
|
||||
// array.
|
||||
if (_this->displays[0].display_modes[0].driverdata) {
|
||||
// Free the previous mode's memory
|
||||
SDL_free(_this->displays[0].display_modes[0].driverdata);
|
||||
_this->displays[0].display_modes[0].driverdata = NULL;
|
||||
}
|
||||
if (WINRT_DuplicateDisplayMode(&(_this->displays[0].display_modes[0]), &newDisplayMode) != 0) {
|
||||
// Uh oh, something went wrong. A malloc call probably failed.
|
||||
SDL_free(newDisplayMode.driverdata);
|
||||
return;
|
||||
}
|
||||
|
||||
// Install 'newDisplayMode' into 'current_mode' and 'desktop_mode'.
|
||||
_this->displays[0].current_mode = newDisplayMode;
|
||||
_this->displays[0].desktop_mode = newDisplayMode;
|
||||
}
|
||||
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
// If the window size changed, send a resize event to SDL and its host app:
|
||||
int window_w = 0;
|
||||
int window_h = 0;
|
||||
SDL_GetWindowSize(WINRT_GlobalSDLWindow, &window_w, &window_h);
|
||||
if ((window_w != newDisplayMode.w) || (window_h != newDisplayMode.h)) {
|
||||
SDL_SendWindowEvent(
|
||||
WINRT_GlobalSDLWindow,
|
||||
SDL_WINDOWEVENT_RESIZED,
|
||||
newDisplayMode.w,
|
||||
newDisplayMode.h);
|
||||
} else {
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// HACK: Make sure that orientation changes
|
||||
// lead to the Direct3D renderer's viewport getting updated:
|
||||
//
|
||||
// For some reason, this doesn't seem to need to be done on Windows 8.x,
|
||||
// even when going from Landscape to LandscapeFlipped. It only seems to
|
||||
// be needed on Windows Phone, at least when I tested on my devices.
|
||||
// I'm not currently sure why this is, but it seems to work fine. -- David L.
|
||||
//
|
||||
// TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
|
||||
const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
|
||||
const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
|
||||
if (oldOrientation != newOrientation)
|
||||
{
|
||||
SDL_SendWindowEvent(
|
||||
WINRT_GlobalSDLWindow,
|
||||
SDL_WINDOWEVENT_SIZE_CHANGED,
|
||||
newDisplayMode.w,
|
||||
newDisplayMode.h);
|
||||
Attempt to emulate WinPhone 8.1's behavior on WinPhone 8.0, with
|
||||
regards to window size. This fixes a rendering bug that occurs
|
||||
when a WinPhone 8.0 app is rotated to either 90 or 270 degrees.
|
||||
*/
|
||||
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
|
||||
switch (currentOrientation) {
|
||||
case DisplayOrientations::Landscape:
|
||||
case DisplayOrientations::LandscapeFlipped: {
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
} break;
|
||||
}
|
||||
#endif
|
||||
|
||||
WINRT_UpdateWindowFlags(window, SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
|
||||
/* The window can move during a resize event, such as when maximizing
|
||||
or resizing from a corner */
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, free the 'driverdata' field of the old 'desktop_mode'.
|
||||
if (oldDisplayMode.driverdata) {
|
||||
SDL_free(oldDisplayMode.driverdata);
|
||||
oldDisplayMode.driverdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_WinRTApp::SDL_WinRTApp() :
|
||||
@@ -286,7 +237,7 @@ SDL_WinRTApp::SDL_WinRTApp() :
|
||||
void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
|
||||
{
|
||||
applicationView->Activated +=
|
||||
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnActivated);
|
||||
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnAppActivated);
|
||||
|
||||
CoreApplication::Suspending +=
|
||||
ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
|
||||
@@ -305,35 +256,61 @@ void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
|
||||
#endif
|
||||
{
|
||||
#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__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
} else {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
|
||||
{
|
||||
CoreWindow^ window = CoreWindow::GetForCurrentThread();
|
||||
if (window) {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f}\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.X,
|
||||
window->Bounds.Y,
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
} else {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
WINRT_ProcessWindowSizeChange();
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// HACK: Make sure that orientation changes
|
||||
// lead to the Direct3D renderer's viewport getting updated:
|
||||
//
|
||||
// For some reason, this doesn't seem to need to be done on Windows 8.x,
|
||||
// even when going from Landscape to LandscapeFlipped. It only seems to
|
||||
// be needed on Windows Phone, at least when I tested on my devices.
|
||||
// I'm not currently sure why this is, but it seems to work fine. -- David L.
|
||||
//
|
||||
// TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
|
||||
SDL_Window * window = WINRT_GlobalSDLWindow;
|
||||
if (window) {
|
||||
SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
|
||||
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SIZE_CHANGED, w, h);
|
||||
}
|
||||
#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",
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f}\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.X,
|
||||
window->Bounds.Y,
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
#endif
|
||||
@@ -344,6 +321,9 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
window->VisibilityChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
|
||||
|
||||
window->Activated +=
|
||||
ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &SDL_WinRTApp::OnWindowActivated);
|
||||
|
||||
window->Closed +=
|
||||
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
|
||||
|
||||
@@ -360,6 +340,12 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
window->PointerReleased +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
|
||||
|
||||
window->PointerEntered +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerEntered);
|
||||
|
||||
window->PointerExited +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerExited);
|
||||
|
||||
window->PointerWheelChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
|
||||
|
||||
@@ -395,7 +381,7 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
// TODO, WinRT: 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_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
// Make sure we know when a user has opened the app's settings pane.
|
||||
// This is needed in order to display a privacy policy, which needs
|
||||
// to be done for network-enabled apps, as per Windows Store requirements.
|
||||
@@ -488,7 +474,7 @@ void SDL_WinRTApp::Uninitialize()
|
||||
{
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
void SDL_WinRTApp::OnSettingsPaneCommandsRequested(
|
||||
Windows::UI::ApplicationSettings::SettingsPane ^p,
|
||||
Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args)
|
||||
@@ -530,14 +516,15 @@ void SDL_WinRTApp::OnSettingsPaneCommandsRequested(
|
||||
args->Request->ApplicationCommands->Append(cmd);
|
||||
}
|
||||
}
|
||||
#endif // if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
|
||||
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, WINRT_GlobalSDLWindow?=%s\n",
|
||||
SDL_Log("%s, size={%f,%f}, bounds={%f,%f,%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
|
||||
__FUNCTION__,
|
||||
args->Size.Width, args->Size.Height,
|
||||
sender->Bounds.X, sender->Bounds.Y, sender->Bounds.Width, sender->Bounds.Height,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
@@ -550,20 +537,26 @@ void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEven
|
||||
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, visible?=%s, WINRT_GlobalSDLWindow?=%s\n",
|
||||
SDL_Log("%s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s\n",
|
||||
__FUNCTION__,
|
||||
(args->Visible ? "yes" : "no"),
|
||||
sender->Bounds.X, sender->Bounds.Y,
|
||||
sender->Bounds.Width, sender->Bounds.Height,
|
||||
(WINRT_GlobalSDLWindow ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
m_windowVisible = args->Visible;
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
|
||||
|
||||
Uint32 latestWindowFlags = WINRT_DetectWindowFlags(WINRT_GlobalSDLWindow);
|
||||
if (args->Visible) {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
if (latestWindowFlags & SDL_WINDOW_MAXIMIZED) {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
|
||||
} else {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
}
|
||||
} else {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
||||
@@ -580,6 +573,59 @@ void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEven
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, WINRT_GlobalSDLWindow?=%s\n\n",
|
||||
__FUNCTION__,
|
||||
(WINRT_GlobalSDLWindow ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
/* There's no property in Win 8.x to tell whether a window is active or
|
||||
not. [De]activation events are, however, sent to the app. We'll just
|
||||
record those, in case the CoreWindow gets wrapped by an SDL_Window at
|
||||
some future time.
|
||||
*/
|
||||
sender->CustomProperties->Insert("SDLHelperWindowActivationState", args->WindowActivationState);
|
||||
|
||||
SDL_Window * window = WINRT_GlobalSDLWindow;
|
||||
if (window) {
|
||||
if (args->WindowActivationState != CoreWindowActivationState::Deactivated) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
if (SDL_GetKeyboardFocus() != window) {
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
|
||||
/* Send a mouse-motion event as appropriate.
|
||||
This doesn't work when called from OnPointerEntered, at least
|
||||
not in WinRT CoreWindow apps (as OnPointerEntered doesn't
|
||||
appear to be called after window-reactivation, at least not
|
||||
in Windows 10, Build 10586.3 (November 2015 update, non-beta).
|
||||
|
||||
Don't do it on WinPhone 8.0 though, as CoreWindow's 'PointerPosition'
|
||||
property isn't available.
|
||||
*/
|
||||
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION >= NTDDI_WINBLUE)
|
||||
Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize);
|
||||
SDL_SendMouseMotion(window, 0, 0, (int)cursorPos.X, (int)cursorPos.Y);
|
||||
#endif
|
||||
|
||||
/* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
|
||||
//WIN_CheckAsyncMouseRelease(data);
|
||||
|
||||
/* TODO, WinRT: implement clipboard support, if possible */
|
||||
///*
|
||||
// * FIXME: Update keyboard state
|
||||
// */
|
||||
//WIN_CheckClipboardUpdate(data->videodata);
|
||||
} else {
|
||||
if (SDL_GetKeyboardFocus() == window) {
|
||||
SDL_SetKeyboardFocus(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
@@ -588,7 +634,7 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
||||
m_windowClosed = true;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
void SDL_WinRTApp::OnAppActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
{
|
||||
CoreWindow::GetForCurrentThread()->Activate();
|
||||
}
|
||||
@@ -688,10 +734,28 @@ void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
|
||||
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerEntered(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer entered", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerEnteredEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerExited(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer exited", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerExitedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
|
||||
@@ -43,11 +43,11 @@ protected:
|
||||
|
||||
// Event Handlers.
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
void OnSettingsPaneCommandsRequested(
|
||||
Windows::UI::ApplicationSettings::SettingsPane ^p,
|
||||
Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args);
|
||||
#endif // if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
@@ -56,16 +56,19 @@ protected:
|
||||
#endif
|
||||
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 OnAppActivated(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 OnExiting(Platform::Object^ sender, Platform::Object^ args);
|
||||
void OnWindowActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ 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 OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerExited(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);
|
||||
|
||||
@@ -594,3 +594,6 @@
|
||||
#define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL
|
||||
#define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL
|
||||
#define SDL_SetWindowsMessageHook SDL_SetWindowsMessageHook_REAL
|
||||
#define SDL_JoystickCurrentPowerLevel SDL_JoystickCurrentPowerLevel_REAL
|
||||
#define SDL_GameControllerFromInstanceID SDL_GameControllerFromInstanceID_REAL
|
||||
#define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_REAL
|
||||
|
||||
@@ -628,3 +628,6 @@ SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_SetWindowsMessageHook,(SDL_WindowsMessageHook a, void *b),(a,b),)
|
||||
#endif
|
||||
SDL_DYNAPI_PROC(int,SDL_GetDisplayDPI,(int a, float *b, float *c, float *d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_JoystickCurrentPowerLevel,(SDL_Joystick *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromInstanceID,(SDL_JoystickID a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromInstanceID,(SDL_JoystickID a),(a),return)
|
||||
|
||||
@@ -649,4 +649,10 @@ SDL_SendSysWMEvent(SDL_SysWMmsg * message)
|
||||
return (posted);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendKeymapChangedEvent(void)
|
||||
{
|
||||
return SDL_SendAppEvent(SDL_KEYMAPCHANGED);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -38,6 +38,7 @@ extern void SDL_QuitInterrupt(void);
|
||||
|
||||
extern int SDL_SendAppEvent(SDL_EventType eventType);
|
||||
extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message);
|
||||
extern int SDL_SendKeymapChangedEvent(void);
|
||||
|
||||
extern int SDL_QuitInit(void);
|
||||
extern int SDL_SendQuit(void);
|
||||
|
||||
@@ -465,7 +465,7 @@ SDL_SYS_HapticOpen(SDL_Haptic * haptic)
|
||||
}
|
||||
|
||||
/* Set the fname. */
|
||||
haptic->hwdata->fname = item->fname;
|
||||
haptic->hwdata->fname = SDL_strdup( item->fname );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -542,11 +542,12 @@ SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
/* Find the joystick in the haptic list. */
|
||||
for (item = SDL_hapticlist; item; item = item->next) {
|
||||
if (SDL_strcmp(item->fname, joystick->hwdata->fname) == 0) {
|
||||
haptic->index = device_index;
|
||||
break;
|
||||
}
|
||||
++device_index;
|
||||
}
|
||||
haptic->index = device_index;
|
||||
|
||||
if (device_index >= MAX_HAPTICS) {
|
||||
return SDL_SetError("Haptic: Joystick doesn't have Haptic capabilities");
|
||||
}
|
||||
@@ -561,7 +562,8 @@ SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
return -1;
|
||||
}
|
||||
|
||||
haptic->hwdata->fname = item->fname;
|
||||
haptic->hwdata->fname = SDL_strdup( joystick->hwdata->fname );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -583,6 +585,7 @@ SDL_SYS_HapticClose(SDL_Haptic * haptic)
|
||||
close(haptic->hwdata->fd);
|
||||
|
||||
/* Free */
|
||||
SDL_free(haptic->hwdata->fname);
|
||||
SDL_free(haptic->hwdata);
|
||||
haptic->hwdata = NULL;
|
||||
}
|
||||
|
||||
@@ -1046,6 +1046,25 @@ SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller)
|
||||
return gamecontroller->joystick;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find the SDL_GameController that owns this instance id
|
||||
*/
|
||||
SDL_GameController *
|
||||
SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
|
||||
{
|
||||
SDL_GameController *gamecontroller = SDL_gamecontrollers;
|
||||
while (gamecontroller) {
|
||||
if (gamecontroller->joystick->instance_id == joyid) {
|
||||
return gamecontroller;
|
||||
}
|
||||
gamecontroller = gamecontroller->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the SDL joystick layer binding for this controller axis mapping
|
||||
*/
|
||||
|
||||
@@ -36,8 +36,10 @@ static const char *s_ControllerMappings [] =
|
||||
#endif
|
||||
#if SDL_JOYSTICK_DINPUT
|
||||
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"e8206058000000000000504944564944,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
|
||||
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"6d0418c2000000000000504944564944,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,",
|
||||
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
|
||||
@@ -46,6 +48,7 @@ static const char *s_ControllerMappings [] =
|
||||
"4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
#endif
|
||||
#if defined(__MACOSX__)
|
||||
"830500000000000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
@@ -53,10 +56,14 @@ static const char *s_ControllerMappings [] =
|
||||
"6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
|
||||
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"11010000000000002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,",
|
||||
"11010000000000001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,",
|
||||
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
|
||||
#endif
|
||||
#if defined(__LINUX__)
|
||||
"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
|
||||
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
@@ -65,11 +72,13 @@ static const char *s_ControllerMappings [] =
|
||||
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
|
||||
"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
|
||||
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
|
||||
"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
|
||||
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
@@ -82,6 +91,10 @@ static const char *s_ControllerMappings [] =
|
||||
#if defined(__ANDROID__)
|
||||
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
||||
#endif
|
||||
#if defined(SDL_JOYSTICK_MFI)
|
||||
"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,",
|
||||
"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,",
|
||||
#endif
|
||||
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
|
||||
"emscripten,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
#endif
|
||||
|
||||
@@ -178,6 +178,7 @@ SDL_JoystickOpen(int device_index)
|
||||
if (joystick->buttons) {
|
||||
SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
|
||||
}
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
|
||||
|
||||
/* Add joystick to list */
|
||||
++joystick->ref_count;
|
||||
@@ -372,6 +373,23 @@ SDL_JoystickInstanceID(SDL_Joystick * joystick)
|
||||
return (joystick->instance_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the SDL_Joystick that owns this instance id
|
||||
*/
|
||||
SDL_Joystick *
|
||||
SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
|
||||
{
|
||||
SDL_Joystick *joystick = SDL_joysticks;
|
||||
while (joystick) {
|
||||
if (joystick->instance_id == joyid) {
|
||||
return joystick;
|
||||
}
|
||||
joystick = joystick->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the friendly name of this joystick
|
||||
*/
|
||||
@@ -619,10 +637,10 @@ SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
|
||||
/* Make sure we're not getting garbage or duplicate events */
|
||||
if (button >= joystick->nbuttons) {
|
||||
return 0;
|
||||
}
|
||||
if (state == joystick->buttons[button]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (state == joystick->buttons[button]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for button
|
||||
* release. */
|
||||
@@ -669,14 +687,17 @@ SDL_JoystickUpdate(void)
|
||||
int i;
|
||||
|
||||
/* Tell the app that everything is centered/unpressed... */
|
||||
for (i = 0; i < joystick->naxes; i++)
|
||||
for (i = 0; i < joystick->naxes; i++) {
|
||||
SDL_PrivateJoystickAxis(joystick, i, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < joystick->nbuttons; i++)
|
||||
for (i = 0; i < joystick->nbuttons; i++) {
|
||||
SDL_PrivateJoystickButton(joystick, i, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < joystick->nhats; i++)
|
||||
for (i = 0; i < joystick->nhats; i++) {
|
||||
SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
|
||||
}
|
||||
|
||||
joystick->force_recentering = SDL_FALSE;
|
||||
}
|
||||
@@ -822,4 +843,21 @@ SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
|
||||
}
|
||||
|
||||
|
||||
/* update the power level for this joystick */
|
||||
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
|
||||
{
|
||||
joystick->epowerlevel = ePowerLevel;
|
||||
}
|
||||
|
||||
|
||||
/* return its power level */
|
||||
SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (SDL_JOYSTICK_POWER_UNKNOWN);
|
||||
}
|
||||
return joystick->epowerlevel;
|
||||
}
|
||||
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -41,6 +41,8 @@ extern int SDL_PrivateJoystickHat(SDL_Joystick * joystick,
|
||||
Uint8 hat, Uint8 value);
|
||||
extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick,
|
||||
Uint8 button, Uint8 state);
|
||||
extern void SDL_PrivateJoystickBatteryLevel( SDL_Joystick * joystick,
|
||||
SDL_JoystickPowerLevel ePowerLevel );
|
||||
|
||||
/* Internal sanity checking functions */
|
||||
extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
|
||||
|
||||
@@ -54,6 +54,7 @@ struct _SDL_Joystick
|
||||
int ref_count; /* Reference count for multiple opens */
|
||||
|
||||
SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
|
||||
SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
|
||||
struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
|
||||
};
|
||||
|
||||
|
||||
@@ -243,6 +243,18 @@ AddHIDElement(const void *value, void *parameter)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kHIDUsage_GD_DPadUp:
|
||||
case kHIDUsage_GD_DPadDown:
|
||||
case kHIDUsage_GD_DPadRight:
|
||||
case kHIDUsage_GD_DPadLeft:
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstButton)) {
|
||||
element = (recElement *) SDL_calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
pDevice->buttons++;
|
||||
headElement = &(pDevice->firstButton);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -265,6 +277,7 @@ AddHIDElement(const void *value, void *parameter)
|
||||
break;
|
||||
|
||||
case kHIDPage_Button:
|
||||
case kHIDPage_Consumer: /* e.g. 'pause' button on Steelseries MFi gamepads. */
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstButton)) {
|
||||
element = (recElement *) SDL_calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
@@ -465,6 +478,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||
curdevice = curdevice->pNext;
|
||||
}
|
||||
curdevice->pNext = device;
|
||||
++device_index; /* bump by one since we counted by pNext. */
|
||||
}
|
||||
|
||||
/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceAdded()? */
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_IOKIT_H
|
||||
#define SDL_JOYSTICK_IOKIT_H
|
||||
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
/* This is the iOS implementation of the SDL joystick API */
|
||||
#include "SDL_sysjoystick_c.h"
|
||||
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#include "SDL_config_iphoneos.h"
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_hints.h"
|
||||
@@ -28,15 +32,221 @@
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
#import <CoreMotion/CoreMotion.h>
|
||||
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#import "SDL_config_iphoneos.h"
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
const char *accelerometerName = "iOS Accelerometer";
|
||||
static id connectObserver = nil;
|
||||
static id disconnectObserver = nil;
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
static const char *accelerometerName = "iOS Accelerometer";
|
||||
static CMMotionManager *motionManager = nil;
|
||||
|
||||
static SDL_JoystickDeviceItem *deviceList = NULL;
|
||||
|
||||
static int numjoysticks = 0;
|
||||
static SDL_JoystickID instancecounter = 0;
|
||||
|
||||
static SDL_JoystickDeviceItem *
|
||||
GetDeviceForIndex(int device_index)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
int i = 0;
|
||||
|
||||
while (i < device_index) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
device = device->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
const char *name = NULL;
|
||||
/* Explicitly retain the controller because SDL_JoystickDeviceItem is a
|
||||
* struct, and ARC doesn't work with structs. */
|
||||
device->controller = (__bridge GCController *) CFBridgingRetain(controller);
|
||||
|
||||
if (controller.vendorName) {
|
||||
name = controller.vendorName.UTF8String;
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
name = "MFi Gamepad";
|
||||
}
|
||||
|
||||
device->name = SDL_strdup(name);
|
||||
|
||||
device->guid.data[0] = 'M';
|
||||
device->guid.data[1] = 'F';
|
||||
device->guid.data[2] = 'i';
|
||||
device->guid.data[3] = 'G';
|
||||
device->guid.data[4] = 'a';
|
||||
device->guid.data[5] = 'm';
|
||||
device->guid.data[6] = 'e';
|
||||
device->guid.data[7] = 'p';
|
||||
device->guid.data[8] = 'a';
|
||||
device->guid.data[9] = 'd';
|
||||
|
||||
if (controller.extendedGamepad) {
|
||||
device->guid.data[10] = 1;
|
||||
} else if (controller.gamepad) {
|
||||
device->guid.data[10] = 2;
|
||||
}
|
||||
|
||||
if (controller.extendedGamepad) {
|
||||
device->naxes = 6; /* 2 thumbsticks and 2 triggers */
|
||||
device->nhats = 1; /* d-pad */
|
||||
device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
|
||||
} else if (controller.gamepad) {
|
||||
device->naxes = 0; /* no traditional analog inputs */
|
||||
device->nhats = 1; /* d-pad */
|
||||
device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
|
||||
}
|
||||
/* TODO: Handle micro profiles on tvOS. */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
while (device != NULL) {
|
||||
if (device->controller == controller) {
|
||||
return;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
|
||||
device = (SDL_JoystickDeviceItem *) SDL_malloc(sizeof(SDL_JoystickDeviceItem));
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_zerop(device);
|
||||
|
||||
device->accelerometer = accelerometer;
|
||||
device->instance_id = instancecounter++;
|
||||
|
||||
if (accelerometer) {
|
||||
device->name = SDL_strdup(accelerometerName);
|
||||
device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
|
||||
device->nhats = 0;
|
||||
device->nbuttons = 0;
|
||||
|
||||
/* Use the accelerometer name as a GUID. */
|
||||
SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
|
||||
} else if (controller) {
|
||||
SDL_SYS_AddMFIJoystickDevice(device, controller);
|
||||
}
|
||||
|
||||
if (deviceList == NULL) {
|
||||
deviceList = device;
|
||||
} else {
|
||||
SDL_JoystickDeviceItem *lastdevice = deviceList;
|
||||
while (lastdevice->next != NULL) {
|
||||
lastdevice = lastdevice->next;
|
||||
}
|
||||
lastdevice->next = device;
|
||||
}
|
||||
|
||||
++numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = numjoysticks - 1;
|
||||
if ((SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK)(SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
}
|
||||
|
||||
static SDL_JoystickDeviceItem *
|
||||
SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
|
||||
{
|
||||
SDL_JoystickDeviceItem *prev = NULL;
|
||||
SDL_JoystickDeviceItem *next = NULL;
|
||||
SDL_JoystickDeviceItem *item = deviceList;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
next = device->next;
|
||||
|
||||
while (item != NULL) {
|
||||
if (item == device) {
|
||||
break;
|
||||
}
|
||||
prev = item;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
/* Unlink the device item from the device list. */
|
||||
if (prev) {
|
||||
prev->next = device->next;
|
||||
} else if (device == deviceList) {
|
||||
deviceList = device->next;
|
||||
}
|
||||
|
||||
if (device->joystick) {
|
||||
device->joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
@autoreleasepool {
|
||||
if (device->controller) {
|
||||
/* The controller was explicitly retained in the struct, so it
|
||||
* should be explicitly released before freeing the struct. */
|
||||
GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller));
|
||||
controller.controllerPausedHandler = nil;
|
||||
device->controller = nil;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
--numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = device->instance_id;
|
||||
if ((SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK)(SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
SDL_free(device->name);
|
||||
SDL_free(device);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
@@ -45,10 +255,48 @@ static int numjoysticks = 0;
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
|
||||
if (!hint || SDL_atoi(hint)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
numjoysticks = 1;
|
||||
@autoreleasepool {
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
|
||||
|
||||
if (!hint || SDL_atoi(hint)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
SDL_SYS_AddJoystickDevice(nil, SDL_TRUE);
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
/* GameController.framework was added in iOS 7. */
|
||||
if (![GCController class]) {
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
for (GCController *controller in [GCController controllers]) {
|
||||
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
}
|
||||
|
||||
connectObserver = [center addObserverForName:GCControllerDidConnectNotification
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
GCController *controller = note.object;
|
||||
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
}];
|
||||
|
||||
disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
GCController *controller = note.object;
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
while (device != NULL) {
|
||||
if (device->controller == controller) {
|
||||
SDL_SYS_RemoveJoystickDevice(device);
|
||||
break;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
}];
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
}
|
||||
|
||||
return numjoysticks;
|
||||
@@ -67,13 +315,15 @@ void SDL_SYS_JoystickDetect()
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return accelerometerName;
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->name : "Unknown";
|
||||
}
|
||||
|
||||
/* 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;
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->instance_id : 0;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
@@ -84,38 +334,80 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
joystick->naxes = 3;
|
||||
joystick->nhats = 0;
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
if (device == NULL) {
|
||||
return SDL_SetError("Could not open Joystick: no hardware device for the specified index");
|
||||
}
|
||||
|
||||
joystick->hwdata = device;
|
||||
joystick->instance_id = device->instance_id;
|
||||
|
||||
joystick->naxes = device->naxes;
|
||||
joystick->nhats = device->nhats;
|
||||
joystick->nbuttons = device->nbuttons;
|
||||
joystick->nballs = 0;
|
||||
joystick->nbuttons = 0;
|
||||
|
||||
device->joystick = joystick;
|
||||
|
||||
@autoreleasepool {
|
||||
if (motionManager == nil) {
|
||||
motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
if (device->accelerometer) {
|
||||
if (motionManager == nil) {
|
||||
motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
|
||||
/* Shorter times between updates can significantly increase CPU usage. */
|
||||
motionManager.accelerometerUpdateInterval = 0.1;
|
||||
[motionManager startAccelerometerUpdates];
|
||||
/* Shorter times between updates can significantly increase CPU usage. */
|
||||
motionManager.accelerometerUpdateInterval = 0.1;
|
||||
[motionManager startAccelerometerUpdates];
|
||||
} else {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
GCController *controller = device->controller;
|
||||
BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
|
||||
|
||||
/* Find the player index of all other connected controllers. */
|
||||
for (GCController *c in [GCController controllers]) {
|
||||
if (c != controller && c.playerIndex >= 0) {
|
||||
usedPlayerIndexSlots[c.playerIndex] = YES;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set this controller's player index to the first unused index.
|
||||
* FIXME: This logic isn't great... but SDL doesn't expose this
|
||||
* concept in its external API, so we don't have much to go on. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!usedPlayerIndexSlots[i]) {
|
||||
controller.playerIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
controller.controllerPausedHandler = ^(GCController *controller) {
|
||||
if (joystick->hwdata) {
|
||||
++joystick->hwdata->num_pause_presses;
|
||||
}
|
||||
};
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to determine if this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
return joystick->hwdata != NULL;
|
||||
}
|
||||
|
||||
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
static void
|
||||
SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
const float maxgforce = SDL_IPHONE_MAX_GFORCE;
|
||||
const SInt16 maxsint16 = 0x7FFF;
|
||||
CMAcceleration accel;
|
||||
|
||||
@autoreleasepool {
|
||||
if (!motionManager.accelerometerActive) {
|
||||
if (!motionManager.isAccelerometerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,9 +436,94 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
|
||||
|
||||
/* pass in data mapped to range of SInt16 */
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
static Uint8
|
||||
SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
|
||||
{
|
||||
Uint8 hat = 0;
|
||||
|
||||
if (dpad.up.isPressed) {
|
||||
hat |= SDL_HAT_UP;
|
||||
} else if (dpad.down.isPressed) {
|
||||
hat |= SDL_HAT_DOWN;
|
||||
}
|
||||
|
||||
if (dpad.left.isPressed) {
|
||||
hat |= SDL_HAT_LEFT;
|
||||
} else if (dpad.right.isPressed) {
|
||||
hat |= SDL_HAT_RIGHT;
|
||||
}
|
||||
|
||||
if (hat == 0) {
|
||||
return SDL_HAT_CENTERED;
|
||||
}
|
||||
|
||||
return hat;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
@autoreleasepool {
|
||||
GCController *controller = joystick->hwdata->controller;
|
||||
Uint8 hatstate = SDL_HAT_CENTERED;
|
||||
int i;
|
||||
|
||||
if (controller.extendedGamepad) {
|
||||
GCExtendedGamepad *gamepad = controller.extendedGamepad;
|
||||
|
||||
/* Axis order matches the XInput Windows mappings. */
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16) (gamepad.leftThumbstick.xAxis.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16) (gamepad.leftThumbstick.yAxis.value * -32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16) ((gamepad.leftTrigger.value * 65535) - 32768));
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16) (gamepad.rightThumbstick.xAxis.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16) (gamepad.rightThumbstick.yAxis.value * -32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16) ((gamepad.rightTrigger.value * 65535) - 32768));
|
||||
|
||||
hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
|
||||
/* Button order matches the XInput Windows mappings. */
|
||||
SDL_PrivateJoystickButton(joystick, 0, gamepad.buttonA.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 1, gamepad.buttonB.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 2, gamepad.buttonX.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 3, gamepad.buttonY.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 4, gamepad.leftShoulder.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 5, gamepad.rightShoulder.isPressed);
|
||||
} else if (controller.gamepad) {
|
||||
GCGamepad *gamepad = controller.gamepad;
|
||||
|
||||
hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
|
||||
/* Button order matches the XInput Windows mappings. */
|
||||
SDL_PrivateJoystickButton(joystick, 0, gamepad.buttonA.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 1, gamepad.buttonB.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 2, gamepad.buttonX.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 3, gamepad.buttonY.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 4, gamepad.leftShoulder.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 5, gamepad.rightShoulder.isPressed);
|
||||
}
|
||||
/* TODO: Handle micro profiles on tvOS. */
|
||||
|
||||
SDL_PrivateJoystickHat(joystick, 0, hatstate);
|
||||
|
||||
for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
|
||||
/* The pause button is always last. */
|
||||
Uint8 pausebutton = joystick->nbuttons - 1;
|
||||
|
||||
SDL_PrivateJoystickButton(joystick, pausebutton, 1);
|
||||
SDL_PrivateJoystickButton(joystick, pausebutton, 0);
|
||||
}
|
||||
|
||||
joystick->hwdata->num_pause_presses = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
@@ -157,15 +534,40 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_SYS_AccelerometerUpdate(joystick);
|
||||
SDL_JoystickDeviceItem *device = joystick->hwdata;
|
||||
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->accelerometer) {
|
||||
SDL_SYS_AccelerometerUpdate(joystick);
|
||||
} else if (device->controller) {
|
||||
SDL_SYS_MFIJoystickUpdate(joystick);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = joystick->hwdata;
|
||||
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
device->joystick = NULL;
|
||||
|
||||
@autoreleasepool {
|
||||
[motionManager stopAccelerometerUpdates];
|
||||
if (device->accelerometer) {
|
||||
[motionManager stopAccelerometerUpdates];
|
||||
} else if (device->controller) {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
GCController *controller = device->controller;
|
||||
controller.controllerPausedHandler = nil;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,29 +576,52 @@ void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
if (connectObserver) {
|
||||
[center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
|
||||
connectObserver = nil;
|
||||
}
|
||||
|
||||
if (disconnectObserver) {
|
||||
[center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
|
||||
disconnectObserver = nil;
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
while (deviceList != NULL) {
|
||||
SDL_SYS_RemoveJoystickDevice(deviceList);
|
||||
}
|
||||
|
||||
motionManager = nil;
|
||||
}
|
||||
|
||||
numjoysticks = 0;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(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 ) ) );
|
||||
if (device) {
|
||||
guid = device->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
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 ) ) );
|
||||
if (joystick->hwdata) {
|
||||
guid = joystick->hwdata->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 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_internal.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_IOS_H
|
||||
#define SDL_JOYSTICK_IOS_H
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
@class GCController;
|
||||
|
||||
typedef struct joystick_hwdata
|
||||
{
|
||||
SDL_bool accelerometer;
|
||||
|
||||
GCController __unsafe_unretained *controller;
|
||||
int num_pause_presses;
|
||||
|
||||
char *name;
|
||||
SDL_Joystick *joystick;
|
||||
SDL_JoystickID instance_id;
|
||||
SDL_JoystickGUID guid;
|
||||
|
||||
int naxes;
|
||||
int nbuttons;
|
||||
int nhats;
|
||||
|
||||
struct joystick_hwdata *next;
|
||||
} joystick_hwdata;
|
||||
|
||||
typedef joystick_hwdata SDL_JoystickDeviceItem;
|
||||
|
||||
#endif /* SDL_JOYSTICK_IOS_H */
|
||||
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -221,8 +221,39 @@ SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickde
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateXInputJoystickBatteryInformation(SDL_Joystick * joystick, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
|
||||
{
|
||||
if ( pBatteryInformation->BatteryType != BATTERY_TYPE_UNKNOWN )
|
||||
{
|
||||
SDL_JoystickPowerLevel ePowerLevel = SDL_JOYSTICK_POWER_UNKNOWN;
|
||||
if (pBatteryInformation->BatteryType == BATTERY_TYPE_WIRED) {
|
||||
ePowerLevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
} else {
|
||||
switch ( pBatteryInformation->BatteryLevel )
|
||||
{
|
||||
case BATTERY_LEVEL_EMPTY:
|
||||
ePowerLevel = SDL_JOYSTICK_POWER_EMPTY;
|
||||
break;
|
||||
case BATTERY_LEVEL_LOW:
|
||||
ePowerLevel = SDL_JOYSTICK_POWER_LOW;
|
||||
break;
|
||||
case BATTERY_LEVEL_MEDIUM:
|
||||
ePowerLevel = SDL_JOYSTICK_POWER_MEDIUM;
|
||||
break;
|
||||
default:
|
||||
case BATTERY_LEVEL_FULL:
|
||||
ePowerLevel = SDL_JOYSTICK_POWER_FULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_PrivateJoystickBatteryLevel( joystick, ePowerLevel );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
|
||||
UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
|
||||
{
|
||||
static WORD s_XInputButtons[] = {
|
||||
XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||
@@ -244,10 +275,12 @@ UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputS
|
||||
for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
|
||||
SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
|
||||
}
|
||||
|
||||
UpdateXInputJoystickBatteryInformation( joystick, pBatteryInformation );
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
|
||||
UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
|
||||
{
|
||||
static WORD s_XInputButtons[] = {
|
||||
XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
|
||||
@@ -283,6 +316,8 @@ UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState
|
||||
hat |= SDL_HAT_RIGHT;
|
||||
}
|
||||
SDL_PrivateJoystickHat(joystick, 0, hat);
|
||||
|
||||
UpdateXInputJoystickBatteryInformation( joystick, pBatteryInformation );
|
||||
}
|
||||
|
||||
void
|
||||
@@ -290,6 +325,7 @@ SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
HRESULT result;
|
||||
XINPUT_STATE_EX XInputState;
|
||||
XINPUT_BATTERY_INFORMATION_EX XBatteryInformation;
|
||||
|
||||
if (!XINPUTGETSTATE)
|
||||
return;
|
||||
@@ -301,12 +337,18 @@ SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_zero( XBatteryInformation );
|
||||
if ( XINPUTGETBATTERYINFORMATION )
|
||||
{
|
||||
result = XINPUTGETBATTERYINFORMATION( joystick->hwdata->userid, BATTERY_DEVTYPE_GAMEPAD, &XBatteryInformation );
|
||||
}
|
||||
|
||||
/* only fire events if the data changed from last time */
|
||||
if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
|
||||
if (SDL_XInputUseOldJoystickMapping()) {
|
||||
UpdateXInputJoystickState_OLD(joystick, &XInputState);
|
||||
UpdateXInputJoystickState_OLD(joystick, &XInputState, &XBatteryInformation);
|
||||
} else {
|
||||
UpdateXInputJoystickState(joystick, &XInputState);
|
||||
UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation);
|
||||
}
|
||||
joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
|
||||
}
|
||||
|
||||
@@ -760,8 +760,8 @@ SDL_RenderDriver D3D11_RenderDriver = {
|
||||
};
|
||||
|
||||
|
||||
static Uint32
|
||||
DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
|
||||
Uint32
|
||||
D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
|
||||
switch (dxgiFormat) {
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
return SDL_PIXELFORMAT_ARGB8888;
|
||||
@@ -2367,7 +2367,7 @@ D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
|
||||
} else {
|
||||
SAFE_RELEASE(rendererData->vertexBuffer);
|
||||
|
||||
vertexBufferDesc.ByteWidth = dataSizeInBytes;
|
||||
vertexBufferDesc.ByteWidth = (UINT) dataSizeInBytes;
|
||||
vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
@@ -2504,7 +2504,7 @@ D3D11_RenderDrawPoints(SDL_Renderer * renderer,
|
||||
a = (float)(renderer->a / 255.0f);
|
||||
|
||||
vertices = SDL_stack_alloc(VertexPositionColor, count);
|
||||
for (i = 0; i < min(count, 128); ++i) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
const VertexPositionColor v = { { points[i].x, points[i].y, 0.0f }, { 0.0f, 0.0f }, { r, g, b, a } };
|
||||
vertices[i] = v;
|
||||
}
|
||||
@@ -2911,7 +2911,7 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||
*/
|
||||
if (SDL_ConvertPixels(
|
||||
rect->w, rect->h,
|
||||
DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
|
||||
D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
|
||||
textureMemory.pData,
|
||||
textureMemory.RowPitch,
|
||||
format,
|
||||
|
||||
@@ -128,7 +128,7 @@ SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
}
|
||||
|
||||
try {
|
||||
std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::defer_lock_t());
|
||||
std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::adopt_lock_t());
|
||||
if (ms == SDL_MUTEX_MAXWAIT) {
|
||||
cond->cpp_cond.wait(
|
||||
cpp_lock
|
||||
|
||||
@@ -45,7 +45,11 @@ SDL_CreateMutex(void)
|
||||
if (mutex) {
|
||||
/* Initialize */
|
||||
/* On SMP systems, a non-zero spin count generally helps performance */
|
||||
#if __WINRT__
|
||||
InitializeCriticalSectionEx(&mutex->cs, 2000, 0);
|
||||
#else
|
||||
InitializeCriticalSectionAndSpinCount(&mutex->cs, 2000);
|
||||
#endif
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,11 @@ SDL_CreateSemaphore(Uint32 initial_value)
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
if (sem) {
|
||||
/* Create the semaphore, with max value 32K */
|
||||
#if __WINRT__
|
||||
sem->id = CreateSemaphoreEx(NULL, initial_value, 32 * 1024, NULL, 0, SEMAPHORE_ALL_ACCESS);
|
||||
#else
|
||||
sem->id = CreateSemaphore(NULL, initial_value, 32 * 1024, NULL);
|
||||
#endif
|
||||
sem->count = initial_value;
|
||||
if (!sem->id) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
@@ -86,7 +90,11 @@ SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
} else {
|
||||
dwMilliseconds = (DWORD) timeout;
|
||||
}
|
||||
#if __WINRT__
|
||||
switch (WaitForSingleObjectEx(sem->id, dwMilliseconds, FALSE)) {
|
||||
#else
|
||||
switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
|
||||
#endif
|
||||
case WAIT_OBJECT_0:
|
||||
InterlockedDecrement(&sem->count);
|
||||
retval = 0;
|
||||
|
||||
@@ -106,7 +106,7 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread)
|
||||
{
|
||||
#elif defined(__CYGWIN__)
|
||||
#elif defined(__CYGWIN__) || defined(__WINRT__)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
@@ -230,7 +230,11 @@ SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
#if __WINRT__
|
||||
WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
|
||||
#else
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
#endif
|
||||
CloseHandle(thread->handle);
|
||||
}
|
||||
|
||||
|
||||
@@ -1125,6 +1125,10 @@ SDL_RestoreMousePosition(SDL_Window *window)
|
||||
}
|
||||
}
|
||||
|
||||
#if __WINRT__
|
||||
extern Uint32 WINRT_DetectWindowFlags(SDL_Window * window);
|
||||
#endif
|
||||
|
||||
static int
|
||||
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||
{
|
||||
@@ -1136,12 +1140,58 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||
/* if we are in the process of hiding don't go back to fullscreen */
|
||||
if ( window->is_hiding && fullscreen )
|
||||
return 0;
|
||||
|
||||
|
||||
#ifdef __MACOSX__
|
||||
/* if the window is going away and no resolution change is necessary,
|
||||
do nothing, or else we may trigger an ugly double-transition
|
||||
*/
|
||||
if (window->is_destroying && (window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP)
|
||||
return 0;
|
||||
|
||||
/* If we're switching between a fullscreen Space and "normal" fullscreen, we need to get back to normal first. */
|
||||
if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN)) {
|
||||
if (!Cocoa_SetWindowFullscreenSpace(window, SDL_FALSE)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
|
||||
display = SDL_GetDisplayForWindow(window);
|
||||
SDL_SetDisplayModeForDisplay(display, NULL);
|
||||
if (_this->SetWindowFullscreen) {
|
||||
_this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
|
||||
if (Cocoa_IsWindowInFullscreenSpace(window) != fullscreen) {
|
||||
return -1;
|
||||
}
|
||||
window->last_fullscreen_flags = window->flags;
|
||||
return 0;
|
||||
}
|
||||
#elif __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
/* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
|
||||
or not. The user can choose this, via OS-provided UI, but this can't
|
||||
be set programmatically.
|
||||
|
||||
Just look at what SDL's WinRT video backend code detected with regards
|
||||
to fullscreen (being active, or not), and figure out a return/error code
|
||||
from that.
|
||||
*/
|
||||
if (fullscreen == !(WINRT_DetectWindowFlags(window) & FULLSCREEN_MASK)) {
|
||||
/* Uh oh, either:
|
||||
1. fullscreen was requested, and we're already windowed
|
||||
2. windowed-mode was requested, and we're already fullscreen
|
||||
|
||||
WinRT 8.x can't resolve either programmatically, so we're
|
||||
giving up.
|
||||
*/
|
||||
return -1;
|
||||
} else {
|
||||
/* Whatever was requested, fullscreen or windowed mode, is already
|
||||
in-place.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
display = SDL_GetDisplayForWindow(window);
|
||||
@@ -1355,6 +1405,18 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
/* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
|
||||
or not. The user can choose this, via OS-provided UI, but this can't
|
||||
be set programmatically.
|
||||
|
||||
Just look at what SDL's WinRT video backend code detected with regards
|
||||
to fullscreen (being active, or not), and figure out a return/error code
|
||||
from that.
|
||||
*/
|
||||
flags = window->flags;
|
||||
#endif
|
||||
|
||||
if (title) {
|
||||
SDL_SetWindowTitle(window, title);
|
||||
}
|
||||
@@ -1964,6 +2026,7 @@ SDL_RestoreWindow(SDL_Window * window)
|
||||
int
|
||||
SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
|
||||
{
|
||||
Uint32 oldflags;
|
||||
CHECK_WINDOW_MAGIC(window, -1);
|
||||
|
||||
flags &= FULLSCREEN_MASK;
|
||||
@@ -1973,10 +2036,17 @@ SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
|
||||
}
|
||||
|
||||
/* clear the previous flags and OR in the new ones */
|
||||
oldflags = window->flags & FULLSCREEN_MASK;
|
||||
window->flags &= ~FULLSCREEN_MASK;
|
||||
window->flags |= flags;
|
||||
|
||||
return SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
|
||||
if (SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
window->flags &= ~FULLSCREEN_MASK;
|
||||
window->flags |= oldflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static SDL_Surface *
|
||||
|
||||
@@ -300,6 +300,22 @@ static SDL_Scancode Android_Keycodes[] = {
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_MEDIA_CONTEXT_MENU */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_TIMER_PROGRAMMING */
|
||||
SDL_SCANCODE_HELP, /* AKEYCODE_HELP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_PREVIOUS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_NEXT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_IN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_OUT */
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_SKIP_FORWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_SKIP_BACKWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_STEP_FORWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_STEP_BACKWARD */
|
||||
};
|
||||
|
||||
static SDL_Scancode
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/scancodes_darwin.h"
|
||||
|
||||
@@ -398,7 +399,7 @@ HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateKeymap(SDL_VideoData *data)
|
||||
UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
|
||||
{
|
||||
TISInputSourceRef key_layout;
|
||||
const void *chr_data;
|
||||
@@ -454,6 +455,9 @@ UpdateKeymap(SDL_VideoData *data)
|
||||
}
|
||||
}
|
||||
SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
|
||||
if (send_event) {
|
||||
SDL_SendKeymapChangedEvent();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -466,7 +470,7 @@ Cocoa_InitKeyboard(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
UpdateKeymap(data);
|
||||
UpdateKeymap(data, SDL_FALSE);
|
||||
|
||||
/* Set our own names for the platform-dependent but layout-independent keys */
|
||||
/* This key is NumLock on the MacBook keyboard. :) */
|
||||
@@ -564,7 +568,7 @@ Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
|
||||
case NSKeyDown:
|
||||
if (![event isARepeat]) {
|
||||
/* See if we need to rebuild the keyboard layout */
|
||||
UpdateKeymap(data);
|
||||
UpdateKeymap(data, SDL_TRUE);
|
||||
}
|
||||
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, code);
|
||||
|
||||
@@ -282,6 +282,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
||||
[center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidFailToEnterFullScreen:) name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
|
||||
[center addObserver:self selector:@selector(windowDidFailToExitFullScreen:) name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
|
||||
} else {
|
||||
[window setDelegate:self];
|
||||
}
|
||||
@@ -413,6 +415,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
||||
[center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
|
||||
[center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
|
||||
[center removeObserver:self name:NSWindowDidExitFullScreenNotification object:window];
|
||||
[center removeObserver:self name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
|
||||
[center removeObserver:self name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
|
||||
} else {
|
||||
[window setDelegate:nil];
|
||||
}
|
||||
@@ -634,6 +638,22 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
||||
inFullscreenTransition = YES;
|
||||
}
|
||||
|
||||
- (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
|
||||
if (window->is_destroying) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetWindowStyle(window, GetWindowStyle(window));
|
||||
|
||||
isFullscreenSpace = NO;
|
||||
inFullscreenTransition = NO;
|
||||
|
||||
[self windowDidExitFullScreen:nil];
|
||||
}
|
||||
|
||||
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
@@ -662,12 +682,31 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
|
||||
SetWindowStyle(window, GetWindowStyle(window));
|
||||
/* As of OS X 10.11, the window seems to need to be resizable when exiting
|
||||
a Space, in order for it to resize back to its windowed-mode size.
|
||||
*/
|
||||
SetWindowStyle(window, GetWindowStyle(window) | NSResizableWindowMask);
|
||||
|
||||
isFullscreenSpace = NO;
|
||||
inFullscreenTransition = YES;
|
||||
}
|
||||
|
||||
- (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
|
||||
if (window->is_destroying) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetWindowStyle(window, (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask));
|
||||
|
||||
isFullscreenSpace = YES;
|
||||
inFullscreenTransition = NO;
|
||||
|
||||
[self windowDidEnterFullScreen:nil];
|
||||
}
|
||||
|
||||
- (void)windowDidExitFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Window *window = _data->window;
|
||||
@@ -675,6 +714,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
||||
|
||||
inFullscreenTransition = NO;
|
||||
|
||||
SetWindowStyle(window, GetWindowStyle(window));
|
||||
|
||||
[nswindow setLevel:kCGNormalWindowLevel];
|
||||
|
||||
if (pendingWindowOperation == PENDING_OPERATION_ENTER_FULLSCREEN) {
|
||||
@@ -1288,13 +1329,23 @@ Cocoa_SetWindowSize(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
|
||||
NSWindow *nswindow = windata->nswindow;
|
||||
NSRect rect;
|
||||
Uint32 moveHack;
|
||||
|
||||
NSRect frame = [nswindow frame];
|
||||
frame.origin.y = (frame.origin.y + frame.size.height) - ((float) window->h);
|
||||
frame.size.width = window->w;
|
||||
frame.size.height = window->h;
|
||||
/* Cocoa will resize the window from the bottom-left rather than the
|
||||
* top-left when -[nswindow setContentSize:] is used, so we must set the
|
||||
* entire frame based on the new size, in order to preserve the position.
|
||||
*/
|
||||
rect.origin.x = window->x;
|
||||
rect.origin.y = window->y;
|
||||
rect.size.width = window->w;
|
||||
rect.size.height = window->h;
|
||||
ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
|
||||
|
||||
[nswindow setFrame:frame display:YES];
|
||||
moveHack = s_moveHack;
|
||||
s_moveHack = 0;
|
||||
[nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES];
|
||||
s_moveHack = moveHack;
|
||||
|
||||
ScheduleContextUpdates(windata);
|
||||
}}
|
||||
@@ -1592,8 +1643,10 @@ Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
|
||||
}
|
||||
|
||||
if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
|
||||
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)
|
||||
&& ![data->listener isInFullscreenSpace]) {
|
||||
/* OpenGL is rendering to the window, so make it visible! */
|
||||
/* Doing this in 10.11 while in a Space breaks things (bug #3152) */
|
||||
[data->nswindow setLevel:CGShieldingWindowLevel()];
|
||||
} else {
|
||||
[data->nswindow setLevel:kCGNormalWindowLevel];
|
||||
@@ -1608,6 +1661,9 @@ Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (data) {
|
||||
if ([data->listener isInFullscreenSpace]) {
|
||||
[NSMenu setMenuBarVisible:YES];
|
||||
}
|
||||
[data->listener close];
|
||||
[data->listener release];
|
||||
if (data->created) {
|
||||
@@ -1662,21 +1718,30 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
|
||||
succeeded = SDL_TRUE;
|
||||
|
||||
/* Wait for the transition to complete, so application changes
|
||||
take effect properly (e.g. setting the window size, etc.)
|
||||
*/
|
||||
const int limit = 10000;
|
||||
int count = 0;
|
||||
while ([data->listener isInFullscreenSpaceTransition]) {
|
||||
if ( ++count == limit ) {
|
||||
/* Uh oh, transition isn't completing. Should we assert? */
|
||||
break;
|
||||
const int maxattempts = 3;
|
||||
int attempt = 0;
|
||||
while (++attempt <= maxattempts) {
|
||||
/* Wait for the transition to complete, so application changes
|
||||
take effect properly (e.g. setting the window size, etc.)
|
||||
*/
|
||||
const int limit = 10000;
|
||||
int count = 0;
|
||||
while ([data->listener isInFullscreenSpaceTransition]) {
|
||||
if ( ++count == limit ) {
|
||||
/* Uh oh, transition isn't completing. Should we assert? */
|
||||
break;
|
||||
}
|
||||
SDL_Delay(1);
|
||||
SDL_PumpEvents();
|
||||
}
|
||||
SDL_Delay(1);
|
||||
SDL_PumpEvents();
|
||||
if ([data->listener isInFullscreenSpace] == (state ? YES : NO))
|
||||
break;
|
||||
/* Try again, the last attempt was interrupted by user gestures */
|
||||
if (![data->listener setFullscreenSpace:(state ? YES : NO)])
|
||||
break; /* ??? */
|
||||
}
|
||||
/* Return TRUE to prevent non-space fullscreen logic from running */
|
||||
succeeded = SDL_TRUE;
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#define IRKBD_CONFIG_FILE NULL /* this will take ms0:/seplugins/pspirkeyb.ini */
|
||||
|
||||
static int irkbd_ready = 0;
|
||||
static SDLKey keymap[256];
|
||||
static SDL_Keycode keymap[256];
|
||||
#endif
|
||||
|
||||
static enum PspHprmKeys hprm = 0;
|
||||
@@ -124,7 +124,7 @@ void PSP_PumpEvents(_THIS)
|
||||
/* not tested */
|
||||
/* SDL_PrivateKeyboard(pressed?SDL_PRESSED:SDL_RELEASED, &sym); */
|
||||
SDL_SendKeyboardKey((keys & keymap_psp[i].id) ?
|
||||
SDL_PRESSED : SDL_RELEASED, SDL_GetScancodeFromKey(keymap[raw]);
|
||||
SDL_PRESSED : SDL_RELEASED, SDL_GetScancodeFromKey(keymap[raw]));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,68 +24,166 @@
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_uikitvideo.h"
|
||||
|
||||
#include "SDL_uikitwindow.h"
|
||||
|
||||
/* Display a UIKit message box */
|
||||
|
||||
static SDL_bool s_showingMessageBox = SDL_FALSE;
|
||||
|
||||
@interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
|
||||
|
||||
@property (nonatomic, assign) int clickedIndex;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLAlertViewDelegate
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
_clickedIndex = (int)buttonIndex;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
SDL_bool
|
||||
UIKit_ShowingMessageBox()
|
||||
{
|
||||
return s_showingMessageBox;
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
static void
|
||||
UIKit_WaitUntilMessageBoxClosed(const SDL_MessageBoxData *messageboxdata, int *clickedindex)
|
||||
{
|
||||
int i;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
*clickedindex = messageboxdata->numbuttons;
|
||||
|
||||
@autoreleasepool {
|
||||
UIAlertView *alert = [[UIAlertView alloc] init];
|
||||
SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
|
||||
|
||||
alert.delegate = delegate;
|
||||
alert.title = @(messageboxdata->title);
|
||||
alert.message = @(messageboxdata->message);
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||
[alert addButtonWithTitle:@(buttons[i].text)];
|
||||
}
|
||||
|
||||
/* Set up for showing the alert */
|
||||
delegate.clickedIndex = messageboxdata->numbuttons;
|
||||
|
||||
[alert show];
|
||||
|
||||
/* Run the main event loop until the alert has finished */
|
||||
/* Note that this needs to be done on the main thread */
|
||||
s_showingMessageBox = SDL_TRUE;
|
||||
while (delegate.clickedIndex == messageboxdata->numbuttons) {
|
||||
while ((*clickedindex) == messageboxdata->numbuttons) {
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||
}
|
||||
s_showingMessageBox = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*buttonid = messageboxdata->buttons[delegate.clickedIndex].buttonid;
|
||||
static BOOL
|
||||
UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
#ifdef __IPHONE_8_0
|
||||
int i;
|
||||
int __block clickedindex = messageboxdata->numbuttons;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
UIWindow *window = nil;
|
||||
UIWindow *alertwindow = nil;
|
||||
|
||||
alert.delegate = nil;
|
||||
if (![UIAlertController class]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
UIAlertController *alert;
|
||||
alert = [UIAlertController alertControllerWithTitle:@(messageboxdata->title)
|
||||
message:@(messageboxdata->message)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; i++) {
|
||||
UIAlertAction *action;
|
||||
UIAlertActionStyle style = UIAlertActionStyleDefault;
|
||||
|
||||
if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
|
||||
style = UIAlertActionStyleCancel;
|
||||
}
|
||||
|
||||
action = [UIAlertAction actionWithTitle:@(buttons[i].text)
|
||||
style:style
|
||||
handler:^(UIAlertAction *action) {
|
||||
clickedindex = i;
|
||||
}];
|
||||
[alert addAction:action];
|
||||
}
|
||||
|
||||
if (messageboxdata->window) {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) messageboxdata->window->driverdata;
|
||||
window = data.uiwindow;
|
||||
}
|
||||
|
||||
if (window == nil || window.rootViewController == nil) {
|
||||
alertwindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
alertwindow.rootViewController = [UIViewController new];
|
||||
alertwindow.windowLevel = UIWindowLevelAlert;
|
||||
|
||||
window = alertwindow;
|
||||
|
||||
[alertwindow makeKeyAndVisible];
|
||||
}
|
||||
|
||||
[window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||
UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
|
||||
|
||||
if (alertwindow) {
|
||||
alertwindow.hidden = YES;
|
||||
}
|
||||
|
||||
*buttonid = messageboxdata->buttons[clickedindex].buttonid;
|
||||
return YES;
|
||||
#else
|
||||
return NO;
|
||||
#endif /* __IPHONE_8_0 */
|
||||
}
|
||||
|
||||
/* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
|
||||
@interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
|
||||
|
||||
@property (nonatomic, assign) int *clickedIndex;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLAlertViewDelegate
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
if (_clickedIndex != NULL) {
|
||||
*_clickedIndex = (int) buttonIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
|
||||
|
||||
static BOOL
|
||||
UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
/* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
|
||||
int i;
|
||||
int clickedindex = messageboxdata->numbuttons;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
UIAlertView *alert = [[UIAlertView alloc] init];
|
||||
SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
|
||||
|
||||
alert.delegate = delegate;
|
||||
alert.title = @(messageboxdata->title);
|
||||
alert.message = @(messageboxdata->message);
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; i++) {
|
||||
[alert addButtonWithTitle:@(buttons[i].text)];
|
||||
}
|
||||
|
||||
delegate.clickedIndex = &clickedindex;
|
||||
|
||||
[alert show];
|
||||
|
||||
UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
|
||||
|
||||
alert.delegate = nil;
|
||||
|
||||
*buttonid = messageboxdata->buttons[clickedindex].buttonid;
|
||||
return YES;
|
||||
#else
|
||||
return NO;
|
||||
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
BOOL success = NO;
|
||||
|
||||
@autoreleasepool {
|
||||
success = UIKit_ShowMessageBoxAlertController(messageboxdata, buttonid);
|
||||
if (!success) {
|
||||
success = UIKit_ShowMessageBoxAlertView(messageboxdata, buttonid);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return SDL_SetError("Could not show message box.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -52,8 +52,6 @@
|
||||
|
||||
@end
|
||||
|
||||
static int UIKit_GL_Initialize(_THIS);
|
||||
|
||||
void *
|
||||
UIKit_GL_GetProcAddress(_THIS, const char *proc)
|
||||
{
|
||||
|
||||
@@ -88,12 +88,8 @@
|
||||
GLint maxsamples = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &maxsamples);
|
||||
|
||||
/* Verify that the sample count is supported before creating any
|
||||
* multisample Renderbuffers, to avoid generating GL errors. */
|
||||
if (samples > maxsamples) {
|
||||
SDL_SetError("Failed creating OpenGL ES framebuffer: Unsupported MSAA sample count");
|
||||
return nil;
|
||||
}
|
||||
/* Clamp the samples to the max supported count. */
|
||||
samples = MIN(samples, maxsamples);
|
||||
}
|
||||
|
||||
if (sRGB) {
|
||||
|
||||
@@ -123,9 +123,22 @@
|
||||
return point;
|
||||
}
|
||||
|
||||
- (float)pressureForTouch:(UITouch *)touch
|
||||
{
|
||||
#ifdef __IPHONE_9_0
|
||||
if ([touch respondsToSelector:@selector(force)]) {
|
||||
return (float) touch.force;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
float pressure = [self pressureForTouch:touch];
|
||||
|
||||
if (!firstFingerDown) {
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||
|
||||
@@ -140,13 +153,15 @@
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||
SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
|
||||
SDL_TRUE, locationInView.x, locationInView.y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
float pressure = [self pressureForTouch:touch];
|
||||
|
||||
if (touch == firstFingerDown) {
|
||||
/* send mouse up */
|
||||
SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
@@ -155,7 +170,7 @@
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||
SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
|
||||
SDL_FALSE, locationInView.x, locationInView.y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +182,8 @@
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
float pressure = [self pressureForTouch:touch];
|
||||
|
||||
if (touch == firstFingerDown) {
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||
|
||||
@@ -176,7 +193,7 @@
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
|
||||
locationInView.x, locationInView.y, 1.0f);
|
||||
locationInView.x, locationInView.y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,7 @@
|
||||
- (void)loadView;
|
||||
- (void)viewDidLayoutSubviews;
|
||||
- (NSUInteger)supportedInterfaceOrientations;
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
|
||||
- (BOOL)prefersStatusBarHidden;
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
- (void)showKeyboard;
|
||||
|
||||
@@ -135,12 +135,6 @@
|
||||
return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
/* We assume most SDL apps don't have a bright white background. */
|
||||
return UIStatusBarStyleLightContent;
|
||||
}
|
||||
|
||||
/*
|
||||
---- Keyboard related functionality below this line ----
|
||||
*/
|
||||
|
||||
@@ -316,6 +316,13 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
||||
for (SDL_uikitview *view in views) {
|
||||
[view setSDLWindow:NULL];
|
||||
}
|
||||
|
||||
/* iOS may still hold a reference to the window after we release it.
|
||||
* We want to make sure the SDL view controller isn't accessed in
|
||||
* that case, because it would contain an invalid pointer to the old
|
||||
* SDL window. */
|
||||
data.uiwindow.rootViewController = nil;
|
||||
data.uiwindow.hidden = YES;
|
||||
}
|
||||
}
|
||||
window->driverdata = NULL;
|
||||
|
||||
@@ -607,25 +607,26 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
break;
|
||||
|
||||
case WM_UNICHAR:
|
||||
if ( wParam == UNICODE_NOCHAR ) {
|
||||
returnCode = 1;
|
||||
break;
|
||||
}
|
||||
/* otherwise fall through to below */
|
||||
case WM_CHAR:
|
||||
{
|
||||
char text[5];
|
||||
if ( WIN_ConvertUTF32toUTF8( (UINT32)wParam, text ) ) {
|
||||
SDL_SendKeyboardText( text );
|
||||
}
|
||||
}
|
||||
returnCode = 0;
|
||||
if ( wParam == UNICODE_NOCHAR ) {
|
||||
returnCode = 1;
|
||||
break;
|
||||
}
|
||||
/* otherwise fall through to below */
|
||||
case WM_CHAR:
|
||||
{
|
||||
char text[5];
|
||||
if ( WIN_ConvertUTF32toUTF8( (UINT32)wParam, text ) ) {
|
||||
SDL_SendKeyboardText( text );
|
||||
}
|
||||
}
|
||||
returnCode = 0;
|
||||
break;
|
||||
|
||||
#ifdef WM_INPUTLANGCHANGE
|
||||
case WM_INPUTLANGCHANGE:
|
||||
{
|
||||
WIN_UpdateKeymap();
|
||||
SDL_SendKeymapChangedEvent();
|
||||
}
|
||||
returnCode = 1;
|
||||
break;
|
||||
@@ -735,7 +736,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
int x, y;
|
||||
int w, h;
|
||||
|
||||
if (data->in_border_change) {
|
||||
if (data->initializing || data->in_border_change) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -813,9 +814,9 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
if ((wParam & 0xFFF0) == SC_KEYMENU) {
|
||||
return (0);
|
||||
}
|
||||
if ((wParam & 0xFFF0) == SC_KEYMENU) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
|
||||
/* Don't start the screensaver or blank the monitor in fullscreen apps */
|
||||
|
||||
@@ -124,7 +124,7 @@ WIN_UpdateKeymap()
|
||||
/* If this key is one of the non-mappable keys, ignore it */
|
||||
/* Not mapping numbers fixes the French layout, giving numeric keycodes for the number keys, which is the expected behavior */
|
||||
if ((keymap[scancode] & SDLK_SCANCODE_MASK) ||
|
||||
/* scancode == SDL_SCANCODE_GRAVE || */ /* Uncomment this line to re-enable the behavior of not mapping the "`"(grave) key to the users actual keyboard layout */
|
||||
/* scancode == SDL_SCANCODE_GRAVE || */ /* Uncomment this line to re-enable the behavior of not mapping the "`"(grave) key to the users actual keyboard layout */
|
||||
(scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0) ) {
|
||||
continue;
|
||||
}
|
||||
@@ -402,7 +402,7 @@ IME_GetReadingString(SDL_VideoData *videodata, HWND hwnd)
|
||||
INT err = 0;
|
||||
BOOL vertical = FALSE;
|
||||
UINT maxuilen = 0;
|
||||
static OSVERSIONINFOA osversion;
|
||||
static OSVERSIONINFOA osversion;
|
||||
|
||||
if (videodata->ime_uiless)
|
||||
return;
|
||||
|
||||
@@ -297,9 +297,12 @@ static WIN_DialogData *CreateDialogData(int w, int h, const char *caption)
|
||||
|
||||
/* Font size - convert to logical font size for dialog parameter. */
|
||||
{
|
||||
HDC ScreenDC = GetDC(0);
|
||||
WordToPass = (WORD)(-72 * NCM.lfMessageFont.lfHeight / GetDeviceCaps(ScreenDC, LOGPIXELSY));
|
||||
ReleaseDC(0, ScreenDC);
|
||||
HDC ScreenDC = GetDC(NULL);
|
||||
int LogicalPixelsY = GetDeviceCaps(ScreenDC, LOGPIXELSY);
|
||||
if (!LogicalPixelsY) /* This can happen if the application runs out of GDI handles */
|
||||
LogicalPixelsY = 72;
|
||||
WordToPass = (WORD)(-72 * NCM.lfMessageFont.lfHeight / LogicalPixelsY);
|
||||
ReleaseDC(NULL, ScreenDC);
|
||||
}
|
||||
|
||||
if (!AddDialogData(dialog, &WordToPass, 2)) {
|
||||
|
||||
@@ -30,43 +30,43 @@
|
||||
#endif
|
||||
|
||||
typedef struct _WIN_GetMonitorDPIData {
|
||||
SDL_VideoData *vid_data;
|
||||
SDL_DisplayMode *mode;
|
||||
SDL_DisplayModeData *mode_data;
|
||||
SDL_VideoData *vid_data;
|
||||
SDL_DisplayMode *mode;
|
||||
SDL_DisplayModeData *mode_data;
|
||||
} WIN_GetMonitorDPIData;
|
||||
|
||||
static BOOL CALLBACK
|
||||
WIN_GetMonitorDPI(HMONITOR hMonitor,
|
||||
HDC hdcMonitor,
|
||||
LPRECT lprcMonitor,
|
||||
LPARAM dwData)
|
||||
HDC hdcMonitor,
|
||||
LPRECT lprcMonitor,
|
||||
LPARAM dwData)
|
||||
{
|
||||
WIN_GetMonitorDPIData *data = (WIN_GetMonitorDPIData*) dwData;
|
||||
UINT hdpi, vdpi;
|
||||
WIN_GetMonitorDPIData *data = (WIN_GetMonitorDPIData*) dwData;
|
||||
UINT hdpi, vdpi;
|
||||
|
||||
if (data->vid_data->GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &hdpi, &vdpi) == S_OK &&
|
||||
hdpi > 0 &&
|
||||
vdpi > 0) {
|
||||
float hsize, vsize;
|
||||
|
||||
data->mode_data->HorzDPI = (float)hdpi;
|
||||
data->mode_data->VertDPI = (float)vdpi;
|
||||
if (data->vid_data->GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &hdpi, &vdpi) == S_OK &&
|
||||
hdpi > 0 &&
|
||||
vdpi > 0) {
|
||||
float hsize, vsize;
|
||||
|
||||
data->mode_data->HorzDPI = (float)hdpi;
|
||||
data->mode_data->VertDPI = (float)vdpi;
|
||||
|
||||
// Figure out the monitor size and compute the diagonal DPI.
|
||||
hsize = data->mode->w / data->mode_data->HorzDPI;
|
||||
vsize = data->mode->h / data->mode_data->VertDPI;
|
||||
|
||||
data->mode_data->DiagDPI = SDL_ComputeDiagonalDPI( data->mode->w,
|
||||
data->mode->h,
|
||||
hsize,
|
||||
vsize );
|
||||
// Figure out the monitor size and compute the diagonal DPI.
|
||||
hsize = data->mode->w / data->mode_data->HorzDPI;
|
||||
vsize = data->mode->h / data->mode_data->VertDPI;
|
||||
|
||||
data->mode_data->DiagDPI = SDL_ComputeDiagonalDPI( data->mode->w,
|
||||
data->mode->h,
|
||||
hsize,
|
||||
vsize );
|
||||
|
||||
// We can only handle one DPI per display mode so end the enumeration.
|
||||
return FALSE;
|
||||
}
|
||||
// We can only handle one DPI per display mode so end the enumeration.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// We didn't get DPI information so keep going.
|
||||
return TRUE;
|
||||
// We didn't get DPI information so keep going.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
@@ -91,11 +91,11 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
|
||||
data->DeviceMode.dmFields =
|
||||
(DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
|
||||
DM_DISPLAYFLAGS);
|
||||
data->ScaleX = 1.0f;
|
||||
data->ScaleY = 1.0f;
|
||||
data->DiagDPI = 0.0f;
|
||||
data->HorzDPI = 0.0f;
|
||||
data->VertDPI = 0.0f;
|
||||
data->ScaleX = 1.0f;
|
||||
data->ScaleY = 1.0f;
|
||||
data->DiagDPI = 0.0f;
|
||||
data->HorzDPI = 0.0f;
|
||||
data->VertDPI = 0.0f;
|
||||
|
||||
/* Fill in the mode information */
|
||||
mode->format = SDL_PIXELFORMAT_UNKNOWN;
|
||||
@@ -109,43 +109,43 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
|
||||
char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
|
||||
LPBITMAPINFO bmi;
|
||||
HBITMAP hbm;
|
||||
int logical_width = GetDeviceCaps( hdc, HORZRES );
|
||||
int logical_height = GetDeviceCaps( hdc, VERTRES );
|
||||
int logical_width = GetDeviceCaps( hdc, HORZRES );
|
||||
int logical_height = GetDeviceCaps( hdc, VERTRES );
|
||||
|
||||
data->ScaleX = (float)logical_width / devmode.dmPelsWidth;
|
||||
data->ScaleY = (float)logical_height / devmode.dmPelsHeight;
|
||||
mode->w = logical_width;
|
||||
mode->h = logical_height;
|
||||
data->ScaleX = (float)logical_width / devmode.dmPelsWidth;
|
||||
data->ScaleY = (float)logical_height / devmode.dmPelsHeight;
|
||||
mode->w = logical_width;
|
||||
mode->h = logical_height;
|
||||
|
||||
// WIN_GetMonitorDPI needs mode->w and mode->h
|
||||
// so only call after those are set.
|
||||
if (vid_data->GetDpiForMonitor) {
|
||||
WIN_GetMonitorDPIData dpi_data;
|
||||
// WIN_GetMonitorDPI needs mode->w and mode->h
|
||||
// so only call after those are set.
|
||||
if (vid_data->GetDpiForMonitor) {
|
||||
WIN_GetMonitorDPIData dpi_data;
|
||||
RECT monitor_rect;
|
||||
|
||||
dpi_data.vid_data = vid_data;
|
||||
dpi_data.mode = mode;
|
||||
dpi_data.mode_data = data;
|
||||
dpi_data.vid_data = vid_data;
|
||||
dpi_data.mode = mode;
|
||||
dpi_data.mode_data = data;
|
||||
monitor_rect.left = devmode.dmPosition.x;
|
||||
monitor_rect.top = devmode.dmPosition.y;
|
||||
monitor_rect.right = monitor_rect.left + 1;
|
||||
monitor_rect.bottom = monitor_rect.top + 1;
|
||||
EnumDisplayMonitors(NULL, &monitor_rect, WIN_GetMonitorDPI, (LPARAM)&dpi_data);
|
||||
} else {
|
||||
// We don't have the Windows 8.1 routine so just
|
||||
// get system DPI.
|
||||
data->HorzDPI = (float)GetDeviceCaps( hdc, LOGPIXELSX );
|
||||
data->VertDPI = (float)GetDeviceCaps( hdc, LOGPIXELSY );
|
||||
if (data->HorzDPI == data->VertDPI) {
|
||||
data->DiagDPI = data->HorzDPI;
|
||||
} else {
|
||||
data->DiagDPI = SDL_ComputeDiagonalDPI( mode->w,
|
||||
mode->h,
|
||||
(float)GetDeviceCaps( hdc, HORZSIZE ) / 25.4f,
|
||||
(float)GetDeviceCaps( hdc, VERTSIZE ) / 25.4f );
|
||||
}
|
||||
}
|
||||
|
||||
EnumDisplayMonitors(NULL, &monitor_rect, WIN_GetMonitorDPI, (LPARAM)&dpi_data);
|
||||
} else {
|
||||
// We don't have the Windows 8.1 routine so just
|
||||
// get system DPI.
|
||||
data->HorzDPI = (float)GetDeviceCaps( hdc, LOGPIXELSX );
|
||||
data->VertDPI = (float)GetDeviceCaps( hdc, LOGPIXELSY );
|
||||
if (data->HorzDPI == data->VertDPI) {
|
||||
data->DiagDPI = data->HorzDPI;
|
||||
} else {
|
||||
data->DiagDPI = SDL_ComputeDiagonalDPI( mode->w,
|
||||
mode->h,
|
||||
(float)GetDeviceCaps( hdc, HORZSIZE ) / 25.4f,
|
||||
(float)GetDeviceCaps( hdc, VERTSIZE ) / 25.4f );
|
||||
}
|
||||
}
|
||||
|
||||
SDL_zero(bmi_data);
|
||||
bmi = (LPBITMAPINFO) bmi_data;
|
||||
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
@@ -175,7 +175,7 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
|
||||
} else if (bmi->bmiHeader.biBitCount == 4) {
|
||||
mode->format = SDL_PIXELFORMAT_INDEX4LSB;
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
/* FIXME: Can we tell what this will be? */
|
||||
if ((devmode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
|
||||
switch (devmode.dmBitsPerPel) {
|
||||
@@ -319,17 +319,17 @@ WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi,
|
||||
{
|
||||
SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
||||
|
||||
if (ddpi) {
|
||||
*ddpi = data->DiagDPI;
|
||||
}
|
||||
if (hdpi) {
|
||||
*hdpi = data->HorzDPI;
|
||||
}
|
||||
if (vdpi) {
|
||||
*vdpi = data->VertDPI;
|
||||
}
|
||||
if (ddpi) {
|
||||
*ddpi = data->DiagDPI;
|
||||
}
|
||||
if (hdpi) {
|
||||
*hdpi = data->HorzDPI;
|
||||
}
|
||||
if (vdpi) {
|
||||
*vdpi = data->VertDPI;
|
||||
}
|
||||
|
||||
return data->DiagDPI != 0.0f ? 0 : -1;
|
||||
return data->DiagDPI != 0.0f ? 0 : -1;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -31,11 +31,11 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
DEVMODE DeviceMode;
|
||||
float ScaleX;
|
||||
float ScaleY;
|
||||
float ScaleX;
|
||||
float ScaleY;
|
||||
float DiagDPI;
|
||||
float HorzDPI;
|
||||
float VertDPI;
|
||||
float HorzDPI;
|
||||
float VertDPI;
|
||||
} SDL_DisplayModeData;
|
||||
|
||||
extern int WIN_InitModes(_THIS);
|
||||
|
||||
@@ -109,7 +109,7 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
|
||||
y = window->y + rect.top;
|
||||
|
||||
data->expected_resize = SDL_TRUE;
|
||||
SetWindowPos( hwnd, top, x, y, w, h, flags );
|
||||
SetWindowPos(hwnd, top, x, y, w, h, flags);
|
||||
data->expected_resize = SDL_FALSE;
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
|
||||
data->created = created;
|
||||
data->mouse_button_flags = 0;
|
||||
data->videodata = videodata;
|
||||
data->initializing = SDL_TRUE;
|
||||
|
||||
window->driverdata = data;
|
||||
|
||||
@@ -165,7 +166,26 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
|
||||
int h = rect.bottom;
|
||||
if ((window->w && window->w != w) || (window->h && window->h != h)) {
|
||||
/* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */
|
||||
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
RECT rect;
|
||||
DWORD style;
|
||||
BOOL menu;
|
||||
int x, y;
|
||||
int w, h;
|
||||
|
||||
/* Figure out what the window area will be */
|
||||
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = window->w;
|
||||
rect.bottom = window->h;
|
||||
menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
|
||||
AdjustWindowRectEx(&rect, style, menu, 0);
|
||||
w = (rect.right - rect.left);
|
||||
h = (rect.bottom - rect.top);
|
||||
x = window->x + rect.left;
|
||||
y = window->y + rect.top;
|
||||
|
||||
SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
} else {
|
||||
window->w = w;
|
||||
window->h = h;
|
||||
@@ -236,6 +256,8 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
|
||||
/* Enable dropping files */
|
||||
DragAcceptFiles(hwnd, TRUE);
|
||||
|
||||
data->initializing = SDL_FALSE;
|
||||
|
||||
/* All done! */
|
||||
return 0;
|
||||
}
|
||||
@@ -492,7 +514,7 @@ WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
|
||||
}
|
||||
|
||||
data->in_border_change = SDL_TRUE;
|
||||
SetWindowLong( hwnd, GWL_STYLE, style );
|
||||
SetWindowLong(hwnd, GWL_STYLE, style);
|
||||
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
data->in_border_change = SDL_FALSE;
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ typedef struct
|
||||
WNDPROC wndproc;
|
||||
SDL_bool created;
|
||||
WPARAM mouse_button_flags;
|
||||
SDL_bool initializing;
|
||||
SDL_bool expected_resize;
|
||||
SDL_bool in_border_change;
|
||||
SDL_bool in_title_click;
|
||||
SDL_bool focus_click_pending;
|
||||
SDL_bool focus_click_pending;
|
||||
struct SDL_VideoData *videodata;
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
|
||||
@@ -57,6 +57,8 @@ extern Uint8 WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint
|
||||
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args);
|
||||
|
||||
|
||||
@@ -306,6 +306,28 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::P
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
SDL_SetMouseFocus(window);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
SDL_SetMouseFocus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
|
||||
@@ -30,8 +30,18 @@
|
||||
|
||||
/* Windows includes */
|
||||
#include <agile.h>
|
||||
#include <wrl/client.h>
|
||||
#include <windows.graphics.display.h>
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_2.h>
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
|
||||
|
||||
/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
|
||||
static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48,{ 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
|
||||
|
||||
|
||||
/* SDL includes */
|
||||
@@ -44,6 +54,7 @@ extern "C" {
|
||||
#include "../../render/SDL_sysrender.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_winrtopengles.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
}
|
||||
|
||||
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
|
||||
@@ -65,6 +76,8 @@ static void WINRT_VideoQuit(_THIS);
|
||||
|
||||
/* Window functions */
|
||||
static int WINRT_CreateWindow(_THIS, SDL_Window * window);
|
||||
static void WINRT_SetWindowSize(_THIS, SDL_Window * window);
|
||||
static void WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
|
||||
static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
|
||||
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
|
||||
|
||||
@@ -123,6 +136,8 @@ WINRT_CreateDevice(int devindex)
|
||||
device->VideoInit = WINRT_VideoInit;
|
||||
device->VideoQuit = WINRT_VideoQuit;
|
||||
device->CreateWindow = WINRT_CreateWindow;
|
||||
device->SetWindowSize = WINRT_SetWindowSize;
|
||||
device->SetWindowFullscreen = WINRT_SetWindowFullscreen;
|
||||
device->DestroyWindow = WINRT_DestroyWindow;
|
||||
device->SetDisplayMode = WINRT_SetDisplayMode;
|
||||
device->PumpEvents = WINRT_PumpEvents;
|
||||
@@ -161,110 +176,178 @@ WINRT_VideoInit(_THIS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode)
|
||||
extern "C"
|
||||
Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
|
||||
|
||||
static void
|
||||
WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC * dxgiMode, SDL_DisplayMode * sdlMode)
|
||||
{
|
||||
SDL_DisplayModeData * driverdata;
|
||||
|
||||
using namespace Windows::Graphics::Display;
|
||||
|
||||
// Go no further if a native window cannot be accessed. This can happen,
|
||||
// for example, if this function is called from certain threads, such as
|
||||
// the SDL/XAML thread.
|
||||
if (!CoreWindow::GetForCurrentThread()) {
|
||||
return SDL_SetError("SDL/WinRT display modes cannot be calculated outside of the main thread, such as in SDL's XAML thread");
|
||||
}
|
||||
|
||||
//SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, DPI = %f\n",
|
||||
// __FUNCTION__,
|
||||
// CoreWindow::GetForCurrentThread()->Bounds.Width, CoreWindow::GetForCurrentThread()->Bounds.Height,
|
||||
// WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
// WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
// WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
// WINRT_DISPLAY_PROPERTY(LogicalDpi));
|
||||
|
||||
// Calculate the display size given the window size, taking into account
|
||||
// the current display's DPI:
|
||||
const float currentDPI = WINRT_DISPLAY_PROPERTY(LogicalDpi);
|
||||
const float dipsPerInch = 96.0f;
|
||||
const int w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
|
||||
const int h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
|
||||
if (w == 0 || w == h) {
|
||||
return SDL_SetError("Unable to calculate the WinRT window/display's size");
|
||||
}
|
||||
|
||||
// Create a driverdata field:
|
||||
driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
|
||||
if (!driverdata) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_zerop(driverdata);
|
||||
|
||||
// Fill in most fields:
|
||||
SDL_zerop(mode);
|
||||
mode->format = SDL_PIXELFORMAT_RGB888;
|
||||
mode->refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
|
||||
mode->w = w;
|
||||
mode->h = h;
|
||||
mode->driverdata = driverdata;
|
||||
driverdata->currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
|
||||
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
|
||||
// On Windows Phone 8.0, the native window's size is always in portrait,
|
||||
// regardless of the device's orientation. This is in contrast to
|
||||
// Windows 8.x/RT and Windows Phone 8.1, which will resize the native window as the device's
|
||||
// orientation changes. In order to compensate for this behavior,
|
||||
// on Windows Phone, the mode's width and height will be swapped when
|
||||
// the device is in a landscape (non-portrait) mode.
|
||||
switch (driverdata->currentOrientation) {
|
||||
case DisplayOrientations::Landscape:
|
||||
case DisplayOrientations::LandscapeFlipped:
|
||||
{
|
||||
const int tmp = mode->h;
|
||||
mode->h = mode->w;
|
||||
mode->w = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
SDL_zerop(sdlMode);
|
||||
sdlMode->w = dxgiMode->Width;
|
||||
sdlMode->h = dxgiMode->Height;
|
||||
sdlMode->refresh_rate = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
|
||||
sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
|
||||
}
|
||||
|
||||
int
|
||||
WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src)
|
||||
static int
|
||||
WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
|
||||
{
|
||||
SDL_DisplayModeData * driverdata;
|
||||
driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
|
||||
if (!driverdata) {
|
||||
return SDL_OutOfMemory();
|
||||
HRESULT hr;
|
||||
IDXGIOutput * dxgiOutput = NULL;
|
||||
DXGI_OUTPUT_DESC dxgiOutputDesc;
|
||||
SDL_VideoDisplay display;
|
||||
char * displayName = NULL;
|
||||
UINT numModes;
|
||||
DXGI_MODE_DESC * dxgiModes = NULL;
|
||||
int functionResult = -1; /* -1 for failure, 0 for success */
|
||||
DXGI_MODE_DESC modeToMatch, closestMatch;
|
||||
|
||||
SDL_zero(display);
|
||||
|
||||
hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
|
||||
if (FAILED(hr)) {
|
||||
if (hr != DXGI_ERROR_NOT_FOUND) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
SDL_memcpy(driverdata, src->driverdata, sizeof(SDL_DisplayModeData));
|
||||
SDL_memcpy(dest, src, sizeof(SDL_DisplayMode));
|
||||
dest->driverdata = driverdata;
|
||||
|
||||
hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
|
||||
if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
SDL_zero(modeToMatch);
|
||||
modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
|
||||
modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
|
||||
hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
|
||||
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
|
||||
/* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
|
||||
when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
|
||||
Services) under the hood. According to the MSDN docs for the similar function,
|
||||
IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
|
||||
when an app is run under a Terminal Services session, hence the assumption.
|
||||
|
||||
In this case, just add an SDL display mode, with approximated values.
|
||||
*/
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
display.name = "Windows Simulator / Terminal Services Display";
|
||||
mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
|
||||
mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
|
||||
mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
mode.refresh_rate = 0; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
if ( ! SDL_AddDisplayMode(&display, &mode)) {
|
||||
goto done;
|
||||
}
|
||||
} else if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
|
||||
goto done;
|
||||
} else {
|
||||
displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
|
||||
display.name = displayName;
|
||||
WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
|
||||
display.current_mode = display.desktop_mode;
|
||||
|
||||
hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
|
||||
if (FAILED(hr)) {
|
||||
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
|
||||
// TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
|
||||
}
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
|
||||
if ( ! dxgiModes) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
|
||||
if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < numModes; ++i) {
|
||||
SDL_DisplayMode sdlMode;
|
||||
WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
|
||||
SDL_AddDisplayMode(&display, &sdlMode);
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_AddVideoDisplay(&display) < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
functionResult = 0; /* 0 for Success! */
|
||||
done:
|
||||
if (dxgiModes) {
|
||||
SDL_free(dxgiModes);
|
||||
}
|
||||
if (dxgiOutput) {
|
||||
dxgiOutput->Release();
|
||||
}
|
||||
if (displayName) {
|
||||
SDL_free(displayName);
|
||||
}
|
||||
return functionResult;
|
||||
}
|
||||
|
||||
static int
|
||||
WINRT_AddDisplaysForAdapter (_THIS, IDXGIFactory2 * dxgiFactory2, int adapterIndex)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDXGIAdapter1 * dxgiAdapter1;
|
||||
|
||||
hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
|
||||
if (FAILED(hr)) {
|
||||
if (hr != DXGI_ERROR_NOT_FOUND) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int outputIndex = 0; ; ++outputIndex) {
|
||||
if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dxgiAdapter1->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
WINRT_InitModes(_THIS)
|
||||
{
|
||||
// Retrieve the display mode:
|
||||
SDL_DisplayMode mode, desktop_mode;
|
||||
if (WINRT_CalcDisplayModeUsingNativeWindow(&mode) != 0) {
|
||||
return -1; // If WINRT_CalcDisplayModeUsingNativeWindow fails, it'll already have set the SDL error
|
||||
}
|
||||
/* HACK: Initialize a single display, for whatever screen the app's
|
||||
CoreApplicationView is on.
|
||||
TODO, WinRT: Try initializing multiple displays, one for each monitor.
|
||||
Appropriate WinRT APIs for this seem elusive, though. -- DavidL
|
||||
*/
|
||||
|
||||
if (WINRT_DuplicateDisplayMode(&desktop_mode, &mode) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (SDL_AddBasicVideoDisplay(&desktop_mode) < 0) {
|
||||
HRESULT hr;
|
||||
IDXGIFactory2 * dxgiFactory2 = NULL;
|
||||
|
||||
hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void **)&dxgiFactory2);
|
||||
if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_AddDisplayMode(&_this->displays[0], &mode);
|
||||
int adapterIndex = 0;
|
||||
for (int adapterIndex = 0; ; ++adapterIndex) {
|
||||
if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -280,6 +363,94 @@ WINRT_VideoQuit(_THIS)
|
||||
WINRT_QuitMouse(_this);
|
||||
}
|
||||
|
||||
static const Uint32 WINRT_DetectableFlags =
|
||||
SDL_WINDOW_MAXIMIZED |
|
||||
SDL_WINDOW_FULLSCREEN_DESKTOP |
|
||||
SDL_WINDOW_SHOWN |
|
||||
SDL_WINDOW_HIDDEN |
|
||||
SDL_WINDOW_MOUSE_FOCUS;
|
||||
|
||||
extern "C" Uint32
|
||||
WINRT_DetectWindowFlags(SDL_Window * window)
|
||||
{
|
||||
Uint32 latestFlags = 0;
|
||||
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
|
||||
bool is_fullscreen = false;
|
||||
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
if (data->appView) {
|
||||
is_fullscreen = data->appView->IsFullScreen;
|
||||
}
|
||||
#elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION == NTDDI_WIN8)
|
||||
is_fullscreen = true;
|
||||
#endif
|
||||
|
||||
if (data->coreWindow.Get()) {
|
||||
if (is_fullscreen) {
|
||||
SDL_VideoDisplay * display = SDL_GetDisplayForWindow(window);
|
||||
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
|
||||
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
|
||||
// On all WinRT platforms, except for WinPhone 8.0, rotate the
|
||||
// window size. This is needed to properly calculate
|
||||
// fullscreen vs. maximized.
|
||||
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
|
||||
switch (currentOrientation) {
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
||||
case DisplayOrientations::Landscape:
|
||||
case DisplayOrientations::LandscapeFlipped:
|
||||
#else
|
||||
case DisplayOrientations::Portrait:
|
||||
case DisplayOrientations::PortraitFlipped:
|
||||
#endif
|
||||
{
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
} break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display->desktop_mode.w != w || display->desktop_mode.h != h) {
|
||||
latestFlags |= SDL_WINDOW_MAXIMIZED;
|
||||
} else {
|
||||
latestFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->coreWindow->Visible) {
|
||||
latestFlags |= SDL_WINDOW_SHOWN;
|
||||
} else {
|
||||
latestFlags |= SDL_WINDOW_HIDDEN;
|
||||
}
|
||||
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
|
||||
// data->coreWindow->PointerPosition is not supported on WinPhone 8.0
|
||||
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
|
||||
#else
|
||||
if (data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
|
||||
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return latestFlags;
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask)
|
||||
{
|
||||
mask &= WINRT_DetectableFlags;
|
||||
if (window) {
|
||||
Uint32 apply = WINRT_DetectWindowFlags(window);
|
||||
if ((apply & mask) & SDL_WINDOW_FULLSCREEN) {
|
||||
window->last_fullscreen_flags = window->flags; // seems necessary to programmatically un-fullscreen, via SDL APIs
|
||||
}
|
||||
window->flags = (window->flags & ~mask) | (apply & mask);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
@@ -290,7 +461,7 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_WindowData *data = new SDL_WindowData;
|
||||
SDL_WindowData *data = new SDL_WindowData; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
|
||||
if (!data) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
@@ -306,8 +477,14 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
*/
|
||||
if (!WINRT_XAMLWasEnabled) {
|
||||
data->coreWindow = CoreWindow::GetForCurrentThread();
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
data->appView = ApplicationView::GetForCurrentView();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Make note of the requested window flags, before they start getting changed. */
|
||||
const Uint32 requestedFlags = window->flags;
|
||||
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
/* Setup the EGL surface, but only if OpenGL ES 2 was requested. */
|
||||
if (!(window->flags & SDL_WINDOW_OPENGL)) {
|
||||
@@ -359,17 +536,10 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
/* Determine as many flags dynamically, as possible. */
|
||||
window->flags =
|
||||
SDL_WINDOW_FULLSCREEN |
|
||||
SDL_WINDOW_SHOWN |
|
||||
SDL_WINDOW_BORDERLESS |
|
||||
SDL_WINDOW_MAXIMIZED |
|
||||
SDL_WINDOW_INPUT_GRABBED;
|
||||
SDL_WINDOW_RESIZABLE;
|
||||
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
if (data->egl_surface) {
|
||||
@@ -377,20 +547,60 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* WinRT does not, as of this writing, appear to support app-adjustable
|
||||
window sizes. Set the window size to whatever the native WinRT
|
||||
CoreWindow is set at.
|
||||
if (WINRT_XAMLWasEnabled) {
|
||||
/* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
window->flags |= SDL_WINDOW_SHOWN;
|
||||
SDL_SetMouseFocus(NULL); // TODO: detect this
|
||||
SDL_SetKeyboardFocus(NULL); // TODO: detect this
|
||||
} else {
|
||||
/* WinRT 8.x apps seem to live in an environment where the OS controls the
|
||||
app's window size, with some apps being fullscreen, depending on
|
||||
user choice of various things. For now, just adapt the SDL_Window to
|
||||
whatever Windows set-up as the native-window's geometry.
|
||||
*/
|
||||
window->x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
|
||||
window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
|
||||
#if NTDDI_VERSION < NTDDI_WIN10
|
||||
/* On WinRT 8.x / pre-Win10, just use the size we were given. */
|
||||
window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
#else
|
||||
/* On Windows 10, we occasionally get control over window size. For windowed
|
||||
mode apps, try this.
|
||||
*/
|
||||
bool didSetSize = false;
|
||||
if (!(requestedFlags & SDL_WINDOW_FULLSCREEN)) {
|
||||
const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
|
||||
WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
|
||||
didSetSize = data->appView->TryResizeView(size);
|
||||
}
|
||||
if (!didSetSize) {
|
||||
/* We either weren't able to set the window size, or a request for
|
||||
fullscreen was made. Get window-size info from the OS.
|
||||
*/
|
||||
window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
}
|
||||
#endif
|
||||
|
||||
TODO, WinRT: if and when non-fullscreen XAML control support is added to SDL, consider making those resizable via SDL_Window's interfaces.
|
||||
*/
|
||||
window->w = _this->displays[0].current_mode.w;
|
||||
window->h = _this->displays[0].current_mode.h;
|
||||
WINRT_UpdateWindowFlags(
|
||||
window,
|
||||
0xffffffff /* Update any window flag(s) that WINRT_UpdateWindow can handle */
|
||||
);
|
||||
|
||||
/* For now, treat WinRT apps as if they always have focus.
|
||||
TODO, WinRT: try tracking keyboard and mouse focus state with respect to snapped apps
|
||||
*/
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
/* Try detecting if the window is active */
|
||||
bool isWindowActive = true; /* Presume the window is active, unless we've been told otherwise */
|
||||
if (data->coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
|
||||
CoreWindowActivationState activationState = \
|
||||
safe_cast<CoreWindowActivationState>(data->coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
|
||||
isWindowActive = (activationState != CoreWindowActivationState::Deactivated);
|
||||
}
|
||||
if (isWindowActive) {
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the WinRT app's IFramworkView can post events on
|
||||
behalf of SDL:
|
||||
@@ -401,6 +611,35 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_SetWindowSize(_THIS, SDL_Window * window)
|
||||
{
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
|
||||
const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
|
||||
WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
|
||||
data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView()
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
||||
{
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
|
||||
if (fullscreen) {
|
||||
if (!data->appView->IsFullScreenMode) {
|
||||
data->appView->TryEnterFullScreenMode(); // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode()
|
||||
}
|
||||
} else {
|
||||
if (data->appView->IsFullScreenMode) {
|
||||
data->appView->ExitFullScreenMode();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WINRT_DestroyWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_events.h"
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WINBLUE /* ApplicationView's functionality only becomes
|
||||
useful for SDL in Win[Phone] 8.1 and up.
|
||||
Plus, it is not available at all in WinPhone 8.0. */
|
||||
#define SDL_WINRT_USE_APPLICATIONVIEW 1
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
@@ -48,25 +54,17 @@ typedef struct SDL_VideoData {
|
||||
*/
|
||||
extern SDL_Window * WINRT_GlobalSDLWindow;
|
||||
|
||||
/* Creates a display mode for Plain Direct3D (non-XAML) apps, using the lone, native window's settings.
|
||||
|
||||
Pass in an allocated SDL_DisplayMode field to store the data in.
|
||||
|
||||
This function will return 0 on success, -1 on failure.
|
||||
|
||||
If this function succeeds, be sure to call SDL_free on the
|
||||
SDL_DisplayMode's driverdata field.
|
||||
/* Updates one or more SDL_Window flags, by querying the OS' native windowing APIs.
|
||||
SDL_Window flags that can be updated should be specified in 'mask'.
|
||||
*/
|
||||
extern int WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode);
|
||||
|
||||
/* Duplicates a display mode, copying over driverdata as necessary */
|
||||
extern int WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src);
|
||||
extern void WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask);
|
||||
extern "C" Uint32 WINRT_DetectWindowFlags(SDL_Window * window); /* detects flags w/o applying them */
|
||||
|
||||
/* Display mode internals */
|
||||
typedef struct
|
||||
{
|
||||
Windows::Graphics::Display::DisplayOrientations currentOrientation;
|
||||
} SDL_DisplayModeData;
|
||||
//typedef struct
|
||||
//{
|
||||
// Windows::Graphics::Display::DisplayOrientations currentOrientation;
|
||||
//} SDL_DisplayModeData;
|
||||
|
||||
#ifdef __cplusplus_winrt
|
||||
|
||||
@@ -77,6 +75,10 @@ typedef struct
|
||||
#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayProperties::NAME)
|
||||
#endif
|
||||
|
||||
/* Converts DIPS to/from physical pixels */
|
||||
#define WINRT_DIPS_TO_PHYSICAL_PIXELS(DIPS) ((int)(0.5f + (((float)(DIPS) * (float)WINRT_DISPLAY_PROPERTY(LogicalDpi)) / 96.f)))
|
||||
#define WINRT_PHYSICAL_PIXELS_TO_DIPS(PHYSPIX) (((float)(PHYSPIX) * 96.f)/WINRT_DISPLAY_PROPERTY(LogicalDpi))
|
||||
|
||||
/* Internal window data */
|
||||
struct SDL_WindowData
|
||||
{
|
||||
@@ -85,6 +87,9 @@ struct SDL_WindowData
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
#endif
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
Windows::UI::ViewManagement::ApplicationView ^ appView;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // ifdef __cplusplus_winrt
|
||||
|
||||
@@ -625,6 +625,7 @@ X11_DispatchEvent(_THIS)
|
||||
}
|
||||
|
||||
X11_UpdateKeymap(_this);
|
||||
SDL_SendKeymapChangedEvent();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1143,6 +1144,7 @@ X11_DispatchEvent(_THIS)
|
||||
notice and reinit our keymap here. This might not be the
|
||||
right approach, but it seems to work. */
|
||||
X11_UpdateKeymap(_this);
|
||||
SDL_SendKeymapChangedEvent();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -357,16 +357,12 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen,
|
||||
int
|
||||
X11_InitModes_XRandR(_THIS)
|
||||
{
|
||||
/* In theory, you _could_ have multiple screens (like DISPLAY=:0.0
|
||||
and DISPLAY=:0.1) but no XRandR system we care about is like this,
|
||||
as all the physical displays would be separate XRandR "outputs" on
|
||||
the one X11 virtual "screen". So we don't use ScreenCount() here. */
|
||||
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
Display *dpy = data->display;
|
||||
const int screencount = ScreenCount(dpy);
|
||||
const int default_screen = DefaultScreen(dpy);
|
||||
RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
|
||||
Atom EDID = X11_XInternAtom(dpy, "EDID", False);
|
||||
const int screen = DefaultScreen(dpy);
|
||||
RROutput primary;
|
||||
XRRScreenResources *res = NULL;
|
||||
Uint32 pixelformat;
|
||||
XVisualInfo vinfo;
|
||||
@@ -374,120 +370,127 @@ X11_InitModes_XRandR(_THIS)
|
||||
int looking_for_primary;
|
||||
int scanline_pad;
|
||||
int output;
|
||||
int i, n;
|
||||
|
||||
if (get_visualinfo(dpy, screen, &vinfo) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
|
||||
if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
|
||||
return SDL_SetError("Palettized video modes are no longer supported");
|
||||
}
|
||||
|
||||
scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
|
||||
pixmapformats = X11_XListPixmapFormats(dpy, &n);
|
||||
if (pixmapformats) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (pixmapformats[i].depth == vinfo.depth) {
|
||||
scanline_pad = pixmapformats[i].scanline_pad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
X11_XFree(pixmapformats);
|
||||
}
|
||||
|
||||
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
|
||||
if (!res) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, screen));
|
||||
int screen, i, n;
|
||||
|
||||
for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
|
||||
for (output = 0; output < res->noutput; output++) {
|
||||
XRROutputInfo *output_info;
|
||||
int display_x, display_y;
|
||||
unsigned long display_mm_width, display_mm_height;
|
||||
SDL_DisplayData *displaydata;
|
||||
char display_name[128];
|
||||
SDL_DisplayMode mode;
|
||||
SDL_DisplayModeData *modedata;
|
||||
SDL_VideoDisplay display;
|
||||
RRMode modeID;
|
||||
RRCrtc output_crtc;
|
||||
XRRCrtcInfo *crtc;
|
||||
for (screen = 0; screen < screencount; screen++) {
|
||||
|
||||
/* The primary output _should_ always be sorted first, but just in case... */
|
||||
if ((looking_for_primary && (res->outputs[output] != primary)) ||
|
||||
(!looking_for_primary && (res->outputs[output] == primary))) {
|
||||
/* we want the primary output first, and then skipped later. */
|
||||
if ((looking_for_primary && (screen != default_screen)) ||
|
||||
(!looking_for_primary && (screen == default_screen))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
|
||||
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
|
||||
if (get_visualinfo(dpy, screen, &vinfo) < 0) {
|
||||
continue; /* uh, skip this screen? */
|
||||
}
|
||||
|
||||
pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
|
||||
if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
|
||||
continue; /* Palettized video modes are no longer supported */
|
||||
}
|
||||
|
||||
scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
|
||||
pixmapformats = X11_XListPixmapFormats(dpy, &n);
|
||||
if (pixmapformats) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (pixmapformats[i].depth == vinfo.depth) {
|
||||
scanline_pad = pixmapformats[i].scanline_pad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
X11_XFree(pixmapformats);
|
||||
}
|
||||
|
||||
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
|
||||
if (!res) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (output = 0; output < res->noutput; output++) {
|
||||
XRROutputInfo *output_info;
|
||||
int display_x, display_y;
|
||||
unsigned long display_mm_width, display_mm_height;
|
||||
SDL_DisplayData *displaydata;
|
||||
char display_name[128];
|
||||
SDL_DisplayMode mode;
|
||||
SDL_DisplayModeData *modedata;
|
||||
SDL_VideoDisplay display;
|
||||
RRMode modeID;
|
||||
RRCrtc output_crtc;
|
||||
XRRCrtcInfo *crtc;
|
||||
|
||||
/* The primary output _should_ always be sorted first, but just in case... */
|
||||
if ((looking_for_primary && ((screen != default_screen) || (res->outputs[output] != primary))) ||
|
||||
(!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
|
||||
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
|
||||
X11_XRRFreeOutputInfo(output_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
|
||||
display_mm_width = output_info->mm_width;
|
||||
display_mm_height = output_info->mm_height;
|
||||
output_crtc = output_info->crtc;
|
||||
X11_XRRFreeOutputInfo(output_info);
|
||||
continue;
|
||||
|
||||
crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
|
||||
if (!crtc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_zero(mode);
|
||||
modeID = crtc->mode;
|
||||
mode.w = crtc->width;
|
||||
mode.h = crtc->height;
|
||||
mode.format = pixelformat;
|
||||
|
||||
display_x = crtc->x;
|
||||
display_y = crtc->y;
|
||||
|
||||
X11_XRRFreeCrtcInfo(crtc);
|
||||
|
||||
displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
|
||||
if (!displaydata) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (!modedata) {
|
||||
SDL_free(displaydata);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
modedata->xrandr_mode = modeID;
|
||||
mode.driverdata = modedata;
|
||||
|
||||
displaydata->screen = screen;
|
||||
displaydata->visual = vinfo.visual;
|
||||
displaydata->depth = vinfo.depth;
|
||||
displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
|
||||
displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
|
||||
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
|
||||
displaydata->scanline_pad = scanline_pad;
|
||||
displaydata->x = display_x;
|
||||
displaydata->y = display_y;
|
||||
displaydata->use_xrandr = 1;
|
||||
displaydata->xrandr_output = res->outputs[output];
|
||||
|
||||
SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
|
||||
SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
|
||||
|
||||
SDL_zero(display);
|
||||
if (*display_name) {
|
||||
display.name = display_name;
|
||||
}
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
}
|
||||
|
||||
SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
|
||||
display_mm_width = output_info->mm_width;
|
||||
display_mm_height = output_info->mm_height;
|
||||
output_crtc = output_info->crtc;
|
||||
X11_XRRFreeOutputInfo(output_info);
|
||||
|
||||
crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
|
||||
if (!crtc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_zero(mode);
|
||||
modeID = crtc->mode;
|
||||
mode.w = crtc->width;
|
||||
mode.h = crtc->height;
|
||||
mode.format = pixelformat;
|
||||
|
||||
display_x = crtc->x;
|
||||
display_y = crtc->y;
|
||||
|
||||
X11_XRRFreeCrtcInfo(crtc);
|
||||
|
||||
displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
|
||||
if (!displaydata) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (!modedata) {
|
||||
SDL_free(displaydata);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
modedata->xrandr_mode = modeID;
|
||||
mode.driverdata = modedata;
|
||||
|
||||
displaydata->screen = screen;
|
||||
displaydata->visual = vinfo.visual;
|
||||
displaydata->depth = vinfo.depth;
|
||||
displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
|
||||
displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
|
||||
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
|
||||
displaydata->scanline_pad = scanline_pad;
|
||||
displaydata->x = display_x;
|
||||
displaydata->y = display_y;
|
||||
displaydata->use_xrandr = 1;
|
||||
displaydata->xrandr_output = res->outputs[output];
|
||||
|
||||
SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
|
||||
SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
|
||||
|
||||
SDL_zero(display);
|
||||
if (*display_name) {
|
||||
display.name = display_name;
|
||||
}
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -542,11 +542,23 @@ X11_CreateWindow(_THIS, SDL_Window * window)
|
||||
(unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
|
||||
|
||||
{
|
||||
Atom protocols[] = {
|
||||
data->WM_DELETE_WINDOW, /* Allow window to be deleted by the WM */
|
||||
data->_NET_WM_PING, /* Respond so WM knows we're alive */
|
||||
};
|
||||
X11_XSetWMProtocols(display, w, protocols, sizeof (protocols) / sizeof (protocols[0]));
|
||||
Atom protocols[2];
|
||||
int proto_count = 0;
|
||||
const char *ping_hint;
|
||||
|
||||
protocols[proto_count] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
|
||||
proto_count++;
|
||||
|
||||
ping_hint = SDL_GetHint(SDL_HINT_VIDEO_X11_NET_WM_PING);
|
||||
/* Default to using ping if there is no hint */
|
||||
if (!ping_hint || SDL_atoi(ping_hint)) {
|
||||
protocols[proto_count] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
|
||||
proto_count++;
|
||||
}
|
||||
|
||||
SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
|
||||
|
||||
X11_XSetWMProtocols(display, w, protocols, proto_count);
|
||||
}
|
||||
|
||||
if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
|
||||
|
||||
Reference in New Issue
Block a user