12constexpr const char *
const WINDOW_DATA_KEY =
"esphome_sdl";
55 SDL_DestroyWindow(this->
window_);
65 ESP_LOGE(TAG,
"%s: %s", what, SDL_GetError());
79 this->
surface_ = SDL_CreateRGBSurfaceWithFormat(0, this->
width_, this->
height_, 16, SDL_PIXELFORMAT_RGB565);
81 return this->
setup_failed_(
"Could not create offscreen surface");
84 if (SDL_Init(SDL_INIT_VIDEO) != 0)
86 this->
window_ = SDL_CreateWindow(
App.
get_name().
c_str(), this->pos_x_, this->pos_y_, this->width_, this->height_,
87 this->window_options_);
92 SDL_SetWindowData(this->
window_, WINDOW_DATA_KEY,
this);
93 this->
renderer_ = SDL_CreateRenderer(this->
window_, -1, SDL_RENDERER_SOFTWARE);
98 return this->
setup_failed_(
"Could not set renderer logical size");
100 SDL_CreateTexture(this->
renderer_, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STATIC, this->
width_, this->
height_);
105 if (SDL_SetTextureBlendMode(this->
texture_, this->
headless_ ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND) != 0)
106 return this->
setup_failed_(
"Could not set texture blend mode");
121 ESP_LOGW(TAG,
"snapshot key did not write a file");
134 this->x_low_ = this->
width_;
155 SDL_Rect rect{x_start, y_start, w,
h};
157 Display::draw_pixels_at(x_start, y_start, w,
h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad);
159 auto stride = x_offset + w + x_pad;
160 auto data = ptr + (stride * y_offset + x_offset) * 2;
161 SDL_UpdateTexture(this->
texture_, &rect, data, stride * 2);
183 SDL_Rect rect{
x,
y, 1, 1};
185 SDL_UpdateTexture(this->
texture_, &rect, &data, 2);
199 callback->second(down);
203 SDL_Window *window = SDL_GetWindowFromID(window_id);
204 if (window ==
nullptr)
206 return static_cast<Sdl *
>(SDL_GetWindowData(window, WINDOW_DATA_KEY));
210 switch (event.type) {
211 case SDL_MOUSEBUTTONDOWN:
212 case SDL_MOUSEBUTTONUP:
213 if (event.button.button == 1) {
214 this->
mouse_x =
event.button.x;
215 this->
mouse_y =
event.button.y;
220 case SDL_MOUSEMOTION:
221 if (event.motion.state & 1) {
222 this->
mouse_x =
event.motion.x;
223 this->
mouse_y =
event.motion.y;
232 if (event.key.repeat != 0)
234 ESP_LOGD(TAG,
"keydown %d", event.key.keysym.sym);
239 ESP_LOGD(TAG,
"keyup %d", event.key.keysym.sym);
243 case SDL_WINDOWEVENT:
244 switch (event.window.event) {
245 case SDL_WINDOWEVENT_SIZE_CHANGED:
246 case SDL_WINDOWEVENT_EXPOSED:
247 case SDL_WINDOWEVENT_RESIZED: {
268 while (SDL_PollEvent(&e)) {
269 if (e.type == SDL_QUIT)
275 case SDL_MOUSEBUTTONDOWN:
276 case SDL_MOUSEBUTTONUP:
277 window_id = e.button.windowID;
279 case SDL_MOUSEMOTION:
280 window_id = e.motion.windowID;
284 window_id = e.key.windowID;
286 case SDL_WINDOWEVENT:
287 window_id = e.window.windowID;
292 ESP_LOGV(TAG,
"Event %d", e.type);
297 if (target ==
nullptr) {
300 ESP_LOGV(TAG,
"Event %d for unknown window %u", e.type, window_id);
309 ESP_LOGE(TAG,
"Snapshot requested but SDL is not set up");
313 this->
shot_target_ = SDL_CreateTexture(this->
renderer_, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET,
316 ESP_LOGE(TAG,
"Could not create capture texture: %s", SDL_GetError());
319 SDL_SetTextureBlendMode(this->
shot_target_, SDL_BLENDMODE_NONE);
329 ok = SDL_SetRenderDrawColor(this->
renderer_, 0, 0, 0, SDL_ALPHA_OPAQUE) == 0 &&
332 SDL_RenderReadPixels(this->
renderer_,
nullptr, SDL_PIXELFORMAT_BGR24, dest,
static_cast<int>(row_stride)) == 0;
333 if (SDL_SetRenderTarget(this->
renderer_,
nullptr) != 0) {
335 ESP_LOGE(TAG,
"Could not restore the render target: %s", SDL_GetError());
341 ESP_LOGE(TAG,
"Could not capture the screen: %s", SDL_GetError());
const StringRef & get_name() const
Get the name of this Application set by pre_setup().
void mark_failed()
Mark this component as failed.
void disable_loop()
Disable this component's loop.
constexpr const char * c_str() const
static uint16_t color_to_565(Color color, ColorOrder color_order=ColorOrder::COLOR_ORDER_RGB)
Rect get_clipping() const
Get the current the clipping rectangle.
DisplayRotation rotation_
int get_height() override
void add_key_listener(int32_t keycode, F &&callback)
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override
static Sdl * instance_for_window_(uint32_t window_id)
The display owning the given window, or nullptr if it is not one of ours.
int get_height_internal() override
void process_key(uint32_t keycode, bool down)
void redraw_(SDL_Rect &rect)
bool setup_failed_(const char *what)
Log an SDL failure during setup, release anything already created, and return false.
void handle_event_(const SDL_Event &event)
bool capture_bgr(uint8_t *dest, size_t row_stride) override
void destroy_renderer_()
Release the window, surface, renderer and textures, and forget them.
void draw_pixel_at(int x, int y, Color color) override
int get_width_internal() override
SDL_Texture * shot_target_
std::map< int32_t, CallbackManager< void(bool)> > key_callbacks_
bool take_snapshot(const char *filename)
Write the current picture to a BMP file in the snapshot directory.
@ DISPLAY_ROTATION_0_DEGREES
@ DISPLAY_ROTATION_270_DEGREES
@ DISPLAY_ROTATION_180_DEGREES
@ DISPLAY_ROTATION_90_DEGREES
Application App
Global storage of Application pointer - only one Application can exist.