summaryrefslogtreecommitdiff
path: root/src/ui/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/window.c')
-rw-r--r--src/ui/window.c124
1 files changed, 88 insertions, 36 deletions
diff --git a/src/ui/window.c b/src/ui/window.c
index a59aa135..ef4a6fca 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -52,7 +52,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
52#include <SDL_syswm.h> 52#include <SDL_syswm.h>
53 53
54#define STB_IMAGE_IMPLEMENTATION 54#define STB_IMAGE_IMPLEMENTATION
55#define STB_IMAGE_RESIZE_IMPLEMENTATION
55#include "stb_image.h" 56#include "stb_image.h"
57#include "stb_image_resize.h"
56 58
57static iWindow *theWindow_ = NULL; 59static iWindow *theWindow_ = NULL;
58 60
@@ -89,7 +91,7 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) {
89 return iFalse; 91 return iFalse;
90 } 92 }
91 else if (equal_Command(cmd, "window.focus.gained")) { 93 else if (equal_Command(cmd, "window.focus.gained")) {
92 setTextColor_LabelWidget(findWidget_App("winbar.app"), uiTextCaution_ColorId); 94 setTextColor_LabelWidget(findWidget_App("winbar.app"), uiTextShortcut_ColorId);
93 setTextColor_LabelWidget(findWidget_App("winbar.title"), uiTextStrong_ColorId); 95 setTextColor_LabelWidget(findWidget_App("winbar.title"), uiTextStrong_ColorId);
94 return iFalse; 96 return iFalse;
95 } 97 }
@@ -541,6 +543,10 @@ static iLabelWidget *newLargeIcon_LabelWidget(const char *text, const char *cmd)
541 return lab; 543 return lab;
542} 544}
543 545
546static int appIconSize_(void) {
547 return lineHeight_Text(uiContent_FontId);
548}
549
544static void setupUserInterface_Window(iWindow *d) { 550static void setupUserInterface_Window(iWindow *d) {
545 /* Children of root cover the entire window. */ 551 /* Children of root cover the entire window. */
546 setFlags_Widget(d->root, resizeChildren_WidgetFlag, iTrue); 552 setFlags_Widget(d->root, resizeChildren_WidgetFlag, iTrue);
@@ -552,8 +558,7 @@ static void setupUserInterface_Window(iWindow *d) {
552 558
553#if defined (LAGRANGE_CUSTOM_FRAME) 559#if defined (LAGRANGE_CUSTOM_FRAME)
554 /* Window title bar. */ { 560 /* Window title bar. */ {
555 const int border = gap_UI / 4; 561 setPadding1_Widget(div, 1);
556 setPadding1_Widget(div, border); /* draggable edges */
557 iWidget *winBar = new_Widget(); 562 iWidget *winBar = new_Widget();
558 setPadding_Widget(winBar, 0, gap_UI / 3, 0, 0); 563 setPadding_Widget(winBar, 0, gap_UI / 3, 0, 0);
559 setId_Widget(winBar, "winbar"); 564 setId_Widget(winBar, "winbar");
@@ -561,11 +566,14 @@ static void setupUserInterface_Window(iWindow *d) {
561 arrangeHeight_WidgetFlag | resizeChildren_WidgetFlag | 566 arrangeHeight_WidgetFlag | resizeChildren_WidgetFlag |
562 arrangeHorizontal_WidgetFlag | collapse_WidgetFlag, 567 arrangeHorizontal_WidgetFlag | collapse_WidgetFlag,
563 iTrue); 568 iTrue);
569 iWidget *appIcon;
570 setId_Widget(
571 addChild_Widget(winBar, iClob(appIcon = makePadding_Widget(0))), "winbar.icon");
564 iLabelWidget *appButton = 572 iLabelWidget *appButton =
565 addChildFlags_Widget(winBar, 573 addChildFlags_Widget(winBar,
566 iClob(new_LabelWidget("Lagrange", NULL)), 574 iClob(new_LabelWidget("Lagrange", NULL)),
567 fixedHeight_WidgetFlag | frameless_WidgetFlag); 575 fixedHeight_WidgetFlag | frameless_WidgetFlag);
568 setTextColor_LabelWidget(appButton, uiTextCaution_ColorId); 576 setTextColor_LabelWidget(appButton, uiTextShortcut_ColorId);
569 setId_Widget(as_Widget(appButton), "winbar.app"); 577 setId_Widget(as_Widget(appButton), "winbar.app");
570 iLabelWidget *appTitle; 578 iLabelWidget *appTitle;
571 setFont_LabelWidget(appButton, uiContentBold_FontId); 579 setFont_LabelWidget(appButton, uiContentBold_FontId);
@@ -594,6 +602,7 @@ static void setupUserInterface_Window(iWindow *d) {
594 setFont_LabelWidget(appClose, uiContent_FontId); 602 setFont_LabelWidget(appClose, uiContent_FontId);
595 setSize_Widget(as_Widget(appMax), as_Widget(appMin)->rect.size); 603 setSize_Widget(as_Widget(appMax), as_Widget(appMin)->rect.size);
596 setSize_Widget(as_Widget(appClose), as_Widget(appMin)->rect.size); 604 setSize_Widget(as_Widget(appClose), as_Widget(appMin)->rect.size);
605 setSize_Widget(appIcon, init_I2(appIconSize_(), as_Widget(appMin)->rect.size.y));
597 addChild_Widget(div, iClob(winBar)); 606 addChild_Widget(div, iClob(winBar));
598 setBackgroundColor_Widget(winBar, uiBackground_ColorId); 607 setBackgroundColor_Widget(winBar, uiBackground_ColorId);
599 } 608 }
@@ -817,25 +826,27 @@ static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos,
817 const int captionHeight = lineHeight_Text(uiContent_FontId) + gap_UI * 2; 826 const int captionHeight = lineHeight_Text(uiContent_FontId) + gap_UI * 2;
818 const int rightEdge = left_Rect(bounds_Widget(findChild_Widget(d->root, "winbar.min"))); 827 const int rightEdge = left_Rect(bounds_Widget(findChild_Widget(d->root, "winbar.min")));
819 d->place.lastHit = SDL_HITTEST_NORMAL; 828 d->place.lastHit = SDL_HITTEST_NORMAL;
820 if (isLeft) { 829 if (snap != maximized_WindowSnap) {
821 return pos->y < captionHeight ? SDL_HITTEST_RESIZE_TOPLEFT 830 if (isLeft) {
822 : pos->y > h - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMLEFT 831 return pos->y < captionHeight ? SDL_HITTEST_RESIZE_TOPLEFT
823 : (d->place.lastHit = SDL_HITTEST_RESIZE_LEFT); 832 : pos->y > h - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMLEFT
824 } 833 : (d->place.lastHit = SDL_HITTEST_RESIZE_LEFT);
825 if (isRight) { 834 }
826 return pos->y < captionHeight ? SDL_HITTEST_RESIZE_TOPRIGHT 835 if (isRight) {
827 : pos->y > h - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMRIGHT 836 return pos->y < captionHeight ? SDL_HITTEST_RESIZE_TOPRIGHT
828 : (d->place.lastHit = SDL_HITTEST_RESIZE_RIGHT); 837 : pos->y > h - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMRIGHT
829 } 838 : (d->place.lastHit = SDL_HITTEST_RESIZE_RIGHT);
830 if (isTop) { 839 }
831 return pos->x < captionHeight ? SDL_HITTEST_RESIZE_TOPLEFT 840 if (isTop) {
832 : pos->x > w - captionHeight ? SDL_HITTEST_RESIZE_TOPRIGHT 841 return pos->x < captionHeight ? SDL_HITTEST_RESIZE_TOPLEFT
833 : SDL_HITTEST_RESIZE_TOP; 842 : pos->x > w - captionHeight ? SDL_HITTEST_RESIZE_TOPRIGHT
834 } 843 : SDL_HITTEST_RESIZE_TOP;
835 if (isBottom) { 844 }
836 return pos->x < captionHeight ? SDL_HITTEST_RESIZE_BOTTOMLEFT 845 if (isBottom) {
837 : pos->x > w - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMRIGHT 846 return pos->x < captionHeight ? SDL_HITTEST_RESIZE_BOTTOMLEFT
838 : SDL_HITTEST_RESIZE_BOTTOM; 847 : pos->x > w - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMRIGHT
848 : SDL_HITTEST_RESIZE_BOTTOM;
849 }
839 } 850 }
840 if (pos->x < rightEdge && pos->y < captionHeight) { 851 if (pos->x < rightEdge && pos->y < captionHeight) {
841 return SDL_HITTEST_DRAGGABLE; 852 return SDL_HITTEST_DRAGGABLE;
@@ -866,6 +877,24 @@ iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) {
866 return iTrue; 877 return iTrue;
867} 878}
868 879
880#if defined (iPlatformLinux) || defined (LAGRANGE_CUSTOM_FRAME)
881static SDL_Surface *loadAppIconSurface_(int resized) {
882 const iBlock *icon = &imageLagrange64_Embedded;
883 int w, h, num;
884 stbi_uc * pixels = stbi_load_from_memory(
885 constData_Block(icon), size_Block(icon), &w, &h, &num, STBI_rgb_alpha);
886 if (resized) {
887 stbi_uc * rsPixels = malloc(num * resized * resized);
888 stbir_resize_uint8(pixels, w, h, 0, rsPixels, resized, resized, 0, num);
889 free(pixels);
890 pixels = rsPixels;
891 w = h = resized;
892 }
893 return SDL_CreateRGBSurfaceWithFormatFrom(
894 pixels, w, h, 8 * num, w * num, SDL_PIXELFORMAT_RGBA32);
895}
896#endif
897
869void init_Window(iWindow *d, iRect rect) { 898void init_Window(iWindow *d, iRect rect) {
870 theWindow_ = d; 899 theWindow_ = d;
871 iZap(d->cursors); 900 iZap(d->cursors);
@@ -932,19 +961,10 @@ void init_Window(iWindow *d, iRect rect) {
932#if defined (iPlatformLinux) 961#if defined (iPlatformLinux)
933 SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio); 962 SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio);
934 /* Load the window icon. */ { 963 /* Load the window icon. */ {
935 int w, h, num; 964 SDL_Surface *surf = loadAppIconSurface_(0);
936 const iBlock *icon = &imageLagrange64_Embedded;
937 stbi_uc *pixels = stbi_load_from_memory(constData_Block(icon),
938 size_Block(icon),
939 &w,
940 &h,
941 &num,
942 STBI_rgb_alpha);
943 SDL_Surface *surf =
944 SDL_CreateRGBSurfaceWithFormatFrom(pixels, w, h, 32, 4 * w, SDL_PIXELFORMAT_RGBA32);
945 SDL_SetWindowIcon(d->win, surf); 965 SDL_SetWindowIcon(d->win, surf);
966 free(surf->pixels);
946 SDL_FreeSurface(surf); 967 SDL_FreeSurface(surf);
947 stbi_image_free(pixels);
948 } 968 }
949#endif 969#endif
950 d->root = new_Widget(); 970 d->root = new_Widget();
@@ -957,7 +977,16 @@ void init_Window(iWindow *d, iRect rect) {
957 setupUserInterface_Window(d); 977 setupUserInterface_Window(d);
958 postCommand_App("bindings.changed"); /* update from bindings */ 978 postCommand_App("bindings.changed"); /* update from bindings */
959 updateRootSize_Window_(d, iFalse); 979 updateRootSize_Window_(d, iFalse);
980 d->appIcon = NULL;
960#if defined (LAGRANGE_CUSTOM_FRAME) 981#if defined (LAGRANGE_CUSTOM_FRAME)
982 /* Load the app icon for drawing in the title bar. */ {
983 SDL_Surface *surf = loadAppIconSurface_(appIconSize_());
984 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
985 d->appIcon = SDL_CreateTextureFromSurface(d->render, surf);
986 free(surf->pixels);
987 SDL_FreeSurface(surf);
988 }
989 /* We need to observe non-client-area events. */
961 SDL_EventState(SDL_SYSWMEVENT, SDL_TRUE); 990 SDL_EventState(SDL_SYSWMEVENT, SDL_TRUE);
962#endif 991#endif
963} 992}
@@ -1256,12 +1285,30 @@ void draw_Window(iWindow *d) {
1256// printf("draw %d\n", d->frameTime); fflush(stdout); 1285// printf("draw %d\n", d->frameTime); fflush(stdout);
1257//#endif 1286//#endif
1258 /* Clear the window. */ 1287 /* Clear the window. */
1259 const iColor back = get_Color(uiSeparator_ColorId); 1288 const int winFlags = SDL_GetWindowFlags(d->win);
1289 const iColor back =
1290 get_Color(winFlags & SDL_WINDOW_INPUT_FOCUS && d->place.snap != maximized_WindowSnap
1291 ? uiAnnotation_ColorId
1292 : uiSeparator_ColorId);
1260 SDL_SetRenderDrawColor(d->render, back.r, back.g, back.b, 255); 1293 SDL_SetRenderDrawColor(d->render, back.r, back.g, back.b, 255);
1261 SDL_RenderClear(d->render); 1294 SDL_RenderClear(d->render);
1262 /* Draw widgets. */ 1295 /* Draw widgets. */
1263 d->frameTime = SDL_GetTicks(); 1296 d->frameTime = SDL_GetTicks();
1264 draw_Widget(d->root); 1297 draw_Widget(d->root);
1298#if defined (LAGRANGE_CUSTOM_FRAME)
1299 /* App icon. */
1300 const iWidget *appIcon = findChild_Widget(d->root, "winbar.icon");
1301 if (isVisible_Widget(appIcon)) {
1302 const int size = appIconSize_();
1303 const iRect rect = bounds_Widget(appIcon);
1304 const iInt2 mid = mid_Rect(rect);
1305 SDL_RenderCopy(
1306 d->render,
1307 d->appIcon,
1308 NULL,
1309 &(SDL_Rect){ left_Rect(rect) + gap_UI * 1.25f, mid.y - size / 2, size, size });
1310 }
1311#endif
1265#if 0 1312#if 0
1266 /* Text cache debugging. */ { 1313 /* Text cache debugging. */ {
1267 SDL_Texture *cache = glyphCache_Text(); 1314 SDL_Texture *cache = glyphCache_Text();
@@ -1363,7 +1410,12 @@ void setSnap_Window(iWindow *d, int snapMode) {
1363 SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP); 1410 SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP);
1364 } 1411 }
1365 else { 1412 else {
1366 SDL_RestoreWindow(d->win); 1413 if (snap_Window(d) == fullscreen_WindowSnap) {
1414 SDL_SetWindowFullscreen(d->win, 0);
1415 }
1416 else {
1417 SDL_RestoreWindow(d->win);
1418 }
1367 } 1419 }
1368} 1420}
1369 1421