diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 8 | ||||
-rw-r--r-- | src/gmdocument.c | 20 | ||||
-rw-r--r-- | src/gmdocument.h | 4 | ||||
-rw-r--r-- | src/gmutil.c | 54 | ||||
-rw-r--r-- | src/gmutil.h | 1 | ||||
-rw-r--r-- | src/ios.m | 3 | ||||
-rw-r--r-- | src/media.c | 16 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 37 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 2 | ||||
-rw-r--r-- | src/ui/lookupwidget.c | 2 | ||||
-rw-r--r-- | src/ui/metrics.c | 2 | ||||
-rw-r--r-- | src/ui/mobile.c | 6 | ||||
-rw-r--r-- | src/ui/root.c | 29 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 2 | ||||
-rw-r--r-- | src/ui/text.c | 3 | ||||
-rw-r--r-- | src/ui/window.c | 38 |
16 files changed, 149 insertions, 78 deletions
@@ -1583,7 +1583,11 @@ iBool isLandscape_App(void) { | |||
1583 | } | 1583 | } |
1584 | 1584 | ||
1585 | enum iAppDeviceType deviceType_App(void) { | 1585 | enum iAppDeviceType deviceType_App(void) { |
1586 | #if defined (iPlatformAppleMobile) | 1586 | #if defined (iPlatformMobilePhone) |
1587 | return phone_AppDeviceType; | ||
1588 | #elif defined (iPlatformMobileTablet) | ||
1589 | return tablet_AppDeviceType; | ||
1590 | #elif defined (iPlatformAppleMobile) | ||
1587 | return isPhone_iOS() ? phone_AppDeviceType : tablet_AppDeviceType; | 1591 | return isPhone_iOS() ? phone_AppDeviceType : tablet_AppDeviceType; |
1588 | #else | 1592 | #else |
1589 | return desktop_AppDeviceType; | 1593 | return desktop_AppDeviceType; |
@@ -2484,7 +2488,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2484 | } | 2488 | } |
2485 | else if (equal_Command(cmd, "tabs.close")) { | 2489 | else if (equal_Command(cmd, "tabs.close")) { |
2486 | iWidget *tabs = findWidget_App("doctabs"); | 2490 | iWidget *tabs = findWidget_App("doctabs"); |
2487 | #if defined (iPlatformAppleMobile) | 2491 | #if defined (iPlatformMobile) |
2488 | /* Can't close the last on mobile. */ | 2492 | /* Can't close the last on mobile. */ |
2489 | if (tabCount_Widget(tabs) == 1 && numRoots_Window(get_Window()) == 1) { | 2493 | if (tabCount_Widget(tabs) == 1 && numRoots_Window(get_Window()) == 1) { |
2490 | postCommand_App("navigate.home"); | 2494 | postCommand_App("navigate.home"); |
diff --git a/src/gmdocument.c b/src/gmdocument.c index b9832f38..75f6f06b 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -82,6 +82,7 @@ struct Impl_GmDocument { | |||
82 | iString url; /* for resolving relative links */ | 82 | iString url; /* for resolving relative links */ |
83 | iString localHost; | 83 | iString localHost; |
84 | iInt2 size; | 84 | iInt2 size; |
85 | int outsideMargin; | ||
85 | iArray layout; /* contents of source, laid out in document space */ | 86 | iArray layout; /* contents of source, laid out in document space */ |
86 | iPtrArray links; | 87 | iPtrArray links; |
87 | enum iGmDocumentBanner bannerType; | 88 | enum iGmDocumentBanner bannerType; |
@@ -239,7 +240,10 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li | |||
239 | iString *path = newRange_String(parts.path); | 240 | iString *path = newRange_String(parts.path); |
240 | if (endsWithCase_String(path, ".gif") || endsWithCase_String(path, ".jpg") || | 241 | if (endsWithCase_String(path, ".gif") || endsWithCase_String(path, ".jpg") || |
241 | endsWithCase_String(path, ".jpeg") || endsWithCase_String(path, ".png") || | 242 | endsWithCase_String(path, ".jpeg") || endsWithCase_String(path, ".png") || |
242 | endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || | 243 | endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || |
244 | #if defined (LAGRANGE_ENABLE_WEBP) | ||
245 | endsWithCase_String(path, ".webp") || | ||
246 | #endif | ||
243 | endsWithCase_String(path, ".hdr") || endsWithCase_String(path, ".pic")) { | 247 | endsWithCase_String(path, ".hdr") || endsWithCase_String(path, ".pic")) { |
244 | link->flags |= imageFileExtension_GmLinkFlag; | 248 | link->flags |= imageFileExtension_GmLinkFlag; |
245 | } | 249 | } |
@@ -896,6 +900,12 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
896 | pos.y += margin; | 900 | pos.y += margin; |
897 | run.bounds.pos = pos; | 901 | run.bounds.pos = pos; |
898 | run.bounds.size.x = d->size.x; | 902 | run.bounds.size.x = d->size.x; |
903 | /* Extend the image to full width, including outside margin, if the viewport | ||
904 | is narrow enough. */ | ||
905 | if (d->outsideMargin < 5 * gap_UI) { | ||
906 | run.bounds.size.x += d->outsideMargin * 2; | ||
907 | run.bounds.pos.x -= d->outsideMargin; | ||
908 | } | ||
899 | const float aspect = (float) imgSize.y / (float) imgSize.x; | 909 | const float aspect = (float) imgSize.y / (float) imgSize.x; |
900 | run.bounds.size.y = d->size.x * aspect; | 910 | run.bounds.size.y = d->size.x * aspect; |
901 | run.visBounds = run.bounds; | 911 | run.visBounds = run.bounds; |
@@ -990,6 +1000,7 @@ void init_GmDocument(iGmDocument *d) { | |||
990 | init_String(&d->url); | 1000 | init_String(&d->url); |
991 | init_String(&d->localHost); | 1001 | init_String(&d->localHost); |
992 | d->bannerType = siteDomain_GmDocumentBanner; | 1002 | d->bannerType = siteDomain_GmDocumentBanner; |
1003 | d->outsideMargin = 0; | ||
993 | d->size = zero_I2(); | 1004 | d->size = zero_I2(); |
994 | init_Array(&d->layout, sizeof(iGmRun)); | 1005 | init_Array(&d->layout, sizeof(iGmRun)); |
995 | init_PtrArray(&d->links); | 1006 | init_PtrArray(&d->links); |
@@ -1543,8 +1554,9 @@ void setBanner_GmDocument(iGmDocument *d, enum iGmDocumentBanner type) { | |||
1543 | d->bannerType = type; | 1554 | d->bannerType = type; |
1544 | } | 1555 | } |
1545 | 1556 | ||
1546 | void setWidth_GmDocument(iGmDocument *d, int width) { | 1557 | void setWidth_GmDocument(iGmDocument *d, int width, int outsideMargin) { |
1547 | d->size.x = width; | 1558 | d->size.x = width; |
1559 | d->outsideMargin = outsideMargin; /* distance to edge of the viewport */ | ||
1548 | doLayout_GmDocument_(d); /* TODO: just flag need-layout and do it later */ | 1560 | doLayout_GmDocument_(d); /* TODO: just flag need-layout and do it later */ |
1549 | } | 1561 | } |
1550 | 1562 | ||
@@ -1698,7 +1710,7 @@ void setUrl_GmDocument(iGmDocument *d, const iString *url) { | |||
1698 | updateIconBasedOnUrl_GmDocument_(d); | 1710 | updateIconBasedOnUrl_GmDocument_(d); |
1699 | } | 1711 | } |
1700 | 1712 | ||
1701 | void setSource_GmDocument(iGmDocument *d, const iString *source, int width, | 1713 | void setSource_GmDocument(iGmDocument *d, const iString *source, int width, int outsideMargin, |
1702 | enum iGmDocumentUpdate updateType) { | 1714 | enum iGmDocumentUpdate updateType) { |
1703 | // printf("[GmDocument] source update (%zu bytes), width:%d, final:%d\n", | 1715 | // printf("[GmDocument] source update (%zu bytes), width:%d, final:%d\n", |
1704 | // size_String(source), width, updateType == final_GmDocumentUpdate); | 1716 | // size_String(source), width, updateType == final_GmDocumentUpdate); |
@@ -1713,7 +1725,7 @@ void setSource_GmDocument(iGmDocument *d, const iString *source, int width, | |||
1713 | if (isNormalized_GmDocument_(d)) { | 1725 | if (isNormalized_GmDocument_(d)) { |
1714 | normalize_GmDocument(d); | 1726 | normalize_GmDocument(d); |
1715 | } | 1727 | } |
1716 | setWidth_GmDocument(d, width); /* re-do layout */ | 1728 | setWidth_GmDocument(d, width, outsideMargin); /* re-do layout */ |
1717 | } | 1729 | } |
1718 | 1730 | ||
1719 | void foldPre_GmDocument(iGmDocument *d, uint16_t preId) { | 1731 | void foldPre_GmDocument(iGmDocument *d, uint16_t preId) { |
diff --git a/src/gmdocument.h b/src/gmdocument.h index 9a7a70df..9f8ee2ef 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -174,11 +174,11 @@ enum iGmDocumentUpdate { | |||
174 | void setThemeSeed_GmDocument (iGmDocument *, const iBlock *seed); | 174 | void setThemeSeed_GmDocument (iGmDocument *, const iBlock *seed); |
175 | void setFormat_GmDocument (iGmDocument *, enum iSourceFormat format); | 175 | void setFormat_GmDocument (iGmDocument *, enum iSourceFormat format); |
176 | void setBanner_GmDocument (iGmDocument *, enum iGmDocumentBanner type); | 176 | void setBanner_GmDocument (iGmDocument *, enum iGmDocumentBanner type); |
177 | void setWidth_GmDocument (iGmDocument *, int width); | 177 | void setWidth_GmDocument (iGmDocument *, int width, int outsideMargin); |
178 | void redoLayout_GmDocument (iGmDocument *); | 178 | void redoLayout_GmDocument (iGmDocument *); |
179 | iBool updateOpenURLs_GmDocument(iGmDocument *); | 179 | iBool updateOpenURLs_GmDocument(iGmDocument *); |
180 | void setUrl_GmDocument (iGmDocument *, const iString *url); | 180 | void setUrl_GmDocument (iGmDocument *, const iString *url); |
181 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, | 181 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, int outsideMargin, |
182 | enum iGmDocumentUpdate updateType); | 182 | enum iGmDocumentUpdate updateType); |
183 | void foldPre_GmDocument (iGmDocument *, uint16_t preId); | 183 | void foldPre_GmDocument (iGmDocument *, uint16_t preId); |
184 | 184 | ||
diff --git a/src/gmutil.c b/src/gmutil.c index 9552c2a1..d87de8f6 100644 --- a/src/gmutil.c +++ b/src/gmutil.c | |||
@@ -511,54 +511,64 @@ const iString *findContainerArchive_Path(const iString *path) { | |||
511 | return NULL; | 511 | return NULL; |
512 | } | 512 | } |
513 | 513 | ||
514 | const char *mediaType_Path(const iString *path) { | 514 | const char *mediaTypeFromFileExtension_String(const iString *d) { |
515 | if (endsWithCase_String(path, ".gmi") || endsWithCase_String(path, ".gemini")) { | 515 | if (endsWithCase_String(d, ".gmi") || endsWithCase_String(d, ".gemini")) { |
516 | return "text/gemini; charset=utf-8"; | 516 | return "text/gemini; charset=utf-8"; |
517 | } | 517 | } |
518 | else if (endsWithCase_String(path, ".pem")) { | 518 | else if (endsWithCase_String(d, ".pem")) { |
519 | return "application/x-pem-file"; | 519 | return "application/x-pem-file"; |
520 | } | 520 | } |
521 | else if (endsWithCase_String(path, ".zip")) { | 521 | else if (endsWithCase_String(d, ".zip")) { |
522 | return "application/zip"; | 522 | return "application/zip"; |
523 | } | 523 | } |
524 | else if (endsWithCase_String(path, ".gpub")) { | 524 | else if (endsWithCase_String(d, ".gpub")) { |
525 | return "application/gpub+zip"; | 525 | return "application/gpub+zip"; |
526 | } | 526 | } |
527 | else if (endsWithCase_String(path, ".xml")) { | 527 | else if (endsWithCase_String(d, ".xml")) { |
528 | return "text/xml"; | 528 | return "text/xml"; |
529 | } | 529 | } |
530 | else if (endsWithCase_String(path, ".png")) { | 530 | else if (endsWithCase_String(d, ".png")) { |
531 | return "image/png"; | 531 | return "image/png"; |
532 | } | 532 | } |
533 | else if (endsWithCase_String(path, ".jpg") || endsWithCase_String(path, ".jpeg")) { | 533 | else if (endsWithCase_String(d, ".webp")) { |
534 | return "image/webp"; | ||
535 | } | ||
536 | else if (endsWithCase_String(d, ".jpg") || endsWithCase_String(d, ".jpeg")) { | ||
534 | return "image/jpeg"; | 537 | return "image/jpeg"; |
535 | } | 538 | } |
536 | else if (endsWithCase_String(path, ".gif")) { | 539 | else if (endsWithCase_String(d, ".gif")) { |
537 | return "image/gif"; | 540 | return "image/gif"; |
538 | } | 541 | } |
539 | else if (endsWithCase_String(path, ".wav")) { | 542 | else if (endsWithCase_String(d, ".wav")) { |
540 | return "audio/wave"; | 543 | return "audio/wave"; |
541 | } | 544 | } |
542 | else if (endsWithCase_String(path, ".ogg")) { | 545 | else if (endsWithCase_String(d, ".ogg")) { |
543 | return "audio/ogg"; | 546 | return "audio/ogg"; |
544 | } | 547 | } |
545 | else if (endsWithCase_String(path, ".mp3")) { | 548 | else if (endsWithCase_String(d, ".mp3")) { |
546 | return "audio/mpeg"; | 549 | return "audio/mpeg"; |
547 | } | 550 | } |
548 | else if (endsWithCase_String(path, ".mid")) { | 551 | else if (endsWithCase_String(d, ".mid")) { |
549 | return "audio/midi"; | 552 | return "audio/midi"; |
550 | } | 553 | } |
551 | else if (endsWithCase_String(path, ".txt") || | 554 | else if (endsWithCase_String(d, ".txt") || |
552 | endsWithCase_String(path, ".md") || | 555 | endsWithCase_String(d, ".md") || |
553 | endsWithCase_String(path, ".c") || | 556 | endsWithCase_String(d, ".c") || |
554 | endsWithCase_String(path, ".h") || | 557 | endsWithCase_String(d, ".h") || |
555 | endsWithCase_String(path, ".cc") || | 558 | endsWithCase_String(d, ".cc") || |
556 | endsWithCase_String(path, ".hh") || | 559 | endsWithCase_String(d, ".hh") || |
557 | endsWithCase_String(path, ".cpp") || | 560 | endsWithCase_String(d, ".cpp") || |
558 | endsWithCase_String(path, ".hpp")) { | 561 | endsWithCase_String(d, ".hpp")) { |
559 | return "text/plain"; | 562 | return "text/plain"; |
560 | } | 563 | } |
561 | const char *mtype = "application/octet-stream"; | 564 | return "application/octet-stream"; |
565 | } | ||
566 | |||
567 | const char *mediaType_Path(const iString *path) { | ||
568 | const char *mtype = mediaTypeFromFileExtension_String(path); | ||
569 | if (iCmpStr(mtype, "application/octet-stream")) { | ||
570 | return mtype; /* extension recognized */ | ||
571 | } | ||
562 | /* If the file is reasonably small and looks like UTF-8, we'll display it as text/plain. */ | 572 | /* If the file is reasonably small and looks like UTF-8, we'll display it as text/plain. */ |
563 | if (fileExists_FileInfo(path) && fileSize_FileInfo(path) <= 5000000) { | 573 | if (fileExists_FileInfo(path) && fileSize_FileInfo(path) <= 5000000) { |
564 | iFile *f = new_File(path); | 574 | iFile *f = new_File(path); |
diff --git a/src/gmutil.h b/src/gmutil.h index f8491781..3c10d45b 100644 --- a/src/gmutil.h +++ b/src/gmutil.h | |||
@@ -133,6 +133,7 @@ const iString * withSpacesEncoded_String(const iString *); | |||
133 | const iString * canonicalUrl_String (const iString *); | 133 | const iString * canonicalUrl_String (const iString *); |
134 | 134 | ||
135 | const char * mediaType_Path (const iString *path); | 135 | const char * mediaType_Path (const iString *path); |
136 | const char * mediaTypeFromFileExtension_String (const iString *); | ||
136 | iRangecc mediaTypeWithoutParameters_Rangecc (iRangecc mime); | 137 | iRangecc mediaTypeWithoutParameters_Rangecc (iRangecc mime); |
137 | 138 | ||
138 | const iString * findContainerArchive_Path (const iString *path); | 139 | const iString * findContainerArchive_Path (const iString *path); |
@@ -264,7 +264,6 @@ void setupApplication_iOS(void) { | |||
264 | selector:@selector(keyboardOffScreen:) | 264 | selector:@selector(keyboardOffScreen:) |
265 | name:UIKeyboardWillHideNotification | 265 | name:UIKeyboardWillHideNotification |
266 | object:nil]; | 266 | object:nil]; |
267 | [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; | ||
268 | /* Media player remote controls. */ | 267 | /* Media player remote controls. */ |
269 | MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; | 268 | MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; |
270 | [[commandCenter pauseCommand] addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { | 269 | [[commandCenter pauseCommand] addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { |
@@ -487,6 +486,8 @@ void init_AVFAudioPlayer(iAVFAudioPlayer *d) { | |||
487 | d->player = NULL; | 486 | d->player = NULL; |
488 | d->volume = 1.0f; | 487 | d->volume = 1.0f; |
489 | d->state = initialized_AVFAudioPlayerState; | 488 | d->state = initialized_AVFAudioPlayerState; |
489 | /* Playback is imminent. */ | ||
490 | [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; | ||
490 | } | 491 | } |
491 | 492 | ||
492 | void deinit_AVFAudioPlayer(iAVFAudioPlayer *d) { | 493 | void deinit_AVFAudioPlayer(iAVFAudioPlayer *d) { |
diff --git a/src/media.c b/src/media.c index eb4a8311..5240ab5d 100644 --- a/src/media.c +++ b/src/media.c | |||
@@ -30,6 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
30 | #include "stb_image.h" | 30 | #include "stb_image.h" |
31 | #include "stb_image_resize.h" | 31 | #include "stb_image_resize.h" |
32 | 32 | ||
33 | #if defined (LAGRANGE_ENABLE_WEBP) | ||
34 | # include <webp/decode.h> | ||
35 | #endif | ||
36 | |||
33 | #include <the_Foundation/file.h> | 37 | #include <the_Foundation/file.h> |
34 | #include <the_Foundation/ptrarray.h> | 38 | #include <the_Foundation/ptrarray.h> |
35 | #include <SDL_hints.h> | 39 | #include <SDL_hints.h> |
@@ -86,8 +90,16 @@ void deinit_GmImage(iGmImage *d) { | |||
86 | void makeTexture_GmImage(iGmImage *d) { | 90 | void makeTexture_GmImage(iGmImage *d) { |
87 | iBlock *data = &d->partialData; | 91 | iBlock *data = &d->partialData; |
88 | d->numBytes = size_Block(data); | 92 | d->numBytes = size_Block(data); |
89 | uint8_t *imgData = stbi_load_from_memory( | 93 | uint8_t *imgData = NULL; |
90 | constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); | 94 | if (cmp_String(&d->props.mime, "image/webp") == 0) { |
95 | #if defined (LAGRANGE_ENABLE_WEBP) | ||
96 | imgData = WebPDecodeRGBA(constData_Block(data), size_Block(data), &d->size.x, &d->size.y); | ||
97 | #endif | ||
98 | } | ||
99 | else { | ||
100 | imgData = stbi_load_from_memory( | ||
101 | constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); | ||
102 | } | ||
91 | if (!imgData) { | 103 | if (!imgData) { |
92 | d->size = zero_I2(); | 104 | d->size = zero_I2(); |
93 | d->texture = NULL; | 105 | d->texture = NULL; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 7e138902..76e843d5 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1054,9 +1054,12 @@ static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) { | |||
1054 | 1054 | ||
1055 | void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { | 1055 | void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { |
1056 | setUrl_GmDocument(d->doc, d->mod.url); | 1056 | setUrl_GmDocument(d->doc, d->mod.url); |
1057 | const int docWidth = documentWidth_DocumentWidget_(d); | ||
1058 | const int outsideMargin = (width_Widget(d) - docWidth) / 2; | ||
1057 | setSource_GmDocument(d->doc, | 1059 | setSource_GmDocument(d->doc, |
1058 | source, | 1060 | source, |
1059 | documentWidth_DocumentWidget_(d), | 1061 | docWidth, |
1062 | outsideMargin, | ||
1060 | isFinished_GmRequest(d->request) ? final_GmDocumentUpdate | 1063 | isFinished_GmRequest(d->request) ? final_GmDocumentUpdate |
1061 | : partial_GmDocumentUpdate); | 1064 | : partial_GmDocumentUpdate); |
1062 | documentWasChanged_DocumentWidget_(d); | 1065 | documentWasChanged_DocumentWidget_(d); |
@@ -1165,13 +1168,25 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode | |||
1165 | iString *key = collectNew_String(); | 1168 | iString *key = collectNew_String(); |
1166 | toString_Sym(SDLK_s, KMOD_PRIMARY, key); | 1169 | toString_Sym(SDLK_s, KMOD_PRIMARY, key); |
1167 | appendFormat_String(src, "\n```\n%s\n```\n", cstr_String(meta)); | 1170 | appendFormat_String(src, "\n```\n%s\n```\n", cstr_String(meta)); |
1168 | makeFooterButtons_DocumentWidget_( | 1171 | const char *mtype = mediaTypeFromFileExtension_String(d->mod.url); |
1169 | d, | 1172 | iArray items; |
1170 | (iMenuItem[]){ { translateCStr_Lang(download_Icon " " saveToDownloads_Label), | 1173 | init_Array(&items, sizeof(iMenuItem)); |
1171 | 0, | 1174 | if (iCmpStr(mtype, "application/octet-stream")) { |
1172 | 0, | 1175 | pushBack_Array( |
1173 | "document.save" } }, | 1176 | &items, |
1174 | 1); | 1177 | &(iMenuItem){ translateCStr_Lang(format_CStr("View as \"%s\"", mtype)), |
1178 | SDLK_RETURN, | ||
1179 | 0, | ||
1180 | format_CStr("document.setmediatype mime:%s", mtype) }); | ||
1181 | } | ||
1182 | pushBack_Array( | ||
1183 | &items, | ||
1184 | &(iMenuItem){ translateCStr_Lang(download_Icon " " saveToDownloads_Label), | ||
1185 | 0, | ||
1186 | 0, | ||
1187 | "document.save" }); | ||
1188 | makeFooterButtons_DocumentWidget_(d, data_Array(&items), size_Array(&items)); | ||
1189 | deinit_Array(&items); | ||
1175 | break; | 1190 | break; |
1176 | } | 1191 | } |
1177 | default: | 1192 | default: |
@@ -2254,7 +2269,7 @@ static iBool updateDocumentWidthRetainingScrollPosition_DocumentWidget_(iDocumen | |||
2254 | /* TODO: First *fully* visible run? */ | 2269 | /* TODO: First *fully* visible run? */ |
2255 | voffset = visibleRange_DocumentWidget_(d).start - top_Rect(run->visBounds); | 2270 | voffset = visibleRange_DocumentWidget_(d).start - top_Rect(run->visBounds); |
2256 | } | 2271 | } |
2257 | setWidth_GmDocument(d->doc, newWidth); | 2272 | setWidth_GmDocument(d->doc, newWidth, (width_Widget(d) - newWidth) / 2); |
2258 | documentRunsInvalidated_DocumentWidget_(d); | 2273 | documentRunsInvalidated_DocumentWidget_(d); |
2259 | if (runLoc && !keepCenter) { | 2274 | if (runLoc && !keepCenter) { |
2260 | run = findRunAtLoc_GmDocument(d->doc, runLoc); | 2275 | run = findRunAtLoc_GmDocument(d->doc, runLoc); |
@@ -3173,6 +3188,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
3173 | document_App() == d) { | 3188 | document_App() == d) { |
3174 | return handleSwipe_DocumentWidget_(d, cmd); | 3189 | return handleSwipe_DocumentWidget_(d, cmd); |
3175 | } | 3190 | } |
3191 | else if (equal_Command(cmd, "document.setmediatype") && document_App() == d) { | ||
3192 | setUrlAndSource_DocumentWidget(d, d->mod.url, string_Command(cmd, "mime"), &d->sourceContent); | ||
3193 | return iTrue; | ||
3194 | } | ||
3176 | return iFalse; | 3195 | return iFalse; |
3177 | } | 3196 | } |
3178 | 3197 | ||
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index ef306ab9..3bfa600b 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -68,7 +68,7 @@ static iInt2 padding_LabelWidget_(const iLabelWidget *d, int corner) { | |||
68 | : corner == 1 ? init_I2(w->padding[2], w->padding[1]) | 68 | : corner == 1 ? init_I2(w->padding[2], w->padding[1]) |
69 | : corner == 2 ? init_I2(w->padding[2], w->padding[3]) | 69 | : corner == 2 ? init_I2(w->padding[2], w->padding[3]) |
70 | : init_I2(w->padding[0], w->padding[3])); | 70 | : init_I2(w->padding[0], w->padding[3])); |
71 | #if defined (iPlatformAppleMobile) | 71 | #if defined (iPlatformMobile) |
72 | return add_I2(widgetPad, | 72 | return add_I2(widgetPad, |
73 | init_I2(flags & tight_WidgetFlag ? 2 * gap_UI : (4 * gap_UI), | 73 | init_I2(flags & tight_WidgetFlag ? 2 * gap_UI : (4 * gap_UI), |
74 | (flags & extraPadding_WidgetFlag ? 1.5f : 1.0f) * 3 * gap_UI / 2)); | 74 | (flags & extraPadding_WidgetFlag ? 1.5f : 1.0f) * 3 * gap_UI / 2)); |
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c index a0a507ca..bf190d58 100644 --- a/src/ui/lookupwidget.c +++ b/src/ui/lookupwidget.c | |||
@@ -388,7 +388,7 @@ void init_LookupWidget(iLookupWidget *d) { | |||
388 | init_Widget(w); | 388 | init_Widget(w); |
389 | setId_Widget(w, "lookup"); | 389 | setId_Widget(w, "lookup"); |
390 | setFlags_Widget(w, focusable_WidgetFlag, iTrue); | 390 | setFlags_Widget(w, focusable_WidgetFlag, iTrue); |
391 | #if defined (iPlatformAppleMobile) | 391 | #if defined (iPlatformMobile) |
392 | setFlags_Widget(w, unhittable_WidgetFlag, iTrue); | 392 | setFlags_Widget(w, unhittable_WidgetFlag, iTrue); |
393 | #endif | 393 | #endif |
394 | d->list = addChildFlags_Widget(w, iClob(new_ListWidget()), | 394 | d->list = addChildFlags_Widget(w, iClob(new_ListWidget()), |
diff --git a/src/ui/metrics.c b/src/ui/metrics.c index 32561ed7..53a52afb 100644 --- a/src/ui/metrics.c +++ b/src/ui/metrics.c | |||
@@ -33,7 +33,7 @@ iInt2 gap2_UI = { defaultGap_Metrics, defaultGap_Metrics }; | |||
33 | int fontSize_UI = defaultFontSize_Metrics; | 33 | int fontSize_UI = defaultFontSize_Metrics; |
34 | 34 | ||
35 | void setScale_Metrics(float scale) { | 35 | void setScale_Metrics(float scale) { |
36 | #if defined (iPlatformAppleMobile) | 36 | #if defined (iPlatformMobile) |
37 | /* iPad needs a bit larger UI elements as the viewing distance is generally longer.*/ | 37 | /* iPad needs a bit larger UI elements as the viewing distance is generally longer.*/ |
38 | if (deviceType_App() == tablet_AppDeviceType) { | 38 | if (deviceType_App() == tablet_AppDeviceType) { |
39 | scale *= 1.1f; | 39 | scale *= 1.1f; |
diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 0ff3fe85..168a92b8 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c | |||
@@ -57,11 +57,13 @@ static enum iFontId labelBoldFont_(void) { | |||
57 | 57 | ||
58 | static void updatePanelSheetMetrics_(iWidget *sheet) { | 58 | static void updatePanelSheetMetrics_(iWidget *sheet) { |
59 | iWidget *navi = findChild_Widget(sheet, "panel.navi"); | 59 | iWidget *navi = findChild_Widget(sheet, "panel.navi"); |
60 | iWidget *naviPad = child_Widget(navi, 0); | 60 | // iWidget *naviPad = child_Widget(navi, 0); |
61 | int naviHeight = lineHeight_Text(labelFont_()) + 4 * gap_UI; | 61 | int naviHeight = lineHeight_Text(labelFont_()) + 4 * gap_UI; |
62 | #if defined (iPlatformMobile) | ||
63 | float left = 0.0f, right = 0.0f, top = 0.0f, bottom = 0.0f; | ||
62 | #if defined (iPlatformAppleMobile) | 64 | #if defined (iPlatformAppleMobile) |
63 | float left, right, top, bottom; | ||
64 | safeAreaInsets_iOS(&left, &top, &right, &bottom); | 65 | safeAreaInsets_iOS(&left, &top, &right, &bottom); |
66 | #endif | ||
65 | setPadding_Widget(sheet, left, 0, right, 0); | 67 | setPadding_Widget(sheet, left, 0, right, 0); |
66 | navi->rect.pos = init_I2(left, top); | 68 | navi->rect.pos = init_I2(left, top); |
67 | iConstForEach(PtrArray, i, findChildren_Widget(sheet, "panel.toppad")) { | 69 | iConstForEach(PtrArray, i, findChildren_Widget(sheet, "panel.toppad")) { |
diff --git a/src/ui/root.c b/src/ui/root.c index a8b9f998..a72f002c 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -83,7 +83,7 @@ static const iMenuItem navMenuItems_[] = { | |||
83 | }; | 83 | }; |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | #if defined (iPlatformAppleMobile) | 86 | #if defined (iPlatformMobile) |
87 | /* Tablet menu. */ | 87 | /* Tablet menu. */ |
88 | static const iMenuItem tabletNavMenuItems_[] = { | 88 | static const iMenuItem tabletNavMenuItems_[] = { |
89 | { folder_Icon " ${menu.openfile}", SDLK_o, KMOD_PRIMARY, "file.open" }, | 89 | { folder_Icon " ${menu.openfile}", SDLK_o, KMOD_PRIMARY, "file.open" }, |
@@ -120,9 +120,9 @@ static const iMenuItem phoneNavMenuItems_[] = { | |||
120 | { "---", 0, 0, NULL }, | 120 | { "---", 0, 0, NULL }, |
121 | { gear_Icon " Settings...", SDLK_COMMA, KMOD_PRIMARY, "preferences" }, | 121 | { gear_Icon " Settings...", SDLK_COMMA, KMOD_PRIMARY, "preferences" }, |
122 | }; | 122 | }; |
123 | #endif /* AppleMobile */ | 123 | #endif /* Mobile */ |
124 | 124 | ||
125 | #if defined (iPlatformAppleMobile) | 125 | #if defined (iPlatformMobile) |
126 | static const iMenuItem identityButtonMenuItems_[] = { | 126 | static const iMenuItem identityButtonMenuItems_[] = { |
127 | { "${menu.identity.notactive}", 0, 0, "ident.showactive" }, | 127 | { "${menu.identity.notactive}", 0, 0, "ident.showactive" }, |
128 | { "---", 0, 0, NULL }, | 128 | { "---", 0, 0, NULL }, |
@@ -498,9 +498,10 @@ static void checkLoadAnimation_Root_(iRoot *d) { | |||
498 | 498 | ||
499 | void updatePadding_Root(iRoot *d) { | 499 | void updatePadding_Root(iRoot *d) { |
500 | if (d == NULL) return; | 500 | if (d == NULL) return; |
501 | #if defined (iPlatformAppleMobile) | ||
502 | iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); | 501 | iWidget *toolBar = findChild_Widget(d->widget, "toolbar"); |
503 | float left, top, right, bottom; | 502 | float bottom = 0.0f; |
503 | #if defined (iPlatformAppleMobile) | ||
504 | float left, top, right; | ||
504 | safeAreaInsets_iOS(&left, &top, &right, &bottom); | 505 | safeAreaInsets_iOS(&left, &top, &right, &bottom); |
505 | /* Respect the safe area insets. */ { | 506 | /* Respect the safe area insets. */ { |
506 | setPadding_Widget(findChild_Widget(d->widget, "navdiv"), left, top, right, 0); | 507 | setPadding_Widget(findChild_Widget(d->widget, "navdiv"), left, top, right, 0); |
@@ -508,6 +509,7 @@ void updatePadding_Root(iRoot *d) { | |||
508 | setPadding_Widget(toolBar, left, 0, right, bottom); | 509 | setPadding_Widget(toolBar, left, 0, right, bottom); |
509 | } | 510 | } |
510 | } | 511 | } |
512 | #endif | ||
511 | if (toolBar) { | 513 | if (toolBar) { |
512 | /* TODO: get this from toolBar height, but it's buggy for some reason */ | 514 | /* TODO: get this from toolBar height, but it's buggy for some reason */ |
513 | const int sidebarBottomPad = isPortrait_App() ? 11 * gap_UI + bottom : 0; | 515 | const int sidebarBottomPad = isPortrait_App() ? 11 * gap_UI + bottom : 0; |
@@ -517,7 +519,6 @@ void updatePadding_Root(iRoot *d) { | |||
517 | are not arranged correctly until it's hidden and reshown. */ | 519 | are not arranged correctly until it's hidden and reshown. */ |
518 | } | 520 | } |
519 | /* Note that `handleNavBarCommands_` also adjusts padding and spacing. */ | 521 | /* Note that `handleNavBarCommands_` also adjusts padding and spacing. */ |
520 | #endif | ||
521 | } | 522 | } |
522 | 523 | ||
523 | void updateToolbarColors_Root(iRoot *d) { | 524 | void updateToolbarColors_Root(iRoot *d) { |
@@ -829,13 +830,13 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { | |||
829 | return iFalse; | 830 | return iFalse; |
830 | } | 831 | } |
831 | 832 | ||
832 | #if defined (iPlatformAppleMobile) | 833 | #if defined (iPlatformMobile) |
833 | static void dismissSidebar_(iWidget *sidebar, const char *toolButtonId) { | 834 | static void dismissSidebar_(iWidget *sidebar, const char *toolButtonId) { |
834 | if (isVisible_Widget(sidebar)) { | 835 | if (isVisible_Widget(sidebar)) { |
835 | postCommandf_App("%s.toggle", cstr_String(id_Widget(sidebar))); | 836 | postCommandf_App("%s.toggle", cstr_String(id_Widget(sidebar))); |
836 | if (toolButtonId) { | 837 | // if (toolButtonId) { |
837 | // setFlags_Widget(findWidget_App(toolButtonId), noBackground_WidgetFlag, iTrue); | 838 | // setFlags_Widget(findWidget_App(toolButtonId), noBackground_WidgetFlag, iTrue); |
838 | } | 839 | // } |
839 | setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); | 840 | setVisualOffset_Widget(sidebar, height_Widget(sidebar), 250, easeIn_AnimFlag); |
840 | } | 841 | } |
841 | } | 842 | } |
@@ -909,7 +910,7 @@ static iBool handleToolBarCommands_(iWidget *toolBar, const char *cmd) { | |||
909 | } | 910 | } |
910 | return iFalse; | 911 | return iFalse; |
911 | } | 912 | } |
912 | #endif /* defined (iPlatformAppleMobile) */ | 913 | #endif /* defined (iPlatformMobile) */ |
913 | 914 | ||
914 | static iLabelWidget *newLargeIcon_LabelWidget(const char *text, const char *cmd) { | 915 | static iLabelWidget *newLargeIcon_LabelWidget(const char *text, const char *cmd) { |
915 | iLabelWidget *lab = newIcon_LabelWidget(text, 0, 0, cmd); | 916 | iLabelWidget *lab = newIcon_LabelWidget(text, 0, 0, cmd); |
@@ -1198,8 +1199,8 @@ void createUserInterface_Root(iRoot *d) { | |||
1198 | #if defined (iPlatformMobile) | 1199 | #if defined (iPlatformMobile) |
1199 | const iBool isPhone = (deviceType_App() == phone_AppDeviceType); | 1200 | const iBool isPhone = (deviceType_App() == phone_AppDeviceType); |
1200 | #endif | 1201 | #endif |
1201 | #if !defined (iHaveNativeMenus) | 1202 | #if !defined (iHaveNativeMenus) || defined (iPlatformMobile) |
1202 | # if defined (iPlatformAppleMobile) | 1203 | # if defined (iPlatformMobile) |
1203 | iLabelWidget *navMenu = | 1204 | iLabelWidget *navMenu = |
1204 | makeMenuButton_LabelWidget(menu_Icon, isPhone ? phoneNavMenuItems_ : tabletNavMenuItems_, | 1205 | makeMenuButton_LabelWidget(menu_Icon, isPhone ? phoneNavMenuItems_ : tabletNavMenuItems_, |
1205 | isPhone ? iElemCount(phoneNavMenuItems_) : iElemCount(tabletNavMenuItems_)); | 1206 | isPhone ? iElemCount(phoneNavMenuItems_) : iElemCount(tabletNavMenuItems_)); |
@@ -1280,9 +1281,9 @@ void createUserInterface_Root(iRoot *d) { | |||
1280 | addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev"))); | 1281 | addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev"))); |
1281 | addChild_Widget(searchBar, iClob(newIcon_LabelWidget(close_Icon, SDLK_ESCAPE, 0, "find.close"))); | 1282 | addChild_Widget(searchBar, iClob(newIcon_LabelWidget(close_Icon, SDLK_ESCAPE, 0, "find.close"))); |
1282 | } | 1283 | } |
1283 | #if defined (iPlatformAppleMobile) | 1284 | #if defined (iPlatformMobile) |
1284 | /* Bottom toolbar. */ | 1285 | /* Bottom toolbar. */ |
1285 | if (isPhone_iOS()) { | 1286 | if (deviceType_App() == phone_AppDeviceType) { |
1286 | iWidget *toolBar = new_Widget(); | 1287 | iWidget *toolBar = new_Widget(); |
1287 | addChild_Widget(root, iClob(toolBar)); | 1288 | addChild_Widget(root, iClob(toolBar)); |
1288 | setId_Widget(toolBar, "toolbar"); | 1289 | setId_Widget(toolBar, "toolbar"); |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index c2ad7bc6..b816b572 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -644,7 +644,7 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { | |||
644 | d->buttonFont = uiLabel_FontId; | 644 | d->buttonFont = uiLabel_FontId; |
645 | d->itemFonts[0] = uiContent_FontId; | 645 | d->itemFonts[0] = uiContent_FontId; |
646 | d->itemFonts[1] = uiContentBold_FontId; | 646 | d->itemFonts[1] = uiContentBold_FontId; |
647 | #if defined (iPlatformAppleMobile) | 647 | #if defined (iPlatformMobile) |
648 | if (deviceType_App() == phone_AppDeviceType) { | 648 | if (deviceType_App() == phone_AppDeviceType) { |
649 | d->itemFonts[0] = defaultBig_FontId; | 649 | d->itemFonts[0] = defaultBig_FontId; |
650 | d->itemFonts[1] = defaultBigBold_FontId; | 650 | d->itemFonts[1] = defaultBigBold_FontId; |
diff --git a/src/ui/text.c b/src/ui/text.c index 006a4d0b..231281eb 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -361,7 +361,7 @@ static void initFonts_Text_(iText *d) { | |||
361 | h12Font = &fontIosevkaTermExtended_Embedded; | 361 | h12Font = &fontIosevkaTermExtended_Embedded; |
362 | h3Font = &fontIosevkaTermExtended_Embedded; | 362 | h3Font = &fontIosevkaTermExtended_Embedded; |
363 | } | 363 | } |
364 | #if defined (iPlatformAppleMobile) | 364 | #if defined (iPlatformMobile) |
365 | const float uiSize = fontSize_UI * 1.1f; | 365 | const float uiSize = fontSize_UI * 1.1f; |
366 | #else | 366 | #else |
367 | const float uiSize = fontSize_UI; | 367 | const float uiSize = fontSize_UI; |
@@ -889,6 +889,7 @@ static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh | |||
889 | resize_Array(&d->visualToLogical, length); | 889 | resize_Array(&d->visualToLogical, length); |
890 | d->bidiLevels = length ? malloc(length) : NULL; | 890 | d->bidiLevels = length ? malloc(length) : NULL; |
891 | FriBidiParType baseDir = (FriBidiParType) FRIBIDI_TYPE_ON; | 891 | FriBidiParType baseDir = (FriBidiParType) FRIBIDI_TYPE_ON; |
892 | /* TODO: If this returns zero (error occurred), act like everything is LTR. */ | ||
892 | fribidi_log2vis(constData_Array(&d->logical), | 893 | fribidi_log2vis(constData_Array(&d->logical), |
893 | length, | 894 | length, |
894 | &baseDir, | 895 | &baseDir, |
diff --git a/src/ui/window.c b/src/ui/window.c index f8391ed9..3ac02495 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -443,7 +443,11 @@ void init_Window(iWindow *d, iRect rect) { | |||
443 | if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { | 443 | if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { |
444 | SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); | 444 | SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); |
445 | } | 445 | } |
446 | #if defined (iPlatformMobile) | ||
447 | const iInt2 minSize = zero_I2(); /* windows aren't independently resizable */ | ||
448 | #else | ||
446 | const iInt2 minSize = init_I2(425, 325); | 449 | const iInt2 minSize = init_I2(425, 325); |
450 | #endif | ||
447 | SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y); | 451 | SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y); |
448 | SDL_SetWindowTitle(d->win, "Lagrange"); | 452 | SDL_SetWindowTitle(d->win, "Lagrange"); |
449 | /* Some info. */ { | 453 | /* Some info. */ { |
@@ -712,7 +716,6 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
712 | } | 716 | } |
713 | } | 717 | } |
714 | #endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */ | 718 | #endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */ |
715 | //printf("MOVED: %d, %d\n", ev->data1, ev->data2); fflush(stdout); | ||
716 | if (unsnap_Window_(d, &newPos)) { | 719 | if (unsnap_Window_(d, &newPos)) { |
717 | return iTrue; | 720 | return iTrue; |
718 | } | 721 | } |
@@ -753,7 +756,13 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
753 | case SDL_WINDOWEVENT_MINIMIZED: | 756 | case SDL_WINDOWEVENT_MINIMIZED: |
754 | d->isMinimized = iTrue; | 757 | d->isMinimized = iTrue; |
755 | return iTrue; | 758 | return iTrue; |
756 | #endif /* defined (iPlatformDesktop) */ | 759 | #else /* if defined (!iPlatformDesktop) */ |
760 | case SDL_WINDOWEVENT_RESIZED: | ||
761 | /* On mobile, this occurs when the display is rotated. */ | ||
762 | invalidate_Window(d); | ||
763 | postRefresh_App(); | ||
764 | return iTrue; | ||
765 | #endif | ||
757 | case SDL_WINDOWEVENT_LEAVE: | 766 | case SDL_WINDOWEVENT_LEAVE: |
758 | unhover_Widget(); | 767 | unhover_Widget(); |
759 | d->isMouseInside = iFalse; | 768 | d->isMouseInside = iFalse; |
@@ -763,19 +772,12 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
763 | d->isMouseInside = iTrue; | 772 | d->isMouseInside = iTrue; |
764 | postCommand_App("window.mouse.entered"); | 773 | postCommand_App("window.mouse.entered"); |
765 | return iTrue; | 774 | return iTrue; |
766 | #if defined (iPlatformMobile) | ||
767 | case SDL_WINDOWEVENT_RESIZED: | ||
768 | /* On mobile, this occurs when the display is rotated. */ | ||
769 | invalidate_Window(d); | ||
770 | postRefresh_App(); | ||
771 | return iTrue; | ||
772 | #endif | ||
773 | case SDL_WINDOWEVENT_FOCUS_GAINED: | 775 | case SDL_WINDOWEVENT_FOCUS_GAINED: |
774 | d->focusGainedAt = SDL_GetTicks(); | 776 | d->focusGainedAt = SDL_GetTicks(); |
775 | setCapsLockDown_Keys(iFalse); | 777 | setCapsLockDown_Keys(iFalse); |
776 | postCommand_App("window.focus.gained"); | 778 | postCommand_App("window.focus.gained"); |
777 | d->isExposed = iTrue; | 779 | d->isExposed = iTrue; |
778 | #if defined (iPlatformMobile) | 780 | #if !defined (iPlatformDesktop) |
779 | /* Returned to foreground, may have lost buffered content. */ | 781 | /* Returned to foreground, may have lost buffered content. */ |
780 | invalidate_Window_(d, iTrue); | 782 | invalidate_Window_(d, iTrue); |
781 | postCommand_App("window.unfreeze"); | 783 | postCommand_App("window.unfreeze"); |
@@ -783,7 +785,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
783 | return iFalse; | 785 | return iFalse; |
784 | case SDL_WINDOWEVENT_FOCUS_LOST: | 786 | case SDL_WINDOWEVENT_FOCUS_LOST: |
785 | postCommand_App("window.focus.lost"); | 787 | postCommand_App("window.focus.lost"); |
786 | #if defined (iPlatformMobile) | 788 | #if !defined (iPlatformDesktop) |
787 | setFreezeDraw_Window(d, iTrue); | 789 | setFreezeDraw_Window(d, iTrue); |
788 | #endif | 790 | #endif |
789 | return iFalse; | 791 | return iFalse; |
@@ -949,6 +951,10 @@ iBool setKeyRoot_Window(iWindow *d, iRoot *root) { | |||
949 | return iFalse; | 951 | return iFalse; |
950 | } | 952 | } |
951 | 953 | ||
954 | iLocalDef iBool isEscapeKeypress_(const SDL_Event *ev) { | ||
955 | return (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) && ev->key.keysym.sym == SDLK_ESCAPE; | ||
956 | } | ||
957 | |||
952 | iBool dispatchEvent_Window(iWindow *d, const SDL_Event *ev) { | 958 | iBool dispatchEvent_Window(iWindow *d, const SDL_Event *ev) { |
953 | if (ev->type == SDL_MOUSEMOTION) { | 959 | if (ev->type == SDL_MOUSEMOTION) { |
954 | /* Hover widget may change. */ | 960 | /* Hover widget may change. */ |
@@ -964,7 +970,11 @@ iBool dispatchEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
964 | } | 970 | } |
965 | if ((ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP || ev->type == SDL_TEXTINPUT) | 971 | if ((ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP || ev->type == SDL_TEXTINPUT) |
966 | && d->keyRoot != root) { | 972 | && d->keyRoot != root) { |
967 | continue; /* Key events go only to the root with keyboard focus. */ | 973 | if (!isEscapeKeypress_(ev)) { |
974 | /* Key events go only to the root with keyboard focus, with the exception | ||
975 | of Escape that will also affect the entire window. */ | ||
976 | continue; | ||
977 | } | ||
968 | } | 978 | } |
969 | if (ev->type == SDL_MOUSEWHEEL && !contains_Rect(rect_Root(root), | 979 | if (ev->type == SDL_MOUSEWHEEL && !contains_Rect(rect_Root(root), |
970 | coord_MouseWheelEvent(&ev->wheel))) { | 980 | coord_MouseWheelEvent(&ev->wheel))) { |
@@ -1015,7 +1025,6 @@ void draw_Window(iWindow *d) { | |||
1015 | if (d->isDrawFrozen) { | 1025 | if (d->isDrawFrozen) { |
1016 | return; | 1026 | return; |
1017 | } | 1027 | } |
1018 | //#if defined (iPlatformMobile) | ||
1019 | /* Check if root needs resizing. */ { | 1028 | /* Check if root needs resizing. */ { |
1020 | iInt2 renderSize; | 1029 | iInt2 renderSize; |
1021 | SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y); | 1030 | SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y); |
@@ -1024,7 +1033,6 @@ void draw_Window(iWindow *d) { | |||
1024 | processEvents_App(postedEventsOnly_AppEventMode); | 1033 | processEvents_App(postedEventsOnly_AppEventMode); |
1025 | } | 1034 | } |
1026 | } | 1035 | } |
1027 | //#endif | ||
1028 | const int winFlags = SDL_GetWindowFlags(d->win); | 1036 | const int winFlags = SDL_GetWindowFlags(d->win); |
1029 | const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; | 1037 | const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; |
1030 | iPaint p; | 1038 | iPaint p; |
@@ -1032,7 +1040,7 @@ void draw_Window(iWindow *d) { | |||
1032 | /* Clear the window. The clear color is visible as a border around the window | 1040 | /* Clear the window. The clear color is visible as a border around the window |
1033 | when the custom frame is being used. */ { | 1041 | when the custom frame is being used. */ { |
1034 | setCurrent_Root(d->roots[0]); | 1042 | setCurrent_Root(d->roots[0]); |
1035 | #if defined (iPlatformAppleMobile) | 1043 | #if defined (iPlatformMobile) |
1036 | iColor back = get_Color(uiBackground_ColorId); | 1044 | iColor back = get_Color(uiBackground_ColorId); |
1037 | if (deviceType_App() == phone_AppDeviceType) { | 1045 | if (deviceType_App() == phone_AppDeviceType) { |
1038 | /* Page background extends to safe area, so fill it completely. */ | 1046 | /* Page background extends to safe area, so fill it completely. */ |