feat: add screenshot app
This commit is contained in:
+14
-4
@@ -59,7 +59,7 @@ BINDIR := bin
|
|||||||
PROGRAMS := $(notdir $(wildcard src/*))
|
PROGRAMS := $(notdir $(wildcard src/*))
|
||||||
|
|
||||||
# Programs with custom Makefiles (built separately).
|
# Programs with custom Makefiles (built separately).
|
||||||
CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop login shell rpgdemo paint tcc
|
CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop login shell rpgdemo paint tcc screenshot
|
||||||
SYSTEM_PROGRAMS := $(filter-out $(CUSTOM_BUILDS),$(PROGRAMS))
|
SYSTEM_PROGRAMS := $(filter-out $(CUSTOM_BUILDS),$(PROGRAMS))
|
||||||
|
|
||||||
# Build targets: system programs go to bin/os/, apps go to bin/apps/<name>/.
|
# Build targets: system programs go to bin/os/, apps go to bin/apps/<name>/.
|
||||||
@@ -81,9 +81,9 @@ CA_CERTS := $(BINDIR)/etc/ca-certificates.crt
|
|||||||
# Common shared assets (wallpapers, etc.)
|
# Common shared assets (wallpapers, etc.)
|
||||||
COMMONKEEP := $(BINDIR)/common/.keep
|
COMMONKEEP := $(BINDIR)/common/.keep
|
||||||
|
|
||||||
.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth login desktop shell rpgdemo paint tcc icons fonts bearssl libc tls libjpeg install-apps
|
.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth login desktop shell rpgdemo paint tcc screenshot icons fonts bearssl libc tls libjpeg libjpegwrite install-apps
|
||||||
|
|
||||||
all: bearssl libc libjpeg tls $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth doom rpgdemo paint tcc login desktop shell icons fonts install-apps $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP)
|
all: bearssl libc libjpeg libjpegwrite tls $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth doom rpgdemo paint tcc screenshot login desktop shell icons fonts install-apps $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP)
|
||||||
|
|
||||||
# Build BearSSL static library (cross-compiled for freestanding x86_64).
|
# Build BearSSL static library (cross-compiled for freestanding x86_64).
|
||||||
BEARSSL_INCLUDES := -isystem $(shell cd .. && pwd)/kernel/freestnd-c-hdrs/x86_64/include -isystem $(abspath include/libc)
|
BEARSSL_INCLUDES := -isystem $(shell cd .. && pwd)/kernel/freestnd-c-hdrs/x86_64/include -isystem $(abspath include/libc)
|
||||||
@@ -124,6 +124,10 @@ weather: bearssl libc tls
|
|||||||
libjpeg: libc
|
libjpeg: libc
|
||||||
$(MAKE) -C lib/libjpeg
|
$(MAKE) -C lib/libjpeg
|
||||||
|
|
||||||
|
# Build libjpegwrite static library (JPEG encoding via stb_image_write).
|
||||||
|
libjpegwrite: libc
|
||||||
|
$(MAKE) -C lib/libjpegwrite
|
||||||
|
|
||||||
# Build imageviewer standalone GUI client (depends on libc and libjpeg).
|
# Build imageviewer standalone GUI client (depends on libc and libjpeg).
|
||||||
imageviewer: libc libjpeg
|
imageviewer: libc libjpeg
|
||||||
$(MAKE) -C src/imageviewer
|
$(MAKE) -C src/imageviewer
|
||||||
@@ -196,6 +200,10 @@ rpgdemo: libc
|
|||||||
doom:
|
doom:
|
||||||
$(MAKE) -C src/doom
|
$(MAKE) -C src/doom
|
||||||
|
|
||||||
|
# Build screenshot tool (depends on libc and libjpegwrite).
|
||||||
|
screenshot: libc libjpegwrite
|
||||||
|
$(MAKE) -C src/screenshot
|
||||||
|
|
||||||
# Build TCC (Tiny C Compiler) via its own Makefile (depends on libc).
|
# Build TCC (Tiny C Compiler) via its own Makefile (depends on libc).
|
||||||
tcc: libc
|
tcc: libc
|
||||||
$(MAKE) -C src/tcc
|
$(MAKE) -C src/tcc
|
||||||
@@ -206,7 +214,7 @@ tcc: libc
|
|||||||
cp include/libc/sys/*.h $(BINDIR)/lib/tcc/include/sys/
|
cp include/libc/sys/*.h $(BINDIR)/lib/tcc/include/sys/
|
||||||
|
|
||||||
# Install app bundles (manifests, icons, data files) into bin/apps/<name>/.
|
# Install app bundles (manifests, icons, data files) into bin/apps/<name>/.
|
||||||
install-apps: doom rpgdemo paint spreadsheet weather wikipedia imageviewer fontpreview pdfviewer disks devexplorer installer volume music bluetooth
|
install-apps: doom rpgdemo paint spreadsheet weather wikipedia imageviewer fontpreview pdfviewer disks devexplorer installer volume music bluetooth screenshot
|
||||||
../scripts/install_apps.sh
|
../scripts/install_apps.sh
|
||||||
|
|
||||||
# Copy man pages into bin/man/ so mkramdisk.sh picks them up.
|
# Copy man pages into bin/man/ so mkramdisk.sh picks them up.
|
||||||
@@ -240,6 +248,7 @@ clean:
|
|||||||
$(MAKE) -C lib/bearssl clean
|
$(MAKE) -C lib/bearssl clean
|
||||||
$(MAKE) -C lib/libc clean
|
$(MAKE) -C lib/libc clean
|
||||||
$(MAKE) -C lib/libjpeg clean
|
$(MAKE) -C lib/libjpeg clean
|
||||||
|
$(MAKE) -C lib/libjpegwrite clean
|
||||||
$(MAKE) -C lib/tls clean
|
$(MAKE) -C lib/tls clean
|
||||||
$(MAKE) -C src/fetch clean
|
$(MAKE) -C src/fetch clean
|
||||||
$(MAKE) -C src/doom clean
|
$(MAKE) -C src/doom clean
|
||||||
@@ -260,4 +269,5 @@ clean:
|
|||||||
$(MAKE) -C src/bluetooth clean
|
$(MAKE) -C src/bluetooth clean
|
||||||
$(MAKE) -C src/paint clean
|
$(MAKE) -C src/paint clean
|
||||||
$(MAKE) -C src/rpgdemo clean
|
$(MAKE) -C src/rpgdemo clean
|
||||||
|
$(MAKE) -C src/screenshot clean
|
||||||
$(MAKE) -C src/tcc clean
|
$(MAKE) -C src/tcc clean
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
|||||||
|
# Makefile for libjpegwrite (JPEG encoding via stb_image_write) on MontaukOS
|
||||||
|
# Copyright (c) 2026 Daniel Hammer
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
# ---- Toolchain ----
|
||||||
|
|
||||||
|
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||||
|
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||||
|
CC := $(TOOLCHAIN_PREFIX)gcc
|
||||||
|
AR := $(TOOLCHAIN_PREFIX)ar
|
||||||
|
else
|
||||||
|
CC := gcc
|
||||||
|
AR := ar
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---- Paths ----
|
||||||
|
|
||||||
|
LIBC_INC := ../../include/libc
|
||||||
|
PROG_INC := ../../include
|
||||||
|
OBJDIR := obj
|
||||||
|
|
||||||
|
# ---- Compiler flags ----
|
||||||
|
|
||||||
|
CFLAGS := \
|
||||||
|
-std=gnu11 \
|
||||||
|
-g -O2 -pipe \
|
||||||
|
-Wall \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-nostdinc \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-PIC \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-fno-tree-loop-distribute-patterns \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-msse \
|
||||||
|
-msse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=small \
|
||||||
|
-I $(PROG_INC) \
|
||||||
|
-isystem $(LIBC_INC) \
|
||||||
|
-isystem $(shell $(CC) -print-file-name=include)
|
||||||
|
|
||||||
|
# ---- Target ----
|
||||||
|
|
||||||
|
TARGET := libjpegwrite.a
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJDIR)/stb_image_write_impl.o
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
$(OBJDIR)/stb_image_write_impl.o: stb_image_write_impl.c Makefile
|
||||||
|
@mkdir -p $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIR) $(TARGET)
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* stb_image_write_impl.c
|
||||||
|
* Single compilation unit for stb_image_write JPEG encoder on MontaukOS
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Only enable JPEG writing. */
|
||||||
|
#define STBI_WRITE_NO_STDIO
|
||||||
|
|
||||||
|
/* Route allocations through libc (which uses MontaukOS heap). */
|
||||||
|
#define STBIW_MALLOC(sz) malloc(sz)
|
||||||
|
#define STBIW_FREE(p) free(p)
|
||||||
|
#define STBIW_REALLOC(p, newsz) realloc(p, newsz)
|
||||||
|
#define STBIW_MEMMOVE(d, s, n) memmove(d, s, n)
|
||||||
|
|
||||||
|
#define STBIW_ASSERT(x) ((void)(x))
|
||||||
|
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include <gui/stb_image_write.h>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# Makefile for screenshot tool on MontaukOS
|
||||||
|
# Copyright (c) 2026 Daniel Hammer
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
# ---- Toolchain ----
|
||||||
|
|
||||||
|
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||||
|
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||||
|
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||||
|
else
|
||||||
|
CXX := g++
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---- Paths ----
|
||||||
|
|
||||||
|
PROJECT_ROOT := $(shell cd ../../.. && pwd)
|
||||||
|
PROGRAMS := $(PROJECT_ROOT)/programs
|
||||||
|
JPEGWRITE_LIB := $(PROGRAMS)/lib/libjpegwrite
|
||||||
|
LIBC_LIB := $(PROGRAMS)/lib/libc
|
||||||
|
PROG_INC := $(PROGRAMS)/include
|
||||||
|
LINK_LD := $(PROGRAMS)/link.ld
|
||||||
|
BINDIR := $(PROGRAMS)/bin
|
||||||
|
OBJDIR := obj
|
||||||
|
|
||||||
|
# ---- Compiler flags ----
|
||||||
|
|
||||||
|
CXXFLAGS := \
|
||||||
|
-std=gnu++20 \
|
||||||
|
-g -O2 -pipe \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-nostdinc \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-PIC \
|
||||||
|
-fno-rtti \
|
||||||
|
-fno-exceptions \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-msse \
|
||||||
|
-msse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=small \
|
||||||
|
-I $(PROG_INC) \
|
||||||
|
-isystem $(PROG_INC)/libc \
|
||||||
|
-isystem $(PROJECT_ROOT)/kernel/freestnd-c-hdrs/x86_64/include \
|
||||||
|
-isystem $(PROJECT_ROOT)/kernel/freestnd-cxx-hdrs/x86_64/include
|
||||||
|
|
||||||
|
# ---- Linker flags ----
|
||||||
|
|
||||||
|
LDFLAGS := \
|
||||||
|
-nostdlib \
|
||||||
|
-static \
|
||||||
|
-Wl,--build-id=none \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-m,elf_x86_64 \
|
||||||
|
-z max-page-size=0x1000 \
|
||||||
|
-T $(LINK_LD)
|
||||||
|
|
||||||
|
# ---- Libraries ----
|
||||||
|
|
||||||
|
LIBS := $(JPEGWRITE_LIB)/libjpegwrite.a $(LIBC_LIB)/liblibc.a
|
||||||
|
|
||||||
|
# ---- Source files ----
|
||||||
|
|
||||||
|
SRCS := main.cpp
|
||||||
|
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||||
|
|
||||||
|
# ---- Target ----
|
||||||
|
|
||||||
|
TARGET := $(BINDIR)/apps/screenshot/screenshot.elf
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS) $(LIBS) $(LINK_LD) Makefile
|
||||||
|
mkdir -p $(BINDIR)/apps/screenshot
|
||||||
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp Makefile
|
||||||
|
mkdir -p $(OBJDIR)
|
||||||
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIR) $(TARGET)
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* main.cpp
|
||||||
|
* MontaukOS Screenshot Tool
|
||||||
|
* Captures the screen framebuffer and saves as JPEG to the user's Pictures directory.
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/config.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define STBI_WRITE_NO_STDIO
|
||||||
|
#include <gui/stb_image_write.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// JPEG write callback - accumulates encoded bytes into a resizable buffer
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
struct JpegBuffer {
|
||||||
|
uint8_t* data;
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void jpeg_write_callback(void* context, void* data, int size) {
|
||||||
|
JpegBuffer* buf = (JpegBuffer*)context;
|
||||||
|
if (size <= 0) return;
|
||||||
|
|
||||||
|
uint64_t needed = buf->size + (uint64_t)size;
|
||||||
|
if (needed > buf->capacity) {
|
||||||
|
uint64_t new_cap = buf->capacity * 2;
|
||||||
|
if (new_cap < needed) new_cap = needed;
|
||||||
|
uint8_t* new_data = (uint8_t*)montauk::realloc(buf->data, new_cap);
|
||||||
|
if (!new_data) return;
|
||||||
|
buf->data = new_data;
|
||||||
|
buf->capacity = new_cap;
|
||||||
|
}
|
||||||
|
montauk::memcpy(buf->data + buf->size, data, size);
|
||||||
|
buf->size += (uint64_t)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Entry point
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
extern "C" void _start() {
|
||||||
|
// Get framebuffer info before doing anything else
|
||||||
|
Montauk::FbInfo fb;
|
||||||
|
montauk::fb_info(&fb);
|
||||||
|
|
||||||
|
int width = (int)fb.width;
|
||||||
|
int height = (int)fb.height;
|
||||||
|
int pitch = (int)fb.pitch;
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
montauk::print("screenshot: no framebuffer available\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the hardware framebuffer (read-only access to screen pixels)
|
||||||
|
uint32_t* hw_fb = (uint32_t*)montauk::fb_map();
|
||||||
|
if (!hw_fb) {
|
||||||
|
montauk::print("screenshot: failed to map framebuffer\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy framebuffer and convert from BGRA (0xAARRGGBB) to packed RGB
|
||||||
|
uint64_t rgb_size = (uint64_t)width * height * 3;
|
||||||
|
uint8_t* rgb = (uint8_t*)montauk::malloc(rgb_size);
|
||||||
|
if (!rgb) {
|
||||||
|
montauk::print("screenshot: out of memory\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
uint32_t* src_row = (uint32_t*)((uint8_t*)hw_fb + y * pitch);
|
||||||
|
uint8_t* dst_row = rgb + y * width * 3;
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
uint32_t px = src_row[x];
|
||||||
|
dst_row[x * 3 + 0] = (px >> 16) & 0xFF; // R
|
||||||
|
dst_row[x * 3 + 1] = (px >> 8) & 0xFF; // G
|
||||||
|
dst_row[x * 3 + 2] = px & 0xFF; // B
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode as JPEG (quality 100 - maximum quality)
|
||||||
|
JpegBuffer jpeg;
|
||||||
|
jpeg.data = (uint8_t*)montauk::malloc(256 * 1024);
|
||||||
|
jpeg.size = 0;
|
||||||
|
jpeg.capacity = 256 * 1024;
|
||||||
|
|
||||||
|
if (!jpeg.data) {
|
||||||
|
montauk::mfree(rgb);
|
||||||
|
montauk::print("screenshot: out of memory for JPEG buffer\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ok = stbi_write_jpg_to_func(jpeg_write_callback, &jpeg,
|
||||||
|
width, height, 3, rgb, 100);
|
||||||
|
montauk::mfree(rgb);
|
||||||
|
|
||||||
|
if (!ok || jpeg.size == 0) {
|
||||||
|
montauk::mfree(jpeg.data);
|
||||||
|
montauk::print("screenshot: JPEG encoding failed\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build output path: 0:/users/<username>/Pictures/screenshot_YYYYMMDD_HHMMSS.jpg
|
||||||
|
char username[32] = {};
|
||||||
|
{
|
||||||
|
auto doc = montauk::config::load("session");
|
||||||
|
const char* name = doc.get_string("session.username", "");
|
||||||
|
if (name[0] == '\0') {
|
||||||
|
doc.destroy();
|
||||||
|
montauk::mfree(jpeg.data);
|
||||||
|
montauk::print("screenshot: no user session\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
montauk::strncpy(username, name, sizeof(username) - 1);
|
||||||
|
doc.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
char home[128];
|
||||||
|
snprintf(home, sizeof(home), "0:/users/%s", username);
|
||||||
|
|
||||||
|
// Ensure Pictures directory exists
|
||||||
|
char pictures_dir[192];
|
||||||
|
snprintf(pictures_dir, sizeof(pictures_dir), "%s/Pictures", home);
|
||||||
|
montauk::fmkdir(pictures_dir);
|
||||||
|
|
||||||
|
// Build filename with timestamp
|
||||||
|
Montauk::DateTime dt;
|
||||||
|
montauk::gettime(&dt);
|
||||||
|
|
||||||
|
char filepath[256];
|
||||||
|
snprintf(filepath, sizeof(filepath),
|
||||||
|
"%s/screenshot_%04d%02d%02d_%02d%02d%02d.jpg",
|
||||||
|
pictures_dir,
|
||||||
|
(int)dt.Year, (int)dt.Month, (int)dt.Day,
|
||||||
|
(int)dt.Hour, (int)dt.Minute, (int)dt.Second);
|
||||||
|
|
||||||
|
// Write JPEG file
|
||||||
|
int fd = montauk::fcreate(filepath);
|
||||||
|
if (fd < 0) {
|
||||||
|
montauk::mfree(jpeg.data);
|
||||||
|
montauk::print("screenshot: failed to create file\n");
|
||||||
|
montauk::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
montauk::fwrite(fd, jpeg.data, 0, jpeg.size);
|
||||||
|
montauk::close(fd);
|
||||||
|
montauk::mfree(jpeg.data);
|
||||||
|
|
||||||
|
// Print confirmation
|
||||||
|
char msg[320];
|
||||||
|
snprintf(msg, sizeof(msg), "Screenshot saved: %s (%dx%d, %llu bytes)\n",
|
||||||
|
filepath, width, height, (unsigned long long)jpeg.size);
|
||||||
|
montauk::print(msg);
|
||||||
|
|
||||||
|
montauk::exit(0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
[app]
|
||||||
|
name = "Screenshot"
|
||||||
|
binary = "screenshot.elf"
|
||||||
|
icon = "screenshot.svg"
|
||||||
|
|
||||||
|
[menu]
|
||||||
|
category = "System"
|
||||||
|
visible = true
|
||||||
@@ -31,6 +31,7 @@ APPS=(
|
|||||||
"bluetooth|apps/scalable/bluetooth.svg"
|
"bluetooth|apps/scalable/bluetooth.svg"
|
||||||
"rpgdemo|apps/scalable/utilities-terminal.svg"
|
"rpgdemo|apps/scalable/utilities-terminal.svg"
|
||||||
"paint|apps/scalable/kolourpaint.svg"
|
"paint|apps/scalable/kolourpaint.svg"
|
||||||
|
"screenshot|apps/scalable/gnome-screenshot.svg"
|
||||||
)
|
)
|
||||||
|
|
||||||
installed=0
|
installed=0
|
||||||
|
|||||||
Reference in New Issue
Block a user