Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ macro(add_sdl_example_executable TARGET)
target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>")
endmacro()

add_sdl_example_executable(video-menubar SOURCES video/01-menubar/menubar.c)
add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/clear.c)
add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/primitives.c)
add_sdl_example_executable(renderer-lines SOURCES renderer/03-lines/lines.c)
Expand Down
165 changes: 165 additions & 0 deletions examples/video/01-menubar/menubar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* This example code $WHAT_IT_DOES.
*
* This code is public domain. Feel free to use it for any purpose!
*/

#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>

SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;

SDL_MenuItem* checkable = NULL;
SDL_MenuItem* new_window = NULL;

typedef enum SDL_EventType_MenuExt
{
MENU_BAR_FILE,
MENU_BAR_FILE_NEW_WINDOW,
MENU_BAR_FILE_DISABLE_NEW_WINDOW,
MENU_BAR_BOOKMARKS,
MENU_BAR_BOOKMARKS_TOOLBAR,
MENU_BAR_BOOKMARKS_TOOLBAR_GITHUB,
MENU_BAR_BOOKMARKS_TOOLBAR_WIKI,
MENU_BAR_BOOKMARKS_TOOLBAR_DISCORD,
MENU_BAR_BOOKMARKS_OTHER_BOOKMARKS,
MENU_BAR_BOOKMARKS_OTHER_BOOKMARKS_STACKOVERFLOW,
MENU_BAR_INCOGNITO,
MENU_BAR_TOP_LEVEL_BUTTON,
MENU_BAR_EXIT,

MENU_BAR_LAST
} SDL_EventType_MenuExt;

static SDL_EventType_MenuExt EVENT_START = (SDL_EventType_MenuExt)0;


void CreateMenuBar()
{
SDL_MenuItem* bar = SDL_CreateMenuBar(window);

{
SDL_MenuItem* menu = SDL_CreateMenuItem(bar, "File", SDL_MENU, MENU_BAR_LAST);
new_window = SDL_CreateMenuItem(menu, "New Window", SDL_MENU_BUTTON, MENU_BAR_FILE_NEW_WINDOW);
checkable = SDL_CreateMenuItem(menu, "Enable New Window", SDL_MENU_CHECKABLE, MENU_BAR_FILE_DISABLE_NEW_WINDOW);

SDL_CheckMenuItem(checkable);
}

{
SDL_MenuItem* menu = SDL_CreateMenuItem(bar, "Bookmarks", SDL_MENU, MENU_BAR_LAST);
SDL_MenuItem* main_bookmarks = SDL_CreateMenuItem(menu, "Bookmarks Toolbar", SDL_MENU, MENU_BAR_LAST);
SDL_MenuItem* discord = SDL_CreateMenuItem(main_bookmarks, "SDL Discord", SDL_MENU_BUTTON, MENU_BAR_BOOKMARKS_TOOLBAR_DISCORD);
SDL_CreateMenuItem(main_bookmarks, "SDL GitHub", SDL_MENU_BUTTON, MENU_BAR_BOOKMARKS_TOOLBAR_GITHUB);
SDL_CreateMenuItemAt(main_bookmarks, 0, "SDL Wiki", SDL_MENU_BUTTON, MENU_BAR_BOOKMARKS_TOOLBAR_WIKI);

SDL_MenuItem *other_bookmarks = SDL_CreateMenuItem(main_bookmarks, "Other Bookmarks", SDL_MENU, MENU_BAR_LAST);
SDL_CreateMenuItem(other_bookmarks, "Stack Overflow", SDL_MENU_BUTTON, MENU_BAR_BOOKMARKS_OTHER_BOOKMARKS_STACKOVERFLOW);

SDL_DestroyMenuItem(discord);


SDL_DisableMenuItem(other_bookmarks);
}

{
// We can't create a top level checkable .
SDL_assert(!SDL_CreateMenuItem(bar, "Incognito", SDL_MENU_CHECKABLE, MENU_BAR_INCOGNITO));

SDL_CreateMenuItem(bar, "Exit", SDL_MENU_BUTTON, MENU_BAR_EXIT);
}

EVENT_START = (SDL_EventType_MenuExt)SDL_RegisterEvents(MENU_BAR_LAST);
}

SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) {
SDL_CreateWindowAndRenderer("menu bar test", 640, 480, 0, &window, &renderer);

CreateMenuBar();

//return SDL_APP_SUCCESS;
return SDL_APP_CONTINUE;
}

SDL_AppResult SDL_AppIterate(void* appstate) {

SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);

return SDL_APP_CONTINUE;
}

SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {

switch (event->common.type)
{
case SDL_EVENT_QUIT:
{
return SDL_APP_SUCCESS;
}
case SDL_EVENT_MENU_BUTTON_CLICKED:
case SDL_EVENT_MENU_CHECKABLE_CLICKED:
{
switch (event->menu.user_event_type) {
case MENU_BAR_BOOKMARKS_TOOLBAR_GITHUB:
{
SDL_OpenURL("https://github.com/libsdl-org/SDL");
break;
}
case MENU_BAR_BOOKMARKS_TOOLBAR_WIKI:
{
SDL_OpenURL("https://wiki.libsdl.org/SDL3/FrontPage");
break;
}
case MENU_BAR_BOOKMARKS_TOOLBAR_DISCORD:
{
SDL_OpenURL("https://discord.gg/BwpFGBWsv8");
break;
}
case MENU_BAR_BOOKMARKS_OTHER_BOOKMARKS_STACKOVERFLOW:
{
SDL_OpenURL("https://stackoverflow.com/questions");
break;
}
case MENU_BAR_FILE_DISABLE_NEW_WINDOW:
{
bool is_checked = false;
SDL_MenuItemChecked(checkable, &is_checked);
if (is_checked) {
SDL_UncheckMenuItem(checkable);
}
else {
SDL_CheckMenuItem(checkable);
}

bool is_enabled = false;
SDL_MenuItemEnabled(new_window, &is_enabled);

if (is_enabled) {
SDL_DisableMenuItem(new_window);
}
else {
SDL_EnableMenuItem(new_window);
}
break;
}
case MENU_BAR_EXIT:
{
return SDL_APP_SUCCESS;
}
}
SDL_Log("%d\n", event->menu.user_event_type);
}
}

return SDL_APP_CONTINUE;
}

void SDL_AppQuit(void* appstate, SDL_AppResult result) {

}


12 changes: 12 additions & 0 deletions include/SDL3/SDL_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ typedef enum SDL_EventType
SDL_EVENT_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
SDL_EVENT_RENDER_DEVICE_LOST, /**< The device has been lost and can't be recovered. */

/* Menu events */
SDL_EVENT_MENU_BUTTON_CLICKED = 0x2100,
SDL_EVENT_MENU_CHECKABLE_CLICKED,

/* Reserved events for private platforms */
SDL_EVENT_PRIVATE0 = 0x4000,
SDL_EVENT_PRIVATE1,
Expand Down Expand Up @@ -981,6 +985,13 @@ typedef struct SDL_UserEvent
void *data2; /**< User defined data pointer */
} SDL_UserEvent;

typedef struct SDL_MenuEvent
{
Uint32 type; /**< SDL_EVENT_MENU_BUTTON_CLICKED or SDL_EVENT_MENU_CHECKABLE_CLICKED */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
Uint16 user_event_type;
} SDL_MenuEvent;

/**
* The structure for all events in SDL.
Expand Down Expand Up @@ -1030,6 +1041,7 @@ typedef union SDL_Event
SDL_RenderEvent render; /**< Render event data */
SDL_DropEvent drop; /**< Drag and drop event data */
SDL_ClipboardEvent clipboard; /**< Clipboard event data */
SDL_MenuEvent menu; /**< Menu event data */

/* This is necessary for ABI compatibility between Visual C++ and GCC.
Visual C++ will respect the push pack pragma and use 52 bytes (size of
Expand Down
51 changes: 51 additions & 0 deletions include/SDL3/SDL_video.h
Original file line number Diff line number Diff line change
Expand Up @@ -3004,6 +3004,57 @@ extern SDL_DECLSPEC bool SDLCALL SDL_EnableScreenSaver(void);
*/
extern SDL_DECLSPEC bool SDLCALL SDL_DisableScreenSaver(void);

typedef enum SDL_MenuItemType
{
SDL_MENUBAR,
SDL_MENU,
SDL_MENU_BUTTON,
SDL_MENU_CHECKABLE,
} SDL_MenuItemType;

typedef union SDL_MenuItem SDL_MenuItem;

