DVX_GUI/dvx/dvxApp.h

230 lines
10 KiB
C

// dvx_app.h — Layer 5: Application API for DVX GUI
//
// The topmost layer and the public-facing API for applications. Aggregates
// all lower layers into a single AppContextT and provides a clean interface
// for window creation, event dispatch, and utilities. Applications interact
// exclusively through dvx*() functions and window callbacks — they never
// need to call the lower WM, compositor, or draw layers directly.
//
// The event loop (dvxRun/dvxUpdate) follows a cooperative model: poll mouse
// and keyboard, dispatch events to the focused window, run the compositor
// for dirty regions, then yield. There's no preemptive scheduling — the
// application must return from callbacks promptly.
#ifndef DVX_APP_H
#define DVX_APP_H
#include "dvxTypes.h"
#include "dvxVideo.h"
#include "dvxDraw.h"
#include "dvxComp.h"
#include "dvxWm.h"
#include <time.h>
// ============================================================
// Application context
// ============================================================
//
// Single monolithic context that owns all GUI state. Allocated on the
// caller's stack (or statically) — no internal heap allocation for the
// context itself. This "god struct" approach keeps the API simple (one
// pointer to pass everywhere) and avoids the overhead of a handle-based
// system with opaque lookups. The tradeoff is a large struct, but on DOS
// memory layout is flat and cache pressure isn't a concern at this level.
typedef struct AppContextT {
DisplayT display;
WindowStackT stack;
DirtyListT dirty;
BlitOpsT blitOps;
BitmapFontT font;
ColorSchemeT colors;
PopupStateT popup;
SysMenuStateT sysMenu;
KbMoveResizeT kbMoveResize;
CursorT cursors[5]; // indexed by CURSOR_xxx
int32_t cursorId; // active cursor shape
uint32_t cursorFg; // pre-packed cursor colors
uint32_t cursorBg;
bool running;
int32_t mouseX;
int32_t mouseY;
int32_t mouseButtons;
int32_t mouseWheel; // wheel delta this frame (positive=down, negative=up)
bool hasMouseWheel; // true if CuteMouse Wheel API detected
int32_t keyModifiers; // current BIOS shift state (KEY_MOD_xxx)
// Previous-frame mouse state for edge detection (button press/release
// transitions and delta-based cursor movement).
int32_t prevMouseX;
int32_t prevMouseY;
int32_t prevMouseButtons;
// Double-click detection for minimized window icons: timestamps and
// window IDs track whether two clicks land on the same icon within
// the system double-click interval.
clock_t lastIconClickTime;
int32_t lastIconClickId; // window ID of last-clicked minimized icon (-1 = none)
clock_t lastCloseClickTime;
int32_t lastCloseClickId; // window ID of last-clicked close gadget (-1 = none)
clock_t lastTitleClickTime;
int32_t lastTitleClickId; // window ID of last-clicked title bar (-1 = none)
// Minimized icon thumbnails are refreshed one per frame (round-robin)
// rather than all at once, to amortize the cost of scaling the content
// buffer down to icon size.
int32_t iconRefreshIdx; // next minimized icon to refresh (staggered)
int32_t frameCount; // frame counter for periodic tasks
// The idle callback allows the host application (e.g. the DV/X shell)
// to do background work (poll serial ports, service DXE apps) during
// frames where no GUI events occurred, instead of just yielding the CPU.
void (*idleCallback)(void *ctx); // called instead of yield when non-NULL
void *idleCtx;
WindowT *modalWindow; // if non-NULL, only this window receives input
// Tooltip state — tooltip appears after the mouse hovers over a widget
// with a tooltip string for a brief delay. Pre-computing W/H avoids
// re-measuring on every paint frame.
clock_t tooltipHoverStart; // when mouse stopped moving
const char *tooltipText; // text to show (NULL = hidden)
int32_t tooltipX; // screen position
int32_t tooltipY;
int32_t tooltipW; // size (pre-computed)
int32_t tooltipH;
// Fixed-point reciprocal (16.16) of font.charHeight, pre-computed so
// that dividing by charHeight (needed for pixel-to-row conversion in
// terminal/text widgets) becomes a multiply+shift instead of an
// integer divide, which is very slow on 486 (40+ cycles per DIV).
uint32_t charHeightRecip; // fixed-point 16.16 reciprocal of font.charHeight
} AppContextT;
// Initialize the entire GUI stack: video mode, input devices, font,
// color scheme, cursor shapes, and internal state. This is the single
// entry point for starting a DVX application. Returns 0 on success.
int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
// Tear down the GUI stack in reverse order: destroy all windows, restore
// text mode, release input devices. Safe to call after a failed dvxInit().
void dvxShutdown(AppContextT *ctx);
// Enter the main event loop. Polls input, dispatches events, composites
// dirty regions, and yields on each iteration. Returns when ctx->running
// becomes false (typically from dvxQuit() or a close callback).
void dvxRun(AppContextT *ctx);
// Process exactly one frame of the event loop. Provided for applications
// that need to integrate the GUI into their own main loop (e.g. the DV/X
// shell polling serial ports between frames). Returns false when the GUI
// wants to exit.
bool dvxUpdate(AppContextT *ctx);
// Create a window at an explicit screen position. The window is raised
// to the top, focused, and its entire region is dirtied for the next
// composite pass.
WindowT *dvxCreateWindow(AppContextT *ctx, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable);
// Convenience wrapper that centers the window on screen.
WindowT *dvxCreateWindowCentered(AppContextT *ctx, const char *title, int32_t w, int32_t h, bool resizable);
// Destroy a window, free all its resources, and dirty its former region.
void dvxDestroyWindow(AppContextT *ctx, WindowT *win);
// Resize a window to exactly fit its widget tree's computed minimum size
// (plus chrome). Used for dialog boxes and other fixed-layout windows
// where the window should shrink-wrap its content.
void dvxFitWindow(AppContextT *ctx, WindowT *win);
// Mark a sub-region of a window's content area as needing repaint. The
// coordinates are relative to the content area, not the screen. The
// onPaint callback will be called during the next composite pass with
// the dirty area.
void dvxInvalidateRect(AppContextT *ctx, WindowT *win, int32_t x, int32_t y, int32_t w, int32_t h);
// Mark the entire window content area as dirty.
void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);
// Minimize a window (show as icon at bottom of screen)
void dvxMinimizeWindow(AppContextT *ctx, WindowT *win);
// Maximize a window (expand to fill screen or maxW/maxH)
void dvxMaximizeWindow(AppContextT *ctx, WindowT *win);
// Request exit from main loop
void dvxQuit(AppContextT *ctx);
// Save the entire screen (backbuffer contents) to a PNG file. Converts
// from native pixel format to RGB for the PNG encoder. Returns 0 on
// success, -1 on failure.
int32_t dvxScreenshot(AppContextT *ctx, const char *path);
// Set window title
void dvxSetTitle(AppContextT *ctx, WindowT *win, const char *title);
// Get the default font
const BitmapFontT *dvxGetFont(const AppContextT *ctx);
// Get the color scheme
const ColorSchemeT *dvxGetColors(const AppContextT *ctx);
// Get the display
DisplayT *dvxGetDisplay(AppContextT *ctx);
// Get blit ops
const BlitOpsT *dvxGetBlitOps(const AppContextT *ctx);
// Load an icon for a window from an image file
int32_t dvxSetWindowIcon(AppContextT *ctx, WindowT *win, const char *path);
// Save a window's content to a PNG file (returns 0 on success, -1 on failure)
int32_t dvxWindowScreenshot(AppContextT *ctx, WindowT *win, const char *path);
// Allocate a new accelerator table. Attach it to a window via
// win->accelTable. The event loop checks the focused window's accel
// table on every keystroke and fires onMenu(cmdId) on match.
AccelTableT *dvxCreateAccelTable(void);
// Free an accelerator table and its entries.
void dvxFreeAccelTable(AccelTableT *table);
// Register a keyboard shortcut. key is an ASCII char or KEY_Fxx constant.
// modifiers is a bitmask of ACCEL_CTRL/ACCEL_SHIFT/ACCEL_ALT. cmdId is
// passed to the window's onMenu callback, matching the convention used
// for menu item IDs so the same handler works for both menus and hotkeys.
void dvxAddAccel(AccelTableT *table, int32_t key, int32_t modifiers, int32_t cmdId);
// Window arrangement functions — operate on all visible, non-minimized
// windows. These mirror the classic Windows 3.x "Window" menu commands.
// Cascade: offset each window diagonally by the title bar height.
void dvxCascadeWindows(AppContextT *ctx);
// Grid tile: arrange windows in an NxM grid filling the screen.
void dvxTileWindows(AppContextT *ctx);
// Horizontal tile: side by side, equal width, full height.
void dvxTileWindowsH(AppContextT *ctx);
// Vertical tile: stacked, full width, equal height.
void dvxTileWindowsV(AppContextT *ctx);
// Load an image file (BMP, PNG, JPEG, GIF) and convert to the display's
// native pixel format. Returns the pixel buffer on success (caller must
// free with dvxFreeImage), or NULL on failure. Output params receive the
// image dimensions and row pitch in bytes.
uint8_t *dvxLoadImage(const AppContextT *ctx, const char *path, int32_t *outW, int32_t *outH, int32_t *outPitch);
// Free a pixel buffer returned by dvxLoadImage.
void dvxFreeImage(uint8_t *data);
// Save native-format pixel data to a PNG file. The pixel data must be
// in the display's native format (as returned by dvxLoadImage or
// captured from a content buffer). Returns 0 on success, -1 on failure.
int32_t dvxSaveImage(const AppContextT *ctx, const uint8_t *data, int32_t w, int32_t h, int32_t pitch, const char *path);
// Copy text to the process-wide clipboard buffer. The clipboard is a
// simple static buffer (not inter-process) — adequate for copy/paste
// within the DVX environment on single-tasking DOS.
void dvxClipboardCopy(const char *text, int32_t len);
// Retrieve the current clipboard contents. Returns a pointer to the
// internal static buffer (valid until the next dvxClipboardCopy), or
// NULL if the clipboard is empty.
const char *dvxClipboardGet(int32_t *outLen);
#endif // DVX_APP_H