diff options
author | Jaakko KeraΜnen <jaakko.keranen@iki.fi> | 2021-05-19 12:08:26 +0300 |
---|---|---|
committer | Jaakko KeraΜnen <jaakko.keranen@iki.fi> | 2021-05-19 12:08:26 +0300 |
commit | f765b50caed9f2858ddf4e20ba3a6427e4750240 (patch) | |
tree | 0546c4d97d705cf8ceb6e807edfa0b05ab128678 | |
parent | 462e5085392eb78610e9b991ed295f0168a079bb (diff) | |
parent | d2a76230effce8586b7d90beff519e221e744bf7 (diff) |
Merge branch 'dev' into work/typesetter
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | sdl2-macos-ios.diff | 85 | ||||
-rw-r--r-- | sdl2-macos-mouse-scrolling.diff | 36 | ||||
-rw-r--r-- | src/app.c | 1 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 8 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 3 | ||||
-rw-r--r-- | src/ui/mobile.c | 18 | ||||
-rw-r--r-- | src/ui/root.c | 5 | ||||
-rw-r--r-- | src/ui/widget.c | 52 | ||||
-rw-r--r-- | src/ui/window.c | 7 |
10 files changed, 147 insertions, 70 deletions
@@ -73,7 +73,7 @@ When using OpenSSL 1.1.1 from Homebrew, you must add its pkgconfig path to your | |||
73 | 73 | ||
74 | export PKG_CONFIG_PATH=/opt/homebrew/Cellar/openssl@1.1/1.1.1i/lib/pkgconfig | 74 | export PKG_CONFIG_PATH=/opt/homebrew/Cellar/openssl@1.1/1.1.1i/lib/pkgconfig |
75 | 75 | ||
76 | Also, SDL's trackpad scrolling behavior on macOS is not optimal for regular GUI apps because it emulates a physical mouse wheel. This may change in a future release of SDL, but at least in 2.0.14 (and earlier) a [small patch](https://git.skyjake.fi/gemini/lagrange/raw/branch/dev/sdl2-macos-mouse-scrolling.diff) is required to allow momentum scrolling to come through as single-pixel mouse wheel events. Note that SDL comes with an Xcode project; use the "Shared Library" target and check that you are doing a Release build. | 76 | Also, SDL's trackpad scrolling behavior on macOS is not optimal for regular GUI apps because it emulates a physical mouse wheel. This may change in a future release of SDL, but at least in 2.0.14 (and earlier) a [small patch](https://git.skyjake.fi/gemini/lagrange/raw/branch/dev/sdl2-macos-ios.diff) is required to allow momentum scrolling to come through as single-pixel mouse wheel events. Note that SDL comes with an Xcode project; use the "Shared Library" target and check that you are doing a Release build. |
77 | 77 | ||
78 | ### Compiling on Windows | 78 | ### Compiling on Windows |
79 | 79 | ||
diff --git a/sdl2-macos-ios.diff b/sdl2-macos-ios.diff new file mode 100644 index 00000000..04d0f2e5 --- /dev/null +++ b/sdl2-macos-ios.diff | |||
@@ -0,0 +1,85 @@ | |||
1 | Only in SDL2-2.0.14/src: .DS_Store | ||
2 | diff -ru SDL2-2.0.14-original/src/events/SDL_mouse.c SDL2-2.0.14/src/events/SDL_mouse.c | ||
3 | --- SDL2-2.0.14-original/src/events/SDL_mouse.c 2020-12-21 19:44:36.000000000 +0200 | ||
4 | +++ SDL2-2.0.14/src/events/SDL_mouse.c 2021-01-06 18:31:18.000000000 +0200 | ||
5 | @@ -647,8 +647,8 @@ | ||
6 | event.wheel.preciseX = x; | ||
7 | event.wheel.preciseY = y; | ||
8 | #endif | ||
9 | - event.wheel.x = integral_x; | ||
10 | - event.wheel.y = integral_y; | ||
11 | + event.wheel.x = x; //integral_x; | ||
12 | + event.wheel.y = y; //integral_y; | ||
13 | event.wheel.direction = (Uint32)direction; | ||
14 | posted = (SDL_PushEvent(&event) > 0); | ||
15 | } | ||
16 | Only in SDL2-2.0.14/src/video: .DS_Store | ||
17 | diff -ru SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m SDL2-2.0.14/src/video/cocoa/SDL_cocoamouse.m | ||
18 | --- SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m 2020-12-21 19:44:36.000000000 +0200 | ||
19 | +++ SDL2-2.0.14/src/video/cocoa/SDL_cocoamouse.m 2021-01-06 18:31:18.000000000 +0200 | ||
20 | @@ -423,10 +423,16 @@ | ||
21 | } | ||
22 | |||
23 | SDL_MouseID mouseID = mouse->mouseID; | ||
24 | - CGFloat x = -[event deltaX]; | ||
25 | - CGFloat y = [event deltaY]; | ||
26 | + CGFloat x = -[event scrollingDeltaX]; | ||
27 | + CGFloat y = [event scrollingDeltaY]; | ||
28 | SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL; | ||
29 | |||
30 | + /* HACK: Make a distinction between precise and imprecise scrolling. | ||
31 | + Trackpad seems to be mouseID 0. */ | ||
32 | + if (![event hasPreciseScrollingDeltas]) { | ||
33 | + mouseID = 1; | ||
34 | + } | ||
35 | + | ||
36 | if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) { | ||
37 | if ([event isDirectionInvertedFromDevice] == YES) { | ||
38 | direction = SDL_MOUSEWHEEL_FLIPPED; | ||
39 | Only in SDL2-2.0.14/src/video/cocoa: SDL_cocoamouse.m.orig | ||
40 | diff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.h | ||
41 | --- SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h 2020-12-21 19:44:36.000000000 +0200 | ||
42 | +++ SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.h 2021-05-17 13:11:13.000000000 +0300 | ||
43 | @@ -58,10 +58,13 @@ | ||
44 | #if !TARGET_OS_TV | ||
45 | - (NSUInteger)supportedInterfaceOrientations; | ||
46 | - (BOOL)prefersStatusBarHidden; | ||
47 | +- (void)setStatusStyle:(UIStatusBarStyle)style; | ||
48 | +- (UIStatusBarStyle)preferredStatusBarStyle; | ||
49 | - (BOOL)prefersHomeIndicatorAutoHidden; | ||
50 | - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures; | ||
51 | |||
52 | @property (nonatomic, assign) int homeIndicatorHidden; | ||
53 | +@property (nonatomic, assign) UIStatusBarStyle statusBarStyle; | ||
54 | #endif | ||
55 | |||
56 | #if SDL_IPHONE_KEYBOARD | ||
57 | diff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.m | ||
58 | --- SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m 2020-12-21 19:44:36.000000000 +0200 | ||
59 | +++ SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.m 2021-05-17 13:11:58.000000000 +0300 | ||
60 | @@ -104,6 +104,7 @@ | ||
61 | #endif | ||
62 | |||
63 | #if !TARGET_OS_TV | ||
64 | + self.statusBarStyle = UIStatusBarStyleDefault; | ||
65 | SDL_AddHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR, | ||
66 | SDL_HideHomeIndicatorHintChanged, | ||
67 | (__bridge void *) self); | ||
68 | @@ -229,6 +230,17 @@ | ||
69 | return hidden; | ||
70 | } | ||
71 | |||
72 | +- (void)setStatusStyle:(UIStatusBarStyle)style | ||
73 | +{ | ||
74 | + self.statusBarStyle = style; | ||
75 | + [self setNeedsStatusBarAppearanceUpdate]; | ||
76 | +} | ||
77 | + | ||
78 | +- (UIStatusBarStyle)preferredStatusBarStyle | ||
79 | +{ | ||
80 | + return self.statusBarStyle; | ||
81 | +} | ||
82 | + | ||
83 | - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures | ||
84 | { | ||
85 | if (self.homeIndicatorHidden >= 0) { | ||
diff --git a/sdl2-macos-mouse-scrolling.diff b/sdl2-macos-mouse-scrolling.diff deleted file mode 100644 index e2f30c24..00000000 --- a/sdl2-macos-mouse-scrolling.diff +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | diff -r 4f06c06b6d19 src/events/SDL_mouse.c | ||
2 | --- a/src/events/SDL_mouse.c Wed Aug 05 15:28:51 2020 +0200 | ||
3 | +++ b/src/events/SDL_mouse.c Tue Nov 10 12:16:06 2020 +0200 | ||
4 | @@ -642,8 +642,8 @@ | ||
5 | event.wheel.preciseX = x; | ||
6 | event.wheel.preciseY = y; | ||
7 | #endif | ||
8 | - event.wheel.x = integral_x; | ||
9 | - event.wheel.y = integral_y; | ||
10 | + event.wheel.x = x; //integral_x; | ||
11 | + event.wheel.y = y; //integral_y; | ||
12 | event.wheel.direction = (Uint32)direction; | ||
13 | posted = (SDL_PushEvent(&event) > 0); | ||
14 | } | ||
15 | diff -r 4f06c06b6d19 src/video/cocoa/SDL_cocoamouse.m | ||
16 | --- a/src/video/cocoa/SDL_cocoamouse.m Wed Aug 05 15:28:51 2020 +0200 | ||
17 | +++ b/src/video/cocoa/SDL_cocoamouse.m Tue Nov 10 12:16:06 2020 +0200 | ||
18 | @@ -424,10 +424,16 @@ | ||
19 | } | ||
20 | |||
21 | SDL_MouseID mouseID = mouse->mouseID; | ||
22 | - CGFloat x = -[event deltaX]; | ||
23 | - CGFloat y = [event deltaY]; | ||
24 | + CGFloat x = -[event scrollingDeltaX]; | ||
25 | + CGFloat y = [event scrollingDeltaY]; | ||
26 | SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL; | ||
27 | |||
28 | + /* HACK: Make a distinction between precise and imprecise scrolling. | ||
29 | + Trackpad seems to be mouseID 0. */ | ||
30 | + if (![event hasPreciseScrollingDeltas]) { | ||
31 | + mouseID = 1; | ||
32 | + } | ||
33 | + | ||
34 | if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) { | ||
35 | if ([event isDirectionInvertedFromDevice] == YES) { | ||
36 | direction = SDL_MOUSEWHEEL_FLIPPED; | ||
@@ -732,6 +732,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
732 | setupApplication_iOS(); | 732 | setupApplication_iOS(); |
733 | #endif | 733 | #endif |
734 | init_Keys(); | 734 | init_Keys(); |
735 | setThemePalette_Color(d->prefs.theme); /* default UI colors */ | ||
735 | loadPrefs_App_(d); | 736 | loadPrefs_App_(d); |
736 | load_Keys(dataDir_App_()); | 737 | load_Keys(dataDir_App_()); |
737 | d->window = new_Window(d->initialWindowRect); | 738 | d->window = new_Window(d->initialWindowRect); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 541489c1..9169ea06 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -571,10 +571,11 @@ static float normScrollPos_DocumentWidget_(const iDocumentWidget *d) { | |||
571 | } | 571 | } |
572 | 572 | ||
573 | static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { | 573 | static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { |
574 | int sm = size_GmDocument(d->doc).y - height_Rect(bounds_Widget(constAs_Widget(d))) + | 574 | const iWidget *w = constAs_Widget(d); |
575 | int sm = size_GmDocument(d->doc).y - height_Rect(bounds_Widget(w)) + | ||
575 | (hasSiteBanner_GmDocument(d->doc) ? 1 : 2) * d->pageMargin * gap_UI; | 576 | (hasSiteBanner_GmDocument(d->doc) ? 1 : 2) * d->pageMargin * gap_UI; |
576 | if (d->phoneToolbar) { | 577 | if (d->phoneToolbar) { |
577 | sm += size_Root(constAs_Widget(d)->root).y - | 578 | sm += size_Root(w->root).y - |
578 | top_Rect(boundsWithoutVisualOffset_Widget(d->phoneToolbar)); | 579 | top_Rect(boundsWithoutVisualOffset_Widget(d->phoneToolbar)); |
579 | } | 580 | } |
580 | return sm; | 581 | return sm; |
@@ -3077,6 +3078,9 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3077 | 0, | 3078 | 0, |
3078 | format_CStr("!open newtab:5 url:%s", cstr_String(linkUrl)) } }, | 3079 | format_CStr("!open newtab:5 url:%s", cstr_String(linkUrl)) } }, |
3079 | 4); | 3080 | 4); |
3081 | if (deviceType_App() == phone_AppDeviceType) { | ||
3082 | removeN_Array(&items, size_Array(&items) - 2, iInvalidSize); | ||
3083 | } | ||
3080 | } | 3084 | } |
3081 | else if (!willUseProxy_App(scheme)) { | 3085 | else if (!willUseProxy_App(scheme)) { |
3082 | pushBack_Array( | 3086 | pushBack_Array( |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 05cd1cc3..0257eda0 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -1162,7 +1162,8 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
1162 | return iTrue; | 1162 | return iTrue; |
1163 | case SDLK_RETURN: | 1163 | case SDLK_RETURN: |
1164 | case SDLK_KP_ENTER: | 1164 | case SDLK_KP_ENTER: |
1165 | if (mods == KMOD_SHIFT || (~d->inFlags & isUrl_InputWidgetFlag && | 1165 | if (mods == KMOD_SHIFT || (d->maxLen == 0 && |
1166 | ~d->inFlags & isUrl_InputWidgetFlag && | ||
1166 | deviceType_App() != desktop_AppDeviceType)) { | 1167 | deviceType_App() != desktop_AppDeviceType)) { |
1167 | pushUndo_InputWidget_(d); | 1168 | pushUndo_InputWidget_(d); |
1168 | deleteMarked_InputWidget_(d); | 1169 | deleteMarked_InputWidget_(d); |
diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 1f5e9758..6c3a0b32 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c | |||
@@ -253,7 +253,9 @@ static iAnyObject *addPanelChild_(iWidget *panel, iAnyObject *child, int64_t fla | |||
253 | } | 253 | } |
254 | } | 254 | } |
255 | if ((elementType == toggle_PrefsElement && precedingElementType != toggle_PrefsElement) || | 255 | if ((elementType == toggle_PrefsElement && precedingElementType != toggle_PrefsElement) || |
256 | (elementType == textInput_PrefsElement && precedingElementType != textInput_PrefsElement)) { | 256 | (elementType == textInput_PrefsElement && precedingElementType != textInput_PrefsElement) || |
257 | (elementType == dropdown_PrefsElement && precedingElementType != dropdown_PrefsElement) || | ||
258 | (elementType == radioButton_PrefsElement && precedingElementType == heading_PrefsElement)) { | ||
257 | flags |= borderTop_WidgetFlag; | 259 | flags |= borderTop_WidgetFlag; |
258 | } | 260 | } |
259 | return addChildFlags_Widget(panel, child, flags); | 261 | return addChildFlags_Widget(panel, child, flags); |
@@ -305,6 +307,7 @@ static iWidget *makeValuePadding_(iWidget *value) { | |||
305 | } | 307 | } |
306 | 308 | ||
307 | static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *value) { | 309 | static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *value) { |
310 | const iBool isInput = isInstance_Object(value, &Class_InputWidget); | ||
308 | iWidget *div = new_Widget(); | 311 | iWidget *div = new_Widget(); |
309 | setFlags_Widget(div, | 312 | setFlags_Widget(div, |
310 | borderBottom_WidgetFlag | arrangeHeight_WidgetFlag | | 313 | borderBottom_WidgetFlag | arrangeHeight_WidgetFlag | |
@@ -313,10 +316,11 @@ static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *val | |||
313 | setBackgroundColor_Widget(div, uiBackgroundSidebar_ColorId); | 316 | setBackgroundColor_Widget(div, uiBackgroundSidebar_ColorId); |
314 | setPadding_Widget(div, gap_UI, gap_UI, 4 * gap_UI, gap_UI); | 317 | setPadding_Widget(div, gap_UI, gap_UI, 4 * gap_UI, gap_UI); |
315 | addChildFlags_Widget(div, iClob(heading), 0); | 318 | addChildFlags_Widget(div, iClob(heading), 0); |
319 | setPadding1_Widget(as_Widget(heading), 0); | ||
316 | //setFixedSize_Widget(as_Widget(heading), init_I2(-1, height_Widget(value))); | 320 | //setFixedSize_Widget(as_Widget(heading), init_I2(-1, height_Widget(value))); |
317 | setFont_LabelWidget(heading, labelFont_()); | 321 | setFont_LabelWidget(heading, labelFont_()); |
318 | setTextColor_LabelWidget(heading, uiTextStrong_ColorId); | 322 | setTextColor_LabelWidget(heading, uiTextStrong_ColorId); |
319 | if (isInstance_Object(value, &Class_InputWidget)) { | 323 | if (isInput) { |
320 | addChildFlags_Widget(div, iClob(value), expand_WidgetFlag); | 324 | addChildFlags_Widget(div, iClob(value), expand_WidgetFlag); |
321 | } | 325 | } |
322 | else if (isInstance_Object(value, &Class_LabelWidget) && | 326 | else if (isInstance_Object(value, &Class_LabelWidget) && |
@@ -332,6 +336,7 @@ static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *val | |||
332 | addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); | 336 | addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); |
333 | addChild_Widget(div, iClob(value)); | 337 | addChild_Widget(div, iClob(value)); |
334 | } | 338 | } |
339 | printTree_Widget(div); | ||
335 | return div; | 340 | return div; |
336 | } | 341 | } |
337 | 342 | ||
@@ -374,7 +379,9 @@ void finalizeSheet_Mobile(iWidget *sheet) { | |||
374 | postRefresh_App(); | 379 | postRefresh_App(); |
375 | return; | 380 | return; |
376 | } | 381 | } |
377 | /* Landscape Layout Β Β Portrait Layout | 382 | /* TODO: In portrait, top panel and detail stack are all stacked together. |
383 | |||
384 | Landscape Layout Β Β Portrait Layout | ||
378 | Β Β | 385 | Β Β |
379 | βββββββββββ¬ββββββDetailβStackββββββ Β Β βββββββββββ¬ β β β β β | 386 | βββββββββββ¬ββββββDetailβStackββββββ Β Β βββββββββββ¬ β β β β β |
380 | β ββββββββββββββββββββββ β Β Β β βDetail | 387 | β ββββββββββββββββββββββ β Β Β β βDetail |
@@ -616,10 +623,9 @@ void finalizeSheet_Mobile(iWidget *sheet) { | |||
616 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); | 623 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); |
617 | iLabelWidget *aboutButton = addChildFlags_Widget(topPanel, | 624 | iLabelWidget *aboutButton = addChildFlags_Widget(topPanel, |
618 | iClob(makePanelButton_(planet_Icon " ${menu.about}", "panel.open")), | 625 | iClob(makePanelButton_(planet_Icon " ${menu.about}", "panel.open")), |
619 | chevron_WidgetFlag); | 626 | chevron_WidgetFlag | borderTop_WidgetFlag); |
620 | addChildFlags_Widget(topPanel, | 627 | addChildFlags_Widget(topPanel, |
621 | iClob(makePanelButton_(info_Icon " ${menu.help}", "!open url:about:help")), | 628 | iClob(makePanelButton_(info_Icon " ${menu.help}", "!open url:about:help")), 0); |
622 | borderTop_WidgetFlag); | ||
623 | /* The About panel. */ { | 629 | /* The About panel. */ { |
624 | iWidget *panel = addChildPanel_(detailStack, aboutButton, NULL); | 630 | iWidget *panel = addChildPanel_(detailStack, aboutButton, NULL); |
625 | iString *msg = collectNew_String(); | 631 | iString *msg = collectNew_String(); |
diff --git a/src/ui/root.c b/src/ui/root.c index 8c98bdd3..9ed62711 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -776,17 +776,12 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { | |||
776 | else if (equal_Command(cmd, "focus.gained")) { | 776 | else if (equal_Command(cmd, "focus.gained")) { |
777 | if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { | 777 | if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { |
778 | if (!isVisible_Widget(searchBar)) { | 778 | if (!isVisible_Widget(searchBar)) { |
779 | // setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); | ||
780 | // arrange_Widget(root_Widget(searchBar)); | ||
781 | // postRefresh_App(); | ||
782 | showCollapsed_Widget(searchBar, iTrue); | 779 | showCollapsed_Widget(searchBar, iTrue); |
783 | } | 780 | } |
784 | } | 781 | } |
785 | } | 782 | } |
786 | else if (equal_Command(cmd, "find.close")) { | 783 | else if (equal_Command(cmd, "find.close")) { |
787 | if (isVisible_Widget(searchBar)) { | 784 | if (isVisible_Widget(searchBar)) { |
788 | //setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iTrue); | ||
789 | //arrange_Widget(searchBar->parent); | ||
790 | showCollapsed_Widget(searchBar, iFalse); | 785 | showCollapsed_Widget(searchBar, iFalse); |
791 | if (isFocused_Widget(findChild_Widget(searchBar, "find.input"))) { | 786 | if (isFocused_Widget(findChild_Widget(searchBar, "find.input"))) { |
792 | setFocus_Widget(NULL); | 787 | setFocus_Widget(NULL); |
diff --git a/src/ui/widget.c b/src/ui/widget.c index 3439fb1b..43bbe56e 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -314,50 +314,48 @@ static void printf_Widget_(const iWidget *d, const char *format, ...) { | |||
314 | delete_String(msg); | 314 | delete_String(msg); |
315 | } | 315 | } |
316 | 316 | ||
317 | static void setWidth_Widget_(iWidget *d, int width) { | 317 | static iBool setWidth_Widget_(iWidget *d, int width) { |
318 | iAssert(width >= 0); | 318 | iAssert(width >= 0); |
319 | TRACE(d, "attempt to set width to %d (current: %d, min width: %d)", width, d->rect.size.x, d->minSize.x); | 319 | TRACE(d, "attempt to set width to %d (current: %d, min width: %d)", width, d->rect.size.x, d->minSize.x); |
320 | width = iMax(width, d->minSize.x); | 320 | width = iMax(width, d->minSize.x); |
321 | if (~d->flags & fixedWidth_WidgetFlag) { //} || d->flags & collapse_WidgetFlag) { | 321 | if (~d->flags & fixedWidth_WidgetFlag) { |
322 | if (d->rect.size.x != width) { | 322 | if (d->rect.size.x != width) { |
323 | d->rect.size.x = width; | 323 | d->rect.size.x = width; |
324 | TRACE(d, "width has changed to %d", width); | 324 | TRACE(d, "width has changed to %d", width); |
325 | if (class_Widget(d)->sizeChanged) { | 325 | if (class_Widget(d)->sizeChanged) { |
326 | const int oldHeight = d->rect.size.y; | 326 | const int oldHeight = d->rect.size.y; |
327 | class_Widget(d)->sizeChanged(d); | 327 | class_Widget(d)->sizeChanged(d); |
328 | if (d->rect.size.y != oldHeight) { | ||
329 | TRACE(d, "sizeChanged() cuased height change to %d; redoing parent", d->rect.size.y); | ||
330 | /* Widget updated its height. */ | ||
331 | arrange_Widget_(d->parent); | ||
332 | TRACE(d, "parent layout redone"); | ||
333 | } | ||
334 | } | 328 | } |
329 | return iTrue; | ||
335 | } | 330 | } |
336 | } | 331 | } |
337 | else { | 332 | else { |
338 | TRACE(d, "changing width not allowed; flags: %x", d->flags); | 333 | TRACE(d, "changing width not allowed; flags: %x", d->flags); |
339 | } | 334 | } |
335 | return iFalse; | ||
340 | } | 336 | } |
341 | 337 | ||
342 | static void setHeight_Widget_(iWidget *d, int height) { | 338 | static iBool setHeight_Widget_(iWidget *d, int height) { |
343 | iAssert(height >= 0); | 339 | iAssert(height >= 0); |
344 | if (d->sizeRef) { | 340 | if (d->sizeRef) { |
345 | return; /* height defined by another widget */ | 341 | return; /* height defined by another widget */ |
346 | } | 342 | } |
347 | TRACE(d, "attempt to set height to %d (current: %d, min height: %d)", height, d->rect.size.y, d->minSize.y); | 343 | TRACE(d, "attempt to set height to %d (current: %d, min height: %d)", height, d->rect.size.y, d->minSize.y); |
348 | height = iMax(height, d->minSize.y); | 344 | height = iMax(height, d->minSize.y); |
349 | if (~d->flags & fixedHeight_WidgetFlag) { //} || d->flags & collapse_WidgetFlag) { | 345 | if (~d->flags & fixedHeight_WidgetFlag) { |
350 | if (d->rect.size.y != height) { | 346 | if (d->rect.size.y != height) { |
351 | d->rect.size.y = height; | 347 | d->rect.size.y = height; |
352 | TRACE(d, "height has changed to %d", height); | 348 | TRACE(d, "height has changed to %d", height); |
353 | if (class_Widget(d)->sizeChanged) { | 349 | if (class_Widget(d)->sizeChanged) { |
354 | class_Widget(d)->sizeChanged(d); | 350 | class_Widget(d)->sizeChanged(d); |
355 | } | 351 | } |
352 | return iTrue; | ||
356 | } | 353 | } |
357 | } | 354 | } |
358 | else { | 355 | else { |
359 | TRACE(d, "changing height not allowed; flags: %x", d->flags); | 356 | TRACE(d, "changing height not allowed; flags: %x", d->flags); |
360 | } | 357 | } |
358 | return iFalse; | ||
361 | } | 359 | } |
362 | 360 | ||
363 | iLocalDef iRect innerRect_Widget_(const iWidget *d) { | 361 | iLocalDef iRect innerRect_Widget_(const iWidget *d) { |
@@ -578,6 +576,12 @@ static void arrange_Widget_(iWidget *d) { | |||
578 | TRACE(d, "...done changing child sizes (EVEN mode)"); | 576 | TRACE(d, "...done changing child sizes (EVEN mode)"); |
579 | } | 577 | } |
580 | } | 578 | } |
579 | /* Children arrange themselves. */ { | ||
580 | iForEach(ObjectList, i, d->children) { | ||
581 | iWidget *child = as_Widget(i.object); | ||
582 | arrange_Widget_(child); | ||
583 | } | ||
584 | } | ||
581 | /* Resize the expanding children to fill the remaining available space. */ | 585 | /* Resize the expanding children to fill the remaining available space. */ |
582 | if (expCount > 0 && (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag))) { | 586 | if (expCount > 0 && (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag))) { |
583 | TRACE(d, "%d expanding children, resizing them %s...", expCount, | 587 | TRACE(d, "%d expanding children, resizing them %s...", expCount, |
@@ -600,16 +604,20 @@ static void arrange_Widget_(iWidget *d) { | |||
600 | TRACE(d, "child %p size is not arranged", child); | 604 | TRACE(d, "child %p size is not arranged", child); |
601 | continue; | 605 | continue; |
602 | } | 606 | } |
607 | iBool sizeChanged = iFalse; | ||
603 | if (child->flags & expand_WidgetFlag) { | 608 | if (child->flags & expand_WidgetFlag) { |
604 | if (d->flags & arrangeHorizontal_WidgetFlag) { | 609 | if (d->flags & arrangeHorizontal_WidgetFlag) { |
605 | setWidth_Widget_(child, avail.x); | 610 | sizeChanged |= setWidth_Widget_(child, avail.x); |
606 | setHeight_Widget_(child, height_Rect(innerRect)); | 611 | sizeChanged |= setHeight_Widget_(child, height_Rect(innerRect)); |
607 | } | 612 | } |
608 | else if (d->flags & arrangeVertical_WidgetFlag) { | 613 | else if (d->flags & arrangeVertical_WidgetFlag) { |
609 | setWidth_Widget_(child, width_Rect(innerRect)); | 614 | sizeChanged |= setWidth_Widget_(child, width_Rect(innerRect)); |
610 | setHeight_Widget_(child, avail.y); | 615 | sizeChanged |= setHeight_Widget_(child, avail.y); |
611 | } | 616 | } |
612 | } | 617 | } |
618 | if (sizeChanged) { | ||
619 | arrange_Widget_(child); /* its children may need rearranging */ | ||
620 | } | ||
613 | } | 621 | } |
614 | } | 622 | } |
615 | if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { | 623 | if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { |
@@ -618,7 +626,9 @@ static void arrange_Widget_(iWidget *d) { | |||
618 | iForEach(ObjectList, i, d->children) { | 626 | iForEach(ObjectList, i, d->children) { |
619 | iWidget *child = as_Widget(i.object); | 627 | iWidget *child = as_Widget(i.object); |
620 | if (isArrangedSize_Widget_(child)) { | 628 | if (isArrangedSize_Widget_(child)) { |
621 | setWidth_Widget_(child, widest); | 629 | if (setWidth_Widget_(child, widest)) { |
630 | arrange_Widget_(child); /* its children may need rearranging */ | ||
631 | } | ||
622 | } | 632 | } |
623 | else { | 633 | else { |
624 | TRACE(d, "child %p cannot be resized (parentCannotResize: %d)", child, | 634 | TRACE(d, "child %p cannot be resized (parentCannotResize: %d)", child, |
@@ -633,7 +643,6 @@ static void arrange_Widget_(iWidget *d) { | |||
633 | d->flags & arrangeVertical_WidgetFlag ? " vert" : ""); | 643 | d->flags & arrangeVertical_WidgetFlag ? " vert" : ""); |
634 | iForEach(ObjectList, i, d->children) { | 644 | iForEach(ObjectList, i, d->children) { |
635 | iWidget *child = as_Widget(i.object); | 645 | iWidget *child = as_Widget(i.object); |
636 | arrange_Widget_(child); | ||
637 | if (isCollapsed_Widget_(child) || !isArrangedPos_Widget_(child)) { | 646 | if (isCollapsed_Widget_(child) || !isArrangedPos_Widget_(child)) { |
638 | TRACE(d, "child %p arranging prohibited", child); | 647 | TRACE(d, "child %p arranging prohibited", child); |
639 | continue; | 648 | continue; |
@@ -726,13 +735,15 @@ static void resetArrangement_Widget_(iWidget *d) { | |||
726 | if (d->flags & arrangeHorizontal_WidgetFlag) { | 735 | if (d->flags & arrangeHorizontal_WidgetFlag) { |
727 | child->rect.pos.x = 0; | 736 | child->rect.pos.x = 0; |
728 | } | 737 | } |
729 | if (d->flags & resizeWidthOfChildren_WidgetFlag && child->flags & expand_WidgetFlag) { | 738 | if (d->flags & resizeWidthOfChildren_WidgetFlag && child->flags & expand_WidgetFlag && |
739 | ~child->flags & fixedWidth_WidgetFlag) { | ||
730 | child->rect.size.x = 0; | 740 | child->rect.size.x = 0; |
731 | } | 741 | } |
732 | if (d->flags & arrangeVertical_WidgetFlag) { | 742 | if (d->flags & arrangeVertical_WidgetFlag) { |
733 | child->rect.pos.y = 0; | 743 | child->rect.pos.y = 0; |
734 | } | 744 | } |
735 | if (d->flags & resizeHeightOfChildren_WidgetFlag && child->flags & expand_WidgetFlag) { | 745 | if (d->flags & resizeHeightOfChildren_WidgetFlag && child->flags & expand_WidgetFlag && |
746 | ~child->flags & fixedHeight_WidgetFlag) { | ||
736 | child->rect.size.y = 0; | 747 | child->rect.size.y = 0; |
737 | } | 748 | } |
738 | } | 749 | } |
@@ -741,6 +752,11 @@ static void resetArrangement_Widget_(iWidget *d) { | |||
741 | 752 | ||
742 | void arrange_Widget(iWidget *d) { | 753 | void arrange_Widget(iWidget *d) { |
743 | if (d) { | 754 | if (d) { |
755 | #if !defined (NDEBUG) | ||
756 | if (tracing_) { | ||
757 | puts("\n==== NEW WIDGET ARRANGEMENT ====\n"); | ||
758 | } | ||
759 | #endif | ||
744 | resetArrangement_Widget_(d); /* back to initial default sizes */ | 760 | resetArrangement_Widget_(d); /* back to initial default sizes */ |
745 | arrange_Widget_(d); | 761 | arrange_Widget_(d); |
746 | } | 762 | } |
diff --git a/src/ui/window.c b/src/ui/window.c index 6b9956ea..87db2f3e 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -59,7 +59,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
59 | 59 | ||
60 | static iWindow *theWindow_ = NULL; | 60 | static iWindow *theWindow_ = NULL; |
61 | 61 | ||
62 | #if defined (iPlatformApple) || defined (iPlatformLinux) | 62 | #if defined (iPlatformApple) || defined (iPlatformLinux) || defined (iPlatformOther) |
63 | static float initialUiScale_ = 1.0f; | 63 | static float initialUiScale_ = 1.0f; |
64 | #else | 64 | #else |
65 | static float initialUiScale_ = 1.1f; | 65 | static float initialUiScale_ = 1.1f; |
@@ -1199,6 +1199,11 @@ void swapRoots_Window(iWindow *d) { | |||
1199 | 1199 | ||
1200 | void setSplitMode_Window(iWindow *d, int splitFlags) { | 1200 | void setSplitMode_Window(iWindow *d, int splitFlags) { |
1201 | const int splitMode = splitFlags & mode_WindowSplit; | 1201 | const int splitMode = splitFlags & mode_WindowSplit; |
1202 | if (deviceType_App() == phone_AppDeviceType) { | ||
1203 | /* There isn't enough room on the phone. */ | ||
1204 | /* TODO: Maybe in landscape only? */ | ||
1205 | return; | ||
1206 | } | ||
1202 | iAssert(current_Root() == NULL); | 1207 | iAssert(current_Root() == NULL); |
1203 | if (d->splitMode != splitMode) { | 1208 | if (d->splitMode != splitMode) { |
1204 | int oldCount = numRoots_Window(d); | 1209 | int oldCount = numRoots_Window(d); |