extern SDL_DECLSPEC SDL_MenuItem *SDL_CreateMenuBar(SDL_Window *window);

/**
* menu_bar_as_item must be a SDL_MENUBAR or SDL_MENU
* event_type will be ignored if type == SDL_MENU
* On MacOS, buttoms created under a menubar will go into the "App" submenu
*/
extern SDL_DECLSPEC SDL_MenuItem *SDL_CreateMenuItemAt(SDL_MenuItem *menu_bar_as_item, size_t index, const char *name, SDL_MenuItemType type, Uint16 event_type);

/**
* menu_bar_as_item must be a SDL_MENUBAR or SDL_MENU
* event_type will be ignored if type == SDL_MENU
* On MacOS, buttoms created under a menubar will go into the "App" submenu
*/
extern SDL_DECLSPEC SDL_MenuItem *SDL_CreateMenuItem(SDL_MenuItem *menu_bar_as_item, const char *name, SDL_MenuItemType type, Uint16 event_type);

/**
* -1 on error
*/
extern SDL_DECLSPEC Sint64 SDL_ChildItems(SDL_MenuItem *menu_bar_as_item);


/**
* Must be a SDL_MENU_CHECKABLE
*/
extern SDL_DECLSPEC bool SDL_CheckMenuItem(SDL_MenuItem *menu_item);

/**
* Must be a SDL_MENU_CHECKABLE
*/
extern SDL_DECLSPEC bool SDL_UncheckMenuItem(SDL_MenuItem *menu_item);

/**
* Must be a SDL_MENU_CHECKABLE
*/
extern SDL_DECLSPEC bool SDL_MenuItemChecked(SDL_MenuItem *menu_item, bool *checked);

extern SDL_DECLSPEC bool SDL_MenuItemEnabled(SDL_MenuItem *menu_item, bool *enabled);
extern SDL_DECLSPEC bool SDL_EnableMenuItem(SDL_MenuItem *menu_item);
extern SDL_DECLSPEC bool SDL_DisableMenuItem(SDL_MenuItem *menu_item);
extern SDL_DECLSPEC bool SDL_DestroyMenuItem(SDL_MenuItem *menu_item);

