Add beginning of NxWM NxConsole application
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4681 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
289f0a16fe
commit
d4f2f57522
40
README.txt
40
README.txt
@ -49,3 +49,43 @@ o Many Graphic Objects
|
||||
Note: Many of the fundamental classed in NxWidgets derive from the Antony
|
||||
Dzeryn's "Woopsi" project: http://woopsi.org/ which also has a BSD style
|
||||
license. See the COPYING file for details.
|
||||
|
||||
Directory Structure
|
||||
===================
|
||||
|
||||
libnxwidgets
|
||||
|
||||
The source code, header files, and build environment for NxWidgets is
|
||||
provided in this directory.
|
||||
|
||||
UnitTests
|
||||
|
||||
Provides a collection of unit-level tests for many of the individual
|
||||
widgets provided by libnxwidgets.
|
||||
|
||||
nxwm
|
||||
|
||||
This directory holds a tiny desktop for small embedded devices with a
|
||||
touchscreen,. NxWM. NxWM is truly multiple window manager but only one
|
||||
window is displayed at a time. This simplification helps performance on
|
||||
LCD based products (in the same way that a tiled window manager helps)
|
||||
and also makes the best use of small displays. It is awkward from a
|
||||
human factors point-of-view trying to manage multiple windows on a
|
||||
small display.
|
||||
|
||||
The window manager consists of a task bar with icons representing the
|
||||
running tasks. If you touch the tasks icon, it comes to the top. Each
|
||||
window has a toolbar with (1) a title, (2) a minimize button, and (3) a
|
||||
stop application button using the standard icons for these things.
|
||||
|
||||
There is always a start window that is available in the task bar. When
|
||||
you touch the start window icon, it brings up the start window containing
|
||||
icons representing all of the available applications. If you touch an
|
||||
icon in the start window, it will be started and added to the task bar.
|
||||
|
||||
There is a base class that defines an add-on application and an
|
||||
interface that supports incorporation of new application. The only
|
||||
application that is provided is NxConsole. This is an NSH session
|
||||
running in a window. I should be able to select the NX icon in the start
|
||||
menu and create as many NSH sessions in windows as I want. (keybard input
|
||||
still comes through serial).
|
||||
|
@ -38,6 +38,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "ctaskbar.hxx"
|
||||
#include "cstartwindow.hxx"
|
||||
@ -90,6 +91,12 @@ extern "C" int MAIN_NAME(int argc, char *argv[]);
|
||||
|
||||
int MAIN_NAME(int argc, char *argv[])
|
||||
{
|
||||
// Call all C++ static constructors
|
||||
|
||||
#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE)
|
||||
up_cxxinitialize();
|
||||
#endif
|
||||
|
||||
// Create an instance of the Task Bar.
|
||||
//
|
||||
// The general sequence for initializing the task bar is:
|
||||
|
@ -42,7 +42,13 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <nuttx/nx/nxtk.h>
|
||||
#include <nuttx/nx/nxconsole.h>
|
||||
|
||||
#include "iapplication.hxx"
|
||||
#include "capplicationwindow.hxx"
|
||||
#include "ctaskbar.hxx"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-Processor Definitions
|
||||
@ -56,37 +62,110 @@
|
||||
|
||||
namespace NxWM
|
||||
{
|
||||
/**
|
||||
* One time NSH initialization. This function must be called exactly
|
||||
* once during the boot-up sequence to initialize the NSH library.
|
||||
*
|
||||
* @return True on successful initialization
|
||||
*/
|
||||
|
||||
bool nshlibInitialize(void);
|
||||
|
||||
/**
|
||||
* This class implements the NxConsole application.
|
||||
*/
|
||||
|
||||
class CNxConsole : public IApplication
|
||||
class CNxConsole : public IApplication, private IApplicationCallback
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* CNxConsole destructor
|
||||
*/
|
||||
protected:
|
||||
CTaskbar *m_taskbar; /**< Reference to the "parent" taskbar */
|
||||
CApplicationWindow *m_window; /**< Reference to the application window */
|
||||
NXCONSOLE m_nxcon; /**< NxConsole handle */
|
||||
pid_t m_pid; /**< Task ID of the NxConsole thread */
|
||||
|
||||
~CNxConsole(void);
|
||||
/**
|
||||
* Called when the window minimize button is pressed.
|
||||
*/
|
||||
|
||||
public:
|
||||
/**
|
||||
* CNxConsole constructor
|
||||
*
|
||||
* @param window. The application window
|
||||
*/
|
||||
void minimize(void);
|
||||
|
||||
CNxConsole(NXWidgets::INxWindow *window);
|
||||
/**
|
||||
* Called when the window minimize close is pressed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the icon associated with the application
|
||||
*
|
||||
* @return An instance if IBitmap that may be used to rend the
|
||||
* application's icon. This is an new IBitmap instance that must
|
||||
* be deleted by the caller when it is no long needed.
|
||||
*/
|
||||
void close(void);
|
||||
|
||||
NXWidgets::IBitmap *getIcon(void);
|
||||
/**
|
||||
* CNxConsole destructor
|
||||
*/
|
||||
|
||||
~CNxConsole(void);
|
||||
|
||||
public:
|
||||
/**
|
||||
* CNxConsole constructor
|
||||
*
|
||||
* @param window. The application window
|
||||
*
|
||||
* @param taskbar. A pointer to the parent task bar instance
|
||||
* @param window. The window to be used by this application.
|
||||
*/
|
||||
|
||||
CNxConsole(CTaskbar *taskbar, CApplicationWindow *window);
|
||||
|
||||
/**
|
||||
* Each implementation of IApplication must provide a method to recover
|
||||
* the contained CApplicationWindow instance.
|
||||
*/
|
||||
|
||||
CApplicationWindow *getWindow(void) const;
|
||||
|
||||
/**
|
||||
* Get the icon associated with the application
|
||||
*
|
||||
* @return An instance if IBitmap that may be used to rend the
|
||||
* application's icon. This is an new IBitmap instance that must
|
||||
* be deleted by the caller when it is no long needed.
|
||||
*/
|
||||
|
||||
NXWidgets::IBitmap *getIcon(void);
|
||||
|
||||
/**
|
||||
* Get the name string associated with the application
|
||||
*
|
||||
* @return A copy if CNxString that contains the name of the application.
|
||||
*/
|
||||
|
||||
NXWidgets::CNxString getName(void);
|
||||
|
||||
/**
|
||||
* Start the application (perhaps in the minimized state).
|
||||
*
|
||||
* @return True if the application was successfully started.
|
||||
*/
|
||||
|
||||
bool run(void);
|
||||
|
||||
/**
|
||||
* Stop the application.
|
||||
*/
|
||||
|
||||
void stop(void);
|
||||
|
||||
/**
|
||||
* The application window is hidden (either it is minimized or it is
|
||||
* maximized, but not at the top of the hierarchy
|
||||
*/
|
||||
|
||||
void hide(void);
|
||||
|
||||
/**
|
||||
* Redraw the entire window. The application has been maximized or
|
||||
* otherwise moved to the top of the hierarchy. This method is call from
|
||||
* CTaskbar when the application window must be displayed
|
||||
*/
|
||||
|
||||
void redraw(void);
|
||||
};
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
@ -160,9 +160,11 @@ namespace NxWM
|
||||
|
||||
/**
|
||||
* Start the application.
|
||||
*
|
||||
* @return True if the application was successfully started.
|
||||
*/
|
||||
|
||||
void run(void);
|
||||
bool run(void);
|
||||
|
||||
/**
|
||||
* Stop the application.
|
||||
|
@ -99,10 +99,12 @@ namespace NxWM
|
||||
virtual NXWidgets::CNxString getName(void) = 0;
|
||||
|
||||
/**
|
||||
* Start the application (pehaps in the minimized state).
|
||||
* Start the application (perhaps in the minimized state).
|
||||
*
|
||||
* @return True if the application was successfully started.
|
||||
*/
|
||||
|
||||
virtual void run(void) = 0;
|
||||
virtual bool run(void) = 0;
|
||||
|
||||
/**
|
||||
* Stop the application.
|
||||
|
@ -198,4 +198,26 @@
|
||||
# define CONFIG_NXWM_STARTWINDOW_HSPACING (2)
|
||||
#endif
|
||||
|
||||
/* NxConsole Window *********************************************************/
|
||||
|
||||
#ifndef CONFIG_NXWM_NXCONSOLE_PRIO
|
||||
# define CONFIG_NXWM_NXCONSOLE_PRIO SCHED_PRIORITY_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NXWM_NXCONSOLE_STACKSIZE
|
||||
# define CONFIG_NXWM_NXCONSOLE_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NXWM_NXCONSOLE_WCOLOR
|
||||
# define CONFIG_NXWM_NXCONSOLE_WCOLOR MKRGB(192,192,192)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NXWM_NXCONSOLE_FONTCOLOR
|
||||
# define CONFIG_NXWM_NXCONSOLE_FONTCOLOR MKRGB(0,0,0)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NXWM_NXCONSOLE_FONTID
|
||||
# define CONFIG_NXWM_NXCONSOLE_FONTID CONFIG_NXWM_DEFAULT_FONTID
|
||||
#endif
|
||||
|
||||
#endif // __INCLUDE_NXWMCONFIG_HXX
|
||||
|
@ -39,6 +39,19 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <semaphore.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <apps/nsh.h>
|
||||
|
||||
#include "cwidgetcontrol.hxx"
|
||||
|
||||
#include "nxwmconfig.hxx"
|
||||
#include "cnxconsole.hxx"
|
||||
#include "nxwmglyphs.hxx"
|
||||
@ -47,6 +60,125 @@
|
||||
* Pre-Processor Definitions
|
||||
********************************************************************************************/
|
||||
|
||||
/********************************************************************************************
|
||||
* Private Types
|
||||
********************************************************************************************/
|
||||
|
||||
namespace NxWM
|
||||
{
|
||||
/**
|
||||
* This structure is used to pass start up parameters to nxcon_task and to assure the
|
||||
* the NxConsole is successfully started.
|
||||
*/
|
||||
|
||||
struct nxcon_task_s
|
||||
{
|
||||
sem_t sem; // Sem that will be posted when the task is successfully initialized
|
||||
NXTKWINDOW hwnd; // Window handle
|
||||
NXCONSOLE nxcon; // NxConsole handle
|
||||
int minor; // Next device minor number
|
||||
bool result; // True if successfully initialized
|
||||
};
|
||||
|
||||
/********************************************************************************************
|
||||
* Private Data
|
||||
********************************************************************************************/
|
||||
|
||||
/**
|
||||
* This global data structure is used to pass start parameters to nxcon_task and to
|
||||
* assure that the NxConsole is successfully started.
|
||||
*/
|
||||
|
||||
static struct nxcon_task_s g_nxconvars;
|
||||
|
||||
/********************************************************************************************
|
||||
* Private Functions
|
||||
********************************************************************************************/
|
||||
|
||||
/**
|
||||
* This is the NxConsole task. This function first redirects output to the console window.
|
||||
*/
|
||||
|
||||
static int nxcon_task(int argc, char *argv[])
|
||||
{
|
||||
// Configure NxConsole
|
||||
|
||||
struct nxcon_window_s wndo; /* Describes the window */
|
||||
wndo.wcolor[0] = CONFIG_NXWM_NXCONSOLE_WCOLOR;
|
||||
wndo.fcolor[0] = CONFIG_NXWM_NXCONSOLE_FONTCOLOR;
|
||||
wndo.fontid = CONFIG_NXWM_NXCONSOLE_FONTID;
|
||||
|
||||
// To stop compiler complaining about "jump to label crosses initialization of 'int fd'
|
||||
|
||||
int fd = -1;
|
||||
|
||||
// Use the window handle to create the NX console
|
||||
|
||||
g_nxconvars.nxcon = nxtk_register(g_nxconvars.hwnd, &wndo, g_nxconvars.minor);
|
||||
if (!g_nxconvars.nxcon)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
// Construct the driver name using this minor number
|
||||
|
||||
char devname[32];
|
||||
snprintf(devname, 32, "/dev/nxcon%d", g_nxconvars.minor);
|
||||
|
||||
// Increment the minor number while it is protect by the semaphore
|
||||
|
||||
g_nxconvars.minor++;
|
||||
|
||||
// Open the NxConsole driver
|
||||
|
||||
fd = open(devname, O_WRONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
goto errout_with_nxcon;
|
||||
}
|
||||
|
||||
// Now re-direct stdout and stderr so that they use the NX console driver.
|
||||
// Note that stdin is retained (file descriptor 0, probably the the serial console).
|
||||
|
||||
(void)fflush(stdout);
|
||||
(void)fflush(stderr);
|
||||
|
||||
(void)fclose(stdout);
|
||||
(void)fclose(stderr);
|
||||
|
||||
(void)dup2(fd, 1);
|
||||
(void)dup2(fd, 2);
|
||||
|
||||
// And we can close our original driver file descriptor
|
||||
|
||||
close(fd);
|
||||
|
||||
// Inform the parent thread that we successfully initialize
|
||||
|
||||
g_nxconvars.result = true;
|
||||
sem_post(&g_nxconvars.sem);
|
||||
|
||||
// Run the NSH console
|
||||
|
||||
#ifdef CONFIG_NSH_CONSOLE
|
||||
(void)nsh_consolemain(argc, argv);
|
||||
#endif
|
||||
|
||||
// We get here if console exits
|
||||
#warning "Missing logic"
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
errout_with_nxcon:
|
||||
nxcon_unregister(g_nxconvars.nxcon);
|
||||
|
||||
errout:
|
||||
g_nxconvars.nxcon = 0;
|
||||
g_nxconvars.result = false;
|
||||
sem_post(&g_nxconvars.sem);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************
|
||||
* CNxConsole Method Implementations
|
||||
********************************************************************************************/
|
||||
@ -59,8 +191,80 @@ using namespace NxWM;
|
||||
* @param window. The application window
|
||||
*/
|
||||
|
||||
CNxConsole::CNxConsole(NXWidgets::INxWindow *window)
|
||||
CNxConsole::CNxConsole(CTaskbar *taskbar, CApplicationWindow *window)
|
||||
{
|
||||
// Save the constructor data
|
||||
|
||||
m_taskbar = taskbar;
|
||||
m_window = window;
|
||||
|
||||
// The NxConsole is not runing
|
||||
|
||||
m_pid = -1;
|
||||
m_nxcon = 0;
|
||||
|
||||
// Add our callbacks to the application window
|
||||
|
||||
window->registerCallbacks(static_cast<IApplicationCallback *>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* CNxConsole destructor
|
||||
*
|
||||
* @param window. The application window
|
||||
*/
|
||||
|
||||
CNxConsole::~CNxConsole(void)
|
||||
{
|
||||
// Although we didn't create it, we are responsible for deleting the
|
||||
// application window
|
||||
|
||||
if (m_window)
|
||||
{
|
||||
delete m_window;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* One time NSH initialization. This function must be called exactly
|
||||
* once during the boot-up sequence to initialize the NSH library.
|
||||
*
|
||||
* @return True on successful initialization
|
||||
*/
|
||||
|
||||
bool nshlibInitialize(void)
|
||||
{
|
||||
// Initialize the global data structure
|
||||
|
||||
sem_init(&g_nxconvars.sem, 0, 0);
|
||||
|
||||
// Initialize the NSH library
|
||||
|
||||
nsh_initialize();
|
||||
|
||||
// If the Telnet console is selected as a front-end, then start the
|
||||
// Telnet daemon.
|
||||
|
||||
#ifdef CONFIG_NSH_TELNET
|
||||
int ret = nsh_telnetstart();
|
||||
if (ret < 0)
|
||||
{
|
||||
// The daemon is NOT running!
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each implementation of IApplication must provide a method to recover
|
||||
* the contained CApplicationWindow instance.
|
||||
*/
|
||||
|
||||
CApplicationWindow *CNxConsole::getWindow(void) const
|
||||
{
|
||||
return m_window;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,7 +277,169 @@ CNxConsole::CNxConsole(NXWidgets::INxWindow *window)
|
||||
|
||||
NXWidgets::IBitmap *CNxConsole::getIcon(void)
|
||||
{
|
||||
NXWidgets::CRlePaletteBitmap *bitmap = new NXWidgets::CRlePaletteBitmap(&g_nshBitmap);
|
||||
return static_cast<NXWidgets::IBitmap *>(bitmap);
|
||||
NXWidgets::CRlePaletteBitmap *bitmap =
|
||||
new NXWidgets::CRlePaletteBitmap(&g_nshBitmap);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name string associated with the application
|
||||
*
|
||||
* @return A copy if CNxString that contains the name of the application.
|
||||
*/
|
||||
|
||||
NXWidgets::CNxString CNxConsole::getName(void)
|
||||
{
|
||||
return NXWidgets::CNxString("NuttShell");
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the application (perhaps in the minimized state).
|
||||
*
|
||||
* @return True if the application was successfully started.
|
||||
*/
|
||||
|
||||
bool CNxConsole::run(void)
|
||||
{
|
||||
// Some sanity checking
|
||||
|
||||
if (m_pid >= 0 || m_nxcon != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Recover the NXTK window instance contained in the application window
|
||||
|
||||
NXWidgets::CNxTkWindow *window = m_window->getWindow();
|
||||
|
||||
// Get the widget control associated with the NXTK window
|
||||
|
||||
NXWidgets::CWidgetControl *control = window->getWidgetControl();
|
||||
|
||||
// Get the window handle from the widget control
|
||||
|
||||
g_nxconvars.hwnd = control->getWindowHandle();
|
||||
|
||||
// Start the NxConsole task
|
||||
|
||||
g_nxconvars.result = false;
|
||||
g_nxconvars.nxcon = 0;
|
||||
|
||||
sched_lock();
|
||||
m_pid = TASK_CREATE("NxConsole", CONFIG_NXWM_NXCONSOLE_PRIO,
|
||||
CONFIG_NXWM_NXCONSOLE_STACKSIZE, nxcon_task,
|
||||
(FAR const char **)0);
|
||||
|
||||
// Did we successfully start the NxConsole task?
|
||||
|
||||
if (m_pid < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait for up to two second for the task to initialize
|
||||
|
||||
struct timespec abstime;
|
||||
clock_gettime(CLOCK_REALTIME, &abstime);
|
||||
abstime.tv_sec += 2;
|
||||
|
||||
int ret = sem_timedwait(&g_nxconvars.sem, &abstime);
|
||||
if (ret == OK && g_nxconvars.result)
|
||||
{
|
||||
// Save the handle to use in the stop method
|
||||
|
||||
m_nxcon = g_nxconvars.nxcon;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stop the application
|
||||
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the application.
|
||||
*/
|
||||
|
||||
void CNxConsole::stop(void)
|
||||
{
|
||||
// Delete the NxConsole task if it is still running (this could strand resources)
|
||||
|
||||
if (m_pid >= 0)
|
||||
{
|
||||
task_delete(m_pid);
|
||||
m_pid = -1;
|
||||
}
|
||||
|
||||
// Destroy the NX console device
|
||||
|
||||
if (m_nxcon)
|
||||
{
|
||||
nxcon_unregister(m_nxcon);
|
||||
m_nxcon = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The application window is hidden (either it is minimized or it is
|
||||
* maximized, but not at the top of the hierarchy
|
||||
*/
|
||||
|
||||
void CNxConsole::hide(void)
|
||||
{
|
||||
// Disable drawing and events
|
||||
#warning "Missing logic"
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraw the entire window. The application has been maximized or
|
||||
* otherwise moved to the top of the hierarchy. This method is call from
|
||||
* CTaskbar when the application window must be displayed
|
||||
*/
|
||||
|
||||
void CNxConsole::redraw(void)
|
||||
{
|
||||
// Recover the NXTK window instance contained in the application window
|
||||
|
||||
NXWidgets::CNxTkWindow *window = m_window->getWindow();
|
||||
|
||||
// Get the size of the window
|
||||
|
||||
struct nxgl_size_s windowSize;
|
||||
(void)window->getSize(&windowSize);
|
||||
|
||||
// Redraw the entire NxConsole window
|
||||
|
||||
struct nxgl_rect_s rect;
|
||||
rect.pt1.x = 0;
|
||||
rect.pt1.y = 0;
|
||||
rect.pt2.x = windowSize.w - 1;
|
||||
rect.pt2.y = windowSize.h - 1;
|
||||
|
||||
nxcon_redraw(m_nxcon, &rect, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the window minimize button is pressed.
|
||||
*/
|
||||
|
||||
void CNxConsole::minimize(void)
|
||||
{
|
||||
m_taskbar->minimizeApplication(static_cast<IApplication*>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the window minimize close is pressed.
|
||||
*/
|
||||
|
||||
void CNxConsole::close(void)
|
||||
{
|
||||
m_taskbar->stopApplication(static_cast<IApplication*>(this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -70,7 +70,7 @@ CStartWindow::CStartWindow(CTaskbar *taskbar, CApplicationWindow *window)
|
||||
m_taskbar = taskbar;
|
||||
m_window = window;
|
||||
|
||||
// Add out callbacks to the application window
|
||||
// Add our callbacks to the application window
|
||||
|
||||
window->registerCallbacks(static_cast<IApplicationCallback *>(this));
|
||||
}
|
||||
@ -133,11 +133,15 @@ NXWidgets::CNxString CStartWindow::getName(void)
|
||||
|
||||
/**
|
||||
* Start the application.
|
||||
*
|
||||
* @return True if the application was successfully started.
|
||||
*/
|
||||
|
||||
void CStartWindow::run(void)
|
||||
bool CStartWindow::run(void)
|
||||
{
|
||||
// We don't have a thread of execution. We only respond to button presses
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -267,7 +267,12 @@ bool CTaskbar::startApplication(IApplication *app, bool minimized)
|
||||
|
||||
// Then start the application (whatever that means)
|
||||
|
||||
app->run();
|
||||
if (!app->run())
|
||||
{
|
||||
stopApplication(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user