1 /*
2     DSDL
3     Copyright (C) 2025 Inochi2D Project <luna@foxgirls.gay>
4 
5     This software is provided 'as-is', without any express or implied
6     warranty.  In no event will the authors be held liable for any damages
7     arising from the use of this software.
8 
9     Permission is granted to anyone to use this software for any purpose,
10     including commercial applications, and to alter it and redistribute it
11     freely, subject to the following restrictions:
12 
13     1. The origin of this software must not be misrepresented; you must not
14         claim that you wrote the original software. If you use this software
15         in a product, an acknowledgment in the product documentation would be
16         appreciated but is not required.
17     2. Altered source versions must be plainly marked as such, and must not be
18         misrepresented as being the original software.
19     3. This notice may not be removed or altered from any source distribution.
20 
21     ==========================================================================
22 
23     Simple DirectMedia Layer
24     Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
25 
26     This software is provided 'as-is', without any express or implied
27     warranty.  In no event will the authors be held liable for any damages
28     arising from the use of this software.
29 
30     Permission is granted to anyone to use this software for any purpose,
31     including commercial applications, and to alter it and redistribute it
32     freely, subject to the following restrictions:
33 
34     1. The origin of this software must not be misrepresented; you must not
35         claim that you wrote the original software. If you use this software
36         in a product, an acknowledgment in the product documentation would be
37         appreciated but is not required.
38     2. Altered source versions must be plainly marked as such, and must not be
39         misrepresented as being the original software.
40     3. This notice may not be removed or altered from any source distribution.
41 */
42 
43 /**
44     SDL Tray
45 
46     SDL offers a way to add items to the "system tray" (more correctly called
47     the "notification area" on Windows). On platforms that offer this concept,
48     an SDL app can add a tray icon, submenus, checkboxes, and clickable
49     entries, and register a callback that is fired when the user clicks on
50     these pieces.
51 
52     See_Also:
53         $(LINK2 https://wiki.libsdl.org/SDL3/CategoryTray, SDL3 Tray Documentation)
54     
55     Copyright: © 2025 Inochi2D Project, © 1997-2025 Sam Lantinga
56     License: Subject to the terms of the Zlib License, as written in the LICENSE file.
57     Authors: 
58         Luna Nielsen
59 */
60 module sdl.tray;
61 import sdl.stdc;
62 import sdl.video;
63 import sdl.surface;
64 
65 extern (C) nothrow @nogc:
66 
67 /**
68     An opaque handle representing a toplevel system tray object.
69 */
70 struct SDL_Tray;
71 
72 /**
73     An opaque handle representing a menu/submenu on a system tray object.
74 */
75 struct SDL_TrayMenu;
76 
77 /**
78     An opaque handle representing an entry on a system tray object.
79 */
80 struct SDL_TrayEntry;
81 
82 /**
83     Flags that control the creation of system tray entries.
84 
85     Some of these flags are required; exactly one of them must be specified at
86     the time a tray entry is created. Other flags are optional; zero or more of
87     those can be OR'ed together with the required flag.
88 
89     See_Also:
90         $(D SDL_InsertTrayEntryAt)
91 */
92 alias SDL_TrayEntryFlags = Uint32;
93 
94 /**
95     Make the entry a simple button. Required.
96 */
97 enum SDL_TRAYENTRY_BUTTON =   0x00000001u; 
98 
99 /**
100     Make the entry a checkbox. Required.
101 */
102 enum SDL_TRAYENTRY_CHECKBOX = 0x00000002u; 
103 
104 /**
105     Prepare the entry to have a submenu. Required
106 */
107 enum SDL_TRAYENTRY_SUBMENU =  0x00000004u; 
108 
109 /**
110     Make the entry disabled. Optional.
111 */
112 enum SDL_TRAYENTRY_DISABLED = 0x80000000u; 
113 
114 /**
115     Make the entry checked. This is valid only for checkboxes. Optional.
116 */
117 enum SDL_TRAYENTRY_CHECKED =  0x40000000u; 
118 
119 /**
120     A callback that is invoked when a tray entry is selected.
121 
122     Params:
123         userdata =  An optional pointer to pass extra data to the callback when
124                     it will be invoked.
125         entry =     The tray entry that was selected.
126 
127     See_Also:
128         $(D SDL_SetTrayEntryCallback)
129 */
130 alias SDL_TrayCallback = void function(void* userdata, SDL_TrayEntry* entry);
131 
132 /**
133     Create an icon to be placed in the operating system's tray, or equivalent.
134 
135     Many platforms advise not using a system tray unless persistence is a
136     necessary feature. Avoid needlessly creating a tray icon, as the user may
137     feel like it clutters their interface.
138 
139     Using tray icons require the video subsystem.
140 
141     Params:
142         icon =      A surface to be used as icon. May be $(D null).
143         tooltip =   A tooltip to be displayed when the mouse hovers the icon in
144                     UTF-8 encoding. Not supported on all platforms. May be $(D null).
145     
146     Returns:
147         The newly created system tray icon.
148 
149     Threadsafety:
150         This function should only be called on the main thread.
151 
152     See_Also:
153         $(D SDL_CreateTrayMenu)
154         $(D SDL_GetTrayMenu)
155         $(D SDL_DestroyTray)
156 */
157 extern SDL_Tray* SDL_CreateTray(SDL_Surface* icon, const(char)* tooltip);
158 
159 /**
160     Updates the system tray icon's icon.
161 
162     Params:
163         tray =  The tray icon to be updated.
164         icon =  The new icon. May be $(D null).
165 
166     Threadsafety:
167         This function should be called on the thread that created the
168         tray.
169 
170     See_Also:
171         $(D SDL_CreateTray)
172 */
173 extern void SDL_SetTrayIcon(SDL_Tray* tray, SDL_Surface* icon);
174 
175 /**
176     Updates the system tray icon's tooltip.
177 
178     Params:
179         tray =      The tray icon to be updated.
180         tooltip =   The new tooltip in UTF-8 encoding. May be $(D null).
181 
182     Threadsafety:
183         This function should be called on the thread that created the
184         tray.
185 
186     See_Also:
187         $(D SDL_CreateTray)
188 */
189 extern void SDL_SetTrayTooltip(SDL_Tray* tray, const(char)* tooltip);
190 
191 /**
192     Create a menu for a system tray.
193 
194     This should be called at most once per tray icon.
195 
196     This function does the same thing as SDL_CreateTraySubmenu(), except that
197     it takes a SDL_Tray instead of a SDL_TrayEntry.
198 
199     A menu does not need to be destroyed; it will be destroyed with the tray.
200 
201     Params:
202         tray =  The tray to bind the menu to.
203     
204     Returns:
205         the newly created menu.
206 
207     Threadsafety:
208         This function should be called on the thread that created the
209         tray.
210 
211     See_Also:
212         $(D SDL_CreateTray)
213         $(D SDL_GetTrayMenu)
214         $(D SDL_GetTrayMenuParentTray)
215 */
216 extern SDL_TrayMenu* SDL_CreateTrayMenu(SDL_Tray* tray);
217 
218 /**
219     Create a submenu for a system tray entry.
220 
221     This should be called at most once per tray entry.
222 
223     This function does the same thing as SDL_CreateTrayMenu, except that it
224     takes a SDL_TrayEntry instead of a SDL_Tray.
225 
226     A menu does not need to be destroyed; it will be destroyed with the tray.
227 
228     Params:
229         entry = The tray entry to bind the menu to.
230     
231     Returns:
232         the newly created menu.
233 
234     Threadsafety:
235         This function should be called on the thread that created the
236         tray.
237 
238     See_Also:
239         $(D SDL_InsertTrayEntryAt)
240         $(D SDL_GetTraySubmenu)
241         $(D SDL_GetTrayMenuParentEntry)
242 */
243 extern SDL_TrayMenu* SDL_CreateTraySubmenu(SDL_TrayEntry* entry);
244 
245 /**
246     Gets a previously created tray menu.
247 
248     You should have called SDL_CreateTrayMenu() on the tray object. This
249     function allows you to fetch it again later.
250 
251     This function does the same thing as SDL_GetTraySubmenu(), except that it
252     takes a SDL_Tray instead of a SDL_TrayEntry.
253 
254     A menu does not need to be destroyed; it will be destroyed with the tray.
255 
256     Params:
257         tray =  The tray entry to bind the menu to.
258     
259     Returns:
260         the newly created menu.
261 
262     Threadsafety:
263         This function should be called on the thread that created the
264         tray.
265 
266     See_Also:
267         $(D SDL_CreateTray)
268         $(D SDL_CreateTrayMenu)
269 */
270 extern SDL_TrayMenu* SDL_GetTrayMenu(SDL_Tray* tray);
271 
272 /**
273     Gets a previously created tray entry submenu.
274 
275     You should have called SDL_CreateTraySubmenu() on the entry object. This
276     function allows you to fetch it again later.
277 
278     This function does the same thing as SDL_GetTrayMenu(), except that it
279     takes a SDL_TrayEntry instead of a SDL_Tray.
280 
281     A menu does not need to be destroyed; it will be destroyed with the tray.
282 
283     Params:
284         entry = The tray entry to bind the menu to.
285     
286     Returns:
287         the newly created menu.
288 
289     Threadsafety:
290         This function should be called on the thread that created the
291         tray.
292 
293     See_Also:
294         $(D SDL_InsertTrayEntryAt)
295         $(D SDL_CreateTraySubmenu)
296 */
297 extern SDL_TrayMenu* SDL_GetTraySubmenu(SDL_TrayEntry* entry);
298 
299 /**
300     Returns a list of entries in the menu, in order.
301 
302     Params:
303         menu =  The menu to get entries from.
304         count = An optional pointer to obtain the number of entries in the
305                 menu.
306     
307     Returns:
308         A $(D null)-terminated list of entries within the given menu. The
309         pointer becomes invalid when any function that inserts or deletes
310         entries in the menu is called.
311 
312     Threadsafety:
313         This function should be called on the thread that created the
314         tray.
315 
316     See_Also:
317         $(D SDL_RemoveTrayEntry)
318         $(D SDL_InsertTrayEntryAt)
319 */
320 extern const(SDL_TrayEntry)** SDL_GetTrayEntries(SDL_TrayMenu* menu, int* count);
321 
322 /**
323     Removes a tray entry.
324 
325     Params:
326         entry = The entry to be deleted.
327 
328     Threadsafety:
329         This function should be called on the thread that created the
330         tray.
331 
332     See_Also:
333         $(D SDL_GetTrayEntries)
334         $(D SDL_InsertTrayEntryAt)
335 */
336 extern void SDL_RemoveTrayEntry(SDL_TrayEntry* entry);
337 
338 /**
339     Insert a tray entry at a given position.
340 
341     If label is $(D null), the entry will be a separator. Many functions won't work
342     for an entry that is a separator.
343 
344     An entry does not need to be destroyed; it will be destroyed with the tray.
345 
346     Params:
347         menu =  The menu to append the entry to.
348         pos =   The desired position for the new entry. Entries at or following
349                 this place will be moved. If pos is -1, the entry is appended.
350         label = The text to be displayed on the entry, in UTF-8 encoding, or
351                 $(D null) for a separator.
352         flags = A combination of flags, some of which are mandatory.
353     
354     Returns:
355         the newly created entry, or $(D null) if pos is out of bounds.
356 
357     Threadsafety:
358         This function should be called on the thread that created the
359         tray.
360 
361     See_Also:
362         $(D SDL_TrayEntryFlags)
363         $(D SDL_GetTrayEntries)
364         $(D SDL_RemoveTrayEntry)
365         $(D SDL_GetTrayEntryParent)
366 */
367 extern SDL_TrayEntry* SDL_InsertTrayEntryAt(SDL_TrayMenu* menu, int pos, const(char)* label, SDL_TrayEntryFlags flags);
368 
369 /**
370     Sets the label of an entry.
371 
372     An entry cannot change between a separator and an ordinary entry; that is,
373     it is not possible to set a non-$(D null) label on an entry that has a $(D null)
374     label (separators), or to set a $(D null) label to an entry that has a non-$(D null)
375     label. The function will silently fail if that happens.
376 
377     Params:
378         entry = The entry to be updated.
379         label = The new label for the entry in UTF-8 encoding.
380 
381     Threadsafety:
382         This function should be called on the thread that created the
383         tray.
384 
385     See_Also:
386         $(D SDL_GetTrayEntries)
387         $(D SDL_InsertTrayEntryAt)
388         $(D SDL_GetTrayEntryLabel)
389 */
390 extern void SDL_SetTrayEntryLabel(SDL_TrayEntry* entry, const(char)* label);
391 
392 /**
393     Gets the label of an entry.
394 
395     If the returned value is $(D null), the entry is a separator.
396 
397     Params:
398         entry = The entry to be read.
399     
400     Returns:
401         the label of the entry in UTF-8 encoding.
402 
403     Threadsafety:
404         This function should be called on the thread that created the
405         tray.
406 
407     See_Also:
408         $(D SDL_GetTrayEntries)
409         $(D SDL_InsertTrayEntryAt)
410         $(D SDL_SetTrayEntryLabel)
411 */
412 extern const(char)* SDL_GetTrayEntryLabel(SDL_TrayEntry* entry);
413 
414 /**
415     Sets whether or not an entry is checked.
416 
417     The entry must have been created with the SDL_TRAYENTRY_CHECKBOX flag.
418 
419     Params:
420         entry =     The entry to be updated.
421         checked =   $(D true) if the entry should be checked; 
422                     $(D false) otherwise.
423 
424     Threadsafety:
425         This function should be called on the thread that created the
426         tray.
427 
428     See_Also:
429         $(D SDL_GetTrayEntries)
430         $(D SDL_InsertTrayEntryAt)
431         $(D SDL_GetTrayEntryChecked)
432 */
433 extern void SDL_SetTrayEntryChecked(SDL_TrayEntry* entry, bool checked);
434 
435 /**
436     Gets whether or not an entry is checked.
437 
438     The entry must have been created with the SDL_TRAYENTRY_CHECKBOX flag.
439 
440     Params:
441         entry = The entry to be read.
442     
443     Returns:
444         $(D true) if the entry is checked; 
445         $(D false) otherwise.
446 
447     Threadsafety:
448         This function should be called on the thread that created the
449         tray.
450 
451     See_Also:
452         $(D SDL_GetTrayEntries)
453         $(D SDL_InsertTrayEntryAt)
454         $(D SDL_SetTrayEntryChecked)
455 */
456 extern bool SDL_GetTrayEntryChecked(SDL_TrayEntry* entry);
457 
458 /**
459     Sets whether or not an entry is enabled.
460 
461     Params:
462         entry =     The entry to be updated.
463         enabled =   $(D true) if the entry should be enabled;
464                     $(D false) otherwise.
465 
466     Threadsafety:
467         This function should be called on the thread that created the
468         tray.
469 
470     See_Also:
471         $(D SDL_GetTrayEntries)
472         $(D SDL_InsertTrayEntryAt)
473         $(D SDL_GetTrayEntryEnabled)
474 */
475 extern void SDL_SetTrayEntryEnabled(SDL_TrayEntry* entry, bool enabled);
476 
477 /**
478     Gets whether or not an entry is enabled.
479 
480     Params:
481         entry = The entry to be read.
482     
483     Returns:
484         $(D true) if the entry is enabled;
485         $(D false) otherwise.
486 
487     Threadsafety:
488         This function should be called on the thread that created the
489         tray.
490 
491     See_Also:
492         $(D SDL_GetTrayEntries)
493         $(D SDL_InsertTrayEntryAt)
494         $(D SDL_SetTrayEntryEnabled)
495 */
496 extern bool SDL_GetTrayEntryEnabled(SDL_TrayEntry* entry);
497 
498 /**
499     Sets a callback to be invoked when the entry is selected.
500 
501     Params:
502         entry =     The entry to be updated.
503         callback =  A callback to be invoked when the entry is selected.
504         userdata =  An optional pointer to pass extra data to the callback when
505                     it will be invoked.
506 
507     Threadsafety:
508         This function should be called on the thread that created the
509         tray.
510 
511     See_Also:
512         $(D SDL_GetTrayEntries)
513         $(D SDL_InsertTrayEntryAt)
514 */
515 extern void SDL_SetTrayEntryCallback(SDL_TrayEntry* entry, SDL_TrayCallback callback, void* userdata);
516 
517 /**
518     Simulate a click on a tray entry.
519 
520     Params:
521         entry = The entry to activate.
522 
523     Threadsafety:
524         This function should be called on the thread that created the
525         tray.
526 */
527 extern void SDL_ClickTrayEntry(SDL_TrayEntry* entry);
528 
529 /**
530     Destroys a tray object.
531 
532     This also destroys all associated menus and entries.
533 
534     Params:
535         tray =   The tray icon to be destroyed.
536 
537     Threadsafety:
538         This function should be called on the thread that created the
539         tray.
540 
541     See_Also:
542         $(D SDL_CreateTray)
543 */
544 extern void SDL_DestroyTray(SDL_Tray* tray);
545 
546 /**
547     Gets the menu containing a certain tray entry.
548 
549     Params:
550         entry = The entry for which to get the parent menu.
551     
552     Returns:
553         the parent menu.
554 
555     Threadsafety:
556         This function should be called on the thread that created the
557         tray.
558 
559     See_Also:
560         $(D SDL_InsertTrayEntryAt)
561 */
562 extern SDL_TrayMenu* SDL_GetTrayEntryParent(SDL_TrayEntry* entry);
563 
564 /**
565     Gets the entry for which the menu is a submenu, if the current menu is a
566     submenu.
567 
568     Either this function or SDL_GetTrayMenuParentTray() will return non-$(D null)
569     for any given menu.
570 
571     Params:
572         menu =  The menu for which to get the parent entry.
573     
574     Returns:
575         The parent entry, or $(D null) if this menu is not a submenu.
576 
577     Threadsafety:
578         This function should be called on the thread that created the
579         tray.
580 
581     See_Also:
582         $(D SDL_CreateTraySubmenu)
583         $(D SDL_GetTrayMenuParentTray)
584 */
585 extern SDL_TrayEntry* SDL_GetTrayMenuParentEntry(SDL_TrayMenu* menu);
586 
587 /**
588     Gets the tray for which this menu is the first-level menu, if the current
589     menu isn't a submenu.
590 
591     Either this function or SDL_GetTrayMenuParentEntry() will 
592     return non-$(D null) for any given menu.
593 
594     Params:
595         menu = the menu for which to get the parent enttrayry.
596     
597     Returns:
598         The parent tray, or $(D null) if this menu is a submenu.
599 
600     Threadsafety:
601         This function should be called on the thread that created the
602         tray.
603 
604     See_Also:
605         $(D SDL_CreateTrayMenu)
606         $(D SDL_GetTrayMenuParentEntry)
607 */
608 extern SDL_Tray* SDL_GetTrayMenuParentTray(SDL_TrayMenu* menu);
609 
610 /**
611     Update the trays.
612 
613     This is called automatically by the event loop and is only needed if you're
614     using trays but aren't handling SDL events.
615 
616     Threadsafety:
617         This function should only be called on the main thread.
618 */
619 extern void SDL_UpdateTrays();