// 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: // HIT_CONTENT, HIT_TITLE, HIT_CLOSE, HIT_RESIZE, // HIT_MENU, HIT_VSCROLL, HIT_HSCROLL, HIT_MINIMIZE, HIT_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, int32_t screenW, int32_t screenH); // 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. // mouseX/mouseY are in/out: on return they hold the clamped position so the // caller can warp the hardware cursor to keep it stuck to the window edge. 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