Skip to content

Commit 07684e8

Browse files
committed
Refactor display API to use getter methods and opaque handles
- Replace direct struct field access with getter functions in C and C++ examples - Make native_display_t an opaque handle managed by the C++ implementation - Update platform-specific display code to use new Display class with pimpl - Refactor window and tray icon classes to use unique_ptr for implementation - Update window and tray icon APIs to use getter methods for IDs - Remove legacy C display struct fields and setters from C API - Update CMake and source file organization for new platform display code
1 parent db3dd06 commit 07684e8

28 files changed

+1040
-653
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_subdirectory(src)
77

88
# Add example programs subdirectory
99
add_subdirectory(examples/display_example)
10+
add_subdirectory(examples/display_c_example)
1011
add_subdirectory(examples/keyboard_example)
1112
add_subdirectory(examples/menu_example)
1213
add_subdirectory(examples/menu_c_example)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(display_c_example)
4+
5+
set(CMAKE_C_STANDARD 99)
6+
7+
add_executable(display_c_example main.c)
8+
9+
target_link_libraries(display_c_example nativeapi)
10+
11+
target_include_directories(display_c_example PRIVATE
12+
${CMAKE_CURRENT_SOURCE_DIR}/../../include
13+
)

examples/display_c_example/main.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
// Include only C API headers
5+
#include "../../src/capi/display_c.h"
6+
#include "../../src/capi/display_manager_c.h"
7+
#include "../../src/capi/geometry_c.h"
8+
9+
int main() {
10+
printf("=== Native API C Display Example ===\n\n");
11+
12+
// Test getting all displays
13+
native_display_list_t display_list = native_display_manager_get_all();
14+
15+
if (display_list.displays != NULL && display_list.count > 0) {
16+
printf("Found %ld display(s):\n\n", display_list.count);
17+
18+
for (size_t i = 0; i < display_list.count; i++) {
19+
native_display_t display = display_list.displays[i];
20+
21+
printf("Display %zu:\n", i + 1);
22+
23+
// Use getter functions for all properties
24+
char* name = native_display_get_name(display);
25+
printf(" Name: %s\n", name ? name : "Unknown");
26+
native_display_free_string(name);
27+
28+
char* id = native_display_get_id(display);
29+
printf(" ID: %s\n", id ? id : "Unknown");
30+
native_display_free_string(id);
31+
32+
native_point_t position = native_display_get_position(display);
33+
printf(" Position: (%.0f, %.0f)\n", position.x, position.y);
34+
35+
native_size_t size = native_display_get_size(display);
36+
printf(" Size: %.0f x %.0f\n", size.width, size.height);
37+
38+
native_rectangle_t work_area = native_display_get_work_area(display);
39+
printf(" Work Area: (%.0f, %.0f) %.0f x %.0f\n",
40+
work_area.x, work_area.y, work_area.width, work_area.height);
41+
42+
double scale_factor = native_display_get_scale_factor(display);
43+
printf(" Scale Factor: %.2f\n", scale_factor);
44+
45+
bool is_primary = native_display_is_primary(display);
46+
printf(" Primary: %s\n", is_primary ? "Yes" : "No");
47+
48+
// Display orientation
49+
printf(" Orientation: ");
50+
native_display_orientation_t orientation = native_display_get_orientation(display);
51+
switch (orientation) {
52+
case NATIVE_DISPLAY_ORIENTATION_PORTRAIT:
53+
printf("Portrait (0°)");
54+
break;
55+
case NATIVE_DISPLAY_ORIENTATION_LANDSCAPE:
56+
printf("Landscape (90°)");
57+
break;
58+
case NATIVE_DISPLAY_ORIENTATION_PORTRAIT_FLIPPED:
59+
printf("Portrait Flipped (180°)");
60+
break;
61+
case NATIVE_DISPLAY_ORIENTATION_LANDSCAPE_FLIPPED:
62+
printf("Landscape Flipped (270°)");
63+
break;
64+
default:
65+
printf("Unknown");
66+
break;
67+
}
68+
printf("\n");
69+
70+
int refresh_rate = native_display_get_refresh_rate(display);
71+
printf(" Refresh Rate: %d Hz\n", refresh_rate);
72+
73+
int bit_depth = native_display_get_bit_depth(display);
74+
printf(" Bit Depth: %d bits\n", bit_depth);
75+
76+
char* manufacturer = native_display_get_manufacturer(display);
77+
if (manufacturer) {
78+
printf(" Manufacturer: %s\n", manufacturer);
79+
}
80+
native_display_free_string(manufacturer);
81+
82+
char* model = native_display_get_model(display);
83+
if (model) {
84+
printf(" Model: %s\n", model);
85+
}
86+
native_display_free_string(model);
87+
88+
char* serial_number = native_display_get_serial_number(display);
89+
if (serial_number) {
90+
printf(" Serial Number: %s\n", serial_number);
91+
}
92+
native_display_free_string(serial_number);
93+
94+
printf("\n");
95+
}
96+
97+
// Clean up memory
98+
native_display_list_free(&display_list);
99+
} else {
100+
printf("No displays found or error occurred\n");
101+
}
102+
103+
// Test getting primary display
104+
printf("=== Primary Display ===\n");
105+
native_display_t primary = native_display_manager_get_primary();
106+
if (primary) {
107+
char* name = native_display_get_name(primary);
108+
printf("Primary display: %s\n", name ? name : "Unknown");
109+
native_display_free_string(name);
110+
111+
native_size_t size = native_display_get_size(primary);
112+
printf("Size: %.0f x %.0f\n", size.width, size.height);
113+
114+
// Free the primary display handle
115+
native_display_free(primary);
116+
} else {
117+
printf("Failed to get primary display\n");
118+
}
119+
120+
// Test getting cursor position
121+
printf("\n=== Cursor Position ===\n");
122+
native_point_t cursor_pos = native_display_manager_get_cursor_position();
123+
printf("Cursor position: (%.0f, %.0f)\n", cursor_pos.x, cursor_pos.y);
124+
125+
return 0;
126+
}

