src/SDL_hints.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 22 Jun 2015 23:36:06 -0700
changeset 9776 952ff8a5076f
parent 9619 b94b6d0bff0f
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Fixed bug 3030 - SDL_RecreateWindow fails to restore title, icon, etc.

Adam M.

It loses the title and icon when window recreation fails. For instance, this may happen when trying to create an OpenGL ES window on a system that doesn't support it. But at that point, the title and icon have already been lost.
slouken@5189
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
slouken@5189
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@5189
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@5189
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@5189
    20
*/
icculus@8093
    21
#include "./SDL_internal.h"
slouken@5189
    22
slouken@5189
    23
#include "SDL_hints.h"
slouken@7432
    24
#include "SDL_error.h"
slouken@5189
    25
slouken@5189
    26
slouken@5189
    27
/* Assuming there aren't many hints set and they aren't being queried in
slouken@7432
    28
   critical performance paths, we'll just use linked lists here.
slouken@5189
    29
 */
slouken@7432
    30
typedef struct SDL_HintWatch {
slouken@7432
    31
    SDL_HintCallback callback;
slouken@7432
    32
    void *userdata;
slouken@7432
    33
    struct SDL_HintWatch *next;
slouken@7432
    34
} SDL_HintWatch;
slouken@7432
    35
slouken@5189
    36
typedef struct SDL_Hint {
slouken@5189
    37
    char *name;
slouken@5189
    38
    char *value;
slouken@5189
    39
    SDL_HintPriority priority;
slouken@7432
    40
    SDL_HintWatch *callbacks;
slouken@5189
    41
    struct SDL_Hint *next;
slouken@5189
    42
} SDL_Hint;
slouken@5189
    43
slouken@5189
    44
static SDL_Hint *SDL_hints;
slouken@5189
    45
tim@5555
    46
SDL_bool
slouken@5200
    47
SDL_SetHintWithPriority(const char *name, const char *value,
slouken@5200
    48
                        SDL_HintPriority priority)
slouken@5189
    49
{
slouken@5189
    50
    const char *env;
icculus@6389
    51
    SDL_Hint *hint;
slouken@7432
    52
    SDL_HintWatch *entry;
slouken@5189
    53
slouken@5189
    54
    if (!name || !value) {
slouken@5189
    55
        return SDL_FALSE;
slouken@5189
    56
    }
slouken@5189
    57
slouken@5189
    58
    env = SDL_getenv(name);
slouken@5189
    59
    if (env && priority < SDL_HINT_OVERRIDE) {
slouken@5189
    60
        return SDL_FALSE;
slouken@5189
    61
    }
slouken@5189
    62
icculus@6389
    63
    for (hint = SDL_hints; hint; hint = hint->next) {
slouken@5189
    64
        if (SDL_strcmp(name, hint->name) == 0) {
slouken@5189
    65
            if (priority < hint->priority) {
slouken@5189
    66
                return SDL_FALSE;
slouken@5189
    67
            }
slouken@7432
    68
            if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
slouken@7432
    69
                for (entry = hint->callbacks; entry; ) {
slouken@7432
    70
                    /* Save the next entry in case this one is deleted */
slouken@7432
    71
                    SDL_HintWatch *next = entry->next;
slouken@7432
    72
                    entry->callback(entry->userdata, name, hint->value, value);
slouken@7432
    73
                    entry = next;
tim@5555
    74
                }
slouken@7719
    75
                SDL_free(hint->value);
slouken@7716
    76
                hint->value = value ? SDL_strdup(value) : NULL;
slouken@5189
    77
            }
slouken@5189
    78
            hint->priority = priority;
slouken@5189
    79
            return SDL_TRUE;
slouken@5189
    80
        }
slouken@5189
    81
    }
slouken@5189
    82
slouken@5189
    83
    /* Couldn't find the hint, add a new one */
slouken@5189
    84
    hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
slouken@5189
    85
    if (!hint) {
slouken@5189
    86
        return SDL_FALSE;
slouken@5189
    87
    }
slouken@5189
    88
    hint->name = SDL_strdup(name);
slouken@7432
    89
    hint->value = value ? SDL_strdup(value) : NULL;
slouken@5189
    90
    hint->priority = priority;
slouken@7432
    91
    hint->callbacks = NULL;
slouken@5189
    92
    hint->next = SDL_hints;
slouken@5189
    93
    SDL_hints = hint;
slouken@5189
    94
    return SDL_TRUE;
slouken@5189
    95
}
slouken@5189
    96
slouken@5200
    97
SDL_bool
slouken@5200
    98
SDL_SetHint(const char *name, const char *value)
slouken@5200
    99
{
slouken@5200
   100
    return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL);
slouken@5200
   101
}
slouken@5200
   102
slouken@5189
   103
const char *
slouken@5189
   104
SDL_GetHint(const char *name)
slouken@5189
   105
{
slouken@5189
   106
    const char *env;
slouken@5189
   107
    SDL_Hint *hint;
slouken@5189
   108
slouken@5189
   109
    env = SDL_getenv(name);
slouken@5189
   110
    for (hint = SDL_hints; hint; hint = hint->next) {
slouken@5189
   111
        if (SDL_strcmp(name, hint->name) == 0) {
slouken@5189
   112
            if (!env || hint->priority == SDL_HINT_OVERRIDE) {
slouken@5189
   113
                return hint->value;
slouken@5189
   114
            }
slouken@5189
   115
            break;
slouken@5189
   116
        }
slouken@5189
   117
    }
slouken@5189
   118
    return env;
slouken@5189
   119
}
slouken@5189
   120
