Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Added a hint to control the Windows timer resolution: SDL_HINT_TIMER_…
Browse files Browse the repository at this point in the history
…RESOLUTION

Added an API to watch hint changes: SDL_AddHintCallback(), SDL_DelHintCallback()
You can now dynamically set the joystick background event hint.
  • Loading branch information
slouken committed Jul 13, 2013
1 parent af63bb8 commit 1f09208
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 89 deletions.
4 changes: 0 additions & 4 deletions Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
Expand Up @@ -67,7 +67,6 @@
04F7808512FB753F00FC43C0 /* SDL_nullframebuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04F7808312FB753F00FC43C0 /* SDL_nullframebuffer.c */; };
04FFAB8B12E23B8D00BA343D /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */; };
04FFAB8C12E23B8D00BA343D /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */; };
22C905CD13A22646003FE4E4 /* SDL_hints_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 22C905CC13A22646003FE4E4 /* SDL_hints_c.h */; };
56EA86FB13E9EC2B002E47EB /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 56EA86F913E9EC2B002E47EB /* SDL_coreaudio.c */; };
56EA86FC13E9EC2B002E47EB /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 56EA86FA13E9EC2B002E47EB /* SDL_coreaudio.h */; };
56ED04E1118A8EE200A56AA6 /* SDL_power.c in Sources */ = {isa = PBXBuildFile; fileRef = 56ED04E0118A8EE200A56AA6 /* SDL_power.c */; };
Expand Down Expand Up @@ -260,7 +259,6 @@
04F7808312FB753F00FC43C0 /* SDL_nullframebuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_nullframebuffer.c; sourceTree = "<group>"; };
04FFAB8912E23B8D00BA343D /* SDL_atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_atomic.c; sourceTree = "<group>"; };
04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_spinlock.c; sourceTree = "<group>"; };
22C905CC13A22646003FE4E4 /* SDL_hints_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_hints_c.h; path = ../../src/SDL_hints_c.h; sourceTree = "<group>"; };
56EA86F913E9EC2B002E47EB /* SDL_coreaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_coreaudio.c; path = coreaudio/SDL_coreaudio.c; sourceTree = "<group>"; };
56EA86FA13E9EC2B002E47EB /* SDL_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_coreaudio.h; path = coreaudio/SDL_coreaudio.h; sourceTree = "<group>"; };
56ED04E0118A8EE200A56AA6 /* SDL_power.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_power.c; path = ../../src/power/SDL_power.c; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -747,7 +745,6 @@
FD99B9D60DD52EDC00FB1D6B /* SDL_fatal.c */,
FD99B9D70DD52EDC00FB1D6B /* SDL_fatal.h */,
0442EC5412FE1C3F004C9285 /* SDL_hints.c */,
22C905CC13A22646003FE4E4 /* SDL_hints_c.h */,
04BAC09B1300C1290055DE28 /* SDL_log.c */,
FD99B9D80DD52EDC00FB1D6B /* SDL.c */,
);
Expand Down Expand Up @@ -967,7 +964,6 @@
0442EC5012FE1C1E004C9285 /* SDL_render_sw_c.h in Headers */,
0402A85A12FE70C600CECEE3 /* SDL_shaders_gles2.h in Headers */,
04BAC09C1300C1290055DE28 /* SDL_assert_c.h in Headers */,
22C905CD13A22646003FE4E4 /* SDL_hints_c.h in Headers */,
56EA86FC13E9EC2B002E47EB /* SDL_coreaudio.h in Headers */,
93CB792313FC5E5200BD3E05 /* SDL_uikitviewcontroller.h in Headers */,
AA628ADC159369E3005138DD /* SDL_rotate.h in Headers */,
Expand Down
45 changes: 42 additions & 3 deletions include/SDL_hints.h
Expand Up @@ -218,13 +218,13 @@ extern "C" {
/**
* \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
*
* The default value is "0".
*
* The variable can be set to the following values:
* "0" - Disable joystick & gamecontroller input events when the
* application is in the background.
* "1" - Enable joystick & gamecontroller input events when the
* application is in the backgroumd.
*
* The default value is "0". This hint may be set at any time.
*/
#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"

Expand All @@ -240,6 +240,23 @@ extern "C" {
#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"


/**
* \brief A variable that controls the timer resolution, in milliseconds.
*
* The higher resolution the timer, the more frequently the CPU services
* timer interrupts, and the more precise delays are, but this takes up
* power and CPU time. This hint is only used on Windows 7 and earlier.
*
* See this blog post for more information:
* http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
*
* If this variable is set to "0", the system timer resolution is not set.
*
* The default value is "1". This hint may be set at any time.
*/
#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"



/**
* \brief An enumeration of hint priorities
Expand Down Expand Up @@ -273,14 +290,36 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name,
extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
const char *value);


/**
* \brief Get a hint
*
* \return The string value of a hint variable.
*/
extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);

/**
* \brief Add a function to watch a particular hint
*
* \param name The hint to watch
* \param callback The function to call when the hint value changes
* \param userdata A pointer to pass to the callback function
*/
typedef void (*SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
extern DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name,
SDL_HintCallback callback,
void *userdata);

/**
* \brief Remove a function watching a particular hint
*
* \param name The hint being watched
* \param callback The function being called when the hint value changes
* \param userdata A pointer being passed to the callback function
*/
extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name,
SDL_HintCallback callback,
void *userdata);

/**
* \brief Clear all hints
*
Expand Down
137 changes: 111 additions & 26 deletions src/SDL_hints.c
Expand Up @@ -21,43 +21,35 @@
#include "SDL_config.h"

#include "SDL_hints.h"
#include "SDL_hints_c.h"
#include "SDL_error.h"


/* Assuming there aren't many hints set and they aren't being queried in
critical performance paths, we'll just use a linked list here.
critical performance paths, we'll just use linked lists here.
*/
typedef struct SDL_HintWatch {
SDL_HintCallback callback;
void *userdata;
struct SDL_HintWatch *next;
} SDL_HintWatch;