/**
* \name OpenGL support functions
Expand Down
11 changes: 11 additions & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,17 @@ SDL3_0.0.0 {
SDL_PutAudioStreamPlanarData;
SDL_GetEventDescription;
SDL_PutAudioStreamDataNoCopy;
SDL_CreateMenuBar;
SDL_CreateMenuItemAt;
SDL_CreateMenuItem;
SDL_ChildItems;
SDL_CheckMenuItem;
SDL_UncheckMenuItem;
SDL_MenuItemChecked;
SDL_MenuItemEnabled;
SDL_EnableMenuItem;
SDL_DisableMenuItem;
SDL_DestroyMenuItem;
# extra symbols go here (don't modify this line)
local: *;
};
11 changes: 11 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1278,3 +1278,14 @@
#define SDL_PutAudioStreamPlanarData SDL_PutAudioStreamPlanarData_REAL
#define SDL_GetEventDescription SDL_GetEventDescription_REAL
#define SDL_PutAudioStreamDataNoCopy SDL_PutAudioStreamDataNoCopy_REAL
#define SDL_CreateMenuBar SDL_CreateMenuBar_REAL
#define SDL_CreateMenuItemAt SDL_CreateMenuItemAt_REAL
#define SDL_CreateMenuItem SDL_CreateMenuItem_REAL
#define SDL_ChildItems SDL_ChildItems_REAL
#define SDL_CheckMenuItem SDL_CheckMenuItem_REAL
#define SDL_UncheckMenuItem SDL_UncheckMenuItem_REAL
#define SDL_MenuItemChecked SDL_MenuItemChecked_REAL
#define SDL_MenuItemEnabled SDL_MenuItemEnabled_REAL
#define SDL_EnableMenuItem SDL_EnableMenuItem_REAL
#define SDL_DisableMenuItem SDL_DisableMenuItem_REAL
#define SDL_DestroyMenuItem SDL_DestroyMenuItem_REAL
11 changes: 11 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1286,3 +1286,14 @@ SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShader
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamPlanarData,(SDL_AudioStream *a,const void * const*b,int c,int d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),(a,b,c),return)
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamDataNoCopy,(SDL_AudioStream *a,const void *b,int c,SDL_AudioStreamDataCompleteCallback d,void *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(SDL_MenuItem*,SDL_CreateMenuBar,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(SDL_MenuItem*,SDL_CreateMenuItemAt,(SDL_MenuItem *a,size_t b,const char *c,SDL_MenuItemType d, Uint16 e), (a,b,c,d,e), return)
SDL_DYNAPI_PROC(SDL_MenuItem*,SDL_CreateMenuItem,(SDL_MenuItem *a, const char *b, SDL_MenuItemType c, Uint16 d),(a,b,c,d), return)
SDL_DYNAPI_PROC(Sint64,SDL_ChildItems, (SDL_MenuItem *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_CheckMenuItem,(SDL_MenuItem *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_UncheckMenuItem,(SDL_MenuItem *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_MenuItemChecked,(SDL_MenuItem *a,bool *b),(a, b),return)
SDL_DYNAPI_PROC(bool,SDL_MenuItemEnabled,(SDL_MenuItem *a,bool *b),(a, b),return)
SDL_DYNAPI_PROC(bool,SDL_EnableMenuItem,(SDL_MenuItem *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_DisableMenuItem,(SDL_MenuItem *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_DestroyMenuItem,(SDL_MenuItem *a),(a),return)
64 changes: 64 additions & 0 deletions src/video/SDL_sysvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,58 @@ typedef enum
SDL_FULLSCREEN_PENDING
} SDL_FullscreenResult;


typedef struct SDL_MenuBar SDL_MenuBar;
typedef struct SDL_Menu SDL_Menu;

typedef struct SDL_MenuItem_CommonData
{
void *platform_data;
SDL_MenuItem *parent;
SDL_Window *window;
SDL_MenuItem *prev;
SDL_MenuItem *next;
SDL_MenuItemType type;
} SDL_MenuItem_CommonData;

typedef struct SDL_Menu_CommonData
{
SDL_MenuItem_CommonData item_common;
SDL_MenuItem *child_list;
Sint64 children;
} SDL_Menu_CommonData;

typedef struct SDL_MenuBar
{
SDL_Menu_CommonData common;
} SDL_MenuBar;

typedef struct SDL_Menu
{
SDL_Menu_CommonData common;
} SDL_Menu;

typedef struct SDL_MenuItem_Button
{
SDL_MenuItem_CommonData common;
} SDL_MenuItem_Button;

typedef struct SDL_MenuItem_Checkable
{
SDL_MenuItem_CommonData common;
bool is_checked;
} SDL_MenuItem_Checkable;

typedef union SDL_MenuItem
{
SDL_MenuItem_CommonData common;
SDL_Menu_CommonData menu_common;
SDL_MenuBar menu_bar;
SDL_Menu menu;
SDL_MenuItem_Button button;
SDL_MenuItem_Checkable checkable;
} SDL_MenuItem;

struct SDL_VideoDevice
{
/* * * */
Expand Down Expand Up @@ -315,6 +367,16 @@ struct SDL_VideoDevice
bool (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);
bool (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window);

bool (*CreateMenuBar)(SDL_MenuBar *menu_bar);
bool (*CreateMenuItemAt)(SDL_MenuItem *menu_item, size_t index, const char *name, Uint16 event_type);
bool (*CheckMenuItem)(SDL_MenuItem *menu_item);
bool (*UncheckMenuItem)(SDL_MenuItem *menu_item);
bool (*MenuItemChecked)(SDL_MenuItem *menu_item, bool *checked);
bool (*MenuItemEnabled)(SDL_MenuItem *menu_item, bool *enabled);
bool (*EnableMenuItem)(SDL_MenuItem *menu_item);
bool (*DisableMenuItem)(SDL_MenuItem *menu_item);
bool (*DestroyMenuItem)(SDL_MenuItem *menu_item);

/* * * */
/*
* OpenGL support
Expand Down Expand Up @@ -612,4 +674,6 @@ extern SDL_Capitalization SDL_GetTextInputCapitalization(SDL_PropertiesID props)
extern bool SDL_GetTextInputAutocorrect(SDL_PropertiesID props);
extern bool SDL_GetTextInputMultiline(SDL_PropertiesID props);

extern Uint32 SDL_GetIndexInMenu(SDL_MenuItem *menu_item);

#endif // SDL_sysvideo_h_
Loading
Loading