diff options
Diffstat (limited to 'src/ui/window.c')
-rw-r--r-- | src/ui/window.c | 142 |
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 | ||
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) { |