void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata);
SDL_EventFilter | filter | イベント発生時に呼ばれる関数 |
void * | userdata | filter へ渡されるポインタ |
filter
関数が真を戻したとき, イベントは内部キューに追加される.
偽を戻したとき, イベントはキューから削除されるが内部状態は更新される.
これにより受信したイベントを動的にフィルタで選択できる.
注意: 別スレッドで実行されている可能性があるため, イベントフィルタで行うことには細心の注意を払うこと. SDL_EVENT_WINDOW_EXPOSEDを扱う場合は例外で, OSがメインスレッドに送ることを保証しているため, このイベントでウィンドウの再描画を行うことができる.
割り込み(例えばCTRL-C)で発生した終了イベントは, アプリケーションには次のイベントポーリングで届けられる.
メモ: 無効化されたイベントはイベントフィルタ関数には届かない. SDL_SetEventEnabled()を参照すること.
メモ: コールバックはユーザのSDL_PushEvent()で発生させたイベントでも呼ばれる. しかし, SDL_PeepEvents()で発生したイベントの場合は呼ばれない.
この関数はスレッドセーフである.
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
// まず警告: これはバカげたやり方である. しかし, イベントフィルタが
// どのように働くかを示している. 実際の場合は, メインループで
// SDL_PollEventから得たイベントをただ処理すればよい. 一般的に, イベ
// ントフィルタを使おうと思ったときは, 立ち止まり, 原点に帰ってそれ
// がよい方法かよく考えるべきである.
// この関数をSDL_SetEventFilterに渡す. ユーザがキーボードのスペース
// バーを押したとき, `userdata`ポインタが示す値を切り替える. これは
// 青色をあらわしていて, 255と0の間の値である. メインプログラムはス
// ペースバーを押すたびにこの値の色でウィンドウをクリアする.
static bool SDLCALL my_event_filter(void *userdata, SDL_Event * event)
{
if ((event->type == SDL_EVENT_KEY_DOWN) && (event->key.key == SDLK_SPACE)) {
Uint8 *blue = (Uint8 *) userdata;
if (*blue == 0) {
*blue = 255;
} else {
*blue = 0;
}
}
return true; // 全てのイベントをキューに追加ために常に真を戻す
}
int main(int argc, char **argv)
{
Uint8 blue = 0;
int quit = 0;
// 単にウィンドウを生成して黒色でクリアする.
// 実際の場合はエラーをチェックすること!
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Hello SDL", 640, 480, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(window, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
// イベントフィルタを設定する...
SDL_SetEventFilter(my_event_filter, &blue);
// イベントループを無限に実行する. 全てのイベントはここに到達する前に
// my_event_filter関数を通過する. フレームごとにウィンドウを`blue`に設定さ
// れた色で塗りつぶす. その値のアドレスはuserdataでフィルタ関数に渡され,
// そこで変えられる.
while (!quit) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_EVENT_QUIT) {
quit = 1;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, blue, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}