1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-11-25 18: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:
Maarten ter Huurne 2014-08-10 02:09:34 +02:00
parent 303ecf298a
commit 7c4fa5d77a
4 changed files with 107 additions and 67 deletions

View File

@ -126,6 +126,7 @@ static const char *colorToString(enum color c)
static void quit_all(int err) {
delete app;
SDL_Quit();
exit(err);
}
@ -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() {

View File

@ -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();

View File

@ -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() {

View File

@ -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