DVX_GUI/dvx/dvxWm.h

199 lines
10 KiB
C

// dvx_wm.h — Layer 4: Window manager for DVX GUI
//
// Manages the window lifecycle, Z-order stack, chrome drawing, hit testing,
// and interactive operations (drag, resize, scroll). This layer bridges the
// low-level drawing/compositing layers below with the high-level application
// API above.
//
// Design philosophy: the WM owns window geometry and chrome, but the
// window's content is owned by the application (via callbacks or the widget
// system). This separation means the WM can move, resize, and repaint
// window frames without involving the application at all — only content
// changes trigger application callbacks.
//
// All WM operations that change visible screen state accept a DirtyListT*
// so they can mark affected regions for compositor repaint. This push-based
// dirty tracking avoids the need for a full-screen diff each frame.
#ifndef DVX_WM_H
#define DVX_WM_H
#include "dvxTypes.h"
// Zero the window stack. Must be called before any other wm function.
void wmInit(WindowStackT *stack);
// Allocate a new WindowT, initialize its geometry and content buffer, and
// push it to the top of the Z-order stack. The returned window has default
// callbacks (all NULL) — the caller should set onPaint/onKey/etc. before
// the next event loop iteration.
WindowT *wmCreateWindow(WindowStackT *stack, DisplayT *d, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable);
// Free the window's content buffer and all attached resources (menu bar,
// scrollbars, widget tree), then remove it from the stack and dirty the
// region it occupied.
void wmDestroyWindow(WindowStackT *stack, WindowT *win);
// Move window at stack index idx to the top of the Z-order. Dirties both
// the old and new top positions so overlapping windows get repainted.
void wmRaiseWindow(WindowStackT *stack, DirtyListT *dl, int32_t idx);
// Transfer keyboard focus to the window at stack index idx. Unfocuses the
// previously focused window and dirties both title bars (since active/
// inactive title colors differ).
void wmSetFocus(WindowStackT *stack, DirtyListT *dl, int32_t idx);
// Recompute contentX/Y/W/H from the window's outer frame dimensions,
// accounting for chrome borders, title bar, menu bar, and scrollbars.
// Must be called after any change to frame size or chrome configuration
// (e.g. adding a menu bar or scrollbar).
void wmUpdateContentRect(WindowT *win);
// Reallocate the per-window content backbuffer to match the current
// contentW/H. Returns 0 on success, -1 if allocation fails. The old
// buffer contents are lost — the caller should trigger a full repaint
// via onPaint after a successful realloc.
int32_t wmReallocContentBuf(WindowT *win, const DisplayT *d);
// Allocate and attach a menu bar to a window. Adjusts the content area
// to make room for the menu bar (CHROME_MENU_HEIGHT pixels). Only one
// menu bar per window is supported.
MenuBarT *wmAddMenuBar(WindowT *win);
// Append a dropdown menu to the menu bar. Returns the MenuT to populate
// with items. The label supports & accelerator markers (e.g. "&File").
MenuT *wmAddMenu(MenuBarT *bar, const char *label);
// Append a clickable item to a menu. The id is passed to the window's
// onMenu callback when the item is selected.
void wmAddMenuItem(MenuT *menu, const char *label, int32_t id);
// Add a checkbox-style item. Check state is toggled on click and
// rendered with a checkmark glyph.
void wmAddMenuCheckItem(MenuT *menu, const char *label, int32_t id, bool checked);
// Add a radio-style item. Radio groups are defined implicitly by
// consecutive radio items in the same menu — selecting one unchecks
// the others in the group.
void wmAddMenuRadioItem(MenuT *menu, const char *label, int32_t id, bool checked);
// Insert a horizontal separator line. Separators are not interactive.
void wmAddMenuSeparator(MenuT *menu);
// Create a cascading submenu attached to the parent menu. Returns the
// child MenuT to populate, or NULL if MAX_MENU_ITEMS is exhausted.
// The child MenuT is heap-allocated and freed when the parent window
// is destroyed.
MenuT *wmAddSubMenu(MenuT *parentMenu, const char *label);
// Attach a vertical scrollbar to the right edge of the window's content
// area. Shrinks contentW by SCROLLBAR_WIDTH pixels to make room. The
// scrollbar's value range and page size determine thumb proportions.
ScrollbarT *wmAddVScrollbar(WindowT *win, int32_t min, int32_t max, int32_t pageSize);
// Attach a horizontal scrollbar to the bottom edge. Shrinks contentH
// by SCROLLBAR_WIDTH pixels.
ScrollbarT *wmAddHScrollbar(WindowT *win, int32_t min, int32_t max, int32_t pageSize);
// Draw the window frame (outer bevel, title bar with text, close/minimize/
// maximize gadgets, and menu bar if present). clipTo restricts drawing to
// only the intersection with the given dirty rectangle, avoiding redundant
// pixel writes outside the damaged region.
void wmDrawChrome(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors, WindowT *win, const RectT *clipTo);
// Blit the window's content backbuffer into the display backbuffer,
// clipped to the dirty rect. This is a pure copy (no drawing) — the
// content was already rendered by the application into contentBuf.
void wmDrawContent(DisplayT *d, const BlitOpsT *ops, WindowT *win, const RectT *clipTo);
// Draw scrollbars (track, arrows, proportional thumb) for a window.
// Drawn after content so scrollbars overlay the content area edge.
void wmDrawScrollbars(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, WindowT *win, const RectT *clipTo);
// Draw icons for all minimized windows along the bottom of the screen.
// Each icon shows a scaled-down preview of the window's content (or a
// default icon) with a beveled border, similar to DESQview/X's icon bar.
void wmDrawMinimizedIcons(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, const WindowStackT *stack, const RectT *clipTo);
// Determine which window and which part of that window is under the given
// screen coordinates. Iterates the stack front-to-back (highest Z first)
// so the topmost window wins. Returns the stack index, or -1 if no window
// was hit (i.e. the desktop). hitPart identifies the chrome region:
// 0=content, 1=title bar, 2=close button, 3=resize edge,
// 4=menu bar, 5=vscroll, 6=hscroll, 7=minimize, 8=maximize
int32_t wmHitTest(const WindowStackT *stack, int32_t mx, int32_t my, int32_t *hitPart);
// For a point within a window's border zone, determine which edge(s)
// are being targeted for resize. Returns a bitmask of RESIZE_xxx flags.
// Corner hits combine two edges (e.g. RESIZE_LEFT | RESIZE_TOP).
int32_t wmResizeEdgeHit(const WindowT *win, int32_t mx, int32_t my);
// Update window position during an active drag. Called on each mouse move
// event while dragWindow is active. Dirties both the old and new window
// positions. The drag offset (mouse position relative to window origin at
// drag start) is applied so the window tracks the mouse smoothly.
void wmDragMove(WindowStackT *stack, DirtyListT *dl, int32_t mouseX, int32_t mouseY);
// Update window dimensions during an active resize. Enforces MIN_WINDOW_W/H
// and optional maxW/maxH constraints. Reallocates the content buffer if the
// content area size changed, then calls onResize to notify the application.
void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_t mouseX, int32_t mouseY);
// Begin a window drag operation. Records the mouse offset from the window
// origin so the window doesn't jump to the cursor position.
void wmDragBegin(WindowStackT *stack, int32_t idx, int32_t mouseX, int32_t mouseY);
// End the current drag operation. Clears dragWindow state.
void wmDragEnd(WindowStackT *stack);
// Begin a window resize operation. Records which edge(s) are being dragged
// and the initial mouse position for delta computation.
void wmResizeBegin(WindowStackT *stack, int32_t idx, int32_t edge, int32_t mouseX, int32_t mouseY);
// End the current resize operation. Clears resizeWindow state.
void wmResizeEnd(WindowStackT *stack);
// Set window title
void wmSetTitle(WindowT *win, DirtyListT *dl, const char *title);
// Handle an initial click on a scrollbar. Determines what was hit (up/down
// arrows, page trough area, or thumb) and either adjusts the value
// immediately (arrows, trough) or begins a thumb drag operation.
void wmScrollbarClick(WindowStackT *stack, DirtyListT *dl, int32_t idx, int32_t orient, int32_t mx, int32_t my);
// Update the scroll value during an active thumb drag. Maps the mouse
// position along the track to a scroll value proportional to the range.
void wmScrollbarDrag(WindowStackT *stack, DirtyListT *dl, int32_t mx, int32_t my);
// End an active scrollbar thumb drag.
void wmScrollbarEnd(WindowStackT *stack);
// Maximize a window (saves current geometry, expands to screen/max bounds)
void wmMaximize(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);
// Minimize a window (hides window, shows icon at bottom of screen)
void wmMinimize(WindowStackT *stack, DirtyListT *dl, WindowT *win);
// Hit-test minimized icons at bottom of screen
// Returns stack index of the minimized window, or -1
int32_t wmMinimizedIconHit(const WindowStackT *stack, const DisplayT *d, int32_t mx, int32_t my);
// Restore a maximized window to its pre-maximize geometry
void wmRestore(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);
// Restore a minimized window
void wmRestoreMinimized(WindowStackT *stack, DirtyListT *dl, WindowT *win);
// Load an icon image for a window (converts to display pixel format)
int32_t wmSetIcon(WindowT *win, const char *path, const DisplayT *d);
// Allocate a heap-resident MenuT for use as a context menu (right-click).
// Unlike menu bar menus (which are embedded in MenuBarT), context menus
// are standalone allocations because they may be shared across windows or
// attached/detached dynamically. Free with wmFreeMenu().
MenuT *wmCreateMenu(void);
// Free a standalone menu allocated with wmCreateMenu(). Also frees any
// heap-allocated submenu children recursively.
void wmFreeMenu(MenuT *menu);
#endif // DVX_WM_H