mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 10:55:06 +00:00
79 lines
3.0 KiB
C++
79 lines
3.0 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
#include <lvgl/insets.h>
|
|
#include <lvgl/insets_math.h>
|
|
#include <lvgl/devices/device_context.h>
|
|
|
|
#include <algorithm>
|
|
#include <new>
|
|
|
|
static DisplayShape get_shape(lv_display_t* display) {
|
|
DisplayShape shape = { .shape = DISPLAY_SHAPE_RECTANGLE, .corner_radius = 0 };
|
|
const auto* wrapper = static_cast<const LvglDeviceContext*>(lv_display_get_driver_data(display));
|
|
if (wrapper != nullptr && wrapper->device != nullptr) {
|
|
display_get_shape(wrapper->device, &shape);
|
|
}
|
|
return shape;
|
|
}
|
|
|
|
struct EdgePadding {
|
|
lv_obj_t* obj;
|
|
// The padding before the display's edge was added
|
|
int32_t base_left;
|
|
int32_t base_right;
|
|
};
|
|
|
|
static void update_edge_padding(void* data) {
|
|
const auto* padding = static_cast<const EdgePadding*>(data);
|
|
lv_display_t* display = lv_obj_get_display(padding->obj);
|
|
lv_area_t coords;
|
|
lv_obj_get_coords(padding->obj, &coords);
|
|
// The curve is widest at the object's edge that is nearest to the display's top or bottom
|
|
const int32_t inset = std::max(lvgl_display_get_row_inset(display, coords.y1), lvgl_display_get_row_inset(display, coords.y2));
|
|
const int32_t right_edge = lv_display_get_horizontal_resolution(display) - 1;
|
|
lv_obj_set_style_pad_left(padding->obj, padding->base_left + std::max<int32_t>(0, inset - coords.x1), LV_STATE_DEFAULT);
|
|
lv_obj_set_style_pad_right(padding->obj, padding->base_right + std::max<int32_t>(0, inset - (right_edge - coords.x2)), LV_STATE_DEFAULT);
|
|
}
|
|
|
|
// The position is final once the layout pass that changed the size has finished
|
|
static void on_size_changed(lv_event_t* event) {
|
|
lv_async_call(update_edge_padding, lv_event_get_user_data(event));
|
|
}
|
|
|
|
static void on_deleted(lv_event_t* event) {
|
|
auto* padding = static_cast<EdgePadding*>(lv_event_get_user_data(event));
|
|
lv_async_call_cancel(update_edge_padding, padding);
|
|
delete padding;
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
void lvgl_obj_add_edge_padding(lv_obj_t* obj) {
|
|
if (get_shape(lv_obj_get_display(obj)).shape == DISPLAY_SHAPE_RECTANGLE) {
|
|
return;
|
|
}
|
|
auto* padding = new(std::nothrow) EdgePadding {
|
|
.obj = obj,
|
|
.base_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN),
|
|
.base_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN)
|
|
};
|
|
if (padding == nullptr) {
|
|
return;
|
|
}
|
|
lv_obj_add_event_cb(obj, on_size_changed, LV_EVENT_SIZE_CHANGED, padding);
|
|
lv_obj_add_event_cb(obj, on_deleted, LV_EVENT_DELETE, padding);
|
|
}
|
|
|
|
void lvgl_display_get_shape(lv_display_t* display, DisplayShape* out_shape) {
|
|
*out_shape = get_shape(display);
|
|
}
|
|
|
|
void lvgl_display_get_insets(lv_display_t* display, LvglInsets* out_insets) {
|
|
*out_insets = lvgl_insets_calculate(get_shape(display), lv_display_get_horizontal_resolution(display), lv_display_get_vertical_resolution(display));
|
|
}
|
|
|
|
int32_t lvgl_display_get_row_inset(lv_display_t* display, int32_t y) {
|
|
return lvgl_insets_calculate_row(get_shape(display), lv_display_get_horizontal_resolution(display), lv_display_get_vertical_resolution(display), y);
|
|
}
|
|
|
|
}
|