From bb7bc6fac4fec804846d11c7d77e1b553ba2be6a Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 9 Oct 2020 07:04:11 +0300 Subject: Fixed memory leak on tab close The DocumentWidget was not actually deleted when a tab was closed, only hidden. --- src/app.c | 10 ++++++++-- src/app.h | 5 ++++- src/audio/player.c | 6 ++++++ src/audio/player.h | 2 ++ src/media.c | 4 ++-- src/ui/documentwidget.c | 40 ++++++++++++++++++++++++++++++++++++---- src/ui/util.c | 3 +-- src/ui/widget.c | 4 +++- 8 files changed, 62 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index ff5ec9b7..0916919e 100644 --- a/src/app.c +++ b/src/app.c @@ -649,12 +649,17 @@ iAny *findWidget_App(const char *id) { return findChild_Widget(app_.window->root, id); } -void addTicker_App(void (*ticker)(iAny *), iAny *context) { +void addTicker_App(iTickerFunc ticker, iAny *context) { iApp *d = &app_; insert_SortedArray(&d->tickers, &(iTicker){ context, ticker }); postRefresh_App(); } +void removeTicker_App(iTickerFunc ticker, iAny *context) { + iApp *d = &app_; + remove_SortedArray(&d->tickers, &(iTicker){ context, ticker }); +} + iGmCerts *certs_App(void) { return app_.certs; } @@ -737,7 +742,8 @@ iDocumentWidget *newTab_App(const iDocumentWidget *duplicateOf, iBool switchToNe doc = new_DocumentWidget(); } setId_Widget(as_Widget(doc), format_CStr("document%03d", ++d->tabEnum)); - appendTabPage_Widget(tabs, iClob(doc), "", 0, 0); + appendTabPage_Widget(tabs, as_Widget(doc), "", 0, 0); + iRelease(doc); /* now owned by the tabs */ addChild_Widget(findChild_Widget(tabs, "tabs.buttons"), iClob(newTabButton)); if (switchToNew) { postCommandf_App("tabs.switch page:%p", doc); diff --git a/src/app.h b/src/app.h index db22230e..bf310d98 100644 --- a/src/app.h +++ b/src/app.h @@ -73,8 +73,11 @@ iObjectList * listDocuments_App (void); iDocumentWidget * document_Command (const char *cmd); iDocumentWidget * newTab_App (const iDocumentWidget *duplicateOf, iBool switchToNew); +typedef void (*iTickerFunc)(iAny *); + iAny * findWidget_App (const char *id); -void addTicker_App (void (*ticker)(iAny *), iAny *context); +void addTicker_App (iTickerFunc ticker, iAny *context); +void removeTicker_App (iTickerFunc ticker, iAny *context); void postRefresh_App (void); void postCommand_App (const char *command); void postCommandf_App (const char *command, ...); diff --git a/src/audio/player.c b/src/audio/player.c index 5b9d0103..07f41f01 100644 --- a/src/audio/player.c +++ b/src/audio/player.c @@ -563,3 +563,9 @@ float streamProgress_Player(const iPlayer *d) { } return 0; } + +iString *metadataLabel_Player(const iPlayer *d) { + return newFormat_String("%d-bit %s %d Hz", SDL_AUDIO_BITSIZE(d->decoder->inputFormat), + SDL_AUDIO_ISFLOAT(d->decoder->inputFormat) ? "float" : "integer", + d->spec.freq); +} diff --git a/src/audio/player.h b/src/audio/player.h index c3552640..fe6717b0 100644 --- a/src/audio/player.h +++ b/src/audio/player.h @@ -45,3 +45,5 @@ iBool isPaused_Player (const iPlayer *); float time_Player (const iPlayer *); float duration_Player (const iPlayer *); float streamProgress_Player (const iPlayer *); /* normalized 0...1 */ + +iString * metadataLabel_Player (const iPlayer *); diff --git a/src/media.c b/src/media.c index 253893fc..c447704b 100644 --- a/src/media.c +++ b/src/media.c @@ -75,8 +75,8 @@ void deinit_GmImage(iGmImage *d) { } void makeTexture_GmImage(iGmImage *d) { - iBlock *data = &d->partialData; - d->numBytes = size_Block(data); + iBlock *data = &d->partialData; + d->numBytes = size_Block(data); uint8_t *imgData = stbi_load_from_memory( constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); if (!imgData) { diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 9d94f200..bbe5ccba 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -191,6 +191,7 @@ struct Impl_DocumentWidget { iAnim outlineOpacity; iArray outline; iWidget * menu; + iWidget * playerMenu; iVisBuf * visBuf; iPtrSet * invalidRuns; }; @@ -241,6 +242,7 @@ void init_DocumentWidget(iDocumentWidget *d) { init_Click(&d->click, d, SDL_BUTTON_LEFT); addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); d->menu = NULL; /* created when clicking */ + d->playerMenu = NULL; #if !defined (iPlatformApple) /* in system menu */ addAction_Widget(w, reload_KeyShortcut, "navigate.reload"); addAction_Widget(w, SDLK_w, KMOD_PRIMARY, "tabs.close"); @@ -249,7 +251,10 @@ void init_DocumentWidget(iDocumentWidget *d) { addAction_Widget(w, navigateForward_KeyShortcut, "navigate.forward"); } +static void animatePlayingAudio_DocumentWidget_(void *); + void deinit_DocumentWidget(iDocumentWidget *d) { + removeTicker_App(animatePlayingAudio_DocumentWidget_, d); delete_VisBuf(d->visBuf); delete_PtrSet(d->invalidRuns); deinit_Array(&d->outline); @@ -1626,7 +1631,7 @@ static void drawPlayerButton_(iPaint *p, iRect rect, const char *label) { adjusted_Rect(shrunk_Rect(frameRect, divi_I2(gap2_UI, 2)), zero_I2(), one_I2()), frame); } - const int fg = isPressed ? uiBackground_ColorId : frame; + const int fg = isPressed ? (permanent_ColorId | uiBackground_ColorId) : uiHeading_ColorId; drawCentered_Text(uiContent_FontId, frameRect, iTrue, fg, "%s", label); } @@ -1704,6 +1709,11 @@ static iBool processAudioPlayerEvents_DocumentWidget_(iDocumentWidget *d, const ev->type != SDL_MOUSEMOTION) { return iFalse; } + if (ev->type == SDL_MOUSEBUTTONDOWN || ev->type == SDL_MOUSEBUTTONUP) { + if (ev->button.button != SDL_BUTTON_LEFT) { + return iFalse; + } + } const iInt2 mouse = init_I2(ev->button.x, ev->button.y); iConstForEach(PtrArray, i, &d->visiblePlayers) { const iGmRun *run = i.ptr; @@ -1722,12 +1732,34 @@ static iBool processAudioPlayerEvents_DocumentWidget_(iDocumentWidget *d, const return iTrue; } else if (contains_Rect(ui.rewindRect, mouse)) { - stop_Player(plr); - start_Player(plr); - setPaused_Player(plr, iTrue); + if (isStarted_Player(plr) && time_Player(plr) > 0.5f) { + stop_Player(plr); + start_Player(plr); + setPaused_Player(plr, iTrue); + } refresh_Widget(d); return iTrue; } + else if (contains_Rect(ui.menuRect, mouse)) { + /* TODO: Add menu items for: + - output device + - Save to Downloads + */ + if (d->playerMenu) { + destroy_Widget(d->playerMenu); + d->playerMenu = NULL; + return iTrue; + } + d->playerMenu = makeMenu_Widget( + as_Widget(d), + (iMenuItem[]){ + { cstrCollect_String(metadataLabel_Player(plr)), 0, 0, NULL }, + }, + 1); + openMenu_Widget(d->playerMenu, + localCoord_Widget(constAs_Widget(d), bottomLeft_Rect(ui.menuRect))); + return iTrue; + } } } return iFalse; diff --git a/src/ui/util.c b/src/ui/util.c index 13a7a7a2..89f71da2 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -498,9 +498,8 @@ iWidget *removeTabPage_Widget(iWidget *tabs, size_t index) { iWidget *button = removeChild_Widget(buttons, child_Widget(buttons, index)); iRelease(button); iWidget *page = child_Widget(pages, index); - ref_Object(page); setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); - removeChild_Widget(pages, page); + removeChild_Widget(pages, page); /* `page` is now ours */ if (tabCount_Widget(tabs) <= 1 && flags_Widget(buttons) & collapse_WidgetFlag) { setFlags_Widget(buttons, hidden_WidgetFlag, iTrue); } diff --git a/src/ui/widget.c b/src/ui/widget.c index 459c2ae1..ea2e3fe2 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -55,7 +55,6 @@ iPtrArray *onTop_RootData_(void) { void destroyPending_Widget(void) { iForEach(PtrSet, i, rootData_.pendingDestruction) { iWidget *widget = *i.value; - removeOne_PtrArray(onTop_RootData_(), widget); if (widget->parent) { iRelease(removeChild_Widget(widget->parent, widget)); } @@ -90,6 +89,9 @@ static void aboutToBeDestroyed_Widget_(iWidget *d) { setFocus_Widget(NULL); return; } + if (flags_Widget(d) & keepOnTop_WidgetFlag) { + removeOne_PtrArray(onTop_RootData_(), d); + } if (isHover_Widget(d)) { rootData_.hover = NULL; } -- cgit v1.2.3