Skip to content

Commit 8b02b30

Browse files
committed
Add C API for tray menu and tray icon with example usage
- Introduce C API headers and implementations for menu, tray icon, and tray manager - Add tray_menu_c_example demonstrating usage of the new C APIs - Update nativeapi.h to include new C API headers - Register new example in CMakeLists.txt
1 parent 5a4cce2 commit 8b02b30

File tree

10 files changed

+2409
-0
lines changed

10 files changed

+2409
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ add_subdirectory(examples/display_example)
1010
add_subdirectory(examples/keyboard_example)
1111
add_subdirectory(examples/window_example)
1212
add_subdirectory(examples/tray_icon_example)
13+
add_subdirectory(examples/tray_menu_c_example)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(tray_menu_c_example VERSION 0.0.1 LANGUAGES CXX)
4+
5+
# Set C++ standard
6+
set(CMAKE_CXX_STANDARD 17)
7+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
8+
9+
# Add example program
10+
add_executable(tray_menu_c_example
11+
"main.c"
12+
)
13+
14+
# Link main library
15+
target_link_libraries(tray_menu_c_example PRIVATE libnativeapi)
16+
17+
# Set example program properties
18+
set_target_properties(tray_menu_c_example PROPERTIES
19+
OUTPUT_NAME "tray_menu_c_example"
20+
)
21+
22+
# Set example program compile options (macOS only)
23+
if(APPLE)
24+
set_source_files_properties("main.cpp"
25+
PROPERTIES
26+
COMPILE_FLAGS "-x objective-c++"
27+
)
28+
endif()
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#ifdef _WIN32
6+
#include <windows.h>
7+
#else
8+
#include <unistd.h>
9+
#endif
10+
11+
// Include individual C API headers instead of the full nativeapi.h
12+
#include "../../src/capi/menu_c.h"
13+
#include "../../src/capi/tray_icon_c.h"
14+
#include "../../src/capi/tray_manager_c.h"
15+
16+
// Callback functions
17+
void on_menu_item_clicked(const native_menu_item_selected_event_t* event, void* user_data) {
18+
printf("Menu item clicked: ID=%ld, Text='%s'\n", event->item_id, event->item_text);
19+
20+
if (strcmp(event->item_text, "Exit") == 0) {
21+
printf("Exiting application...\n");
22+
exit(0);
23+
} else if (strcmp(event->item_text, "Show Message") == 0) {
24+
printf("Hello from tray menu!\n");
25+
}
26+
}
27+
28+
void on_checkbox_state_changed(const native_menu_item_state_changed_event_t* event, void* user_data) {
29+
printf("Checkbox state changed: ID=%ld, Checked=%s\n",
30+
event->item_id, event->checked ? "true" : "false");
31+
}
32+
33+
void on_tray_left_click(void* user_data) {
34+
printf("Tray icon left clicked!\n");
35+
}
36+
37+
void on_tray_right_click(void* user_data) {
38+
printf("Tray icon right clicked!\n");
39+
}
40+
41+
void on_tray_double_click(void* user_data) {
42+
printf("Tray icon double clicked!\n");
43+
}
44+
45+
void on_menu_will_show(native_menu_id_t menu_id, void* user_data) {
46+
printf("Menu will show: ID=%ld\n", menu_id);
47+
}
48+
49+
void on_menu_did_hide(native_menu_id_t menu_id, void* user_data) {
50+
printf("Menu did hide: ID=%ld\n", menu_id);
51+
}
52+
53+
int main() {
54+
printf("=== Tray Menu C API Example ===\n");
55+
56+
// Check if system tray is supported
57+
if (!native_tray_manager_is_supported()) {
58+
printf("Error: System tray is not supported on this platform!\n");
59+
return 1;
60+
}
61+
62+
printf("System tray is supported.\n");
63+
64+
// Create a menu
65+
native_menu_t menu = native_menu_create();
66+
if (!menu) {
67+
printf("Error: Failed to create menu!\n");
68+
return 1;
69+
}
70+
71+
printf("Created menu with ID: %ld\n", native_menu_get_id(menu));
72+
73+
// Create menu items
74+
native_menu_item_t item1 = native_menu_item_create("Show Message", NATIVE_MENU_ITEM_TYPE_NORMAL);
75+
native_menu_item_t item2 = native_menu_item_create("Settings", NATIVE_MENU_ITEM_TYPE_NORMAL);
76+
native_menu_item_t checkbox = native_menu_item_create("Enable Notifications", NATIVE_MENU_ITEM_TYPE_CHECKBOX);
77+
native_menu_item_t separator = native_menu_item_create_separator();
78+
native_menu_item_t exit_item = native_menu_item_create("Exit", NATIVE_MENU_ITEM_TYPE_NORMAL);
79+
80+
if (!item1 || !item2 || !checkbox || !separator || !exit_item) {
81+
printf("Error: Failed to create menu items!\n");
82+
native_menu_destroy(menu);
83+
return 1;
84+
}
85+
86+
// Set up menu item properties
87+
native_menu_item_set_enabled(item1, true);
88+
native_menu_item_set_tooltip(item1, "Click to show a message");
89+
90+
// Set up keyboard accelerator for exit item
91+
native_keyboard_accelerator_t exit_accel = {
92+
.modifiers = NATIVE_ACCELERATOR_MODIFIER_CTRL,
93+
.key = "Q"
94+
};
95+
native_menu_item_set_accelerator(exit_item, &exit_accel);
96+
97+
// Set checkbox state
98+
native_menu_item_set_checked(checkbox, true);
99+
100+
// Set up event handlers
101+
native_menu_item_set_on_click(item1, on_menu_item_clicked, NULL);
102+
native_menu_item_set_on_click(item2, on_menu_item_clicked, NULL);
103+
native_menu_item_set_on_click(exit_item, on_menu_item_clicked, NULL);
104+
native_menu_item_set_on_state_changed(checkbox, on_checkbox_state_changed, NULL);
105+
106+
// Add items to menu
107+
native_menu_add_item(menu, item1);
108+
native_menu_add_item(menu, item2);
109+
native_menu_add_item(menu, checkbox);
110+
native_menu_add_item(menu, separator);
111+
native_menu_add_item(menu, exit_item);
112+
113+
printf("Added %zu items to menu\n", native_menu_get_item_count(menu));
114+
115+
// Set menu callbacks
116+
native_menu_set_on_will_show(menu, on_menu_will_show, NULL);
117+
native_menu_set_on_did_hide(menu, on_menu_did_hide, NULL);
118+
119+
// Create a submenu example
120+
native_menu_t submenu = native_menu_create();
121+
if (submenu) {
122+
native_menu_item_t sub_item1 = native_menu_item_create("Sub Item 1", NATIVE_MENU_ITEM_TYPE_NORMAL);
123+
native_menu_item_t sub_item2 = native_menu_item_create("Sub Item 2", NATIVE_MENU_ITEM_TYPE_NORMAL);
124+
125+
if (sub_item1 && sub_item2) {
126+
native_menu_add_item(submenu, sub_item1);
127+
native_menu_add_item(submenu, sub_item2);
128+
129+
// Create submenu item and add to main menu
130+
native_menu_item_t submenu_item = native_menu_create_and_add_submenu(menu, "More Options", submenu);
131+
if (submenu_item) {
132+
printf("Created submenu with %zu items\n", native_menu_get_item_count(submenu));
133+
}
134+
}
135+
}
136+
137+
// Create tray icon
138+
native_tray_icon_t tray_icon = native_tray_manager_create();
139+
if (!tray_icon) {
140+
printf("Error: Failed to create tray icon!\n");
141+
native_menu_destroy(menu);
142+
return 1;
143+
}
144+
145+
printf("Created tray icon with ID: %ld\n", native_tray_icon_get_id(tray_icon));
146+
147+
// Set up tray icon properties
148+
native_tray_icon_set_title(tray_icon, "My App");
149+
native_tray_icon_set_tooltip(tray_icon, "My Application - Right click for menu");
150+
151+
// Set the context menu
152+
native_tray_icon_set_context_menu(tray_icon, menu);
153+
154+
// Set up tray icon event handlers
155+
native_tray_icon_set_on_left_click(tray_icon, on_tray_left_click, NULL);
156+
native_tray_icon_set_on_right_click(tray_icon, on_tray_right_click, NULL);
157+
native_tray_icon_set_on_double_click(tray_icon, on_tray_double_click, NULL);
158+
159+
// Show the tray icon
160+
if (native_tray_icon_show(tray_icon)) {
161+
printf("Tray icon is now visible\n");
162+
} else {
163+
printf("Warning: Failed to show tray icon\n");
164+
}
165+
166+
// Get tray icon bounds
167+
native_rectangle_t bounds;
168+
if (native_tray_icon_get_bounds(tray_icon, &bounds)) {
169+
printf("Tray icon bounds: x=%.1f, y=%.1f, width=%.1f, height=%.1f\n",
170+
bounds.x, bounds.y, bounds.width, bounds.height);
171+
}
172+
173+
// Demonstrate menu item lookup
174+
native_menu_item_t found_item = native_menu_find_item_by_text(menu, "Exit");
175+
if (found_item) {
176+
printf("Found 'Exit' menu item with ID: %ld\n", native_menu_item_get_id(found_item));
177+
178+
// Get accelerator info
179+
native_keyboard_accelerator_t accel;
180+
if (native_menu_item_get_accelerator(found_item, &accel)) {
181+
char accel_str[64];
182+
if (native_keyboard_accelerator_to_string(&accel, accel_str, sizeof(accel_str)) > 0) {
183+
printf("Exit item accelerator: %s\n", accel_str);
184+
}
185+
}
186+
}
187+
188+
// Show all managed tray icons
189+
native_tray_icon_list_t tray_list = native_tray_manager_get_all();
190+
printf("Total managed tray icons: %zu\n", tray_list.count);
191+
native_tray_icon_list_free(tray_list);
192+
193+
printf("\n=== Tray icon and menu are now active ===\n");
194+
printf("- Left click the tray icon to see left click message\n");
195+
printf("- Right click the tray icon to open context menu\n");
196+
printf("- Double click the tray icon to see double click message\n");
197+
printf("- Use menu items to interact with the application\n");
198+
printf("- Click 'Exit' to quit\n");
199+
printf("\nRunning... (Press Ctrl+C to force quit)\n");
200+
201+
// Simple event loop (in a real application, you'd use the platform's event loop)
202+
// This is just to keep the program running so the tray icon stays active
203+
while (1) {
204+
// In a real application, you would handle events here
205+
// For this demo, we'll just sleep and let the system handle tray events
206+
207+
#ifdef _WIN32
208+
Sleep(1000); // Windows - sleep for 1000ms
209+
#else
210+
sleep(1); // Unix/Linux/macOS - sleep for 1 second
211+
#endif
212+
}
213+
214+
// Cleanup (this won't be reached due to the infinite loop above)
215+
native_tray_icon_destroy(tray_icon);
216+
native_menu_destroy(menu);
217+
if (submenu) {
218+
native_menu_destroy(submenu);
219+
}
220+
221+
return 0;
222+
}

include/nativeapi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@
2121
#include "../src/capi/display_manager_c.h"
2222
#include "../src/capi/geometry_c.h"
2323
#include "../src/capi/keyboard_monitor_c.h"
24+
#include "../src/capi/menu_c.h"
25+
#include "../src/capi/tray_icon_c.h"
26+
#include "../src/capi/tray_manager_c.h"
2427
#include "../src/capi/window_c.h"
2528
#include "../src/capi/window_manager_c.h"

0 commit comments

Comments
 (0)