diff --git a/client/src/gui/gui.c b/client/src/gui/gui.c index 828ccb9..bcd6e56 100644 --- a/client/src/gui/gui.c +++ b/client/src/gui/gui.c @@ -120,8 +120,7 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) { } _mousePointer = imageLoad("mouse.png"); - surfaceSet(_mousePointer); - _mouseTransparency = surfacePixelGet(_mousePointer, surfaceWidthGet() - 2, 0); // Find our transparency color. + _mouseTransparency = surfacePixelGet(_mousePointer, surfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color. __guiFontVGA8x8 = fontLoad("vga8x8.dat"); __guiFontVGA8x14 = fontLoad("vga8x14.dat"); diff --git a/client/src/gui/surface.c b/client/src/gui/surface.c index 171f017..cdb5b35 100644 --- a/client/src/gui/surface.c +++ b/client/src/gui/surface.c @@ -203,8 +203,8 @@ SurfaceT *surfaceGet(void) { } -int16_t surfaceHeightGet(void) { - return __surfaceActive->height; +int16_t surfaceHeightGet(SurfaceT *surface) { + return surface->height; } @@ -405,8 +405,8 @@ void surfaceStartup(uint8_t bits) { } -int16_t surfaceWidthGet() { - return __surfaceActive->width; +int16_t surfaceWidthGet(SurfaceT *surface) { + return surface->width; } diff --git a/client/src/gui/surface.h b/client/src/gui/surface.h index bd41c71..80ba64a 100644 --- a/client/src/gui/surface.h +++ b/client/src/gui/surface.h @@ -55,14 +55,14 @@ void surfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, Color 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(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); void surfaceShutdown(void); void surfaceStartup(uint8_t bits); -int16_t surfaceWidthGet(void); +int16_t surfaceWidthGet(SurfaceT *surface); #endif // SURFACE_H diff --git a/client/src/gui/wmwindow.c b/client/src/gui/wmwindow.c index 2be5cf5..8147def 100644 --- a/client/src/gui/wmwindow.c +++ b/client/src/gui/wmwindow.c @@ -3,11 +3,15 @@ #include "font.h" +#define ICON_SIZE 32 + + uint8_t __MAGIC_WINDOW = 0; static WindowT **_windowList = NULL; static WindowT *_windowTop = NULL; +static int16_t _iconCount = 0; static void windowCache(WindowT *w); @@ -28,7 +32,7 @@ static void windowCache(WindowT *w) { ColorT widgetColor; SurfaceT *target = surfaceGet(); - // Move the window to 0,0 to cache to it's own surface. + // Move the window to 0,0 to draw it into it's own surface. originalX = w->base.r.x; originalY = w->base.r.y; w->base.r.x = 0; @@ -37,8 +41,7 @@ static void windowCache(WindowT *w) { // Do we have a cached surface already? if (w->cached) { // Did the size change? - surfaceSet(w->cached); - if ((surfaceWidthGet() != w->base.r.w) || (surfaceHeightGet() != w->base.r.h)) { + if ((surfaceWidthGet(w->cached) != w->base.r.w) || (surfaceHeightGet(w->cached) != w->base.r.h)) { // Yeah. We will recreate it. surfaceDestroy(&w->cached); } @@ -196,7 +199,7 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl // If the window is resizable, we need to get two more arguments for the content size. if (win->flags & WIN_RESIZE) { va_start(args, flags); - width = va_arg(args, int); + width = va_arg(args, int); height = va_arg(args, int); va_end(args); } else { @@ -206,13 +209,20 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl height = win->bounds.y2 - win->bounds.y; guiWidgetDirtySet(W(win), 1); } + // Create content surface and clear it. win->content = surfaceCreate(width, height); surfaceSet(win->content); surfaceClear(GUI_LIGHTGRAY); surfaceSet(t); + // Do we need scrollbars? + if (width > win->bounds.x2 - win->bounds.x) win->flags |= WIN_SCROLL_H; + if (height > win->bounds.y2 - win->bounds.y) win->flags |= WIN_SCROLL_V; + + // Add to window list. arrput(_windowList, win); + // Focus us. windowFocusSet(win); return win; @@ -339,6 +349,12 @@ void windowMoveTo(WindowT *w, uint16_t x, uint16_t y) { void windowPaint(struct WidgetS *widget, ...) { + int16_t x; + int16_t y; + int16_t px; + int16_t py; + int16_t xi; + int16_t yi; WindowT *w = (WindowT *)widget; // Do we need redrawn? @@ -347,8 +363,24 @@ void windowPaint(struct WidgetS *widget, ...) { windowCache(w); } - // By now we have a valid cached window. Blit it. - surfaceBlit(w->base.r.x, w->base.r.y, 0, 0, w->cached); + // Are we minimized? + if (w->flags & WIN_IS_ICON) { + // Draw iconized version of contents. + yi = (surfaceHeightGet(w->content) - 1) / ICON_SIZE; + xi = (surfaceWidthGet(w->content) - 1) / ICON_SIZE; + py = videoDisplayHeightGet() - ICON_SIZE - 2; + for (y=0; ycontent) - 1; y+=yi) { + px = (ICON_SIZE + 1) * _iconCount; + for (x=0; xcontent) - 1; x+=xi) { + surfacePixelSet(px++, py, surfacePixelGet(w->content, x, y)); + } + py++; + } + _iconCount++; + } else { + // By now we have a valid cached window. Blit it. + surfaceBlit(w->base.r.x, w->base.r.y, 0, 0, w->cached); + } } @@ -393,6 +425,7 @@ void wmUpdate(EventT *event) { if (arrlen(_windowList) > 0) { // Paint all windows. + _iconCount = 0; for (i=0; ix <= 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. + // Are we inside the window content? Most likely, check first. 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. } - //***TODO*** Are we inside the close button? + // Are we inside the close button? Does not include button frame on purpose. + if (win->flags & WIN_CLOSE && event->x < win->close.x2 && event->x > win->close.x && event->y < win->close.y2 && event->y > win->close.y) { + //***TODO*** Close. + } - // Are we inside the title bar to begin dragging? - if (event->x <= win->titlebar.x2 && event->x >= win->titlebar.x && event->y <= win->titlebar.y2 && event->y >= win->titlebar.y) { + // Are we inside the title bar to begin dragging? Does not include titlebar frame on purpose. + if (event->x < win->titlebar.x2 && event->x > win->titlebar.x && event->y < win->titlebar.y2 && event->y > win->titlebar.y) { dragging = 1; dragOffset.x = event->x - win->base.r.x; dragOffset.y = event->y - win->base.r.y; break; } - //***TODO*** Are we inside the minimize button? - //***TODO*** Are we inside the maximize button? + // Are we inside the minimize button? Does not include button frame on purpose. + if (win->flags & WIN_MINIMIZE &&event->x < win->minimize.x2 && event->x > win->minimize.x && event->y < win->minimize.y2 && event->y > win->minimize.y) { + win->flags |= WIN_IS_ICON; + } + + // Are we inside the maximize button? Does not include button frame on purpose. + if (win->flags & WIN_MAXIMIZE &&event->x < win->maximize.x2 && event->x > win->maximize.x && event->y < win->maximize.y2 && event->y > win->maximize.y) { + //***TODO*** Maximize. + } } else { // On topmost window. @@ -469,8 +512,8 @@ void wmUpdate(EventT *event) { if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) { // Bring this window forward. 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) { + // If we happened to be in the title bar, go ahead and start dragging. Does not include titlebar frame on purpose. + if (event->x < win->titlebar.x2 && event->x > win->titlebar.x && event->y < win->titlebar.y2 && event->y > win->titlebar.y) { dragging = 1; dragOffset.x = event->x - win->base.r.x; dragOffset.y = event->y - win->base.r.y; @@ -482,6 +525,29 @@ void wmUpdate(EventT *event) { } // On topmost window. + // Do we have minimized windows? + if (_iconCount > 0) { + // Are we inside the minimized icons area? + if (event->x < (ICON_SIZE + 1) * _iconCount && event->y >= videoDisplayHeightGet() - ICON_SIZE - 1) { + // Figure out which icon we're over. + x2 = 0; + for (i=0; iflags & WIN_IS_ICON) { + x2 += ICON_SIZE; + // This window? + if (event->x < x2) { + // Restore it and stop looking for icons. + _windowList[i]->flags &= ~WIN_IS_ICON; + windowFocusSet(_windowList[i]); + break; + } + // Next! (Skips pixel between icons.) + x2++; + } + } + } // Minimized windows? + } + } // Button just went down. } // Dragging. diff --git a/client/src/gui/wmwindow.h b/client/src/gui/wmwindow.h index 332134f..20d75e8 100644 --- a/client/src/gui/wmwindow.h +++ b/client/src/gui/wmwindow.h @@ -5,11 +5,14 @@ #include "gui.h" -#define WIN_NONE 0 -#define WIN_CLOSE 1 -#define WIN_MAXIMIZE 2 -#define WIN_MINIMIZE 4 -#define WIN_RESIZE 8 +#define WIN_NONE 0 +#define WIN_CLOSE 1 +#define WIN_MAXIMIZE 2 +#define WIN_MINIMIZE 4 +#define WIN_RESIZE 8 +#define WIN_SCROLL_V 16 +#define WIN_SCROLL_H 32 +#define WIN_IS_ICON 64 typedef struct WindowS { diff --git a/client/src/platform/sdl2.c b/client/src/platform/sdl2.c index 6617846..83a338a 100644 --- a/client/src/platform/sdl2.c +++ b/client/src/platform/sdl2.c @@ -83,6 +83,8 @@ void platformEventGet(EventT *event) { void platformShutdown(void) { + SDL_ShowCursor(SDL_ENABLE); + surfaceShutdown(); if (_texture) { @@ -155,6 +157,8 @@ uint8_t platformStartup(int16_t width, int16_t height, int16_t depth) { SDL_RenderSetLogicalSize(_renderer, width, height); SDL_SetWindowSize(_window, width * _windowScale, height * _windowScale); + SDL_ShowCursor(SDL_DISABLE); + _width = width; _height = height;