fix: various bug fixes in desktop components
This commit is contained in:
@@ -177,6 +177,9 @@ struct DesktopState {
|
|||||||
Rect temp_icon_rect;
|
Rect temp_icon_rect;
|
||||||
|
|
||||||
int screen_w, screen_h;
|
int screen_w, screen_h;
|
||||||
|
uint32_t* background_cache;
|
||||||
|
int background_cache_pitch;
|
||||||
|
bool background_cache_dirty;
|
||||||
|
|
||||||
// IDs of external windows we've sent a close event to but that haven't
|
// IDs of external windows we've sent a close event to but that haven't
|
||||||
// been destroyed yet by their owning process. Prevents the poll loop
|
// been destroyed yet by their owning process. Prevents the poll loop
|
||||||
|
|||||||
@@ -12,16 +12,17 @@ namespace gui {
|
|||||||
|
|
||||||
// Fast horizontal line
|
// Fast horizontal line
|
||||||
inline void draw_hline(Framebuffer& fb, int x, int y, int w, Color c) {
|
inline void draw_hline(Framebuffer& fb, int x, int y, int w, Color c) {
|
||||||
for (int i = 0; i < w; i++) fb.put_pixel(x + i, y, c);
|
fb.fill_rect(x, y, w, 1, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast vertical line
|
// Fast vertical line
|
||||||
inline void draw_vline(Framebuffer& fb, int x, int y, int h, Color c) {
|
inline void draw_vline(Framebuffer& fb, int x, int y, int h, Color c) {
|
||||||
for (int i = 0; i < h; i++) fb.put_pixel(x, y + i, c);
|
fb.fill_rect(x, y, 1, h, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rectangle outline
|
// Rectangle outline
|
||||||
inline void draw_rect(Framebuffer& fb, int x, int y, int w, int h, Color c) {
|
inline void draw_rect(Framebuffer& fb, int x, int y, int w, int h, Color c) {
|
||||||
|
if (w <= 0 || h <= 0) return;
|
||||||
draw_hline(fb, x, y, w, c);
|
draw_hline(fb, x, y, w, c);
|
||||||
draw_hline(fb, x, y + h - 1, w, c);
|
draw_hline(fb, x, y + h - 1, w, c);
|
||||||
draw_vline(fb, x, y, h, c);
|
draw_vline(fb, x, y, h, c);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <montauk/syscall.h>
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
#include "gui/gui.hpp"
|
#include "gui/gui.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
@@ -18,6 +19,46 @@ class Framebuffer {
|
|||||||
int fb_height;
|
int fb_height;
|
||||||
int fb_pitch; // in bytes
|
int fb_pitch; // in bytes
|
||||||
|
|
||||||
|
static inline void fill_pixels(uint32_t* dst, int count, uint32_t pixel) {
|
||||||
|
if (!dst || count <= 0) return;
|
||||||
|
|
||||||
|
uint64_t pixel64 = ((uint64_t)pixel << 32) | pixel;
|
||||||
|
if (((uint64_t)dst & 4) && count > 0) {
|
||||||
|
*dst++ = pixel;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* dst64 = (uint64_t*)dst;
|
||||||
|
int pairs = count / 2;
|
||||||
|
for (int i = 0; i < pairs; i++) {
|
||||||
|
dst64[i] = pixel64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count & 1) {
|
||||||
|
((uint32_t*)(dst64 + pairs))[0] = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t blend_pixel(uint32_t dst, uint32_t src, uint32_t alpha) {
|
||||||
|
uint32_t inv_a = 255 - alpha;
|
||||||
|
uint32_t sr = (src >> 16) & 0xFF;
|
||||||
|
uint32_t sg = (src >> 8) & 0xFF;
|
||||||
|
uint32_t sb = src & 0xFF;
|
||||||
|
uint32_t dr = (dst >> 16) & 0xFF;
|
||||||
|
uint32_t dg = (dst >> 8) & 0xFF;
|
||||||
|
uint32_t db = dst & 0xFF;
|
||||||
|
|
||||||
|
uint32_t rr = alpha * sr + inv_a * dr;
|
||||||
|
uint32_t gg = alpha * sg + inv_a * dg;
|
||||||
|
uint32_t bb = alpha * sb + inv_a * db;
|
||||||
|
|
||||||
|
rr = (rr + 1 + (rr >> 8)) >> 8;
|
||||||
|
gg = (gg + 1 + (gg >> 8)) >> 8;
|
||||||
|
bb = (bb + 1 + (bb >> 8)) >> 8;
|
||||||
|
|
||||||
|
return 0xFF000000 | (rr << 16) | (gg << 8) | bb;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Framebuffer() : hw_fb(nullptr), back_buf(nullptr), fb_width(0), fb_height(0), fb_pitch(0) {
|
Framebuffer() : hw_fb(nullptr), back_buf(nullptr), fb_width(0), fb_height(0), fb_pitch(0) {
|
||||||
Montauk::FbInfo info;
|
Montauk::FbInfo info;
|
||||||
@@ -75,6 +116,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void fill_rect(int x, int y, int w, int h, Color c) {
|
inline void fill_rect(int x, int y, int w, int h, Color c) {
|
||||||
|
if (!back_buf) return;
|
||||||
|
|
||||||
// Clip to screen bounds
|
// Clip to screen bounds
|
||||||
int x0 = x < 0 ? 0 : x;
|
int x0 = x < 0 ? 0 : x;
|
||||||
int y0 = y < 0 ? 0 : y;
|
int y0 = y < 0 ? 0 : y;
|
||||||
@@ -88,9 +131,7 @@ public:
|
|||||||
|
|
||||||
for (int row = y0; row < y1; row++) {
|
for (int row = y0; row < y1; row++) {
|
||||||
uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + row * fb_pitch) + x0;
|
uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + row * fb_pitch) + x0;
|
||||||
for (int col = 0; col < clipped_w; col++) {
|
fill_pixels(dst, clipped_w, pixel);
|
||||||
dst[col] = pixel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,59 +177,85 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void blit(int x, int y, int w, int h, const uint32_t* pixels) {
|
inline void blit(int x, int y, int w, int h, const uint32_t* pixels) {
|
||||||
for (int row = 0; row < h; row++) {
|
if (!back_buf || !pixels || w <= 0 || h <= 0) return;
|
||||||
int dy = y + row;
|
|
||||||
if (dy < 0 || dy >= fb_height) continue;
|
int src_x = 0;
|
||||||
for (int col = 0; col < w; col++) {
|
int src_y = 0;
|
||||||
int dx = x + col;
|
int dst_x = x;
|
||||||
if (dx < 0 || dx >= fb_width) continue;
|
int dst_y = y;
|
||||||
uint32_t* dst_row = (uint32_t*)((uint8_t*)back_buf + dy * fb_pitch);
|
int copy_w = w;
|
||||||
dst_row[dx] = pixels[row * w + col];
|
int copy_h = h;
|
||||||
}
|
|
||||||
|
if (dst_x < 0) { src_x = -dst_x; copy_w += dst_x; dst_x = 0; }
|
||||||
|
if (dst_y < 0) { src_y = -dst_y; copy_h += dst_y; dst_y = 0; }
|
||||||
|
if (dst_x + copy_w > fb_width) copy_w = fb_width - dst_x;
|
||||||
|
if (dst_y + copy_h > fb_height) copy_h = fb_height - dst_y;
|
||||||
|
if (copy_w <= 0 || copy_h <= 0) return;
|
||||||
|
|
||||||
|
uint64_t row_bytes = (uint64_t)copy_w * sizeof(uint32_t);
|
||||||
|
for (int row = 0; row < copy_h; row++) {
|
||||||
|
uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + (dst_y + row) * fb_pitch) + dst_x;
|
||||||
|
const uint32_t* src = pixels + (src_y + row) * w + src_x;
|
||||||
|
montauk::memcpy(dst, src, row_bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void blit_alpha(int x, int y, int w, int h, const uint32_t* pixels) {
|
inline void blit_alpha(int x, int y, int w, int h, const uint32_t* pixels) {
|
||||||
for (int row = 0; row < h; row++) {
|
if (!back_buf || !pixels || w <= 0 || h <= 0) return;
|
||||||
int dy = y + row;
|
|
||||||
if (dy < 0 || dy >= fb_height) continue;
|
|
||||||
for (int col = 0; col < w; col++) {
|
|
||||||
int dx = x + col;
|
|
||||||
if (dx < 0 || dx >= fb_width) continue;
|
|
||||||
|
|
||||||
uint32_t src = pixels[row * w + col];
|
int src_x = 0;
|
||||||
uint8_t sa = (src >> 24) & 0xFF;
|
int src_y = 0;
|
||||||
|
int dst_x = x;
|
||||||
|
int dst_y = y;
|
||||||
|
int copy_w = w;
|
||||||
|
int copy_h = h;
|
||||||
|
|
||||||
|
if (dst_x < 0) { src_x = -dst_x; copy_w += dst_x; dst_x = 0; }
|
||||||
|
if (dst_y < 0) { src_y = -dst_y; copy_h += dst_y; dst_y = 0; }
|
||||||
|
if (dst_x + copy_w > fb_width) copy_w = fb_width - dst_x;
|
||||||
|
if (dst_y + copy_h > fb_height) copy_h = fb_height - dst_y;
|
||||||
|
if (copy_w <= 0 || copy_h <= 0) return;
|
||||||
|
|
||||||
|
for (int row = 0; row < copy_h; row++) {
|
||||||
|
uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + (dst_y + row) * fb_pitch) + dst_x;
|
||||||
|
const uint32_t* src = pixels + (src_y + row) * w + src_x;
|
||||||
|
for (int col = 0; col < copy_w; col++) {
|
||||||
|
uint32_t s = src[col];
|
||||||
|
uint8_t sa = (s >> 24) & 0xFF;
|
||||||
if (sa == 0) continue;
|
if (sa == 0) continue;
|
||||||
|
|
||||||
uint8_t sr = (src >> 16) & 0xFF;
|
|
||||||
uint8_t sg = (src >> 8) & 0xFF;
|
|
||||||
uint8_t sb = src & 0xFF;
|
|
||||||
|
|
||||||
if (sa == 255) {
|
if (sa == 255) {
|
||||||
uint32_t* dst_row = (uint32_t*)((uint8_t*)back_buf + dy * fb_pitch);
|
dst[col] = s;
|
||||||
dst_row[dx] = src;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color sc = {sr, sg, sb, sa};
|
dst[col] = blend_pixel(dst[col], s, sa);
|
||||||
put_pixel_alpha(dx, dy, sc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void copy_from(const uint32_t* pixels, int src_pitch_bytes) {
|
||||||
|
if (!back_buf || !pixels || src_pitch_bytes <= 0) return;
|
||||||
|
uint64_t row_bytes = (uint64_t)fb_width * sizeof(uint32_t);
|
||||||
|
for (int row = 0; row < fb_height; row++) {
|
||||||
|
uint32_t* dst = (uint32_t*)((uint8_t*)back_buf + row * fb_pitch);
|
||||||
|
const uint32_t* src = (const uint32_t*)((const uint8_t*)pixels + row * src_pitch_bytes);
|
||||||
|
montauk::memcpy(dst, src, row_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void clear(Color c) {
|
inline void clear(Color c) {
|
||||||
fill_rect(0, 0, fb_width, fb_height, c);
|
fill_rect(0, 0, fb_width, fb_height, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void flip() {
|
inline void flip() {
|
||||||
|
if (!hw_fb || !back_buf) return;
|
||||||
|
|
||||||
// Copy back buffer to hardware framebuffer, row by row (pitch may differ)
|
// Copy back buffer to hardware framebuffer, row by row (pitch may differ)
|
||||||
int row_pixels = fb_width;
|
uint64_t row_bytes = (uint64_t)fb_width * sizeof(uint32_t);
|
||||||
for (int y = 0; y < fb_height; y++) {
|
for (int y = 0; y < fb_height; y++) {
|
||||||
uint32_t* src = (uint32_t*)((uint8_t*)back_buf + y * fb_pitch);
|
uint32_t* src = (uint32_t*)((uint8_t*)back_buf + y * fb_pitch);
|
||||||
uint32_t* dst = (uint32_t*)((uint8_t*)hw_fb + y * fb_pitch);
|
uint32_t* dst = (uint32_t*)((uint8_t*)hw_fb + y * fb_pitch);
|
||||||
for (int x = 0; x < row_pixels; x++) {
|
montauk::memcpy(dst, src, row_bytes);
|
||||||
dst[x] = src[x];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -237,6 +237,13 @@ struct TrueTypeFont {
|
|||||||
GlyphCache* gc = get_cache(pixel_size);
|
GlyphCache* gc = get_cache(pixel_size);
|
||||||
int cx = x;
|
int cx = x;
|
||||||
int baseline = y + gc->ascent;
|
int baseline = y + gc->ascent;
|
||||||
|
int fb_w = fb.width();
|
||||||
|
int fb_h = fb.height();
|
||||||
|
int fb_pitch = fb.pitch();
|
||||||
|
uint32_t* fb_pixels = fb.buffer();
|
||||||
|
if (!fb_pixels) return;
|
||||||
|
uint32_t src_rgb = 0xFF000000 | ((uint32_t)color.r << 16) |
|
||||||
|
((uint32_t)color.g << 8) | color.b;
|
||||||
|
|
||||||
for (int i = 0; text[i]; i++) {
|
for (int i = 0; text[i]; i++) {
|
||||||
CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]);
|
CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]);
|
||||||
@@ -245,12 +252,41 @@ struct TrueTypeFont {
|
|||||||
if (g->bitmap) {
|
if (g->bitmap) {
|
||||||
int gx = cx + g->xoff;
|
int gx = cx + g->xoff;
|
||||||
int gy = baseline + g->yoff;
|
int gy = baseline + g->yoff;
|
||||||
for (int row = 0; row < g->height; row++) {
|
|
||||||
for (int col = 0; col < g->width; col++) {
|
int row0 = gy < 0 ? -gy : 0;
|
||||||
uint8_t alpha = g->bitmap[row * g->width + col];
|
int col0 = gx < 0 ? -gx : 0;
|
||||||
if (alpha > 0) {
|
int row1 = gy + g->height > fb_h ? fb_h - gy : g->height;
|
||||||
Color c = {color.r, color.g, color.b, alpha};
|
int col1 = gx + g->width > fb_w ? fb_w - gx : g->width;
|
||||||
fb.put_pixel_alpha(gx + col, gy + row, c);
|
|
||||||
|
if (row0 < row1 && col0 < col1) {
|
||||||
|
for (int row = row0; row < row1; row++) {
|
||||||
|
uint8_t* alpha_row = g->bitmap + row * g->width + col0;
|
||||||
|
uint32_t* dst = (uint32_t*)((uint8_t*)fb_pixels + (gy + row) * fb_pitch) + gx + col0;
|
||||||
|
|
||||||
|
for (int col = col0; col < col1; col++) {
|
||||||
|
uint8_t alpha = *alpha_row++;
|
||||||
|
if (alpha == 0) {
|
||||||
|
dst++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (alpha == 255) {
|
||||||
|
*dst++ = src_rgb;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t d = *dst;
|
||||||
|
uint32_t inv_a = 255 - alpha;
|
||||||
|
uint32_t dr = (d >> 16) & 0xFF;
|
||||||
|
uint32_t dg = (d >> 8) & 0xFF;
|
||||||
|
uint32_t db = d & 0xFF;
|
||||||
|
uint32_t rr = alpha * color.r + inv_a * dr;
|
||||||
|
uint32_t gg = alpha * color.g + inv_a * dg;
|
||||||
|
uint32_t bb = alpha * color.b + inv_a * db;
|
||||||
|
|
||||||
|
rr = (rr + 1 + (rr >> 8)) >> 8;
|
||||||
|
gg = (gg + 1 + (gg >> 8)) >> 8;
|
||||||
|
bb = (bb + 1 + (bb >> 8)) >> 8;
|
||||||
|
*dst++ = 0xFF000000 | (rr << 16) | (gg << 8) | bb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,6 +463,7 @@ namespace fonts {
|
|||||||
inline bool init() {
|
inline bool init() {
|
||||||
auto load = [](const char* path) -> TrueTypeFont* {
|
auto load = [](const char* path) -> TrueTypeFont* {
|
||||||
TrueTypeFont* f = (TrueTypeFont*)montauk::malloc(sizeof(TrueTypeFont));
|
TrueTypeFont* f = (TrueTypeFont*)montauk::malloc(sizeof(TrueTypeFont));
|
||||||
|
if (!f) return nullptr;
|
||||||
montauk::memset(f, 0, sizeof(TrueTypeFont));
|
montauk::memset(f, 0, sizeof(TrueTypeFont));
|
||||||
if (!f->init(path)) {
|
if (!f->init(path)) {
|
||||||
montauk::mfree(f);
|
montauk::mfree(f);
|
||||||
|
|||||||
@@ -8,6 +8,19 @@
|
|||||||
|
|
||||||
namespace filemanager {
|
namespace filemanager {
|
||||||
|
|
||||||
|
static bool path_is_same_or_descendant(const char* path, const char* root) {
|
||||||
|
if (!path || !root) return false;
|
||||||
|
|
||||||
|
int root_len = montauk::slen(root);
|
||||||
|
while (root_len > 0 && root[root_len - 1] == '/') root_len--;
|
||||||
|
if (root_len <= 0) return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < root_len; i++) {
|
||||||
|
if (path[i] == '\0' || path[i] != root[i]) return false;
|
||||||
|
}
|
||||||
|
return path[root_len] == '\0' || path[root_len] == '/';
|
||||||
|
}
|
||||||
|
|
||||||
void filemanager_do_copy(FileManagerState* fm) {
|
void filemanager_do_copy(FileManagerState* fm) {
|
||||||
if (fm->selected < 0 || fm->selected >= fm->entry_count) return;
|
if (fm->selected < 0 || fm->selected >= fm->entry_count) return;
|
||||||
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm) ||
|
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm) ||
|
||||||
@@ -36,11 +49,13 @@ void filemanager_do_paste(FileManagerState* fm) {
|
|||||||
const char* basename = path_basename(fm->clipboard_path);
|
const char* basename = path_basename(fm->clipboard_path);
|
||||||
char dst[512];
|
char dst[512];
|
||||||
filemanager_build_fullpath(dst, 512, fm->current_path, basename);
|
filemanager_build_fullpath(dst, 512, fm->current_path, basename);
|
||||||
|
if (montauk::streq(dst, fm->clipboard_path)) return;
|
||||||
|
|
||||||
// Check if source is a directory by trying to readdir it
|
// Check if source is a directory by trying to readdir it
|
||||||
const char* probe[1];
|
const char* probe[1];
|
||||||
int probe_count = montauk::readdir(fm->clipboard_path, probe, 1);
|
int probe_count = montauk::readdir(fm->clipboard_path, probe, 1);
|
||||||
bool src_is_dir = (probe_count >= 0);
|
bool src_is_dir = (probe_count >= 0);
|
||||||
|
if (src_is_dir && path_is_same_or_descendant(dst, fm->clipboard_path)) return;
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
if (src_is_dir)
|
if (src_is_dir)
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ void filemanager_read_dir(FileManagerState* fm) {
|
|||||||
|
|
||||||
// Sort: directories first, then alphabetical (case-insensitive)
|
// Sort: directories first, then alphabetical (case-insensitive)
|
||||||
for (int i = 1; i < fm->entry_count; i++) {
|
for (int i = 1; i < fm->entry_count; i++) {
|
||||||
char tmp_name[64];
|
char tmp_name[128];
|
||||||
int tmp_type = fm->entry_types[i];
|
int tmp_type = fm->entry_types[i];
|
||||||
int tmp_size = fm->entry_sizes[i];
|
int tmp_size = fm->entry_sizes[i];
|
||||||
bool tmp_isdir = fm->is_dir[i];
|
bool tmp_isdir = fm->is_dir[i];
|
||||||
@@ -385,9 +385,11 @@ bool filemanager_delete_recursive(const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool filemanager_copy_file(const char* src, const char* dst) {
|
bool filemanager_copy_file(const char* src, const char* dst) {
|
||||||
|
if (!src || !dst || montauk::streq(src, dst)) return false;
|
||||||
|
|
||||||
int sfd = montauk::open(src);
|
int sfd = montauk::open(src);
|
||||||
if (sfd < 0) return false;
|
if (sfd < 0) return false;
|
||||||
int size = (int)montauk::getsize(sfd);
|
uint64_t size = montauk::getsize(sfd);
|
||||||
|
|
||||||
// Create destination
|
// Create destination
|
||||||
int dfd = montauk::fcreate(dst);
|
int dfd = montauk::fcreate(dst);
|
||||||
@@ -396,33 +398,46 @@ bool filemanager_copy_file(const char* src, const char* dst) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
// Cap at 4 MB to avoid exhausting memory
|
static constexpr uint64_t COPY_CHUNK = 64 * 1024;
|
||||||
if (size > 4 * 1024 * 1024) {
|
uint64_t buf_size = size < COPY_CHUNK ? size : COPY_CHUNK;
|
||||||
montauk::close(sfd);
|
uint8_t* buf = (uint8_t*)montauk::malloc(buf_size);
|
||||||
montauk::close(dfd);
|
|
||||||
montauk::fdelete(dst);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint8_t* buf = (uint8_t*)montauk::malloc(size);
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
montauk::close(sfd);
|
montauk::close(sfd);
|
||||||
montauk::close(dfd);
|
montauk::close(dfd);
|
||||||
montauk::fdelete(dst);
|
montauk::fdelete(dst);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
montauk::read(sfd, buf, 0, size);
|
|
||||||
montauk::fwrite(dfd, buf, 0, size);
|
uint64_t off = 0;
|
||||||
|
while (off < size) {
|
||||||
|
uint64_t todo64 = size - off;
|
||||||
|
if (todo64 > buf_size) todo64 = buf_size;
|
||||||
|
int todo = (int)todo64;
|
||||||
|
int got = montauk::read(sfd, buf, off, todo64);
|
||||||
|
if (got != todo) { ok = false; break; }
|
||||||
|
int wrote = montauk::fwrite(dfd, buf, off, todo64);
|
||||||
|
if (wrote != todo) { ok = false; break; }
|
||||||
|
off += todo64;
|
||||||
|
}
|
||||||
|
|
||||||
montauk::mfree(buf);
|
montauk::mfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
montauk::close(sfd);
|
montauk::close(sfd);
|
||||||
montauk::close(dfd);
|
montauk::close(dfd);
|
||||||
|
if (!ok) {
|
||||||
|
montauk::fdelete(dst);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursive directory copy
|
// Recursive directory copy
|
||||||
bool filemanager_copy_dir_recursive(const char* src, const char* dst) {
|
bool filemanager_copy_dir_recursive(const char* src, const char* dst) {
|
||||||
|
if (!src || !dst || montauk::streq(src, dst)) return false;
|
||||||
|
|
||||||
montauk::fmkdir(dst);
|
montauk::fmkdir(dst);
|
||||||
|
|
||||||
const char* names[64];
|
const char* names[64];
|
||||||
|
|||||||
@@ -130,12 +130,14 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
if (grad_option.contains(mx, cy)) {
|
if (grad_option.contains(mx, cy)) {
|
||||||
s.bg_gradient = true;
|
s.bg_gradient = true;
|
||||||
s.bg_image = false;
|
s.bg_image = false;
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (solid_option.contains(mx, cy)) {
|
if (solid_option.contains(mx, cy)) {
|
||||||
s.bg_gradient = false;
|
s.bg_gradient = false;
|
||||||
s.bg_image = false;
|
s.bg_image = false;
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -146,6 +148,7 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
wallpaper_scan_home(st->desktop->home_dir, &st->wp_files);
|
wallpaper_scan_home(st->desktop->home_dir, &st->wp_files);
|
||||||
st->wp_scanned = true;
|
st->wp_scanned = true;
|
||||||
}
|
}
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -162,6 +165,7 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
str_append(fullpath, st->wp_files.names[i], 256);
|
str_append(fullpath, st->wp_files.names[i], 256);
|
||||||
wallpaper_load(&s, fullpath,
|
wallpaper_load(&s, fullpath,
|
||||||
st->desktop->screen_w, st->desktop->screen_h);
|
st->desktop->screen_w, st->desktop->screen_h);
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -173,6 +177,7 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
int idx = mtk::hit_swatch_row(mx, cy, x + 70, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
int idx = mtk::hit_swatch_row(mx, cy, x + 70, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
s.bg_grad_top = bg_palette[idx];
|
s.bg_grad_top = bg_palette[idx];
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -181,6 +186,7 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
idx = mtk::hit_swatch_row(mx, cy, x + 70, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
idx = mtk::hit_swatch_row(mx, cy, x + 70, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
s.bg_grad_bottom = bg_palette[idx];
|
s.bg_grad_bottom = bg_palette[idx];
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -189,6 +195,7 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
int idx = mtk::hit_swatch_row(mx, cy, x + 70, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
int idx = mtk::hit_swatch_row(mx, cy, x + 70, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
s.bg_solid = bg_palette[idx];
|
s.bg_solid = bg_palette[idx];
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -199,6 +206,7 @@ bool settings_handle_appearance_click(Window* win, SettingsState* st, int mx, in
|
|||||||
int idx = mtk::hit_swatch_row(mx, cy, x + 110, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
int idx = mtk::hit_swatch_row(mx, cy, x + 110, y, SWATCH_COUNT, SWATCH_SIZE, SWATCH_GAP);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
s.panel_color = panel_palette[idx];
|
s.panel_color = panel_palette[idx];
|
||||||
|
desktop_mark_background_dirty(st->desktop);
|
||||||
settings_persist(st);
|
settings_persist(st);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include <gui/mtk.hpp>
|
#include <gui/mtk.hpp>
|
||||||
#include <montauk/config.h>
|
#include <montauk/config.h>
|
||||||
|
|
||||||
|
void desktop_mark_background_dirty(DesktopState* ds);
|
||||||
|
|
||||||
namespace settings_app {
|
namespace settings_app {
|
||||||
|
|
||||||
struct SettingsState {
|
struct SettingsState {
|
||||||
|
|||||||
@@ -149,26 +149,24 @@ void desktop_draw_lock_screen(DesktopState* ds) {
|
|||||||
// Desktop Composition
|
// Desktop Composition
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
void gui::desktop_compose(DesktopState* ds) {
|
void desktop_mark_background_dirty(DesktopState* ds) {
|
||||||
Framebuffer& fb = ds->fb;
|
if (ds) ds->background_cache_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Desktop background gradient
|
static void desktop_render_background_to(uint32_t* buf, int pitch, DesktopState* ds) {
|
||||||
int sw = ds->screen_w;
|
int sw = ds->screen_w;
|
||||||
int sh = ds->screen_h;
|
int sh = ds->screen_h;
|
||||||
int grad_start = PANEL_HEIGHT;
|
int grad_start = PANEL_HEIGHT;
|
||||||
int grad_range = sh - grad_start;
|
int grad_range = sh - grad_start;
|
||||||
if (grad_range < 1) grad_range = 1;
|
if (grad_range < 1) grad_range = 1;
|
||||||
|
|
||||||
uint32_t* buf = fb.buffer();
|
|
||||||
int pitch = fb.pitch();
|
|
||||||
|
|
||||||
for (int y = 0; y < sh; y++) {
|
for (int y = 0; y < sh; y++) {
|
||||||
uint32_t* row = (uint32_t*)((uint8_t*)buf + y * pitch);
|
uint32_t* row = (uint32_t*)((uint8_t*)buf + y * pitch);
|
||||||
if (ds->settings.bg_image && ds->settings.bg_wallpaper) {
|
if (ds->settings.bg_image && ds->settings.bg_wallpaper) {
|
||||||
// Wallpaper covers the entire screen; panel draws on top
|
// Wallpaper covers the entire screen; panel draws on top
|
||||||
uint32_t* wp = ds->settings.bg_wallpaper + y * ds->settings.bg_wallpaper_w;
|
uint32_t* wp = ds->settings.bg_wallpaper + y * ds->settings.bg_wallpaper_w;
|
||||||
int cw = sw < ds->settings.bg_wallpaper_w ? sw : ds->settings.bg_wallpaper_w;
|
int cw = sw < ds->settings.bg_wallpaper_w ? sw : ds->settings.bg_wallpaper_w;
|
||||||
for (int x = 0; x < cw; x++) row[x] = wp[x];
|
montauk::memcpy(row, wp, (uint64_t)cw * sizeof(uint32_t));
|
||||||
} else if (y < grad_start) {
|
} else if (y < grad_start) {
|
||||||
// Panel area - will be overwritten by panel drawing
|
// Panel area - will be overwritten by panel drawing
|
||||||
uint32_t px = ds->settings.panel_color.to_pixel();
|
uint32_t px = ds->settings.panel_color.to_pixel();
|
||||||
@@ -187,6 +185,46 @@ void gui::desktop_compose(DesktopState* ds) {
|
|||||||
for (int x = 0; x < sw; x++) row[x] = px;
|
for (int x = 0; x < sw; x++) row[x] = px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool desktop_prepare_background_cache(DesktopState* ds) {
|
||||||
|
if (!ds) return false;
|
||||||
|
|
||||||
|
int pitch = ds->fb.pitch();
|
||||||
|
uint64_t bytes = (uint64_t)ds->screen_h * (uint64_t)pitch;
|
||||||
|
if (!ds->background_cache) {
|
||||||
|
ds->background_cache = (uint32_t*)montauk::alloc(bytes);
|
||||||
|
if (!ds->background_cache) return false;
|
||||||
|
ds->background_cache_pitch = pitch;
|
||||||
|
ds->background_cache_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds->background_cache_pitch != pitch) {
|
||||||
|
montauk::free(ds->background_cache);
|
||||||
|
ds->background_cache = (uint32_t*)montauk::alloc(bytes);
|
||||||
|
if (!ds->background_cache) return false;
|
||||||
|
ds->background_cache_pitch = pitch;
|
||||||
|
ds->background_cache_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds->background_cache_dirty) {
|
||||||
|
desktop_render_background_to(ds->background_cache, ds->background_cache_pitch, ds);
|
||||||
|
ds->background_cache_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui::desktop_compose(DesktopState* ds) {
|
||||||
|
Framebuffer& fb = ds->fb;
|
||||||
|
|
||||||
|
int sw = ds->screen_w;
|
||||||
|
int sh = ds->screen_h;
|
||||||
|
|
||||||
|
if (desktop_prepare_background_cache(ds))
|
||||||
|
fb.copy_from(ds->background_cache, ds->background_cache_pitch);
|
||||||
|
else
|
||||||
|
desktop_render_background_to(fb.buffer(), fb.pitch(), ds);
|
||||||
|
|
||||||
// Lock screen: draw overlay and card, then cursor, and return early
|
// Lock screen: draw overlay and card, then cursor, and return early
|
||||||
if (ds->screen_locked) {
|
if (ds->screen_locked) {
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ void desktop_draw_vol_popup(gui::DesktopState* ds);
|
|||||||
|
|
||||||
// compose.cpp
|
// compose.cpp
|
||||||
void desktop_draw_lock_screen(gui::DesktopState* ds);
|
void desktop_draw_lock_screen(gui::DesktopState* ds);
|
||||||
|
void desktop_mark_background_dirty(gui::DesktopState* ds);
|
||||||
|
|
||||||
// main.cpp
|
// main.cpp
|
||||||
void desktop_scan_apps(gui::DesktopState* ds);
|
void desktop_scan_apps(gui::DesktopState* ds);
|
||||||
|
|||||||
@@ -61,8 +61,13 @@ void desktop_scan_apps(DesktopState* ds) {
|
|||||||
if (sz == 0 || sz > 4096) { montauk::close(fh); continue; }
|
if (sz == 0 || sz > 4096) { montauk::close(fh); continue; }
|
||||||
|
|
||||||
char* text = (char*)montauk::malloc(sz + 1);
|
char* text = (char*)montauk::malloc(sz + 1);
|
||||||
montauk::read(fh, (uint8_t*)text, 0, sz);
|
if (!text) { montauk::close(fh); continue; }
|
||||||
|
int bytes_read = montauk::read(fh, (uint8_t*)text, 0, sz);
|
||||||
montauk::close(fh);
|
montauk::close(fh);
|
||||||
|
if (bytes_read != (int)sz) {
|
||||||
|
montauk::mfree(text);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
text[sz] = '\0';
|
text[sz] = '\0';
|
||||||
|
|
||||||
auto doc = montauk::toml::parse(text);
|
auto doc = montauk::toml::parse(text);
|
||||||
@@ -77,6 +82,10 @@ void desktop_scan_apps(DesktopState* ds) {
|
|||||||
const char* category = doc.get_string("menu.category", "Applications");
|
const char* category = doc.get_string("menu.category", "Applications");
|
||||||
bool visible = doc.get_bool("menu.visible", true);
|
bool visible = doc.get_bool("menu.visible", true);
|
||||||
bool launch_with_home = doc.get_bool("launch.pass_home_dir", true);
|
bool launch_with_home = doc.get_bool("launch.pass_home_dir", true);
|
||||||
|
if (binary[0] == '\0') {
|
||||||
|
doc.destroy();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
montauk::strncpy(app->name, name, sizeof(app->name));
|
montauk::strncpy(app->name, name, sizeof(app->name));
|
||||||
montauk::strncpy(app->category, category, sizeof(app->category));
|
montauk::strncpy(app->category, category, sizeof(app->category));
|
||||||
@@ -154,6 +163,9 @@ void desktop_build_menu(DesktopState* ds) {
|
|||||||
void gui::desktop_init(DesktopState* ds) {
|
void gui::desktop_init(DesktopState* ds) {
|
||||||
ds->screen_w = ds->fb.width();
|
ds->screen_w = ds->fb.width();
|
||||||
ds->screen_h = ds->fb.height();
|
ds->screen_h = ds->fb.height();
|
||||||
|
ds->background_cache = nullptr;
|
||||||
|
ds->background_cache_pitch = ds->fb.pitch();
|
||||||
|
ds->background_cache_dirty = true;
|
||||||
|
|
||||||
// Immediately clear the screen to hide flanterm boot text
|
// Immediately clear the screen to hide flanterm boot text
|
||||||
ds->fb.clear(colors::DESKTOP_BG);
|
ds->fb.clear(colors::DESKTOP_BG);
|
||||||
@@ -355,9 +367,41 @@ static void desktop_clear_window_dirty(DesktopState* ds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool desktop_panel_refresh_due(const DesktopState* ds, uint64_t now) {
|
static bool desktop_netcfg_equal(const Montauk::NetCfg& a, const Montauk::NetCfg& b) {
|
||||||
|
if (a.ipAddress != b.ipAddress || a.subnetMask != b.subnetMask ||
|
||||||
|
a.gateway != b.gateway || a.dnsServer != b.dnsServer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if (a.macAddress[i] != b.macAddress[i]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool desktop_refresh_panel_state(DesktopState* ds, uint64_t now) {
|
||||||
if (ds->screen_locked) return false;
|
if (ds->screen_locked) return false;
|
||||||
return (now - ds->net_cfg_last_poll > 5000) || (now - ds->vol_last_poll > 5000);
|
|
||||||
|
bool changed = false;
|
||||||
|
if (now - ds->net_cfg_last_poll > 5000) {
|
||||||
|
Montauk::NetCfg next;
|
||||||
|
montauk::get_netcfg(&next);
|
||||||
|
if (!desktop_netcfg_equal(next, ds->cached_net_cfg)) {
|
||||||
|
ds->cached_net_cfg = next;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
ds->net_cfg_last_poll = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now - ds->vol_last_poll > 5000) {
|
||||||
|
int v = montauk::audio_get_volume(0);
|
||||||
|
if (v >= 0 && !ds->vol_muted && v != ds->vol_level) {
|
||||||
|
ds->vol_level = v;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
ds->vol_last_poll = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool desktop_poll_external_windows(DesktopState* ds) {
|
bool desktop_poll_external_windows(DesktopState* ds) {
|
||||||
@@ -386,7 +430,12 @@ bool desktop_poll_external_windows(DesktopState* ds) {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
montauk::strncpy(ds->windows[i].title, extWins[e].title, MAX_TITLE_LEN);
|
if (!montauk::streq(ds->windows[i].title, extWins[e].title)) {
|
||||||
|
montauk::strncpy(ds->windows[i].title, extWins[e].title, MAX_TITLE_LEN);
|
||||||
|
if (ds->windows[i].state != WIN_MINIMIZED && ds->windows[i].state != WIN_CLOSED) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Update dirty flag and cursor
|
// Update dirty flag and cursor
|
||||||
if (extWins[e].dirty) {
|
if (extWins[e].dirty) {
|
||||||
ds->windows[i].dirty = true;
|
ds->windows[i].dirty = true;
|
||||||
@@ -405,9 +454,8 @@ bool desktop_poll_external_windows(DesktopState* ds) {
|
|||||||
currentVa = 0;
|
currentVa = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t va = montauk::win_map(extId);
|
uint64_t va = currentVa;
|
||||||
if (!remapRequested && va != 0 && va != currentVa) {
|
if (remapRequested || currentVa == 0) {
|
||||||
montauk::win_unmap(extId);
|
|
||||||
va = montauk::win_map(extId);
|
va = montauk::win_map(extId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,7 +464,6 @@ bool desktop_poll_external_windows(DesktopState* ds) {
|
|||||||
ds->windows[i].content_w = extWins[e].width;
|
ds->windows[i].content_w = extWins[e].width;
|
||||||
ds->windows[i].content_h = extWins[e].height;
|
ds->windows[i].content_h = extWins[e].height;
|
||||||
ds->windows[i].dirty = true;
|
ds->windows[i].dirty = true;
|
||||||
montauk::strncpy(ds->windows[i].title, extWins[e].title, MAX_TITLE_LEN);
|
|
||||||
changed = true;
|
changed = true;
|
||||||
// Clear from closing list if the slot was reused
|
// Clear from closing list if the slot was reused
|
||||||
for (int c = 0; c < ds->closing_ext_count; c++) {
|
for (int c = 0; c < ds->closing_ext_count; c++) {
|
||||||
@@ -532,6 +579,7 @@ bool desktop_poll_external_windows(DesktopState* ds) {
|
|||||||
|
|
||||||
void gui::desktop_run(DesktopState* ds) {
|
void gui::desktop_run(DesktopState* ds) {
|
||||||
uint64_t lastClockToken = 0;
|
uint64_t lastClockToken = 0;
|
||||||
|
uint64_t nextClockPollMs = 0;
|
||||||
uint64_t lastLauncherBlinkToken = ~0ull;
|
uint64_t lastLauncherBlinkToken = ~0ull;
|
||||||
uint64_t inputSerial = montauk::input_wait(0, 0);
|
uint64_t inputSerial = montauk::input_wait(0, 0);
|
||||||
bool firstFrame = true;
|
bool firstFrame = true;
|
||||||
@@ -588,7 +636,7 @@ void gui::desktop_run(DesktopState* ds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t now = montauk::get_milliseconds();
|
uint64_t now = montauk::get_milliseconds();
|
||||||
sceneChanged |= desktop_panel_refresh_due(ds, now);
|
sceneChanged |= desktop_refresh_panel_state(ds, now);
|
||||||
|
|
||||||
uint64_t launcherBlinkToken = desktop_launcher_blink_token(ds, now);
|
uint64_t launcherBlinkToken = desktop_launcher_blink_token(ds, now);
|
||||||
if (launcherBlinkToken != lastLauncherBlinkToken) {
|
if (launcherBlinkToken != lastLauncherBlinkToken) {
|
||||||
@@ -596,10 +644,13 @@ void gui::desktop_run(DesktopState* ds) {
|
|||||||
sceneChanged = true;
|
sceneChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t clockToken = desktop_clock_token();
|
if (now >= nextClockPollMs) {
|
||||||
if (clockToken != lastClockToken) {
|
nextClockPollMs = now + 1000;
|
||||||
lastClockToken = clockToken;
|
uint64_t clockToken = desktop_clock_token();
|
||||||
sceneChanged = true;
|
if (clockToken != lastClockToken) {
|
||||||
|
lastClockToken = clockToken;
|
||||||
|
sceneChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sceneChanged |= desktop_has_visible_dirty_window(ds);
|
sceneChanged |= desktop_has_visible_dirty_window(ds);
|
||||||
|
|||||||
@@ -106,13 +106,6 @@ void gui::desktop_draw_panel(DesktopState* ds) {
|
|||||||
draw_text(fb, date_x, clock_y, date_str, colors::PANEL_TEXT);
|
draw_text(fb, date_x, clock_y, date_str, colors::PANEL_TEXT);
|
||||||
|
|
||||||
// Volume icon (to the left of the date)
|
// Volume icon (to the left of the date)
|
||||||
uint64_t now = montauk::get_milliseconds();
|
|
||||||
if (now - ds->vol_last_poll > 5000) {
|
|
||||||
int v = montauk::audio_get_volume(0);
|
|
||||||
if (v >= 0 && !ds->vol_muted) ds->vol_level = v;
|
|
||||||
ds->vol_last_poll = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vol_icon_x = date_x - 16 - 12;
|
int vol_icon_x = date_x - 16 - 12;
|
||||||
int vol_icon_y = (PANEL_HEIGHT - 16) / 2;
|
int vol_icon_y = (PANEL_HEIGHT - 16) / 2;
|
||||||
ds->vol_icon_rect = {vol_icon_x, vol_icon_y, 16, 16};
|
ds->vol_icon_rect = {vol_icon_x, vol_icon_y, 16, 16};
|
||||||
@@ -135,11 +128,6 @@ void gui::desktop_draw_panel(DesktopState* ds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Network icon (to the left of the volume icon)
|
// Network icon (to the left of the volume icon)
|
||||||
if (now - ds->net_cfg_last_poll > 5000) {
|
|
||||||
montauk::get_netcfg(&ds->cached_net_cfg);
|
|
||||||
ds->net_cfg_last_poll = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_icon_x = vol_icon_x - 16 - 10;
|
int net_icon_x = vol_icon_x - 16 - 10;
|
||||||
int net_icon_y = (PANEL_HEIGHT - 16) / 2;
|
int net_icon_y = (PANEL_HEIGHT - 16) / 2;
|
||||||
ds->net_icon_rect = {net_icon_x, net_icon_y, 16, 16};
|
ds->net_icon_rect = {net_icon_x, net_icon_y, 16, 16};
|
||||||
|
|||||||
Reference in New Issue
Block a user