fix: fix Screenshot fullscreen flickering

This commit is contained in:
2026-05-10 12:50:23 +02:00
parent 72e4fa080a
commit 525f92cdf0
4 changed files with 54 additions and 79 deletions
+10 -78
View File
@@ -61,12 +61,6 @@ struct JpegBuffer {
bool failed;
};
struct AreaRenderCache {
uint32_t* dimmed_pixels;
int width;
int height;
};
static int g_win_w = INIT_W;
static int g_win_h = INIT_H;
static int g_mouse_x = -1;
@@ -352,34 +346,6 @@ static uint32_t dim_pixel(uint32_t px) {
return (px & 0xFF000000u) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
static void free_area_render_cache(AreaRenderCache* cache) {
if (!cache) return;
if (cache->dimmed_pixels)
montauk::mfree(cache->dimmed_pixels);
cache->dimmed_pixels = nullptr;
cache->width = 0;
cache->height = 0;
}
static void build_area_render_cache(const ScreenBuffer& screen, AreaRenderCache* cache) {
if (!cache || !screen.pixels || screen.width <= 0 || screen.height <= 0)
return;
uint64_t count = (uint64_t)screen.width * (uint64_t)screen.height;
uint64_t bytes = count * sizeof(uint32_t);
uint32_t* dimmed = (uint32_t*)montauk::malloc(bytes);
if (!dimmed)
return;
for (uint64_t i = 0; i < count; i++)
dimmed[i] = dim_pixel(screen.pixels[i]);
free_area_render_cache(cache);
cache->dimmed_pixels = dimmed;
cache->width = screen.width;
cache->height = screen.height;
}
// ============================================================================
// Area selection window
// ============================================================================
@@ -462,8 +428,7 @@ static bool draw_fullscreen_preview(Canvas& c,
const ScreenBuffer& screen,
const Rect& preview,
const Rect& selection,
bool has_selection,
const AreaRenderCache* cache) {
bool has_selection) {
if (!screen.pixels || preview.x != 0 || preview.y != 0 ||
preview.w != c.w || preview.h != c.h ||
screen.width != c.w || screen.height != c.h) {
@@ -471,24 +436,9 @@ static bool draw_fullscreen_preview(Canvas& c,
}
uint64_t bytes = (uint64_t)c.w * (uint64_t)c.h * sizeof(uint32_t);
Rect sel = clamp_rect_to_preview(selection, preview);
bool draw_dimmed = has_selection && !sel.empty() &&
cache && cache->dimmed_pixels &&
cache->width == screen.width &&
cache->height == screen.height;
if (draw_dimmed)
montauk::memcpy(c.pixels, cache->dimmed_pixels, bytes);
else
montauk::memcpy(c.pixels, screen.pixels, bytes);
if (draw_dimmed) {
for (int y = 0; y < sel.h; y++) {
uint32_t* dst = c.pixels + (sel.y + y) * c.w + sel.x;
uint32_t* src = screen.pixels + (sel.y + y) * screen.width + sel.x;
montauk::memcpy(dst, src, (uint64_t)sel.w * sizeof(uint32_t));
}
}
(void)selection;
(void)has_selection;
montauk::memcpy(c.pixels, screen.pixels, bytes);
return true;
}
@@ -497,10 +447,9 @@ static void draw_scaled_preview(Canvas& c,
const ScreenBuffer& screen,
const Rect& preview,
const Rect& selection,
bool has_selection,
const AreaRenderCache* cache) {
bool has_selection) {
if (!screen.pixels || preview.empty()) return;
if (draw_fullscreen_preview(c, screen, preview, selection, has_selection, cache))
if (draw_fullscreen_preview(c, screen, preview, selection, has_selection))
return;
Rect sel = clamp_rect_to_preview(selection, preview);
@@ -525,8 +474,7 @@ static void draw_scaled_preview(Canvas& c,
static void draw_area_selector(Canvas& c,
const ScreenBuffer& screen,
const AreaSelectorState& st,
const AreaRenderCache* cache) {
const AreaSelectorState& st) {
mtk::Theme theme = app_theme();
if (!st.fullscreen)
c.fill(theme.window_bg);
@@ -534,7 +482,7 @@ static void draw_area_selector(Canvas& c,
Rect preview = area_preview_rect(screen, st);
if (!st.fullscreen)
c.fill_rect(preview.x - 1, preview.y - 1, preview.w + 2, preview.h + 2, theme.border);
draw_scaled_preview(c, screen, preview, st.selection_view, st.has_selection || st.dragging, cache);
draw_scaled_preview(c, screen, preview, st.selection_view, st.has_selection || st.dragging);
if ((st.has_selection || st.dragging) && !st.selection_view.empty()) {
Rect sel = clamp_rect_to_preview(st.selection_view, preview);
@@ -715,12 +663,9 @@ static bool run_area_selector(const ScreenBuffer& screen, Rect* out_area) {
win.set_flags(Montauk::WIN_FLAG_FULLSCREEN);
mtk::StandaloneHost host(&win);
AreaRenderCache cache = {};
Canvas canvas = host.canvas();
draw_area_selector(canvas, screen, st, &cache);
draw_area_selector(canvas, screen, st);
host.present();
if (st.fullscreen)
build_area_render_cache(screen, &cache);
bool accepted = false;
while (true) {
@@ -736,18 +681,6 @@ static bool run_area_selector(const ScreenBuffer& screen, Rect* out_area) {
bool redraw = false;
AreaEventResult result = handle_area_selector_event(win, screen, st, ev, &redraw);
for (int drain = 0; result == AREA_EVENT_CONTINUE && drain < 64; drain++) {
Montauk::WinEvent queued;
int qr = win.poll(&queued);
if (qr < 0) {
result = AREA_EVENT_CANCEL;
break;
}
if (qr == 0)
break;
result = handle_area_selector_event(win, screen, st, queued, &redraw);
}
if (result == AREA_EVENT_ACCEPT) {
accepted = true;
break;
@@ -757,7 +690,7 @@ static bool run_area_selector(const ScreenBuffer& screen, Rect* out_area) {
if (redraw) {
canvas = host.canvas();
draw_area_selector(canvas, screen, st, &cache);
draw_area_selector(canvas, screen, st);
host.present();
}
}
@@ -770,7 +703,6 @@ static bool run_area_selector(const ScreenBuffer& screen, Rect* out_area) {
}
win.destroy();
free_area_render_cache(&cache);
return accepted;
}