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.c142
1 files changed, 138 insertions, 4 deletions
diff --git a/src/ui/window.c b/src/ui/window.c
index 2d65a655..6356b292 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -84,8 +84,32 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) {
84 } 84 }
85 else if (equal_Command(cmd, "window.focus.lost")) { 85 else if (equal_Command(cmd, "window.focus.lost")) {
86 setFocus_Widget(NULL); 86 setFocus_Widget(NULL);
87 setTextColor_LabelWidget(findWidget_App("winbar.app"), uiAnnotation_ColorId);
88 setTextColor_LabelWidget(findWidget_App("winbar.title"), uiAnnotation_ColorId);
87 return iFalse; 89 return iFalse;
88 } 90 }
91 else if (equal_Command(cmd, "window.focus.gained")) {
92 setTextColor_LabelWidget(findWidget_App("winbar.app"), uiTextCaution_ColorId);
93 setTextColor_LabelWidget(findWidget_App("winbar.title"), uiTextStrong_ColorId);
94 return iFalse;
95 }
96 else if (equal_Command(cmd, "window.fullscreen.changed")) {
97 iWidget *winBar = findWidget_App("winbar");
98 if (winBar) {
99 setFlags_Widget(winBar, hidden_WidgetFlag, arg_Command(cmd));
100 arrange_Widget(get_Window()->root);
101 postRefresh_App();
102 }
103 return iFalse;
104 }
105 else if (equal_Command(cmd, "window.minimize")) {
106 SDL_MinimizeWindow(get_Window()->win);
107 return iTrue;
108 }
109 else if (equal_Command(cmd, "window.close")) {
110 SDL_PushEvent(&(SDL_Event){ .type = SDL_QUIT });
111 return iTrue;
112 }
89 else if (handleCommand_App(cmd)) { 113 else if (handleCommand_App(cmd)) {
90 return iTrue; 114 return iTrue;
91 } 115 }
@@ -503,6 +527,12 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) {
503 return iFalse; 527 return iFalse;
504} 528}
505 529
530static iLabelWidget *newLargeIcon_LabelWidget(const char *text, const char *cmd) {
531 iLabelWidget *lab = newIcon_LabelWidget(text, 0, 0, cmd);
532 setFont_LabelWidget(lab, uiLabelLarge_FontId);
533 return lab;
534}
535
506static void setupUserInterface_Window(iWindow *d) { 536static void setupUserInterface_Window(iWindow *d) {
507 /* Children of root cover the entire window. */ 537 /* Children of root cover the entire window. */
508 setFlags_Widget(d->root, resizeChildren_WidgetFlag, iTrue); 538 setFlags_Widget(d->root, resizeChildren_WidgetFlag, iTrue);
@@ -512,11 +542,58 @@ static void setupUserInterface_Window(iWindow *d) {
512 setId_Widget(div, "navdiv"); 542 setId_Widget(div, "navdiv");
513 addChild_Widget(d->root, iClob(div)); 543 addChild_Widget(d->root, iClob(div));
514 544
545#if defined (LAGRANGE_CUSTOM_FRAME)
546 /* Window title bar. */ {
547 const int border = gap_UI / 4;
548 setPadding1_Widget(div, border); /* draggable edges */
549 iWidget *winBar = new_Widget();
550 setId_Widget(winBar, "winbar");
551 setFlags_Widget(winBar,
552 arrangeHeight_WidgetFlag | resizeChildren_WidgetFlag |
553 arrangeHorizontal_WidgetFlag | collapse_WidgetFlag,
554 iTrue);
555 iLabelWidget *appButton =
556 addChildFlags_Widget(winBar,
557 iClob(new_LabelWidget("Lagrange", NULL)),
558 fixedHeight_WidgetFlag | frameless_WidgetFlag);
559 setTextColor_LabelWidget(appButton, uiTextCaution_ColorId);
560 setId_Widget(as_Widget(appButton), "winbar.app");
561 iLabelWidget *appTitle;
562 setFont_LabelWidget(appButton, uiContentBold_FontId);
563 setId_Widget(addChildFlags_Widget(winBar,
564 iClob(appTitle = new_LabelWidget("", NULL)),
565 expand_WidgetFlag | alignLeft_WidgetFlag |
566 fixedHeight_WidgetFlag | frameless_WidgetFlag |
567 commandOnClick_WidgetFlag),
568 "winbar.title");
569 setTextColor_LabelWidget(appTitle, uiTextStrong_ColorId);
570 iLabelWidget *appMin, *appMax, *appClose;
571 setId_Widget(addChildFlags_Widget(
572 winBar,
573 iClob(appMin = newLargeIcon_LabelWidget("\u2014", "window.minimize")),
574 frameless_WidgetFlag),
575 "winbar.min");
576 setSize_Widget(as_Widget(appMin),
577 init_I2(gap_UI * 11.5f, height_Widget(appTitle)));
578 addChildFlags_Widget(
579 winBar,
580 iClob(appMax = newLargeIcon_LabelWidget("\u25a1", "window.maximize toggle:1")),
581 frameless_WidgetFlag);
582 addChildFlags_Widget(winBar,
583 iClob(appClose = newLargeIcon_LabelWidget("\u2a2f", "window.close")),
584 frameless_WidgetFlag);
585 setSize_Widget(as_Widget(appMax), as_Widget(appMin)->rect.size);
586 setSize_Widget(as_Widget(appClose), as_Widget(appMin)->rect.size);
587 addChild_Widget(div, iClob(winBar));
588 setBackgroundColor_Widget(winBar, uiBackground_ColorId);
589 }
590#endif
591
515 /* Navigation bar. */ { 592 /* Navigation bar. */ {
516 iWidget *navBar = new_Widget(); 593 iWidget *navBar = new_Widget();
517 setId_Widget(navBar, "navbar"); 594 setId_Widget(navBar, "navbar");
518 /*setPadding_Widget(navBar, gap_UI / 2, 0, gap_UI / 2, 0);*/ 595 int topPad = !findChild_Widget(div, "winbar") ? gap_UI / 2 : 0;
519 setPadding_Widget(navBar, gap_UI, gap_UI / 2, gap_UI, gap_UI / 2); 596 setPadding_Widget(navBar, gap_UI, topPad, gap_UI, gap_UI / 2);
520 setFlags_Widget(navBar, 597 setFlags_Widget(navBar,
521 arrangeHeight_WidgetFlag | resizeChildren_WidgetFlag | 598 arrangeHeight_WidgetFlag | resizeChildren_WidgetFlag |
522 arrangeHorizontal_WidgetFlag, 599 arrangeHorizontal_WidgetFlag,
@@ -697,7 +774,7 @@ static float pixelRatio_Window_(const iWindow *d) {
697 SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(d->win), NULL, NULL, &vdpi); 774 SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(d->win), NULL, NULL, &vdpi);
698 const float factor = vdpi / 96.0f; 775 const float factor = vdpi / 96.0f;
699 return iMax(1.0f, factor); 776 return iMax(1.0f, factor);
700#else 777#else
701 int dx, x; 778 int dx, x;
702 SDL_GetRendererOutputSize(d->render, &dx, NULL); 779 SDL_GetRendererOutputSize(d->render, &dx, NULL);
703 SDL_GetWindowSize(d->win, &x, NULL); 780 SDL_GetWindowSize(d->win, &x, NULL);
@@ -712,12 +789,61 @@ static void drawBlank_Window_(iWindow *d) {
712 SDL_RenderPresent(d->render); 789 SDL_RenderPresent(d->render);
713} 790}
714 791
792#if defined (LAGRANGE_CUSTOM_FRAME)
793static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) {
794 iWindow *d = data;
795 iAssert(d->win == win);
796 int w, h;
797 SDL_GetWindowSize(win, &w, &h);
798 /* TODO: Check if inside the caption label widget. */
799 const iBool isLeft = pos->x < gap_UI;
800 const iBool isRight = pos->x >= w - gap_UI;
801 const iBool isTop = pos->y < gap_UI;
802 const iBool isBottom = pos->y >= h - gap_UI;
803 const int captionHeight = lineHeight_Text(uiContent_FontId) + gap_UI * 2;
804 const int rightEdge = left_Rect(bounds_Widget(findChild_Widget(d->root, "winbar.min")));
805 if (isLeft) {
806 return pos->y < captionHeight ? SDL_HITTEST_RESIZE_TOPLEFT
807 : pos->y > h - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMLEFT
808 : SDL_HITTEST_RESIZE_LEFT;
809 }
810 if (isRight) {
811 return pos->y < captionHeight ? SDL_HITTEST_RESIZE_TOPRIGHT
812 : pos->y > h - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMRIGHT
813 : SDL_HITTEST_RESIZE_RIGHT;
814 }
815 if (isTop) {
816 return pos->x < captionHeight ? SDL_HITTEST_RESIZE_TOPLEFT
817 : pos->x > w - captionHeight ? SDL_HITTEST_RESIZE_TOPRIGHT
818 : SDL_HITTEST_RESIZE_TOP;
819 }
820 if (isBottom) {
821 return pos->x < captionHeight ? SDL_HITTEST_RESIZE_BOTTOMLEFT
822 : pos->x > w - captionHeight ? SDL_HITTEST_RESIZE_BOTTOMRIGHT
823 : SDL_HITTEST_RESIZE_BOTTOM;
824 }
825 if (pos->x < rightEdge && pos->y < captionHeight) {
826 return SDL_HITTEST_DRAGGABLE;
827 }
828 return SDL_HITTEST_NORMAL;
829}
830#endif
831
715iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) { 832iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) {
716 flags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN; 833 flags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN;
834#if defined (LAGRANGE_CUSTOM_FRAME)
835 /* We are drawing a custom frame so hide the default one. */
836 flags |= SDL_WINDOW_BORDERLESS;
837#endif
717 if (SDL_CreateWindowAndRenderer( 838 if (SDL_CreateWindowAndRenderer(
718 width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) { 839 width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) {
719 return iFalse; 840 return iFalse;
720 } 841 }
842#if defined (LAGRANGE_CUSTOM_FRAME)
843 /* Register a handler for window hit testing (drag, resize). */
844 SDL_SetWindowHitTest(d->win, hitTest_Window_, d);
845 SDL_SetWindowResizable(d->win, SDL_TRUE);
846#endif
721 return iTrue; 847 return iTrue;
722} 848}
723 849
@@ -776,6 +902,9 @@ void init_Window(iWindow *d, iRect rect) {
776 d->pixelRatio = pixelRatio_Window_(d); 902 d->pixelRatio = pixelRatio_Window_(d);
777 setPixelRatio_Metrics(d->pixelRatio * d->uiScale); 903 setPixelRatio_Metrics(d->pixelRatio * d->uiScale);
778#if defined (iPlatformMsys) 904#if defined (iPlatformMsys)
905 SDL_Rect usable;
906 SDL_GetDisplayUsableBounds(0, &usable);
907 SDL_SetWindowMaximumSize(d->win, usable.w, usable.h);
779 SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio); 908 SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio);
780 useExecutableIconResource_SDLWindow(d->win); 909 useExecutableIconResource_SDLWindow(d->win);
781#endif 910#endif
@@ -1006,7 +1135,8 @@ void draw_Window(iWindow *d) {
1006// printf("draw %d\n", d->frameTime); fflush(stdout); 1135// printf("draw %d\n", d->frameTime); fflush(stdout);
1007//#endif 1136//#endif
1008 /* Clear the window. */ 1137 /* Clear the window. */
1009 SDL_SetRenderDrawColor(d->render, 0, 0, 0, 255); 1138 const iColor back = get_Color(uiSeparator_ColorId);
1139 SDL_SetRenderDrawColor(d->render, back.r, back.g, back.b, 255);
1010 SDL_RenderClear(d->render); 1140 SDL_RenderClear(d->render);
1011 /* Draw widgets. */ 1141 /* Draw widgets. */
1012 d->frameTime = SDL_GetTicks(); 1142 d->frameTime = SDL_GetTicks();
@@ -1030,6 +1160,10 @@ void resize_Window(iWindow *d, int w, int h) {
1030 1160
1031void setTitle_Window(iWindow *d, const iString *title) { 1161void setTitle_Window(iWindow *d, const iString *title) {
1032 SDL_SetWindowTitle(d->win, cstr_String(title)); 1162 SDL_SetWindowTitle(d->win, cstr_String(title));
1163 iLabelWidget *bar = findChild_Widget(d->root, "winbar.title");
1164 if (bar) {
1165 updateText_LabelWidget(bar, title);
1166 }
1033} 1167}
1034 1168
1035void setUiScale_Window(iWindow *d, float uiScale) { 1169void setUiScale_Window(iWindow *d, float uiScale) {