slouken@7432
   121
void
slouken@7432
   122
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
slouken@7432
   123
{
slouken@7432
   124
    SDL_Hint *hint;
slouken@7432
   125
    SDL_HintWatch *entry;
slouken@7432
   126
    const char *value;
slouken@7432
   127
slouken@7432
   128
    if (!name || !*name) {
slouken@7432
   129
        SDL_InvalidParamError("name");
slouken@7432
   130
        return;
slouken@7432
   131
    }
slouken@7432
   132
    if (!callback) {
slouken@7432
   133
        SDL_InvalidParamError("callback");
slouken@7432
   134
        return;
slouken@7432
   135
    }
slouken@7432
   136
slouken@7432
   137
    SDL_DelHintCallback(name, callback, userdata);
slouken@7432
   138
slouken@7432
   139
    entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
philipp@9202
   140
    if (!entry) {
philipp@9202
   141
        SDL_OutOfMemory();
philipp@9202
   142
        return;
philipp@9202
   143
    }
slouken@7432
   144
    entry->callback = callback;
slouken@7432
   145
    entry->userdata = userdata;
slouken@7432
   146
slouken@7432
   147
    for (hint = SDL_hints; hint; hint = hint->next) {
slouken@7432
   148
        if (SDL_strcmp(name, hint->name) == 0) {
slouken@7432
   149
            break;
slouken@7432
   150
        }
slouken@7432
   151
    }
slouken@7432
   152
    if (!hint) {
slouken@7432
   153
        /* Need to add a hint entry for this watcher */
slouken@7432
   154
        hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
slouken@7432
   155
        if (!hint) {
philipp@9202
   156
            SDL_OutOfMemory();
philipp@9204
   157
            SDL_free(entry);
slouken@7432
   158
            return;
slouken@7432
   159
        }
slouken@7432
   160
        hint->name = SDL_strdup(name);
slouken@7432
   161
        hint->value = NULL;
slouken@7432
   162
        hint->priority = SDL_HINT_DEFAULT;
slouken@7432
   163
        hint->callbacks = NULL;
slouken@7432
   164
        hint->next = SDL_hints;
slouken@7432
   165
        SDL_hints = hint;
slouken@7432
   166
    }
slouken@7432
   167
slouken@7432
   168
    /* Add it to the callbacks for this hint */
slouken@7432
   169
    entry->next = hint->callbacks;
slouken@7432
   170
    hint->callbacks = entry;
slouken@7432
   171
slouken@7432
   172
    /* Now call it with the current value */
slouken@7432
   173
    value = SDL_GetHint(name);
slouken@7432
   174
    callback(userdata, name, value, value);
slouken@7432
   175
}
slouken@7432
   176
slouken@7432
   177
void
slouken@7432
   178
SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
slouken@7432
   179
{
slouken@7432
   180
    SDL_Hint *hint;
slouken@7432
   181
    SDL_HintWatch *entry, *prev;
slouken@7432
   182
slouken@7432
   183
    for (hint = SDL_hints; hint; hint = hint->next) {
slouken@7432
   184
        if (SDL_strcmp(name, hint->name) == 0) {
slouken@7432
   185
            prev = NULL;
slouken@7432
   186
            for (entry = hint->callbacks; entry; entry = entry->next) {
slouken@7432
   187
                if (callback == entry->callback && userdata == entry->userdata) {
slouken@7432
   188
                    if (prev) {
slouken@7432
   189
                        prev->next = entry->next;
slouken@7432
   190
                    } else {
slouken@7432
   191
                        hint->callbacks = entry->next;
slouken@7432
   192
                    }
slouken@7432
   193
                    SDL_free(entry);
slouken@7432
   194
                    break;
slouken@7432
   195
                }
slouken@7432
   196
                prev = entry;
slouken@7432
   197
            }
slouken@7432
   198
            return;
slouken@7432
   199
        }
slouken@7432
   200
    }
slouken@7432
   201
}
slouken@7432
   202
slouken@5273
   203
void SDL_ClearHints(void)
slouken@5189
   204
{
slouken@5189
   205
    SDL_Hint *hint;
slouken@7432
   206
    SDL_HintWatch *entry;
slouken@5189
   207
slouken@5189
   208
    while (SDL_hints) {
slouken@5189
   209
        hint = SDL_hints;
slouken@5189
   210
        SDL_hints = hint->next;
slouken@5189
   211
slouken@5189
   212
        SDL_free(hint->name);
slouken@7719
   213
        SDL_free(hint->value);
slouken@7432
   214
        for (entry = hint->callbacks; entry; ) {
slouken@7432
   215
            SDL_HintWatch *freeable = entry;
slouken@7432
   216
            entry = entry->next;
slouken@7432
   217
            SDL_free(freeable);
slouken@7432
   218
        }
slouken@5189
   219
        SDL_free(hint);
slouken@5189
   220
    }
slouken@5189
   221
}
slouken@5189
   222
slouken@5189
   223
/* vi: set ts=4 sw=4 expandtab: */