examples/display_example/main.cpp

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ using nativeapi::Display;
99
using nativeapi::DisplayManager;
1010
using nativeapi::DisplayOrientation;
1111
using nativeapi::Point;
12+
using nativeapi::Size;
13+
using nativeapi::Rectangle;
1214

1315
// Helper function to convert orientation enum to string
1416
std::string orientationToString(DisplayOrientation orientation) {
@@ -78,64 +80,73 @@ void printDisplayInfo(const Display& display, bool isPrimary = false) {
7880
const int tableWidth = 70;
7981

8082
std::cout << createTableBorder("+", "+", "-", tableWidth) << std::endl;
81-
std::cout << formatTableRow("Display: " + display.name, tableWidth)
83+
std::cout << formatTableRow("Display: " + display.GetName(), tableWidth)
8284
<< std::endl;
8385
std::cout << createTableBorder("+", "+", "-", tableWidth) << std::endl;
84-
std::cout << formatTableRow("ID: " + display.id, tableWidth) << std::endl;
86+
std::cout << formatTableRow("ID: " + display.GetId(), tableWidth) << std::endl;
8587

86-
// Format position string
88+
// Format position string using getter methods
89+
Point position = display.GetPosition();
8790
std::string positionStr = "Position: (" +
88-
std::to_string((int)display.position.x) + ", " +
89-
std::to_string((int)display.position.y) + ")";
91+
std::to_string((int)position.x) + ", " +
92+
std::to_string((int)position.y) + ")";
9093
std::cout << formatTableRow(positionStr, tableWidth) << std::endl;
9194

92-
// Format size string with proper separator
93-
std::string sizeStr = "Size: " + std::to_string((int)display.size.width) +
94-
" x " + std::to_string((int)display.size.height);
95+
// Format size string with proper separator using getter methods
96+
Size size = display.GetSize();
97+
std::string sizeStr = "Size: " + std::to_string((int)size.width) +
98+
" x " + std::to_string((int)size.height);
9599
std::cout << formatTableRow(sizeStr, tableWidth) << std::endl;
96100

97-
// Format work area string with proper formatting
101+
// Format work area string with proper formatting using getter methods
102+
Rectangle workArea = display.GetWorkArea();
98103
std::string workAreaStr =
99-
"Work Area: (" + std::to_string((int)display.workArea.x) + ", " +
100-
std::to_string((int)display.workArea.y) + ") " +
101-
std::to_string((int)display.workArea.width) + " x " +
102-
std::to_string((int)display.workArea.height);
104+
"Work Area: (" + std::to_string((int)workArea.x) + ", " +
105+
std::to_string((int)workArea.y) + ") " +
106+
std::to_string((int)workArea.width) + " x " +
107+
std::to_string((int)workArea.height);
103108
std::cout << formatTableRow(workAreaStr, tableWidth) << std::endl;
104109

105-
// Format scale factor string
110+
// Format scale factor string using getter methods
106111
std::stringstream scaleStream;
107112
scaleStream << "Scale Factor: " << std::fixed << std::setprecision(2)
108-
<< display.scaleFactor;
113+
<< display.GetScaleFactor();
109114
std::cout << formatTableRow(scaleStream.str(), tableWidth) << std::endl;
110115

111-
// Format primary status
116+
// Format primary status using getter methods
112117
std::string primaryStr =
113-
"Primary: " + std::string(display.isPrimary ? "Yes" : "No");
118+
"Primary: " + std::string(display.IsPrimary() ? "Yes" : "No");
114119
std::cout << formatTableRow(primaryStr, tableWidth) << std::endl;
115120

116-
// Format orientation
121+
// Format orientation using getter methods
117122
std::string orientationStr =
118-
"Orientation: " + orientationToString(display.orientation);
123+
"Orientation: " + orientationToString(display.GetOrientation());
119124
std::cout << formatTableRow(orientationStr, tableWidth) << std::endl;
120125

121-
// Format refresh rate
126+
// Format refresh rate using getter methods
122127
std::string refreshStr =
123-
"Refresh Rate: " + std::to_string(display.refreshRate) + " Hz";
128+
"Refresh Rate: " + std::to_string(display.GetRefreshRate()) + " Hz";
124129
std::cout << formatTableRow(refreshStr, tableWidth) << std::endl;
125130

126-
if (display.bitDepth > 0) {
131+
// Format bit depth using getter methods
132+
int bitDepth = display.GetBitDepth();
133+
if (bitDepth > 0) {
127134
std::string bitDepthStr =
128-
"Bit Depth: " + std::to_string(display.bitDepth) + " bits";
135+
"Bit Depth: " + std::to_string(bitDepth) + " bits";
129136
std::cout << formatTableRow(bitDepthStr, tableWidth) << std::endl;
130137
}
131138

132-
if (!display.manufacturer.empty()) {
133-
std::string manufacturerStr = "Manufacturer: " + display.manufacturer;
139+
// Format manufacturer using getter methods
140+
std::string manufacturer = display.GetManufacturer();
141+
if (!manufacturer.empty()) {
142+
std::string manufacturerStr = "Manufacturer: " + manufacturer;
134143
std::cout << formatTableRow(manufacturerStr, tableWidth) << std::endl;
135144
}
136145

137-
if (!display.model.empty()) {
138-
std::string modelStr = "Model: " + display.model;
146+
// Format model using getter methods
147+
std::string model = display.GetModel();
148+
if (!model.empty()) {
149+
std::string modelStr = "Model: " + model;
139150
std::cout << formatTableRow(modelStr, tableWidth) << std::endl;
140151
}
141152

@@ -170,7 +181,7 @@ int main() {
170181
if (displays.size() > 1) {
171182
std::cout << "📱 SECONDARY DISPLAYS:" << std::endl;
172183
for (const auto& display : displays) {
173-
if (!display.isPrimary) {
184+
if (!display.IsPrimary()) {
174185
printDisplayInfo(display);
175186
std::cout << std::endl;
176187
}
@@ -183,16 +194,19 @@ int main() {
183194
<< cursorPos.y << ")" << std::endl;
184195
std::cout << std::endl;
185196

186-
// Display summary statistics
197+
// Display summary statistics using getter methods
187198
double totalWidth = 0, totalHeight = 0;
188-
double minScaleFactor = displays[0].scaleFactor;
189-
double maxScaleFactor = displays[0].scaleFactor;
199+
double minScaleFactor = displays[0].GetScaleFactor();
200+
double maxScaleFactor = displays[0].GetScaleFactor();
190201

191202
for (const auto& display : displays) {
192-
totalWidth += display.size.width;
193-
totalHeight = std::max(totalHeight, display.size.height);
194-
minScaleFactor = std::min(minScaleFactor, display.scaleFactor);
195-
maxScaleFactor = std::max(maxScaleFactor, display.scaleFactor);
203+
Size size = display.GetSize();
204+
double scaleFactor = display.GetScaleFactor();
205+
206+
totalWidth += size.width;
207+
totalHeight = std::max(totalHeight, size.height);
208+
minScaleFactor = std::min(minScaleFactor, scaleFactor);
209+
maxScaleFactor = std::max(maxScaleFactor, scaleFactor);
196210
}
197211

198212
const int summaryWidth = 60;
@@ -238,12 +252,23 @@ int main() {
238252
std::cout << "C API - Found " << display_list.count
239253
<< " display(s):" << std::endl;
240254
for (size_t i = 0; i < display_list.count; ++i) {
241-
const native_display_t& display = display_list.displays[i];
255+
native_display_t display = display_list.displays[i];
242256
std::cout << "Display " << (i + 1) << ":" << std::endl;
243-
std::cout << " Name: " << (display.name ? display.name : "Unknown") << std::endl;
244-
std::cout << " ID: " << (display.id ? display.id : "Unknown") << std::endl;
245-
std::cout << " Size: " << display.size.width << " x " << display.size.height << std::endl;
246-
std::cout << " Primary: " << (display.is_primary ? "Yes" : "No") << std::endl;
257+
258+
// Use getter functions instead of direct struct access
259+
char* name = native_display_get_name(display);
260+
std::cout << " Name: " << (name ? name : "Unknown") << std::endl;
261+
native_display_free_string(name);
262+
263+
char* id = native_display_get_id(display);
264+
std::cout << " ID: " << (id ? id : "Unknown") << std::endl;
265+
native_display_free_string(id);
266+
267+
native_size_t size = native_display_get_size(display);
268+
std::cout << " Size: " << size.width << " x " << size.height << std::endl;
269+
270+
bool is_primary = native_display_is_primary(display);
271+
std::cout << " Primary: " << (is_primary ? "Yes" : "No") << std::endl;
247272
std::cout << std::endl;
248273
}
249274

examples/window_example/main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ int main() {
260260
// Get all windows and destroy them to trigger app exit
261261
auto windows = window_manager.GetAll();
262262
for (auto& window : windows) {
263-
window_manager.Destroy(window->id);
263+
window_manager.Destroy(window->GetId());
264264
}
265265
});
266266
context_menu->AddItem(exit_item);
@@ -295,11 +295,11 @@ int main() {
295295

296296
display_manager.AddListener<nativeapi::DisplayAddedEvent>(
297297
[](const nativeapi::DisplayAddedEvent& event) {
298-
std::cout << "Display added: " << event.GetDisplay().id << std::endl;
298+
std::cout << "Display added: " << event.GetDisplay().GetId() << std::endl;
299299
});
300300
display_manager.AddListener<nativeapi::DisplayRemovedEvent>(
301301
[](const nativeapi::DisplayRemovedEvent& event) {
302-
std::cout << "Display removed: " << event.GetDisplay().id << std::endl;
302+
std::cout << "Display removed: " << event.GetDisplay().GetId() << std::endl;
303303
});
304304

305305
RunApp(window_ptr);

src/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ file(GLOB CAPI_SOURCES "capi/*.cpp" "capi/*.c")
2323

2424
# Platform-specific source files
2525
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
26-
file(GLOB PLATFORM_SOURCES "platform/linux/*_linux.cpp")
26+
file(GLOB PLATFORM_SOURCES "platform/linux/*_linux.cpp" "platform/linux/display_linux.cpp")
2727
# Find packages for Linux
2828
find_package(PkgConfig REQUIRED)
2929
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
3030
pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)
3131
pkg_check_modules(XI REQUIRED IMPORTED_TARGET xi)
3232
elseif(APPLE)
33-
file(GLOB PLATFORM_SOURCES "platform/macos/*_macos.mm")
33+
file(GLOB PLATFORM_SOURCES "platform/macos/*_macos.mm" "platform/macos/display_macos.mm")
3434
elseif(WIN32)
35-
file(GLOB PLATFORM_SOURCES "platform/windows/*_windows.cpp")
35+
file(GLOB PLATFORM_SOURCES "platform/windows/*_windows.cpp" "platform/windows/display_windows.cpp")
3636
else()
3737
set(PLATFORM_SOURCES "")
3838
endif()

0 commit comments

Comments
 (0)