Optimized window drawing. Added window caching.
This commit is contained in:
parent
7d32a1df31
commit
10196882ef
12 changed files with 585 additions and 231 deletions
|
@ -4,8 +4,8 @@ CONFIG -= qt
|
|||
CONFIG += console
|
||||
CONFIG += c99
|
||||
|
||||
#CONFIG += BACKEND_SDL2
|
||||
CONFIG += BACKEND_DJGPP
|
||||
CONFIG += BACKEND_SDL2
|
||||
#CONFIG += BACKEND_DJGPP
|
||||
|
||||
SHARED = $$PWD/../shared
|
||||
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
#include "font.h"
|
||||
#include "gui.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
|
||||
static FontT *_font = NULL;
|
||||
static ColorT _foreground = 0;
|
||||
static ColorT _background = 0;
|
||||
static uint8_t _allowMods = 1;
|
||||
|
||||
|
||||
void fontColorSet(ColorT foreground, ColorT background) {
|
||||
_foreground = foreground;
|
||||
_background = background;
|
||||
}
|
||||
|
||||
|
||||
FontT *fontFromRAMLoad(uint8_t *pointer) {
|
||||
FontT *font = NULL;
|
||||
uint32_t size = 0;
|
||||
|
@ -67,7 +80,12 @@ FontT *fontLoad(char *filename) {
|
|||
}
|
||||
|
||||
|
||||
void fontRender(FontT *font, char *string, ColorT foreground, ColorT background, uint16_t x, uint16_t y) {
|
||||
void fontModsEnabledSet(uint8_t enabled) {
|
||||
_allowMods = enabled;
|
||||
}
|
||||
|
||||
|
||||
void fontRender(char *string, uint16_t x, uint16_t y) {
|
||||
uint8_t cx;
|
||||
uint8_t cy;
|
||||
uint16_t offset;
|
||||
|
@ -83,37 +101,54 @@ void fontRender(FontT *font, char *string, ColorT foreground, ColorT background,
|
|||
for (c=0; c<strlen(string); c++) {
|
||||
character = string[c];
|
||||
|
||||
if (_allowMods) {
|
||||
// Change _foreground to GUI Color Index.
|
||||
if (character == 1) {
|
||||
character = string[++c];
|
||||
if (character == 16) character = 0; // Because we can't pass NULL in a string, 16 is used for black.
|
||||
_foreground = __guiBaseColors[character];
|
||||
continue;
|
||||
}
|
||||
// Change _background to GUI Color Index.
|
||||
if (character == 2) {
|
||||
character = string[++c];
|
||||
if (character == 16) character = 0; // Because we can't pass NULL in a string, 16 is used for black.
|
||||
_background = __guiBaseColors[character];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Find character position in font grid.
|
||||
cx = character % font->span;
|
||||
cy = character / font->span;
|
||||
cx = character % _font->span;
|
||||
cy = character / _font->span;
|
||||
|
||||
yp = y;
|
||||
|
||||
// Half byte or full byte font?
|
||||
if (font->width == 4) {
|
||||
if (_font->width == 4) {
|
||||
// Half Byte.
|
||||
|
||||
// Which half of the byte do we want?
|
||||
odd = ((cx & 1) == 1);
|
||||
|
||||
// Find offset byte based on font bits.
|
||||
offset = cy * (font->span / 2) * font->height + cx * ((float)font->width / 8.0f);
|
||||
offset = cy * (_font->span / 2) * _font->height + cx * ((float)_font->width / 8.0f);
|
||||
|
||||
for (yl=0; yl<font->height; yl++) {
|
||||
for (yl=0; yl<_font->height; yl++) {
|
||||
// We do 4 pixels unrolled hoping it's fast.
|
||||
data = font->bits[offset];
|
||||
offset += (font->span / 2);
|
||||
data = _font->bits[offset];
|
||||
offset += (_font->span / 2);
|
||||
|
||||
if (odd) {
|
||||
surfacePixelSet(x, yp, (data & 0x08) ? foreground : background);
|
||||
surfacePixelSet(x + 1, yp, (data & 0x04) ? foreground : background);
|
||||
surfacePixelSet(x + 2, yp, (data & 0x02) ? foreground : background);
|
||||
surfacePixelSet(x + 3, yp, (data & 0x01) ? foreground : background);
|
||||
surfacePixelSet(x, yp, (data & 0x08) ? _foreground : _background);
|
||||
surfacePixelSet(x + 1, yp, (data & 0x04) ? _foreground : _background);
|
||||
surfacePixelSet(x + 2, yp, (data & 0x02) ? _foreground : _background);
|
||||
surfacePixelSet(x + 3, yp, (data & 0x01) ? _foreground : _background);
|
||||
} else {
|
||||
surfacePixelSet(x, yp, (data & 0x80) ? foreground : background);
|
||||
surfacePixelSet(x + 1, yp, (data & 0x40) ? foreground : background);
|
||||
surfacePixelSet(x + 2, yp, (data & 0x20) ? foreground : background);
|
||||
surfacePixelSet(x + 3, yp, (data & 0x10) ? foreground : background);
|
||||
surfacePixelSet(x, yp, (data & 0x80) ? _foreground : _background);
|
||||
surfacePixelSet(x + 1, yp, (data & 0x40) ? _foreground : _background);
|
||||
surfacePixelSet(x + 2, yp, (data & 0x20) ? _foreground : _background);
|
||||
surfacePixelSet(x + 3, yp, (data & 0x10) ? _foreground : _background);
|
||||
}
|
||||
|
||||
yp++;
|
||||
|
@ -122,38 +157,43 @@ void fontRender(FontT *font, char *string, ColorT foreground, ColorT background,
|
|||
// Full Byte.
|
||||
|
||||
// Find offset byte based on font bits.
|
||||
offset = cy * font->span * font->height + cx;
|
||||
offset = cy * _font->span * _font->height + cx;
|
||||
|
||||
// Draw out 8 lines.
|
||||
for (yl=0; yl<font->height; yl++) {
|
||||
for (yl=0; yl<_font->height; yl++) {
|
||||
// We do 8 pixels unrolled hoping it's fast.
|
||||
data = font->bits[offset];
|
||||
offset += font->span;
|
||||
data = _font->bits[offset];
|
||||
offset += _font->span;
|
||||
|
||||
surfacePixelSet(x, yp, (data & 0x80) ? foreground : background);
|
||||
surfacePixelSet(x + 1, yp, (data & 0x40) ? foreground : background);
|
||||
surfacePixelSet(x + 2, yp, (data & 0x20) ? foreground : background);
|
||||
surfacePixelSet(x + 3, yp, (data & 0x10) ? foreground : background);
|
||||
surfacePixelSet(x + 4, yp, (data & 0x08) ? foreground : background);
|
||||
surfacePixelSet(x + 5, yp, (data & 0x04) ? foreground : background);
|
||||
surfacePixelSet(x + 6, yp, (data & 0x02) ? foreground : background);
|
||||
surfacePixelSet(x + 7, yp, (data & 0x01) ? foreground : background);
|
||||
surfacePixelSet(x, yp, (data & 0x80) ? _foreground : _background);
|
||||
surfacePixelSet(x + 1, yp, (data & 0x40) ? _foreground : _background);
|
||||
surfacePixelSet(x + 2, yp, (data & 0x20) ? _foreground : _background);
|
||||
surfacePixelSet(x + 3, yp, (data & 0x10) ? _foreground : _background);
|
||||
surfacePixelSet(x + 4, yp, (data & 0x08) ? _foreground : _background);
|
||||
surfacePixelSet(x + 5, yp, (data & 0x04) ? _foreground : _background);
|
||||
surfacePixelSet(x + 6, yp, (data & 0x02) ? _foreground : _background);
|
||||
surfacePixelSet(x + 7, yp, (data & 0x01) ? _foreground : _background);
|
||||
|
||||
yp++;
|
||||
}
|
||||
}
|
||||
|
||||
x += font->width;
|
||||
x += _font->width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fontSet(FontT *font) {
|
||||
_font = font;
|
||||
}
|
||||
|
||||
|
||||
void fontUnload(FontT **font) {
|
||||
FontT *f = *font;
|
||||
|
||||
free(f->bits);
|
||||
free(f);
|
||||
f = NULL;
|
||||
*font = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,10 +17,13 @@ typedef struct FontS {
|
|||
} FontT;
|
||||
|
||||
|
||||
void fontColorSet(ColorT foreground, ColorT background);
|
||||
FontT *fontFromRAMLoad(uint8_t *pointer);
|
||||
uint16_t fontHeightGet(FontT *font);
|
||||
FontT *fontLoad(char *filename);
|
||||
void fontRender(FontT *font, char *string, ColorT foreground, ColorT background, uint16_t x, uint16_t y);
|
||||
void fontModsEnabledSet(uint8_t enabled);
|
||||
void fontRender(char *string, uint16_t x, uint16_t y);
|
||||
void fontSet(FontT *font);
|
||||
void fontUnload(FontT **font);
|
||||
uint16_t fontWidthGet(FontT *font);
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ typedef struct WidgetCatalogS {
|
|||
|
||||
ColorT *__guiBaseColors = NULL;
|
||||
SurfaceT *__guiBackBuffer = NULL;
|
||||
FontT *__guiFontVGA8x8 = NULL;
|
||||
FontT *__guiFontVGA8x14 = NULL;
|
||||
FontT *__guiFontVGA8x16 = NULL;
|
||||
|
||||
|
||||
static uint8_t _magicCount = 0;
|
||||
|
@ -23,29 +25,27 @@ static SurfaceT *_mousePointer = NULL;
|
|||
static ColorT _mouseTransparency;
|
||||
|
||||
|
||||
void guiRun(void) {
|
||||
void guiEventsDo(void) {
|
||||
EventT event = { 0 };
|
||||
|
||||
while (_guiRunning) {
|
||||
// Read mouse & keyboard.
|
||||
platformEventGet(&event);
|
||||
// Read mouse & keyboard.
|
||||
platformEventGet(&event);
|
||||
|
||||
// Paint desktop.
|
||||
surfaceSet(__guiBackBuffer);
|
||||
surfaceClear(GUI_CYAN);
|
||||
// Paint desktop.
|
||||
surfaceSet(__guiBackBuffer);
|
||||
surfaceClear(GUI_CYAN);
|
||||
|
||||
// Paint GUI.
|
||||
wmPaint(&event);
|
||||
// Paint GUI.
|
||||
wmPaint(&event);
|
||||
|
||||
// Paint mouse pointer.
|
||||
surfaceBlitWithTransparency(__guiBackBuffer, event.x, event.y, _mousePointer, _mouseTransparency);
|
||||
// Paint mouse pointer.
|
||||
surfaceBlitWithTransparency(__guiBackBuffer, event.x, event.y, _mousePointer, _mouseTransparency);
|
||||
|
||||
// Copy to screen.
|
||||
videoBlit(0, 0, __guiBackBuffer);
|
||||
// Copy to screen.
|
||||
videoBlit(0, 0, __guiBackBuffer);
|
||||
|
||||
// Emergency Exit?
|
||||
if (event.flags & EVENT_FLAG_KEYPRESS && event.key == KEY_ESC) guiStop();
|
||||
}
|
||||
// Emergency Exit?
|
||||
if (event.flags & EVENT_FLAG_KEYPRESS && event.key == KEY_ESC) guiStop();
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,9 +56,20 @@ void guiRegister(WidgetRegisterT widgetRegister) {
|
|||
}
|
||||
|
||||
|
||||
void guiRun(void) {
|
||||
|
||||
while (_guiRunning) {
|
||||
|
||||
// Process all GUI events.
|
||||
guiEventsDo();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void guiShutdown(void) {
|
||||
|
||||
free(__guiBaseColors);
|
||||
DEL(__guiBaseColors);
|
||||
|
||||
while (hmlen(_widgetCatalog) > 0) {
|
||||
if (_widgetCatalog[0].value->unregister) _widgetCatalog[0].value->unregister(NULL);
|
||||
|
@ -68,10 +79,12 @@ void guiShutdown(void) {
|
|||
|
||||
wmShutdown();
|
||||
|
||||
fontUnload(&__guiFontVGA8x16);
|
||||
fontUnload(&__guiFontVGA8x14);
|
||||
fontUnload(&__guiFontVGA8x8);
|
||||
|
||||
surfaceDestroy(_mousePointer);
|
||||
surfaceDestroy(__guiBackBuffer);
|
||||
surfaceDestroy(&_mousePointer);
|
||||
surfaceDestroy(&__guiBackBuffer);
|
||||
|
||||
platformShutdown();
|
||||
}
|
||||
|
@ -111,10 +124,15 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
|
|||
_mousePointer = imageLoad("mouse.png");
|
||||
_mouseTransparency = surfacePixelGet(_mousePointer, surfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color.
|
||||
|
||||
__guiFontVGA8x8 = fontLoad("vga8x8.dat");
|
||||
__guiFontVGA8x14 = fontLoad("vga8x14.dat");
|
||||
__guiFontVGA8x16 = fontLoad("vga8x16.dat");
|
||||
fontSet(__guiFontVGA8x14);
|
||||
fontColorSet(GUI_WHITE, GUI_BLACK);
|
||||
|
||||
wmStartup();
|
||||
|
||||
// Register all known widgets with the GUI.
|
||||
guiRegister(windowRegister);
|
||||
|
||||
return SUCCESS;
|
||||
|
@ -135,4 +153,16 @@ void guiWidgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, ui
|
|||
widget->r.h = h;
|
||||
|
||||
widget->reg = hmget(_widgetCatalog, magic);
|
||||
|
||||
widget->dirty = 1; // Everything starts dirty to force a paint.
|
||||
}
|
||||
|
||||
|
||||
uint8_t guiWidgetDirtyGet(WidgetT *widget) {
|
||||
return widget->dirty;
|
||||
}
|
||||
|
||||
|
||||
void guiWidgetDirtySet(WidgetT *widget, uint8_t dirty) {
|
||||
widget->dirty = dirty;
|
||||
}
|
||||
|
|
|
@ -31,16 +31,17 @@ typedef struct RectS {
|
|||
} RectT;
|
||||
|
||||
typedef struct RegisterS {
|
||||
char *widgetName;
|
||||
WidgetEventT paint;
|
||||
WidgetEventT destroy;
|
||||
GuiCallbackT unregister;
|
||||
char *widgetName; // Text name of widget.
|
||||
WidgetEventT paint; // Paint routine.
|
||||
WidgetEventT destroy; // Destroy routine.
|
||||
GuiCallbackT unregister; // Unregister routine.
|
||||
} RegisterT;
|
||||
|
||||
typedef struct WidgetS {
|
||||
uint8_t magic;
|
||||
RectT r;
|
||||
RegisterT *reg;
|
||||
uint8_t magic; // Magic ID of widget.
|
||||
RectT r; // Outer bounds, except for windows.
|
||||
RegisterT *reg; // Registration information.
|
||||
uint8_t dirty; // Is the widget dirty?
|
||||
} WidgetT;
|
||||
|
||||
typedef RegisterT *(*WidgetRegisterT)(uint8_t);
|
||||
|
@ -49,7 +50,9 @@ typedef RegisterT *(*WidgetRegisterT)(uint8_t);
|
|||
extern SurfaceT *__guiBackBuffer;
|
||||
extern SurfaceT *__guiScreenBuffer;
|
||||
extern ColorT *__guiBaseColors;
|
||||
extern FontT *__guiFontVGA8x8;
|
||||
extern FontT *__guiFontVGA8x14;
|
||||
extern FontT *__guiFontVGA8x16;
|
||||
|
||||
|
||||
#define GUI_BLACK __guiBaseColors[0]
|
||||
|
@ -70,13 +73,19 @@ extern FontT *__guiFontVGA8x14;
|
|||
#define GUI_WHITE __guiBaseColors[15]
|
||||
|
||||
|
||||
void guiModesShow(void);
|
||||
#define W (WidgetT *) // Cast any widget to base WidgetT type.
|
||||
#define C(n) ((n) << 3) // Multiply by 8 to get "cells".
|
||||
|
||||
|
||||
void guiEventsDo(void);
|
||||
void guiRegister(WidgetRegisterT widgetRegister);
|
||||
void guiRun(void);
|
||||
void guiShutdown(void);
|
||||
uint8_t guiStartup(int16_t width, int16_t height, int16_t depth);
|
||||
void guiStop(void);
|
||||
void guiWidgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
uint8_t guiWidgetDirtyGet(WidgetT *widget);
|
||||
void guiWidgetDirtySet(WidgetT *widget, uint8_t dirty);
|
||||
|
||||
|
||||
#endif // GUI_H
|
||||
|
|
|
@ -111,8 +111,6 @@ SurfaceT *surfaceCreate(int16_t width, int16_t height) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
memset(surface->buffer.bits8, 0, surface->bytes);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
@ -160,9 +158,19 @@ void surfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c)
|
|||
}
|
||||
|
||||
|
||||
void surfaceDestroy(SurfaceT *surface) {
|
||||
free(surface->buffer.bits8);
|
||||
free(surface);
|
||||
void surfaceBoxHighlight(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT highlight, ColorT shadow) {
|
||||
surfaceLineH(x1, x2, y1, highlight);
|
||||
surfaceLineV(x1, y1, y2, highlight);
|
||||
surfaceLineH(x1, x2, y2, shadow);
|
||||
surfaceLineV(x2, y1, y2, shadow);
|
||||
}
|
||||
|
||||
|
||||
void surfaceDestroy(SurfaceT **surface) {
|
||||
SurfaceT *s = *surface;
|
||||
DEL(s->buffer.bits8);
|
||||
DEL(s);
|
||||
*surface = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -176,6 +184,66 @@ int16_t surfaceHeightGet(SurfaceT *surface) {
|
|||
}
|
||||
|
||||
|
||||
void surfaceLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT color) {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t dx;
|
||||
int16_t dy;
|
||||
int16_t incX;
|
||||
int16_t incY;
|
||||
int16_t balance;
|
||||
|
||||
if (x2 >= x1) {
|
||||
dx = x2 - x1;
|
||||
incX = 1;
|
||||
} else {
|
||||
dx = x1 - x2;
|
||||
incX = -1;
|
||||
}
|
||||
|
||||
if (y2 >= y1) {
|
||||
dy = y2 - y1;
|
||||
incY = 1;
|
||||
} else {
|
||||
dy = y1 - y2;
|
||||
incY = -1;
|
||||
}
|
||||
|
||||
x = x1;
|
||||
y = y1;
|
||||
|
||||
if (dx >= dy) {
|
||||
dy <<= 1;
|
||||
balance = dy - dx;
|
||||
dx <<= 1;
|
||||
while (x != x2) {
|
||||
surfacePixelSet(x, y, color);
|
||||
if (balance >= 0) {
|
||||
y += incY;
|
||||
balance -= dx;
|
||||
}
|
||||
balance += dy;
|
||||
x += incX;
|
||||
}
|
||||
surfacePixelSet(x, y, color);
|
||||
} else {
|
||||
dx <<= 1;
|
||||
balance = dx - dy;
|
||||
dy <<= 1;
|
||||
while (y != y2) {
|
||||
surfacePixelSet(x, y, color);
|
||||
if (balance >= 0) {
|
||||
x += incX;
|
||||
balance -= dy;
|
||||
}
|
||||
balance += dx;
|
||||
y += incY;
|
||||
}
|
||||
surfacePixelSet(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void surfaceLineH(int16_t x1, int16_t x2, int16_t y, ColorT c) {
|
||||
int16_t i;
|
||||
int16_t t;
|
||||
|
|
|
@ -52,9 +52,11 @@ ColorT surfaceColorMake(uint8_t r, uint8_t g, uint8_t b);
|
|||
SurfaceT *surfaceCreate(int16_t width, int16_t height);
|
||||
void surfaceBox(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c);
|
||||
void surfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c);
|
||||
void surfaceDestroy(SurfaceT *surface);
|
||||
void surfaceBoxHighlight(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT highlight, ColorT shadow);
|
||||
void surfaceDestroy(SurfaceT **surface);
|
||||
SurfaceT *surfaceGet(void);
|
||||
int16_t surfaceHeightGet(SurfaceT *surface);
|
||||
void surfaceLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT color);
|
||||
void surfaceLineH(int16_t x1, int16_t x2, int16_t y, ColorT c);
|
||||
void surfaceLineV(int16_t x, int16_t y1, int16_t y2, ColorT c);
|
||||
void surfaceSet(SurfaceT *surface);
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
#include "font.h"
|
||||
|
||||
|
||||
#define USE_CACHING
|
||||
|
||||
|
||||
uint8_t __MAGIC_WINDOW = 0;
|
||||
|
||||
static WindowT **_windowList = NULL;
|
||||
static WindowT *_windowTop = NULL;
|
||||
|
||||
|
||||
WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title, uint8_t flags, ...) {
|
||||
|
@ -22,8 +26,12 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl
|
|||
win->maximize.x = win->maximize.y = win->maximize.x2 = win->maximize.y2 = 0;
|
||||
win->bounds.x = win->bounds.y = win->bounds.x2 = win->bounds.y2 = 0;
|
||||
|
||||
win->cached = NULL;
|
||||
|
||||
arrput(_windowList, win);
|
||||
|
||||
windowFocusSet(win);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
|
@ -32,169 +40,288 @@ void windowDestroy(struct WidgetS *widget, ...) {
|
|||
uint16_t i;
|
||||
WindowT *window = (WindowT *)widget;
|
||||
|
||||
// Find the window to delete.
|
||||
for (i=0; i<arrlen(_windowList); i++) {
|
||||
if (window == _windowList[i]) {
|
||||
// Was it the focused window?
|
||||
if (_windowList[i] == _windowTop) {
|
||||
// Find new topmost window on next call to focus.
|
||||
_windowTop = NULL;
|
||||
}
|
||||
// Free the title.
|
||||
if (_windowList[i]->title) DEL(_windowList[i]->title);
|
||||
// Free cached surface.
|
||||
if (_windowList[i]->cached) surfaceDestroy(&_windowList[i]->cached);
|
||||
// Delete the window.
|
||||
DEL(_windowList[i]);
|
||||
// Remove it from window list.
|
||||
arrdel(_windowList, i);
|
||||
// Fixup focus.
|
||||
windowFocusSet(NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void windowPaint(struct WidgetS *widget, ...) {
|
||||
WindowT *w = (WindowT *)widget;
|
||||
uint16_t x1 = w->base.r.x;
|
||||
uint16_t y1 = w->base.r.y;
|
||||
uint16_t x2 = w->base.r.x + w->base.r.w - 1;
|
||||
uint16_t y2 = w->base.r.y + w->base.r.h - 1;
|
||||
uint16_t tx1;
|
||||
uint16_t ty1;
|
||||
uint16_t tx2;
|
||||
uint16_t ty2;
|
||||
uint16_t minimizeOffset = 0;
|
||||
ColorT titleBackgroundColor = GUI_DARKGRAY;
|
||||
void windowFocusSet(WindowT *win) {
|
||||
int16_t i;
|
||||
|
||||
// Fake Window contents.
|
||||
surfaceBoxFilled(x1, y1, x2, y2, GUI_BLACK);
|
||||
|
||||
// If we need a titlebar, it's 18px.
|
||||
if (w->title || w->flags & WIN_CLOSE || w->flags & WIN_MAXIMIZE || w->flags & WIN_MINIMIZE) {
|
||||
|
||||
// Draw title bar background.
|
||||
y1 -= 18;
|
||||
surfaceBoxFilled(x1, y1, x2, y1 + 17, titleBackgroundColor);
|
||||
|
||||
// Close box?
|
||||
if (w->flags & WIN_CLOSE) {
|
||||
// 26px wide, 18 tall including highlight and shadow.
|
||||
w->close.x = x1 + 1;
|
||||
w->close.y = y1 + 1;
|
||||
w->close.x2 = w->close.x + 24;
|
||||
w->close.y2 = w->close.y + 15;
|
||||
surfaceBoxFilled(w->close.x + 1, w->close.y + 1, w->close.x2 - 1, w->close.y2 - 1, GUI_LIGHTGRAY);
|
||||
surfaceLineH(w->close.x, w->close.x2, w->close.y, GUI_WHITE);
|
||||
surfaceLineV(w->close.x, w->close.y, w->close.y2, GUI_WHITE);
|
||||
// Button is 8px down, 3px tall, and 4px in on both sides.
|
||||
tx1 = w->close.x + 4;
|
||||
ty1 = w->close.y + 7;
|
||||
tx2 = w->close.x2 - 4;
|
||||
ty2 = w->close.y + 9;
|
||||
surfaceLineH(tx1, tx2, ty1, GUI_WHITE);
|
||||
surfacePixelSet(tx1, ty1 + 1, GUI_WHITE);
|
||||
surfaceLineH(tx1, tx2, ty2, GUI_BLACK);
|
||||
surfaceLineV(tx2, ty1, ty2, GUI_BLACK);
|
||||
// Set titlebar area.
|
||||
w->titlebar.x = w->close.x2 + 2;
|
||||
// Do we have a focused window at the moment?
|
||||
if (!_windowTop || !win) {
|
||||
// If there's a list of windows, use the topmost.
|
||||
if (arrlen(_windowList) > 0) {
|
||||
_windowTop = _windowList[arrlen(_windowList) - 1];
|
||||
guiWidgetDirtySet(W(_windowTop), 1);
|
||||
} else {
|
||||
// No close box - set titlebar area.
|
||||
w->titlebar.x = x1;
|
||||
// If no list, set it to NULL.
|
||||
_windowTop = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Did they even pass in a window? If not, we're just intended to fixup _windowTop.
|
||||
if (!win) return;
|
||||
|
||||
// Are we already the topmost window?
|
||||
if (win == _windowTop) return;
|
||||
|
||||
// Mark old focus and new focus dirty to repaint title bar.
|
||||
guiWidgetDirtySet(W(win), 1);
|
||||
guiWidgetDirtySet(W(_windowTop), 1);
|
||||
|
||||
// Change who has focus.
|
||||
_windowTop = win;
|
||||
|
||||
// Reorder window list.
|
||||
i = arrlen(_windowList) - 2;
|
||||
if (i >= 0) {
|
||||
for (; i>=0; i--) {
|
||||
if (_windowList[i] == win) {
|
||||
arrdel(_windowList, i);
|
||||
arrput(_windowList, win);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void windowMoveTo(WindowT *w, uint16_t x, uint16_t y) {
|
||||
int16_t dx = x - w->base.r.x;
|
||||
int16_t dy = y - w->base.r.y;
|
||||
|
||||
// This is all because we draw the window at 0,0 in order to cache it.
|
||||
// To keep the coordinates correct, we have to adjust them all when
|
||||
// the window is moved.
|
||||
|
||||
if (w->title || w->flags & WIN_CLOSE || w->flags & WIN_MAXIMIZE || w->flags & WIN_MINIMIZE) {
|
||||
if (w->flags & WIN_CLOSE) {
|
||||
w->close.x += dx;
|
||||
w->close.y += dy;
|
||||
w->close.x2 += dx;
|
||||
w->close.y2 += dy;
|
||||
}
|
||||
w->titlebar.y = y1;
|
||||
w->titlebar.x2 = x2;
|
||||
w->titlebar.y2 = y1 + 17;
|
||||
|
||||
// Maximize box?
|
||||
if (w->flags & WIN_MAXIMIZE) {
|
||||
// 26px wide, 18 tall including highlight and shadow.
|
||||
w->maximize.y = y1 + 1;
|
||||
w->maximize.x2 = x2 - 1;
|
||||
w->maximize.x = w->maximize.x2 - 24;
|
||||
w->maximize.y2 = w->maximize.y + 15;
|
||||
surfaceBoxFilled(w->maximize.x + 1, w->maximize.y + 1, w->maximize.x2 - 1, w->maximize.y2 - 1, GUI_LIGHTGRAY);
|
||||
surfaceLineH(w->maximize.x, w->maximize.x2, w->maximize.y, GUI_WHITE);
|
||||
surfaceLineV(w->maximize.x, w->maximize.y, w->maximize.y2, GUI_WHITE);
|
||||
// Button is 3px down, and 4px in on both sides.
|
||||
tx1 = w->maximize.x + 4;
|
||||
ty1 = w->maximize.y + 4;
|
||||
tx2 = w->maximize.x2 - 3;
|
||||
ty2 = w->maximize.y + 12;
|
||||
surfaceLineH(tx1, tx2, ty1, GUI_WHITE);
|
||||
surfaceLineV(tx1, ty1, ty2, GUI_WHITE);
|
||||
surfaceLineH(tx1, tx2, ty2, GUI_BLACK);
|
||||
surfaceLineV(tx2, ty1, ty2, GUI_BLACK);
|
||||
// Move minimize button over.
|
||||
minimizeOffset = 26;
|
||||
// Set titlebar area.
|
||||
w->titlebar.x2 -= 26;
|
||||
w->maximize.x += dx;
|
||||
w->maximize.y += dy;
|
||||
w->maximize.x2 += dx;
|
||||
w->maximize.y2 += dy;
|
||||
}
|
||||
|
||||
// Minimize box?
|
||||
if (w->flags & WIN_MINIMIZE) {
|
||||
// 26px wide, 18 tall including highlight and shadow.
|
||||
w->minimize.y = y1 + 1;
|
||||
w->minimize.x2 = x2 - 1 - minimizeOffset;
|
||||
w->minimize.x = w->minimize.x2 - 24;
|
||||
w->minimize.y2 = w->minimize.y + 15;
|
||||
surfaceBoxFilled(w->minimize.x + 1, w->minimize.y + 1, w->minimize.x2 - 1, w->minimize.y2 - 1, GUI_LIGHTGRAY);
|
||||
surfaceLineH(w->minimize.x, w->minimize.x2, w->minimize.y, GUI_WHITE);
|
||||
surfaceLineV(w->minimize.x, w->minimize.y, w->minimize.y2, GUI_WHITE);
|
||||
tx1 = w->minimize.x + 10;
|
||||
ty1 = w->minimize.y + 6;
|
||||
tx2 = w->minimize.x2 - 8;
|
||||
ty2 = w->minimize.y + 9;
|
||||
surfaceLineH(tx1, tx2, ty1, GUI_WHITE);
|
||||
surfaceLineV(tx1, ty1, ty2, GUI_WHITE);
|
||||
surfaceLineH(tx1, tx2, ty2, GUI_BLACK);
|
||||
surfaceLineV(tx2, ty1, ty2, GUI_BLACK);
|
||||
// Set titlebar area.
|
||||
w->titlebar.x2 -= 26;
|
||||
w->minimize.x += dx;
|
||||
w->minimize.y += dy;
|
||||
w->minimize.x2 += dx;
|
||||
w->minimize.y2 += dy;
|
||||
}
|
||||
|
||||
// Title font area is 12px high.
|
||||
surfaceLineH(w->titlebar.x, w->titlebar.x2 - 1, w->titlebar.y, GUI_WHITE);
|
||||
surfaceLineV(w->titlebar.x, w->titlebar.y, w->titlebar.y2 - 1, GUI_WHITE);
|
||||
if (w->title) {
|
||||
ty1 = w->titlebar.y + 2;
|
||||
tx1 = w->titlebar.x + 2 + (w->titlebar.x2 - w->titlebar.x - 4) * 0.5 - ((strlen(w->title) * 8) * 0.5);
|
||||
fontRender(__guiFontVGA8x14, w->title, GUI_WHITE, titleBackgroundColor, tx1, ty1);
|
||||
w->titlebar.x += dx;
|
||||
w->titlebar.y += dy;
|
||||
w->titlebar.x2 += dx;
|
||||
w->titlebar.y2 += dy;
|
||||
}
|
||||
|
||||
w->bounds.x += dx;
|
||||
w->bounds.y += dy;
|
||||
w->bounds.x2 += dx;
|
||||
w->bounds.y2 += dy;
|
||||
|
||||
w->base.r.x = x;
|
||||
w->base.r.y = y;
|
||||
}
|
||||
|
||||
|
||||
void windowPaint(struct WidgetS *widget, ...) {
|
||||
int16_t i;
|
||||
int16_t x1;
|
||||
int16_t y1;
|
||||
int16_t x2;
|
||||
int16_t y2;
|
||||
int16_t tx1;
|
||||
int16_t tx2;
|
||||
int16_t ty2;
|
||||
int16_t originalX;
|
||||
int16_t originalY;
|
||||
WindowT *w;
|
||||
SurfaceT *target;
|
||||
ColorT titleBackgroundColor;
|
||||
ColorT widgetColor;
|
||||
|
||||
target = surfaceGet();
|
||||
w = (WindowT *)widget;
|
||||
|
||||
#ifdef USE_CACHING
|
||||
// Do we need redrawn?
|
||||
if (guiWidgetDirtyGet(widget)) {
|
||||
guiWidgetDirtySet(widget, 0);
|
||||
|
||||
// Move the window to 0,0 to cache to it's own surface.
|
||||
originalX = w->base.r.x;
|
||||
originalY = w->base.r.y;
|
||||
w->base.r.x = 0;
|
||||
w->base.r.y = 0;
|
||||
|
||||
// Do we have a cached surface already?
|
||||
if (w->cached) {
|
||||
// Did the size change?
|
||||
if ((surfaceWidthGet(w->cached) != w->base.r.w) || (surfaceHeightGet(w->cached) != w->base.r.h)) {
|
||||
// Yeah. We will recreate it.
|
||||
surfaceDestroy(&w->cached);
|
||||
}
|
||||
}
|
||||
// Do we need to create a surface?
|
||||
if (!w->cached) {
|
||||
w->cached = surfaceCreate(w->base.r.w, w->base.r.h);
|
||||
}
|
||||
|
||||
// Draw into cache.
|
||||
surfaceSet(w->cached);
|
||||
#endif
|
||||
|
||||
// Determine some colors.
|
||||
titleBackgroundColor = (w == _windowTop) ? GUI_DARKGRAY : GUI_LIGHTGRAY;
|
||||
widgetColor = (w == _windowTop) ? GUI_LIGHTGRAY : GUI_DARKGRAY;
|
||||
|
||||
// Get ready!
|
||||
x1 = w->base.r.x;
|
||||
y1 = w->base.r.y;
|
||||
x2 = w->base.r.x + w->base.r.w - 1;
|
||||
y2 = w->base.r.y + w->base.r.h - 1;
|
||||
|
||||
// Draw border.
|
||||
surfaceBoxHighlight(x1, y1, x2, y2, GUI_WHITE, GUI_BLACK);
|
||||
x1++; y1++; x2--; y2--;
|
||||
for (i=0; i<3; i++) {
|
||||
surfaceBox(x1, y1, x2, y2, GUI_LIGHTGRAY);
|
||||
x1++; y1++; x2--; y2--;
|
||||
}
|
||||
surfaceBoxHighlight(x1, y1, x2, y2, GUI_BLACK, GUI_WHITE);
|
||||
x1++; y1++; x2--; y2--;
|
||||
|
||||
// Do we need a titlebar?
|
||||
if (w->title || w->flags & WIN_CLOSE || w->flags & WIN_MAXIMIZE || w->flags & WIN_MINIMIZE) {
|
||||
tx1 = x1;
|
||||
tx2 = x2;
|
||||
ty2 = y1 + 20;
|
||||
|
||||
// Close box?
|
||||
if (w->flags & WIN_CLOSE) {
|
||||
tx1 += 20;
|
||||
w->close.x = x1;
|
||||
w->close.y = y1;
|
||||
w->close.x2 = tx1 - 1;
|
||||
w->close.y2 = ty2 - 1;
|
||||
surfaceBoxFilled(w->close.x + 1, w->close.y + 1, w->close.x2 - 1, w->close.y2 - 1, titleBackgroundColor);
|
||||
surfaceBoxHighlight(w->close.x + 3, w->close.y + 8, w->close.x2 - 3, w->close.y2 - 8, GUI_WHITE, widgetColor);
|
||||
surfaceBoxHighlight(w->close.x, w->close.y, w->close.x2, w->close.y2, GUI_WHITE, GUI_BLACK);
|
||||
} else {
|
||||
w->close.x = w->close.y = w->close.x2 = w->close.y2 = 0;
|
||||
}
|
||||
|
||||
// Maximize box?
|
||||
if (w->flags & WIN_MAXIMIZE) {
|
||||
tx2 -= 20;
|
||||
w->maximize.x = tx2 + 1;
|
||||
w->maximize.y = y1;
|
||||
w->maximize.x2 = tx2 + 20;
|
||||
w->maximize.y2 = ty2 - 1;
|
||||
surfaceBoxFilled(w->maximize.x + 1, w->maximize.y + 1, w->maximize.x2 - 1, w->maximize.y2 - 1, titleBackgroundColor);
|
||||
surfaceLine(w->maximize.x + 4, w->maximize.y + 10, w->maximize.x + 10, w->maximize.y + 4, GUI_WHITE);
|
||||
surfaceLine(w->maximize.x + 4, w->maximize.y + 10, w->maximize.x + 10, w->maximize.y2 - 3, GUI_WHITE);
|
||||
surfaceLine(w->maximize.x2 - 3, w->maximize.y + 10, w->maximize.x2 - 9, w->maximize.y + 4, widgetColor);
|
||||
surfaceLine(w->maximize.x2 - 3, w->maximize.y + 10, w->maximize.x2 - 9, w->maximize.y2 - 3, widgetColor);
|
||||
surfaceBoxHighlight(w->maximize.x, w->maximize.y, w->maximize.x2, w->maximize.y2, GUI_WHITE, GUI_BLACK);
|
||||
} else {
|
||||
w->maximize.x = w->maximize.y = w->maximize.x2 = w->maximize.y2 = 0;
|
||||
}
|
||||
|
||||
// Minimize box?
|
||||
if (w->flags & WIN_MINIMIZE) {
|
||||
tx2 -= 20;
|
||||
w->minimize.x = tx2 + 1;
|
||||
w->minimize.y = y1;
|
||||
w->minimize.x2 = tx2 + 20;
|
||||
w->minimize.y2 = ty2 - 1;
|
||||
surfaceBoxFilled(w->minimize.x + 1, w->minimize.y + 1, w->minimize.x2 - 1, w->minimize.y2 - 1, titleBackgroundColor);
|
||||
surfaceBoxHighlight(w->minimize.x + 7, w->minimize.y + 7, w->minimize.x2 - 7, w->minimize.y2 - 7, GUI_WHITE, widgetColor);
|
||||
surfaceBoxHighlight(w->minimize.x, w->minimize.y, w->minimize.x2, w->minimize.y2, GUI_WHITE, GUI_BLACK);
|
||||
} else {
|
||||
w->minimize.x = w->minimize.y = w->minimize.x2 = w->maximize.y2 = 0;
|
||||
}
|
||||
|
||||
// Draw titlebar background.
|
||||
w->titlebar.x = tx1;
|
||||
w->titlebar.y = y1;
|
||||
w->titlebar.x2 = tx2;
|
||||
w->titlebar.y2 = ty2 - 1;
|
||||
surfaceBoxFilled(w->titlebar.x + 1, w->titlebar.y + 1, w->titlebar.x2 - 1, w->titlebar.y2 - 1, titleBackgroundColor);
|
||||
if (w->title) {
|
||||
fontSet(__guiFontVGA8x16);
|
||||
fontColorSet(GUI_WHITE, titleBackgroundColor);
|
||||
fontRender(w->title, w->titlebar.x + 12, w->titlebar.y + 2);
|
||||
}
|
||||
surfaceBoxHighlight(w->titlebar.x, w->titlebar.y, w->titlebar.x2, w->titlebar.y2, GUI_WHITE, GUI_BLACK);
|
||||
} else {
|
||||
w->close.x = w->close.y = w->close.x2 = w->close.y2 = 0;
|
||||
w->maximize.x = w->maximize.y = w->maximize.x2 = w->maximize.y2 = 0;
|
||||
w->minimize.x = w->minimize.y = w->minimize.x2 = w->maximize.y2 = 0;
|
||||
w->titlebar.x = w->titlebar.y = w->titlebar.x2 = w->titlebar.y2 = 0;
|
||||
}
|
||||
|
||||
// Find content area.
|
||||
y1 += 20;
|
||||
w->bounds.x = x1;
|
||||
w->bounds.y = y1;
|
||||
w->bounds.x2 = x2;
|
||||
w->bounds.y2 = y2;
|
||||
|
||||
// Resize handle.
|
||||
if (w->flags & WIN_RESIZE) {
|
||||
x1 = w->base.r.x + w->base.r.w - 2;
|
||||
x2 = x1 - 3;
|
||||
y1 = w->base.r.y + w->base.r.h - 21;
|
||||
surfaceLineH(x1, x2, y1, GUI_BLACK);
|
||||
surfaceLineH(x1, x2, y1 + 1, GUI_WHITE);
|
||||
x1 = w->base.r.x + w->base.r.w - 21;
|
||||
y1 = w->base.r.y + w->base.r.h - 2;
|
||||
y2 = y1 - 3;
|
||||
surfaceLineV(x1, y1, y2, GUI_BLACK);
|
||||
surfaceLineV(x1 + 1, y1, y2, GUI_WHITE);
|
||||
}
|
||||
|
||||
// Fake Window contents.
|
||||
surfaceBoxFilled(w->bounds.x, w->bounds.y, w->bounds.x2, w->bounds.y2, GUI_BLACK);
|
||||
|
||||
#ifdef USE_CACHING
|
||||
// Fixup all the widget coordinates.
|
||||
windowMoveTo(w, originalX, originalY);
|
||||
}
|
||||
|
||||
// Innermost shadow frame. 1px wide.
|
||||
x1--;
|
||||
y1--;
|
||||
x2++;
|
||||
y2++;
|
||||
surfaceLineH(x1, x2, y2, GUI_WHITE);
|
||||
surfaceLineV(x2, y1, y2, GUI_WHITE);
|
||||
surfaceLineH(x1, x2, y1, GUI_DARKGRAY);
|
||||
surfaceLineV(x1, y1, y2, GUI_DARKGRAY);
|
||||
|
||||
// Frame Border. 4px wide.
|
||||
x1 -= 4;
|
||||
y1 -= 4;
|
||||
x2 += 4;
|
||||
y2 += 4;
|
||||
surfaceBoxFilled(x1, y1, x1 + 3, y2, GUI_LIGHTGRAY);
|
||||
surfaceBoxFilled(x2, y1, x2 - 3, y2, GUI_LIGHTGRAY);
|
||||
surfaceBoxFilled(x1, y1, x2, y1 + 3, GUI_LIGHTGRAY);
|
||||
surfaceBoxFilled(x1, y2, x2, y2 - 3, GUI_LIGHTGRAY);
|
||||
|
||||
// Resize handle.
|
||||
if (w->flags & WIN_RESIZE) {
|
||||
ty1 = y2 - 15 - 3;
|
||||
tx1 = x2 - 15 - 3;
|
||||
surfaceLineH(x2, x2 - 3, ty1, GUI_DARKGRAY);
|
||||
surfaceLineH(x2, x2 - 3, ty1 + 1, GUI_WHITE);
|
||||
surfaceLineV(tx1, y2, y2 - 3, GUI_DARKGRAY);
|
||||
surfaceLineV(tx1 + 1, y2, y2 - 3, GUI_WHITE);
|
||||
}
|
||||
|
||||
// Outermost shadow frame. 1px wide.
|
||||
x1--;
|
||||
y1--;
|
||||
x2++;
|
||||
y2++;
|
||||
surfaceLineH(x1, x2, y1, GUI_WHITE);
|
||||
surfaceLineV(x1, y1, y2, GUI_WHITE);
|
||||
surfaceLineH(x1, x2, y2, GUI_DARKGRAY);
|
||||
surfaceLineV(x2, y1, y2, GUI_DARKGRAY);
|
||||
w->bounds.x = x1;
|
||||
w->bounds.x2 = x2;
|
||||
w->bounds.y = y1;
|
||||
w->bounds.y2 = y2;
|
||||
// By now we have a valid cached window. Blit it.
|
||||
surfaceBlit(target, w->base.r.x, w->base.r.y, w->cached);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -215,6 +342,8 @@ RegisterT *windowRegister(uint8_t magic) {
|
|||
|
||||
void wmPaint(EventT *event) {
|
||||
int16_t i;
|
||||
int16_t x2;
|
||||
int16_t y2;
|
||||
WidgetT *widget;
|
||||
WindowT *win;
|
||||
static uint8_t dragging = 0;
|
||||
|
@ -233,25 +362,29 @@ void wmPaint(EventT *event) {
|
|||
// Get top window.
|
||||
win = _windowList[arrlen(_windowList) - 1];
|
||||
|
||||
// Get right/bottom of window.
|
||||
x2 = win->base.r.x + win->base.r.w - 1;
|
||||
y2 = win->base.r.y + win->base.r.h - 1;
|
||||
|
||||
// Wrap left button processing with a 'for' so we can 'break' out of it.
|
||||
for (;;) {
|
||||
// Is the left mouse button down?
|
||||
if (event->buttons & BUTTON_LEFT) {
|
||||
|
||||
// DEBUG - draw active regions. ***TODO*** No resize grabber here.
|
||||
surfaceBox(win->bounds.x, win->bounds.y, win->bounds.x2, win->bounds.y2, GUI_YELLOW);
|
||||
surfaceBox(win->base.r.x, win->base.r.y, win->base.r.x + win->base.r.w - 1, win->base.r.y + win->base.r.h - 1, GUI_YELLOW);
|
||||
surfaceBox(win->close.x, win->close.y, win->close.x2, win->close.y2, GUI_RED);
|
||||
surfaceBox(win->titlebar.x, win->titlebar.y, win->titlebar.x2, win->titlebar.y2, GUI_RED);
|
||||
surfaceBox(win->minimize.x, win->minimize.y, win->minimize.x2, win->minimize.y2, GUI_RED);
|
||||
surfaceSet(__guiBackBuffer);
|
||||
surfaceBox(win->base.r.x, win->base.r.y, x2, y2, GUI_YELLOW);
|
||||
surfaceBox(win->bounds.x, win->bounds.y, win->bounds.x2, win->bounds.y2, GUI_CYAN);
|
||||
surfaceBox(win->close.x, win->close.y, win->close.x2, win->close.y2, GUI_LIGHTBLUE);
|
||||
surfaceBox(win->titlebar.x, win->titlebar.y, win->titlebar.x2, win->titlebar.y2, GUI_LIGHTCYAN);
|
||||
surfaceBox(win->minimize.x, win->minimize.y, win->minimize.x2, win->minimize.y2, GUI_LIGHTGREEN);
|
||||
surfaceBox(win->maximize.x, win->maximize.y, win->maximize.x2, win->maximize.y2, GUI_RED);
|
||||
|
||||
// Are we currently dragging?
|
||||
if (dragging) {
|
||||
|
||||
// Move window to new mouse location.
|
||||
win->base.r.x = event->x - dragOffset.x;
|
||||
win->base.r.y = event->y - dragOffset.y;
|
||||
windowMoveTo(win, event->x - dragOffset.x, event->y - dragOffset.y);
|
||||
break;
|
||||
|
||||
} else { // Dragging.
|
||||
|
@ -260,11 +393,10 @@ void wmPaint(EventT *event) {
|
|||
if (event->flags & EVENT_FLAG_LEFT_DOWN) {
|
||||
|
||||
// Are we on the topmost window?
|
||||
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
||||
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
|
||||
|
||||
//***TODO*** Are we inside the window content? Most likely, check first.
|
||||
if (event->x <= (win->base.r.x + win->base.r.w - 1) && event->x >= win->base.r.x &&
|
||||
event->y <= (win->base.r.y + win->base.r.h - 1) && event->y >= win->base.r.y) {
|
||||
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
||||
//***TODO*** Send to window for processing.
|
||||
}
|
||||
|
||||
|
@ -288,10 +420,13 @@ void wmPaint(EventT *event) {
|
|||
if (i >= 0) {
|
||||
for (; i>=0; i--) {
|
||||
win = _windowList[i];
|
||||
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
||||
// Get right/bottom of window.
|
||||
x2 = win->base.r.x + win->base.r.w - 1;
|
||||
y2 = win->base.r.y + win->base.r.h - 1;
|
||||
// Inside this window?
|
||||
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
|
||||
// Bring this window forward.
|
||||
arrdel(_windowList, i);
|
||||
arrput(_windowList, win);
|
||||
windowFocusSet(win);
|
||||
// If we happened to be in the title bar, go ahead and start dragging.
|
||||
if (event->x <= win->titlebar.x2 && event->x >= win->titlebar.x && event->y <= win->titlebar.y2 && event->y >= win->titlebar.y) {
|
||||
dragging = 1;
|
||||
|
|
|
@ -13,22 +13,25 @@
|
|||
|
||||
|
||||
typedef struct WindowS {
|
||||
WidgetT base;
|
||||
char *title;
|
||||
uint8_t flags;
|
||||
RectT close;
|
||||
RectT titlebar;
|
||||
RectT minimize;
|
||||
RectT maximize;
|
||||
RectT bounds;
|
||||
WidgetT base; // Required by all widgets.
|
||||
char *title; // Title of window.
|
||||
uint8_t flags; // Window flags (see defines above).
|
||||
RectT close; // Coordinates of close box, if any.
|
||||
RectT titlebar; // Coordinates of title bar, if any.
|
||||
RectT minimize; // Coordinates of minimize box, if any.
|
||||
RectT maximize; // Coordinates of maximize box, if any.
|
||||
RectT bounds; // Inside edge of window frame.
|
||||
SurfaceT *cached; // Once rendered, keep a cached copy for faster redrawing.
|
||||
} WindowT;
|
||||
|
||||
|
||||
extern uint8_t __MAGIC_WINDOW;
|
||||
extern uint8_t __MAGIC_WINDOW; // Magic ID assigned to us from the GUI.
|
||||
|
||||
|
||||
WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title, uint8_t flags, ...);
|
||||
void windowDestroy(struct WidgetS *widget, ...);
|
||||
void windowFocusSet(WindowT *win);
|
||||
void windowMoveTo(WindowT *win, uint16_t x, uint16_t y);
|
||||
void windowPaint(struct WidgetS *widget, ...);
|
||||
RegisterT *windowRegister(uint8_t magic);
|
||||
|
||||
|
|
|
@ -25,3 +25,61 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int tui(int argc, char *argv[]) {
|
||||
EventT event = { 0 };
|
||||
uint16_t x = 5;
|
||||
uint16_t y = 5;
|
||||
uint16_t tx;
|
||||
uint16_t ty;
|
||||
FontT *vga8x16 = NULL;
|
||||
FontT *vga8x8 = NULL;
|
||||
|
||||
(void)argc;
|
||||
|
||||
memoryStartup(argv[0]);
|
||||
logOpenByHandle(memoryLogHandleGet());
|
||||
|
||||
if (guiStartup(800, 600, 32) == SUCCESS) {
|
||||
|
||||
vga8x8 = fontLoad("vga8x8.dat");
|
||||
vga8x16 = fontLoad("vga8x16.dat");
|
||||
|
||||
// Run until keypress.
|
||||
while (1) {
|
||||
// Paint desktop.
|
||||
surfaceSet(__guiBackBuffer);
|
||||
surfaceClear(GUI_CYAN);
|
||||
|
||||
// Paint GUI.
|
||||
ty = y;
|
||||
fontSet(vga8x16);
|
||||
fontRender("\x1\xf\x2\x8 Title Bar _ \xfe X ", C(x), C(ty++)); ty++;
|
||||
fontSet(vga8x8);
|
||||
fontRender("\x2\x7\xda\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xbf\x1e", C(x), C(ty++));
|
||||
for (tx=0; tx<10; tx++) fontRender("\xb3 \xb3\xb0", C(x), C(ty++));
|
||||
fontRender("\xc0\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xd9\x1f", C(x), C(ty++));
|
||||
fontRender("\x11\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x10\xfe", C(x), C(ty++));
|
||||
|
||||
// Copy to screen.
|
||||
videoBlit(0, 0, __guiBackBuffer);
|
||||
|
||||
// Check for exit.
|
||||
platformEventGet(&event);
|
||||
if (event.flags & EVENT_FLAG_KEYPRESS && event.key == KEY_ESC) break;
|
||||
}
|
||||
|
||||
fontUnload(&vga8x16);
|
||||
fontUnload(&vga8x8);
|
||||
|
||||
guiShutdown();
|
||||
}
|
||||
|
||||
logClose();
|
||||
memoryShutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -187,18 +187,22 @@ void platformEventGet(EventT *event) {
|
|||
int16_t meta = bioskey(KEYBOARD_META_EXTENDED);
|
||||
int16_t key = 0;
|
||||
union REGS regs;
|
||||
static int32_t lastX = 0;
|
||||
static int32_t lastY = 0;
|
||||
|
||||
// Read mouse motion.
|
||||
regs.x.ax = MOUSE_GETMOTION;
|
||||
int86(MOUSE_INT, ®s, ®s);
|
||||
dx = regs.x.cx; // Temporary assignment changes values to signed.
|
||||
dy = regs.x.dx; // Don't skip this step. :-)
|
||||
x = event->x + dx;
|
||||
y = event->y + dy;
|
||||
x = lastX + dx;
|
||||
y = lastY + dy;
|
||||
if (x < 0) x = 0;
|
||||
if (x > w - 1) x = w - 1;
|
||||
if (y < 0) y = 0;
|
||||
if (y > h - 1) y = h - 1;
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
event->x = x;
|
||||
event->y = y;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifdef BACKEND_SDL2
|
||||
|
||||
|
||||
#include "sdl2.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
|
@ -104,7 +104,7 @@ void platformShutdown(void) {
|
|||
}
|
||||
|
||||
|
||||
void platformStartup(int16_t width, int16_t height, int16_t depth) {
|
||||
uint8_t platformStartup(int16_t width, int16_t height, int16_t depth) {
|
||||
SDL_PixelFormatEnum pixelFormat;
|
||||
|
||||
(void)depth;
|
||||
|
@ -159,6 +159,8 @@ void platformStartup(int16_t width, int16_t height, int16_t depth) {
|
|||
_height = height;
|
||||
|
||||
surfaceStartup(depth);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue