summaryrefslogtreecommitdiff
path: root/src/ui/util.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-09-20 11:37:23 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-09-20 11:37:23 +0300
commit2d81addf78d6a8b0fb2f2959b04a385c4adffdf2 (patch)
tree5e0f45b9c945499bc6a6669563de13c5203981a6 /src/ui/util.c
parent201021092d204680b353c82ce9e9beb76f3044e8 (diff)
Experimenting with independent popup windows
Toe dipping into multiple window support by allowing popup menu widgets to be displayed in independent windows. This is not a 100% replacement for native menus, but it gets pretty close.
Diffstat (limited to 'src/ui/util.c')
-rw-r--r--src/ui/util.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/src/ui/util.c b/src/ui/util.c
index 721aed2d..38977b96 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -613,6 +613,8 @@ iBool isAction_Widget(const iWidget *d) {
613/*-----------------------------------------------------------------------------------------------*/ 613/*-----------------------------------------------------------------------------------------------*/
614 614
615static iBool isCommandIgnoredByMenus_(const char *cmd) { 615static iBool isCommandIgnoredByMenus_(const char *cmd) {
616 if (equal_Command(cmd, "window.focus.lost") ||
617 equal_Command(cmd, "window.focus.gained")) return iTrue;
616 /* TODO: Perhaps a common way of indicating which commands are notifications and should not 618 /* TODO: Perhaps a common way of indicating which commands are notifications and should not
617 be reacted to by menus? */ 619 be reacted to by menus? */
618 return equal_Command(cmd, "media.updated") || 620 return equal_Command(cmd, "media.updated") ||
@@ -810,6 +812,10 @@ static void updateMenuItemFonts_Widget_(iWidget *d) {
810 } 812 }
811} 813}
812 814
815iLocalDef iBool isUsingMenuPopupWindows_(void) {
816 return deviceType_App() == desktop_AppDeviceType;
817}
818
813void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) { 819void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {
814 const iRect rootRect = rect_Root(d->root); 820 const iRect rootRect = rect_Root(d->root);
815 const iInt2 rootSize = rootRect.size; 821 const iInt2 rootSize = rootRect.size;
@@ -822,6 +828,26 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {
822 processEvents_App(postedEventsOnly_AppEventMode); 828 processEvents_App(postedEventsOnly_AppEventMode);
823 setFlags_Widget(d, hidden_WidgetFlag, iFalse); 829 setFlags_Widget(d, hidden_WidgetFlag, iFalse);
824 setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); 830 setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue);
831 if (isUsingMenuPopupWindows_()) {
832 if (postCommands) {
833 postCommand_Widget(d, "menu.opened");
834 }
835 updateMenuItemFonts_Widget_(d);
836 iRoot *oldRoot = current_Root();
837 setFlags_Widget(d, keepOnTop_WidgetFlag, iFalse);
838 setUserData_Object(d, parent_Widget(d));
839 removeChild_Widget(parent_Widget(d), d); /* we'll borrow the widget for a while */
840 iInt2 mousePos;
841 SDL_GetGlobalMouseState(&mousePos.x, &mousePos.y);
842 iWindow *win = newPopup_Window(sub_I2(mousePos, divi_I2(gap2_UI, 2)), d);
843 SDL_SetWindowTitle(win->win, "Menu");
844 addPopup_App(win); /* window takes the widget */
845 SDL_ShowWindow(win->win);
846 draw_Window(win);
847 setCurrent_Window(mainWindow_App());
848 setCurrent_Root(oldRoot);
849 return;
850 }
825 raise_Widget(d); 851 raise_Widget(d);
826 setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); 852 setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse);
827 if (isPortraitPhone) { 853 if (isPortraitPhone) {
@@ -836,7 +862,7 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {
836 arrange_Widget(d); 862 arrange_Widget(d);
837 if (isPortraitPhone) { 863 if (isPortraitPhone) {
838 if (isSlidePanel) { 864 if (isSlidePanel) {
839 d->rect.pos = zero_I2(); //neg_I2(bounds_Widget(parent_Widget(d)).pos); 865 d->rect.pos = zero_I2();
840 } 866 }
841 else { 867 else {
842 d->rect.pos = init_I2(0, rootSize.y); 868 d->rect.pos = init_I2(0, rootSize.y);
@@ -856,7 +882,7 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {
856 float l, t, r, b; 882 float l, t, r, b;
857 safeAreaInsets_iOS(&l, &t, &r, &b); 883 safeAreaInsets_iOS(&l, &t, &r, &b);
858 topExcess += t; 884 topExcess += t;
859 bottomExcess += iMax(b, get_Window()->keyboardHeight); 885 bottomExcess += iMax(b, get_MainWindow()->keyboardHeight);
860 leftExcess += l; 886 leftExcess += l;
861 rightExcess += r; 887 rightExcess += r;
862 } 888 }
@@ -884,6 +910,18 @@ void closeMenu_Widget(iWidget *d) {
884 if (d == NULL || flags_Widget(d) & hidden_WidgetFlag) { 910 if (d == NULL || flags_Widget(d) & hidden_WidgetFlag) {
885 return; /* Already closed. */ 911 return; /* Already closed. */
886 } 912 }
913 if (isUsingMenuPopupWindows_()) {
914 iWindow *win = window_Widget(d);
915 iAssert(type_Window(win) == popup_WindowType);
916 iWidget *originalParent = userData_Object(d);
917 setUserData_Object(d, NULL);
918 win->roots[0]->widget = NULL;
919 setRoot_Widget(d, originalParent->root);
920 addChild_Widget(originalParent, d);
921 setFlags_Widget(d, keepOnTop_WidgetFlag, iTrue);
922 SDL_HideWindow(win->win);
923 collect_Garbage(win, (iDeleteFunc) delete_Window); /* get rid of it after event processing */
924 }
887 setFlags_Widget(d, hidden_WidgetFlag, iTrue); 925 setFlags_Widget(d, hidden_WidgetFlag, iTrue);
888 setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iTrue); 926 setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iTrue);
889 postRefresh_App(); 927 postRefresh_App();