summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app.c21
-rw-r--r--src/ui/root.c3
-rw-r--r--src/ui/window.c59
-rw-r--r--src/ui/window.h6
4 files changed, 63 insertions, 26 deletions
diff --git a/src/app.c b/src/app.c
index 624e5899..52b004e2 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1177,9 +1177,7 @@ static int run_App_(iApp *d) {
1177 runTickers_App_(d); 1177 runTickers_App_(d);
1178 refresh_App(); 1178 refresh_App();
1179 /* Change the widget tree while we are not iterating through it. */ 1179 /* Change the widget tree while we are not iterating through it. */
1180 if (d->window->splitMode != d->window->pendingSplitMode) { 1180 checkPendingSplit_Window(d->window);
1181 setSplitMode_Window(d->window, d->window->pendingSplitMode);
1182 }
1183 recycle_Garbage(); 1181 recycle_Garbage();
1184 } 1182 }
1185 SDL_DelEventWatch(resizeWatcher_, d); 1183 SDL_DelEventWatch(resizeWatcher_, d);
@@ -1691,14 +1689,16 @@ iBool handleCommand_App(const char *cmd) {
1691 return iTrue; 1689 return iTrue;
1692 } 1690 }
1693 else if (equal_Command(cmd, "ui.split")) { 1691 else if (equal_Command(cmd, "ui.split")) {
1692 if (argLabel_Command(cmd, "swap")) {
1693 swapRoots_Window(d->window);
1694 return iTrue;
1695 }
1694 d->window->pendingSplitMode = 1696 d->window->pendingSplitMode =
1695 (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); 1697 (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1);
1698 const char *url = suffixPtr_Command(cmd, "url");
1699 setCStr_String(get_Window()->pendingSplitUrl, url ? url : "");
1696 return iTrue; 1700 return iTrue;
1697 } 1701 }
1698// else if (equal_Command(cmd, "window.updatelayout")) {
1699// resize_Window(d->window, -1, -1);
1700// return iTrue;
1701// }
1702 else if (equal_Command(cmd, "window.retain")) { 1702 else if (equal_Command(cmd, "window.retain")) {
1703 d->prefs.retainWindowSize = arg_Command(cmd); 1703 d->prefs.retainWindowSize = arg_Command(cmd);
1704 return iTrue; 1704 return iTrue;
@@ -1993,6 +1993,13 @@ iBool handleCommand_App(const char *cmd) {
1993 return iTrue; 1993 return iTrue;
1994 } 1994 }
1995 const int newTab = argLabel_Command(cmd, "newtab"); 1995 const int newTab = argLabel_Command(cmd, "newtab");
1996 if (newTab & otherRoot_OpenTabFlag && numRoots_Window(get_Window()) == 1) {
1997 /* Need to split first. */
1998 postCommandf_App("ui.split arg:3 newtab:%d url:%s",
1999 newTab & ~otherRoot_OpenTabFlag,
2000 cstr_String(url));
2001 return iTrue;
2002 }
1996 iRoot *root = get_Root(); 2003 iRoot *root = get_Root();
1997 iRoot *oldRoot = root; 2004 iRoot *oldRoot = root;
1998 if (newTab & otherRoot_OpenTabFlag) { 2005 if (newTab & otherRoot_OpenTabFlag) {
diff --git a/src/ui/root.c b/src/ui/root.c
index cd6959c4..bec42719 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -1252,7 +1252,8 @@ void createUserInterface_Root(iRoot *d) {
1252 }, 1252 },
1253 4); 1253 4);
1254 iWidget *splitMenu = makeMenu_Widget(root, (iMenuItem[]){ 1254 iWidget *splitMenu = makeMenu_Widget(root, (iMenuItem[]){
1255 { "Single Frame", '1', 0, "ui.split arg:0" }, 1255 { "Merge Tabs", '1', 0, "ui.split arg:0" },
1256 { "Swap Sides", SDLK_x, 0, "ui.split swap:1" },
1256 { "---", 0, 0, NULL }, 1257 { "---", 0, 0, NULL },
1257 { "Horizontal", '2', 0, "ui.split arg:3 axis:0" }, 1258 { "Horizontal", '2', 0, "ui.split arg:3 axis:0" },
1258 { "Horizontal 1:2", SDLK_d, 0, "ui.split arg:1 axis:0" }, 1259 { "Horizontal 1:2", SDLK_d, 0, "ui.split arg:1 axis:0" },
diff --git a/src/ui/window.c b/src/ui/window.c
index b3840602..e78bb81e 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -403,6 +403,7 @@ void init_Window(iWindow *d, iRect rect) {
403 d->size = zero_I2(); /* will be updated below */ 403 d->size = zero_I2(); /* will be updated below */
404 iZap(d->roots); 404 iZap(d->roots);
405 d->splitMode = d->pendingSplitMode = 0; 405 d->splitMode = d->pendingSplitMode = 0;
406 d->pendingSplitUrl = new_String();
406 d->hover = NULL; 407 d->hover = NULL;
407 d->mouseGrab = NULL; 408 d->mouseGrab = NULL;
408 d->focus = NULL; 409 d->focus = NULL;
@@ -414,6 +415,7 @@ void init_Window(iWindow *d, iRect rect) {
414 d->isDrawFrozen = iTrue; 415 d->isDrawFrozen = iTrue;
415 d->isExposed = iFalse; 416 d->isExposed = iFalse;
416 d->isMinimized = iFalse; 417 d->isMinimized = iFalse;
418 d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */
417 d->isMouseInside = iTrue; 419 d->isMouseInside = iTrue;
418 d->ignoreClick = iFalse; 420 d->ignoreClick = iFalse;
419 d->focusGainedAt = 0; 421 d->focusGainedAt = 0;
@@ -521,6 +523,7 @@ void deinit_Window(iWindow *d) {
521 } 523 }
522 } 524 }
523 setCurrent_Root(NULL); 525 setCurrent_Root(NULL);
526 delete_String(d->pendingSplitUrl);
524 deinit_Text(); 527 deinit_Text();
525 SDL_DestroyRenderer(d->render); 528 SDL_DestroyRenderer(d->render);
526 SDL_DestroyWindow(d->win); 529 SDL_DestroyWindow(d->win);
@@ -561,10 +564,12 @@ iRoot *otherRoot_Window(const iWindow *d, iRoot *root) {
561 return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0]; 564 return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0];
562} 565}
563 566
564static void invalidate_Window_(iWindow *d) { 567void invalidate_Window(iWindow *d) {
565 iUnused(d); 568 if (d && !d->isInvalidated) {
566 resetFonts_Text(); 569 d->isInvalidated = iTrue;
567 postCommand_App("theme.changed auto:1"); /* forces UI invalidation */ 570 resetFonts_Text();
571 postCommand_App("theme.changed auto:1"); /* forces UI invalidation */
572 }
568} 573}
569 574
570static iBool isNormalPlacement_Window_(const iWindow *d) { 575static iBool isNormalPlacement_Window_(const iWindow *d) {
@@ -734,7 +739,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {
734 return iTrue; 739 return iTrue;
735 case SDL_WINDOWEVENT_RESTORED: 740 case SDL_WINDOWEVENT_RESTORED:
736 updateSize_Window_(d, iTrue); 741 updateSize_Window_(d, iTrue);
737 invalidate_Window_(d); 742 invalidate_Window(d);
738 d->isMinimized = iFalse; 743 d->isMinimized = iFalse;
739 postRefresh_App(); 744 postRefresh_App();
740 return iTrue; 745 return iTrue;
@@ -809,7 +814,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
809 } 814 }
810 case SDL_RENDER_TARGETS_RESET: 815 case SDL_RENDER_TARGETS_RESET:
811 case SDL_RENDER_DEVICE_RESET: { 816 case SDL_RENDER_DEVICE_RESET: {
812 invalidate_Window_(d); 817 invalidate_Window(d);
813 break; 818 break;
814 } 819 }
815 default: { 820 default: {
@@ -892,7 +897,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
892 removeMacMenus_(); 897 removeMacMenus_();
893 insertMacMenus_(); 898 insertMacMenus_();
894#endif 899#endif
895 invalidate_Window_(d); 900 invalidate_Window(d);
896 iForIndices(i, d->roots) { 901 iForIndices(i, d->roots) {
897 if (d->roots[i]) { 902 if (d->roots[i]) {
898 updatePreferencesLayout_Widget(findChild_Widget(d->roots[i]->widget, "prefs")); 903 updatePreferencesLayout_Widget(findChild_Widget(d->roots[i]->widget, "prefs"));
@@ -1008,6 +1013,7 @@ void draw_Window(iWindow *d) {
1008 /* Draw widgets. */ 1013 /* Draw widgets. */
1009 d->frameTime = SDL_GetTicks(); 1014 d->frameTime = SDL_GetTicks();
1010 if (isExposed_Window(d)) { 1015 if (isExposed_Window(d)) {
1016 d->isInvalidated = iFalse;
1011 iForIndices(i, d->roots) { 1017 iForIndices(i, d->roots) {
1012 iRoot *root = d->roots[i]; 1018 iRoot *root = d->roots[i];
1013 if (root) { 1019 if (root) {
@@ -1159,7 +1165,25 @@ void setKeyboardHeight_Window(iWindow *d, int height) {
1159 } 1165 }
1160} 1166}
1161 1167
1162void setSplitMode_Window(iWindow *d, int splitMode) { 1168void checkPendingSplit_Window(iWindow *d) {
1169 if (d->splitMode != d->pendingSplitMode) {
1170 setSplitMode_Window(d, d->pendingSplitMode);
1171 if (!isEmpty_String(d->pendingSplitUrl)) {
1172 postCommandf_Root(d->keyRoot, "open url:%s", cstr_String(d->pendingSplitUrl));
1173 clear_String(d->pendingSplitUrl);
1174 }
1175 }
1176}
1177
1178void swapRoots_Window(iWindow *d) {
1179 if (numRoots_Window(d) == 2) {
1180 iSwap(iRoot *, d->roots[0], d->roots[1]);
1181 updateSize_Window_(d, iTrue);
1182 }
1183}
1184
1185void setSplitMode_Window(iWindow *d, int splitFlags) {
1186 const int splitMode = splitFlags & mode_WindowSplit;
1163 iAssert(current_Root() == NULL); 1187 iAssert(current_Root() == NULL);
1164 if (d->splitMode != splitMode) { 1188 if (d->splitMode != splitMode) {
1165 int oldCount = numRoots_Window(d); 1189 int oldCount = numRoots_Window(d);
@@ -1183,7 +1207,7 @@ void setSplitMode_Window(iWindow *d, int splitMode) {
1183 moveTabButtonToEnd_Widget(findChild_Widget(docTabs, "newtab")); 1207 moveTabButtonToEnd_Widget(findChild_Widget(docTabs, "newtab"));
1184 iRelease(tabs); 1208 iRelease(tabs);
1185 } 1209 }
1186 else if ((splitMode & mask_WindowSplit) && oldCount == 1) { 1210 else if (splitMode && oldCount == 1) {
1187 /* Add a second root. */ 1211 /* Add a second root. */
1188 iDocumentWidget *moved = document_Root(d->roots[0]); 1212 iDocumentWidget *moved = document_Root(d->roots[0]);
1189 iAssert(d->roots[1] == NULL); 1213 iAssert(d->roots[1] == NULL);
@@ -1201,10 +1225,11 @@ void setSplitMode_Window(iWindow *d, int splitMode) {
1201 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ 1225 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */
1202 setRoot_Widget(as_Widget(moved), d->roots[1]); 1226 setRoot_Widget(as_Widget(moved), d->roots[1]);
1203 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); 1227 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0);
1204 //showTabPage_Widget(docTabs1, as_Widget(moved)); 1228 if (~splitFlags & noEvents_WindowSplit) {
1205 postCommandf_App("tabs.switch page:%p", moved); 1229 postCommandf_App("tabs.switch page:%p", moved);
1230 }
1206 } 1231 }
1207 else { 1232 else if (~splitFlags & noEvents_WindowSplit) {
1208 postCommand_Root(d->roots[1], "navigate.home"); 1233 postCommand_Root(d->roots[1], "navigate.home");
1209 } 1234 }
1210 } 1235 }
@@ -1232,12 +1257,10 @@ void setSplitMode_Window(iWindow *d, int splitMode) {
1232 } 1257 }
1233 } 1258 }
1234#endif 1259#endif
1235// windowSizeChanged_Window_(d); 1260 if (~splitFlags & noEvents_WindowSplit) {
1236 updateSize_Window_(d, iTrue); 1261 updateSize_Window_(d, iTrue);
1237// postCommand_App("window.resized"); 1262 postCommand_App("window.unfreeze");
1238 // postCommand_App("metrics.resized"); 1263 }
1239// postCommand_App("window.updatelayout");
1240 postCommand_App("window.unfreeze");
1241 } 1264 }
1242} 1265}
1243 1266
diff --git a/src/ui/window.h b/src/ui/window.h
index ad577ce4..677001e5 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -65,6 +65,7 @@ enum iWindowSplit {
65 mode_WindowSplit = vertical_WindowSplit | equal_WindowSplit, 65 mode_WindowSplit = vertical_WindowSplit | equal_WindowSplit,
66 mask_WindowSplit = equal_WindowSplit, 66 mask_WindowSplit = equal_WindowSplit,
67 merge_WindowSplit = iBit(10), 67 merge_WindowSplit = iBit(10),
68 noEvents_WindowSplit = iBit(11),
68}; 69};
69 70
70struct Impl_Window { 71struct Impl_Window {
@@ -74,12 +75,14 @@ struct Impl_Window {
74 iBool isExposed; 75 iBool isExposed;
75 iBool isMinimized; 76 iBool isMinimized;
76 iBool isMouseInside; 77 iBool isMouseInside;
78 iBool isInvalidated;
77 iBool ignoreClick; 79 iBool ignoreClick;
78 uint32_t focusGainedAt; 80 uint32_t focusGainedAt;
79 SDL_Renderer *render; 81 SDL_Renderer *render;
80 iInt2 size; 82 iInt2 size;
81 int splitMode; 83 int splitMode;
82 int pendingSplitMode; 84 int pendingSplitMode;
85 iString * pendingSplitUrl; /* URL to open in a newly opened split */
83 iRoot * roots[2]; /* root widget and UI state; second one is for split mode */ 86 iRoot * roots[2]; /* root widget and UI state; second one is for split mode */
84 iRoot * keyRoot; /* root that has the current keyboard input focus */ 87 iRoot * keyRoot; /* root that has the current keyboard input focus */
85 iWidget * hover; 88 iWidget * hover;
@@ -101,6 +104,7 @@ struct Impl_Window {
101 104
102iBool processEvent_Window (iWindow *, const SDL_Event *); 105iBool processEvent_Window (iWindow *, const SDL_Event *);
103iBool dispatchEvent_Window (iWindow *, const SDL_Event *); 106iBool dispatchEvent_Window (iWindow *, const SDL_Event *);
107void invalidate_Window (iWindow *); /* discard all cached graphics */
104void draw_Window (iWindow *); 108void draw_Window (iWindow *);
105void drawWhileResizing_Window(iWindow *d, int w, int h); /* workaround for SDL bug */ 109void drawWhileResizing_Window(iWindow *d, int w, int h); /* workaround for SDL bug */
106void resize_Window (iWindow *, int w, int h); 110void resize_Window (iWindow *, int w, int h);
@@ -114,6 +118,8 @@ void setKeyboardHeight_Window(iWindow *, int height);
114void setSplitMode_Window (iWindow *, int splitMode); 118void setSplitMode_Window (iWindow *, int splitMode);
115void showToolbars_Window (iWindow *, iBool show); 119void showToolbars_Window (iWindow *, iBool show);
116iBool postContextClick_Window (iWindow *, const SDL_MouseButtonEvent *); 120iBool postContextClick_Window (iWindow *, const SDL_MouseButtonEvent *);
121void checkPendingSplit_Window(iWindow *);
122void swapRoots_Window (iWindow *);
117 123
118uint32_t id_Window (const iWindow *); 124uint32_t id_Window (const iWindow *);
119iInt2 size_Window (const iWindow *); 125iInt2 size_Window (const iWindow *);