mirror of
git://projects.qi-hardware.com/gmenu2x.git
synced 2024-11-22 13:05:20 +02:00
Launch application after destructing menu
This allows all destructors to do their job before we pass control to a new process.
This commit is contained in:
parent
303ecf298a
commit
7c4fa5d77a
@ -125,8 +125,9 @@ static const char *colorToString(enum color c)
|
||||
}
|
||||
|
||||
static void quit_all(int err) {
|
||||
delete app;
|
||||
exit(err);
|
||||
delete app;
|
||||
SDL_Quit();
|
||||
exit(err);
|
||||
}
|
||||
|
||||
const string GMenu2X::getHome(void)
|
||||
@ -163,11 +164,31 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
|
||||
DEBUG("Home path: %s.\n", gmenu2x_home.c_str());
|
||||
|
||||
app = new GMenu2X();
|
||||
DEBUG("Starting main()\n");
|
||||
app->main();
|
||||
GMenu2X::run();
|
||||
|
||||
return 0;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void GMenu2X::run() {
|
||||
auto menu = new GMenu2X();
|
||||
app = menu;
|
||||
DEBUG("Starting main()\n");
|
||||
menu->mainLoop();
|
||||
|
||||
app = nullptr;
|
||||
Launcher *toLaunch = menu->toLaunch.release();
|
||||
delete menu;
|
||||
|
||||
SDL_Quit();
|
||||
unsetenv("SDL_FBCON_DONT_CLEAR");
|
||||
|
||||
if (toLaunch) {
|
||||
toLaunch->exec();
|
||||
// If control gets here, execution failed. Since we already destructed
|
||||
// everything, the easiest solution is to exit and let the system
|
||||
// respawn the menu.
|
||||
delete toLaunch;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CPUFREQ
|
||||
@ -194,7 +215,6 @@ void GMenu2X::initCPULimits() {
|
||||
#endif
|
||||
|
||||
GMenu2X::GMenu2X()
|
||||
: appToLaunch(nullptr)
|
||||
{
|
||||
usbnet = samba = inet = web = false;
|
||||
useSelectionPng = false;
|
||||
@ -219,7 +239,9 @@ GMenu2X::GMenu2X()
|
||||
|
||||
if( SDL_Init(SDL_INIT_TIMER) < 0) {
|
||||
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
|
||||
quit();
|
||||
// TODO: We don't use exceptions, so don't put things that can fail
|
||||
// in a constructor.
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bg = NULL;
|
||||
@ -232,7 +254,9 @@ GMenu2X::GMenu2X()
|
||||
* a black screen for a couple of seconds. */
|
||||
if( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
|
||||
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
|
||||
quit();
|
||||
// TODO: We don't use exceptions, so don't put things that can fail
|
||||
// in a constructor.
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
s = Surface::openOutputSurface(resX, resY, confInt["videoBpp"]);
|
||||
@ -275,22 +299,17 @@ GMenu2X::GMenu2X()
|
||||
}
|
||||
|
||||
GMenu2X::~GMenu2X() {
|
||||
if (PowerSaver::isRunning())
|
||||
if (PowerSaver::isRunning()) {
|
||||
delete PowerSaver::getInstance();
|
||||
quit();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_INOTIFY
|
||||
delete monitor;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GMenu2X::quit() {
|
||||
fflush(NULL);
|
||||
sc.clear();
|
||||
delete s;
|
||||
|
||||
SDL_Quit();
|
||||
unsetenv("SDL_FBCON_DONT_CLEAR");
|
||||
#ifdef ENABLE_INOTIFY
|
||||
delete monitor;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GMenu2X::initBG() {
|
||||
@ -567,12 +586,10 @@ void GMenu2X::writeTmp(int selelem, const string &selectordir) {
|
||||
}
|
||||
}
|
||||
|
||||
void GMenu2X::main() {
|
||||
void GMenu2X::mainLoop() {
|
||||
if (!fileExists(CARD_ROOT))
|
||||
CARD_ROOT = "";
|
||||
|
||||
appToLaunch = nullptr;
|
||||
|
||||
// Recover last session
|
||||
readTmp();
|
||||
if (lastSelectorElement > -1 && menu->selLinkApp() &&
|
||||
@ -600,10 +617,12 @@ void GMenu2X::main() {
|
||||
for (auto layer : layers) {
|
||||
layer->paint(*s);
|
||||
}
|
||||
if (appToLaunch) {
|
||||
s->flip();
|
||||
|
||||
// Exit main loop once we have something to launch.
|
||||
if (toLaunch) {
|
||||
break;
|
||||
}
|
||||
s->flip();
|
||||
|
||||
// Handle touchscreen events.
|
||||
if (ts.available()) {
|
||||
@ -630,11 +649,6 @@ void GMenu2X::main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appToLaunch) {
|
||||
appToLaunch->drawRun();
|
||||
appToLaunch->launch(fileToLaunch);
|
||||
}
|
||||
}
|
||||
|
||||
void GMenu2X::explorer() {
|
||||
@ -645,24 +659,20 @@ void GMenu2X::explorer() {
|
||||
|
||||
string command = cmdclean(fd.getPath()+"/"+fd.getFile());
|
||||
chdir(fd.getPath().c_str());
|
||||
quit();
|
||||
#ifdef ENABLE_CPUFREQ
|
||||
setClock(cpuFreqAppDefault);
|
||||
#endif
|
||||
|
||||
Launcher launcher(vector<string> { "/bin/sh", "-c", command });
|
||||
launcher.exec();
|
||||
|
||||
//if execution continues then something went wrong and as we already called SDL_Quit we cannot continue
|
||||
//try relaunching gmenu2x
|
||||
ERROR("Error executing selected application, re-launching gmenu2x\n");
|
||||
main();
|
||||
toLaunch.reset(new Launcher(
|
||||
vector<string> { "/bin/sh", "-c", command }));
|
||||
}
|
||||
}
|
||||
|
||||
void GMenu2X::queueLaunch(LinkApp *app, const std::string &file) {
|
||||
appToLaunch = app;
|
||||
fileToLaunch = file;
|
||||
void GMenu2X::queueLaunch(
|
||||
unique_ptr<Launcher>&& launcher, shared_ptr<Layer> launchLayer
|
||||
) {
|
||||
toLaunch = move(launcher);
|
||||
layers.push_back(launchLayer);
|
||||
}
|
||||
|
||||
void GMenu2X::showHelpPopup() {
|
||||
|
@ -38,8 +38,8 @@ class Button;
|
||||
class Font;
|
||||
class HelpPopup;
|
||||
class IconButton;
|
||||
class Launcher;
|
||||
class Layer;
|
||||
class LinkApp;
|
||||
class MediaMonitor;
|
||||
class Menu;
|
||||
class Surface;
|
||||
@ -76,8 +76,7 @@ private:
|
||||
MediaMonitor *monitor;
|
||||
#endif
|
||||
|
||||
LinkApp *appToLaunch;
|
||||
std::string fileToLaunch;
|
||||
std::unique_ptr<Launcher> toLaunch;
|
||||
|
||||
std::vector<std::shared_ptr<Layer>> layers;
|
||||
|
||||
@ -120,9 +119,10 @@ private:
|
||||
void initBG();
|
||||
|
||||
public:
|
||||
static void run();
|
||||
|
||||
GMenu2X();
|
||||
~GMenu2X();
|
||||
void quit();
|
||||
|
||||
/* Returns the home directory of gmenu2x, usually
|
||||
* ~/.gmenu2x */
|
||||
@ -162,7 +162,7 @@ public:
|
||||
std::unique_ptr<Font> font;
|
||||
|
||||
//Status functions
|
||||
void main();
|
||||
void mainLoop();
|
||||
void showContextMenu();
|
||||
void showHelpPopup();
|
||||
void showManual();
|
||||
@ -184,7 +184,9 @@ public:
|
||||
* The launch won't happen immediately; it will happen after control
|
||||
* returns to the main loop.
|
||||
*/
|
||||
void queueLaunch(LinkApp *app, const std::string &file);
|
||||
void queueLaunch(std::unique_ptr<Launcher>&& launcher,
|
||||
std::shared_ptr<Layer> launchLayer);
|
||||
|
||||
void saveSelection();
|
||||
void writeConfig();
|
||||
void writeSkinConfig();
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "delegate.h"
|
||||
#include "gmenu2x.h"
|
||||
#include "launcher.h"
|
||||
#include "layer.h"
|
||||
#include "menu.h"
|
||||
#include "selector.h"
|
||||
#include "surface.h"
|
||||
@ -55,6 +56,31 @@ using namespace std;
|
||||
|
||||
static array<const char *, 4> tokens = { "%f", "%F", "%u", "%U", };
|
||||
|
||||
|
||||
/**
|
||||
* Displays the launch message (loading screen).
|
||||
*/
|
||||
class LaunchLayer: public Layer {
|
||||
public:
|
||||
LaunchLayer(LinkApp& app) : app(app) {}
|
||||
|
||||
void paint(Surface &s) override {
|
||||
app.drawLaunch(s);
|
||||
}
|
||||
|
||||
bool handleButtonPress(InputManager::Button) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool handleTouchscreen(Touchscreen&) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
LinkApp& app;
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_LIBOPK
|
||||
LinkApp::LinkApp(GMenu2X *gmenu2x_, const char* linkfile,
|
||||
struct OPK *opk, const char *metadata_)
|
||||
@ -323,9 +349,9 @@ bool LinkApp::save() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void LinkApp::drawRun() {
|
||||
void LinkApp::drawLaunch(Surface& s) {
|
||||
//Darkened background
|
||||
gmenu2x->s->box(0, 0, gmenu2x->resX, gmenu2x->resY, 0,0,0,150);
|
||||
s.box(0, 0, gmenu2x->resX, gmenu2x->resY, 0,0,0,150);
|
||||
|
||||
string text = getLaunchMsg().empty()
|
||||
? gmenu2x->tr.translate("Launching $1", getTitle().c_str(), nullptr)
|
||||
@ -336,25 +362,25 @@ void LinkApp::drawRun() {
|
||||
int halfBoxW = boxW/2;
|
||||
|
||||
//outer box
|
||||
gmenu2x->s->box(gmenu2x->halfX-2-halfBoxW, gmenu2x->halfY-23, halfBoxW*2+5, 47, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BG]);
|
||||
s.box(gmenu2x->halfX-2-halfBoxW, gmenu2x->halfY-23, halfBoxW*2+5, 47, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BG]);
|
||||
//inner rectangle
|
||||
gmenu2x->s->rectangle(gmenu2x->halfX-halfBoxW, gmenu2x->halfY-21, boxW, 42, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BORDER]);
|
||||
s.rectangle(gmenu2x->halfX-halfBoxW, gmenu2x->halfY-21, boxW, 42, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BORDER]);
|
||||
|
||||
int x = gmenu2x->halfX+10-halfBoxW;
|
||||
/*if (!getIcon().empty())
|
||||
gmenu2x->sc[getIcon()]->blit(gmenu2x->s,x,104);
|
||||
else
|
||||
gmenu2x->sc["icons/generic.png"]->blit(gmenu2x->s,x,104);*/
|
||||
iconSurface->blit(gmenu2x->s,x,gmenu2x->halfY-16);
|
||||
gmenu2x->font->write(gmenu2x->s, text, x+42, gmenu2x->halfY+1, Font::HAlignLeft, Font::VAlignMiddle );
|
||||
gmenu2x->s->flip();
|
||||
iconSurface->blit(&s, x, gmenu2x->halfY - 16);
|
||||
gmenu2x->font->write(&s, text, x + 42, gmenu2x->halfY + 1, Font::HAlignLeft, Font::VAlignMiddle);
|
||||
}
|
||||
|
||||
void LinkApp::start() {
|
||||
if (!selectordir.empty())
|
||||
if (selectordir.empty()) {
|
||||
gmenu2x->queueLaunch(prepareLaunch(""), make_shared<LaunchLayer>(*this));
|
||||
} else {
|
||||
selector();
|
||||
else
|
||||
gmenu2x->queueLaunch(this, "");
|
||||
}
|
||||
}
|
||||
|
||||
void LinkApp::showManual() {
|
||||
@ -510,11 +536,13 @@ void LinkApp::selector(int startSelection, const string &selectorDir) {
|
||||
selectordir = selectedDir;
|
||||
}
|
||||
gmenu2x->writeTmp(selection, selectedDir);
|
||||
gmenu2x->queueLaunch(this, selectedDir + sel.getFile());
|
||||
gmenu2x->queueLaunch(
|
||||
prepareLaunch(selectedDir + sel.getFile()),
|
||||
make_shared<LaunchLayer>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
void LinkApp::launch(const string &selectedFile) {
|
||||
unique_ptr<Launcher> LinkApp::prepareLaunch(const string &selectedFile) {
|
||||
save();
|
||||
|
||||
if (!isOpk()) {
|
||||
@ -568,7 +596,6 @@ void LinkApp::launch(const string &selectedFile) {
|
||||
gmenu2x->setClock(clock());
|
||||
}
|
||||
#endif
|
||||
gmenu2x->quit();
|
||||
|
||||
vector<string> commandLine;
|
||||
if (isOpk()) {
|
||||
@ -582,12 +609,8 @@ void LinkApp::launch(const string &selectedFile) {
|
||||
commandLine = { "/bin/sh", "-c", exec + " " + params };
|
||||
}
|
||||
|
||||
Launcher launcher(move(commandLine), consoleApp);
|
||||
launcher.exec();
|
||||
|
||||
//if execution continues then something went wrong and as we already called SDL_Quit we cannot continue
|
||||
//try relaunching gmenu2x
|
||||
gmenu2x->main();
|
||||
return std::unique_ptr<Launcher>(new Launcher(
|
||||
move(commandLine), consoleApp));
|
||||
}
|
||||
|
||||
const string &LinkApp::getExec() {
|
||||
|
@ -23,9 +23,11 @@
|
||||
|
||||
#include "link.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class GMenu2X;
|
||||
class Launcher;
|
||||
|
||||
/**
|
||||
Parses links files.
|
||||
@ -95,8 +97,11 @@ public:
|
||||
const std::string &getFile() { return file; }
|
||||
void renameFile(const std::string &name);
|
||||
|
||||
void drawRun();
|
||||
void launch(const std::string &selectedFile);
|
||||
private:
|
||||
void drawLaunch(Surface& s);
|
||||
std::unique_ptr<Launcher> prepareLaunch(const std::string &selectedFile);
|
||||
|
||||
friend class LaunchLayer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user