typedef struct SDL_Hint {
char *name;
char *value;
SDL_HintPriority priority;
SDL_HintChangedCb callback;
SDL_HintWatch *callbacks;
struct SDL_Hint *next;
} SDL_Hint;

static SDL_Hint *SDL_hints;

SDL_bool
SDL_RegisterHintChangedCb(const char *name, SDL_HintChangedCb hintCb)
{
SDL_Hint *hint;

for (hint = SDL_hints; hint; hint = hint->next) {
if (SDL_strcmp(name, hint->name) == 0) {
hint->callback = hintCb;
return SDL_TRUE;
}
}

return SDL_FALSE;
}

SDL_bool
SDL_SetHintWithPriority(const char *name, const char *value,
SDL_HintPriority priority)
{
const char *env;
SDL_Hint *hint;
SDL_HintWatch *entry;

if (!name || !value) {
return SDL_FALSE;
Expand All @@ -73,12 +65,21 @@ SDL_SetHintWithPriority(const char *name, const char *value,
if (priority < hint->priority) {
return SDL_FALSE;
}
if (SDL_strcmp(hint->value, value) != 0) {
if (hint->callback != NULL) {
(*hint->callback)(name, hint->value, value);
if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
for (entry = hint->callbacks; entry; ) {
/* Save the next entry in case this one is deleted */
SDL_HintWatch *next = entry->next;
entry->callback(entry->userdata, name, hint->value, value);
entry = next;
}
if (hint->value) {
SDL_free(hint->value);
}
if (value) {
hint->value = SDL_strdup(value);
} else {
hint->value = NULL;
}
SDL_free(hint->value);
hint->value = SDL_strdup(value);
}
hint->priority = priority;
return SDL_TRUE;
Expand All @@ -91,9 +92,9 @@ SDL_SetHintWithPriority(const char *name, const char *value,
return SDL_FALSE;
}
hint->name = SDL_strdup(name);
hint->value = SDL_strdup(value);
hint->value = value ? SDL_strdup(value) : NULL;
hint->priority = priority;
hint->callback = NULL;
hint->callbacks = NULL;
hint->next = SDL_hints;
SDL_hints = hint;
return SDL_TRUE;
Expand Down Expand Up @@ -123,16 +124,100 @@ SDL_GetHint(const char *name)
return env;
}

void
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
SDL_Hint *hint;
SDL_HintWatch *entry;
const char *value;

if (!name || !*name) {
SDL_InvalidParamError("name");
return;
}
if (!callback) {
SDL_InvalidParamError("callback");
return;
}

SDL_DelHintCallback(name, callback, userdata);

entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
entry->callback = callback;
entry->userdata = userdata;

for (hint = SDL_hints; hint; hint = hint->next) {
if (SDL_strcmp(name, hint->name) == 0) {
break;
}
}
if (!hint) {
/* Need to add a hint entry for this watcher */
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
if (!hint) {
return;
}
hint->name = SDL_strdup(name);
hint->value = NULL;
hint->priority = SDL_HINT_DEFAULT;
hint->callbacks = NULL;
hint->next = SDL_hints;
SDL_hints = hint;
}

/* Add it to the callbacks for this hint */
entry->next = hint->callbacks;
hint->callbacks = entry;

/* Now call it with the current value */
value = SDL_GetHint(name);
callback(userdata, name, value, value);
}

void
SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
SDL_Hint *hint;
SDL_HintWatch *entry, *prev;

for (hint = SDL_hints; hint; hint = hint->next) {
if (SDL_strcmp(name, hint->name) == 0) {
prev = NULL;
for (entry = hint->callbacks; entry; entry = entry->next) {
if (callback == entry->callback && userdata == entry->userdata) {
if (prev) {
prev->next = entry->next;
} else {
hint->callbacks = entry->next;
}
SDL_free(entry);
break;
}
prev = entry;
}
return;
}
}
}

void SDL_ClearHints(void)
{
SDL_Hint *hint;
SDL_HintWatch *entry;

while (SDL_hints) {
hint = SDL_hints;
SDL_hints = hint->next;

SDL_free(hint->name);
SDL_free(hint->value);
if (hint->value) {
SDL_free(hint->value);
}
for (entry = hint->callbacks; entry; ) {
SDL_HintWatch *freeable = entry;
entry = entry->next;
SDL_free(freeable);
}
SDL_free(hint);
}
}
Expand Down
34 changes: 0 additions & 34 deletions src/SDL_hints_c.h

This file was deleted.

19 changes: 13 additions & 6 deletions src/joystick/SDL_joystick.c
Expand Up @@ -36,17 +36,24 @@ static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
static SDL_Joystick *SDL_joysticks = NULL;
static SDL_Joystick *SDL_updating_joystick = NULL;

static void
SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
if (hint && *hint == '1') {
SDL_joystick_allows_background_events = SDL_TRUE;
} else {
SDL_joystick_allows_background_events = SDL_FALSE;
}
}

int
SDL_JoystickInit(void)
{
const char *hint;
int status;

/* Check to see if we should allow joystick events while in the background */
hint = SDL_GetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS);
if (hint && *hint == '1') {
SDL_joystick_allows_background_events = SDL_TRUE;
}
/* See if we should allow joystick events while in the background */
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
SDL_JoystickAllowBackgroundEventsChanged, NULL);

#if !SDL_EVENTS_DISABLED
if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
Expand Down

0 comments on commit 1f09208

Please sign in to comment.