diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-02-11 21:53:31 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-02-11 21:53:31 +0200 |
commit | 73c8166d5c8b397c166ee9ece0173f2b278b6ddb (patch) | |
tree | c365e8d387a0d1a02e0de69209d3f80164443157 /src | |
parent | bfdda501cb01df95c968c9f5378bb91cd66eea87 (diff) |
Windows: Experimenting with a custom window frame and title bar
Added the build option ENABLE_CUSTOM_FRAME that causes the window
to be created as borderless. Lagrange's own UI widgets are used to
draw the title bar elements, including the window buttons.
There is plenty of sizing behavior still missing, for instance
snapping to fullscreen left/right side, double-clicking the frame
edges, and proper maximize mode that doesn't cover the entire screen.
The window system menu is also missing, but that can be shown
manually when appropriate.
A command-line option should also be provided to disable winbar
in case the default title bar is required.
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 20 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 4 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 12 | ||||
-rw-r--r-- | src/ui/labelwidget.h | 1 | ||||
-rw-r--r-- | src/ui/widget.c | 2 | ||||
-rw-r--r-- | src/ui/window.c | 142 |
6 files changed, 171 insertions, 10 deletions
@@ -1112,14 +1112,24 @@ iBool handleCommand_App(const char *cmd) { | |||
1112 | return iTrue; | 1112 | return iTrue; |
1113 | } | 1113 | } |
1114 | else if (equal_Command(cmd, "window.maximize")) { | 1114 | else if (equal_Command(cmd, "window.maximize")) { |
1115 | SDL_MaximizeWindow(d->window->win); | 1115 | if (!argLabel_Command(cmd, "toggle")) { |
1116 | SDL_MaximizeWindow(d->window->win); | ||
1117 | } | ||
1118 | else { | ||
1119 | if (SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_MAXIMIZED) { | ||
1120 | SDL_RestoreWindow(d->window->win); | ||
1121 | } | ||
1122 | else { | ||
1123 | SDL_MaximizeWindow(d->window->win); | ||
1124 | } | ||
1125 | } | ||
1116 | return iTrue; | 1126 | return iTrue; |
1117 | } | 1127 | } |
1118 | else if (equal_Command(cmd, "window.fullscreen")) { | 1128 | else if (equal_Command(cmd, "window.fullscreen")) { |
1119 | SDL_SetWindowFullscreen(d->window->win, | 1129 | const iBool wasFull = |
1120 | SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_FULLSCREEN_DESKTOP | 1130 | (SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; |
1121 | ? 0 | 1131 | SDL_SetWindowFullscreen(d->window->win, wasFull ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); |
1122 | : SDL_WINDOW_FULLSCREEN_DESKTOP); | 1132 | postCommandf_App("window.fullscreen.changed arg:%d", !wasFull); |
1123 | return iTrue; | 1133 | return iTrue; |
1124 | } | 1134 | } |
1125 | else if (equal_Command(cmd, "font.set")) { | 1135 | else if (equal_Command(cmd, "font.set")) { |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index e35892cf..6ec76c0a 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -633,7 +633,9 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | |||
633 | iUrl parts; | 633 | iUrl parts; |
634 | init_Url(&parts, d->mod.url); | 634 | init_Url(&parts, d->mod.url); |
635 | if (equalCase_Rangecc(parts.scheme, "about")) { | 635 | if (equalCase_Rangecc(parts.scheme, "about")) { |
636 | pushBackCStr_StringArray(title, "Lagrange"); | 636 | if (!findWidget_App("winbar")) { |
637 | pushBackCStr_StringArray(title, "Lagrange"); | ||
638 | } | ||
637 | } | 639 | } |
638 | else if (!isEmpty_Range(&parts.host)) { | 640 | else if (!isEmpty_Range(&parts.host)) { |
639 | pushBackRange_StringArray(title, parts.host); | 641 | pushBackRange_StringArray(title, parts.host); |
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 57136509..d7e6c020 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -38,6 +38,7 @@ struct Impl_LabelWidget { | |||
38 | int font; | 38 | int font; |
39 | int key; | 39 | int key; |
40 | int kmods; | 40 | int kmods; |
41 | int forceFg; | ||
41 | iString command; | 42 | iString command; |
42 | iBool alignVisual; /* align according to visible bounds, not typography */ | 43 | iBool alignVisual; /* align according to visible bounds, not typography */ |
43 | iClick click; | 44 | iClick click; |
@@ -177,6 +178,9 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int | |||
177 | } | 178 | } |
178 | *fg = uiTextPressed_ColorId | permanent_ColorId; | 179 | *fg = uiTextPressed_ColorId | permanent_ColorId; |
179 | } | 180 | } |
181 | if (d->forceFg >= 0) { | ||
182 | *fg = d->forceFg; | ||
183 | } | ||
180 | } | 184 | } |
181 | 185 | ||
182 | static void draw_LabelWidget_(const iLabelWidget *d) { | 186 | static void draw_LabelWidget_(const iLabelWidget *d) { |
@@ -277,6 +281,7 @@ void updateSize_LabelWidget(iLabelWidget *d) { | |||
277 | void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { | 281 | void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { |
278 | init_Widget(&d->widget); | 282 | init_Widget(&d->widget); |
279 | d->font = uiLabel_FontId; | 283 | d->font = uiLabel_FontId; |
284 | d->forceFg = none_ColorId; | ||
280 | initCStr_String(&d->label, label); | 285 | initCStr_String(&d->label, label); |
281 | if (cmd) { | 286 | if (cmd) { |
282 | initCStr_String(&d->command, cmd); | 287 | initCStr_String(&d->command, cmd); |
@@ -304,6 +309,13 @@ void setFont_LabelWidget(iLabelWidget *d, int fontId) { | |||
304 | updateSize_LabelWidget(d); | 309 | updateSize_LabelWidget(d); |
305 | } | 310 | } |
306 | 311 | ||
312 | void setTextColor_LabelWidget(iLabelWidget *d, int color) { | ||
313 | if (d && d->forceFg != color) { | ||
314 | d->forceFg = color; | ||
315 | refresh_Widget(d); | ||
316 | } | ||
317 | } | ||
318 | |||
307 | void setText_LabelWidget(iLabelWidget *d, const iString *text) { | 319 | void setText_LabelWidget(iLabelWidget *d, const iString *text) { |
308 | updateText_LabelWidget(d, text); | 320 | updateText_LabelWidget(d, text); |
309 | updateSize_LabelWidget(d); | 321 | updateSize_LabelWidget(d); |
diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h index c91793e5..266c3b02 100644 --- a/src/ui/labelwidget.h +++ b/src/ui/labelwidget.h | |||
@@ -31,6 +31,7 @@ iDeclareObjectConstructionArgs(LabelWidget, const char *label, const char *comma | |||
31 | 31 | ||
32 | void setAlignVisually_LabelWidget(iLabelWidget *, iBool alignVisual); | 32 | void setAlignVisually_LabelWidget(iLabelWidget *, iBool alignVisual); |
33 | void setFont_LabelWidget (iLabelWidget *, int fontId); | 33 | void setFont_LabelWidget (iLabelWidget *, int fontId); |
34 | void setTextColor_LabelWidget (iLabelWidget *, int color); | ||
34 | void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ | 35 | void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ |
35 | void setTextCStr_LabelWidget (iLabelWidget *, const char *text); | 36 | void setTextCStr_LabelWidget (iLabelWidget *, const char *text); |
36 | void setCommand_LabelWidget (iLabelWidget *, const iString *command); | 37 | void setCommand_LabelWidget (iLabelWidget *, const iString *command); |
diff --git a/src/ui/widget.c b/src/ui/widget.c index ddb3f092..b60c67e3 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -149,6 +149,8 @@ void setPos_Widget(iWidget *d, iInt2 pos) { | |||
149 | } | 149 | } |
150 | 150 | ||
151 | void setSize_Widget(iWidget *d, iInt2 size) { | 151 | void setSize_Widget(iWidget *d, iInt2 size) { |
152 | if (size.x < 0) size.x = d->rect.size.x; | ||
153 | if (size.y < 0) size.y = d->rect.size.y; | ||
152 | d->rect.size = size; | 154 | d->rect.size = size; |
153 | setFlags_Widget(d, fixedSize_WidgetFlag, iTrue); | 155 | setFlags_Widget(d, fixedSize_WidgetFlag, iTrue); |
154 | } | 156 | } |
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 | ||
530 | static 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 | |||
506 | static void setupUserInterface_Window(iWindow *d) { | 536 | static 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) | ||
793 | static 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 | |||
715 | iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) { | 832 | iBool 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 | ||
1031 | void setTitle_Window(iWindow *d, const iString *title) { | 1161 | void 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 | ||
1035 | void setUiScale_Window(iWindow *d, float uiScale) { | 1169 | void setUiScale_Window(iWindow *d, float uiScale) { |