* apps/graphics/nxwm/src/cnxterm.cxx
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
********************************************************************************************/
* Included Files
********************************************************************************************/
#include <nuttx/config.h>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <sys/boardctl.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sched.h>
#include <assert.h>
#include <debug.h>
#include <unistd.h>
#include <nuttx/sched.h>
#include "nshlib/nshlib.h"
#include "graphics/nxwidgets/cwidgetcontrol.hxx"
#include "graphics/nxwm/nxwmconfig.hxx"
#include "graphics/nxglyphs.hxx"
#include "graphics/nxwm/cnxterm.hxx"
* Pre-Processor Definitions
********************************************************************************************/
#ifdef CONFIG_NSH_USBKBD
# warning You probably do not really want CONFIG_NSH_USBKBD, try CONFIG_NXWM_KEYBOARD_USBHOST
#endif
* Private Types
********************************************************************************************/
namespace NxWM
{
* This structure is used to pass start up parameters to the NxTerm task and to assure the
* the NxTerm is successfully started.
*/
struct SNxTerm
{
FAR void *console;
sem_t exclSem;
sem_t waitSem;
NXTKWINDOW hwnd;
NXTERM nxterm;
int minor;
struct nxterm_window_s wndo;
bool result;
};
* Private Data
********************************************************************************************/
* This global data structure is used to pass start parameters to NxTerm task and to
* assure that the NxTerm is successfully started.
*/
static struct SNxTerm g_nxtermvars;
}
* Private Functions
********************************************************************************************/
* CNxTerm Method Implementations
********************************************************************************************/
using namespace NxWM;
* CNxTerm constructor
*
* @param window. The application window
*/
CNxTerm::CNxTerm(CTaskbar *taskbar, CApplicationWindow *window)
{
m_taskbar = taskbar;
m_window = window;
m_pid = -1;
m_nxterm = 0;
NXWidgets::CNxString myName = getName();
window->setWindowLabel(myName);
window->registerCallbacks(static_cast<IApplicationCallback *>(this));
}
* CNxTerm destructor
*
* @param window. The application window
*/
CNxTerm::~CNxTerm(void)
{
stop();
delete m_window;
}
* Each implementation of IApplication must provide a method to recover
* the contained CApplicationWindow instance.
*/
IApplicationWindow *CNxTerm::getWindow(void) const
{
return static_cast<IApplicationWindow*>(m_window);
}
* 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 *CNxTerm::getIcon(void)
{
NXWidgets::CRlePaletteBitmap *bitmap =
new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_NXTERM_ICON);
return bitmap;
}
* Get the name string associated with the application
*
* @return A copy if CNxString that contains the name of the application.
*/
NXWidgets::CNxString CNxTerm::getName(void)
{
return NXWidgets::CNxString("NuttShell");
}
* Start the application (perhaps in the minimized state).
*
* @return True if the application was successfully started.
*/
bool CNxTerm::run(void)
{
if (m_pid >= 0 || m_nxterm != 0)
{
gerr("ERROR: All ready running or connected\n");
return false;
}
if (sem_wait(&g_nxtermvars.exclSem) != 0)
{
gerr("ERROR: Failed to get semaphore\n");
return false;
}
NXWidgets::INxWindow *window = m_window->getWindow();
NXWidgets::CWidgetControl *control = window->getWidgetControl();
g_nxtermvars.hwnd = control->getWindowHandle();
g_nxtermvars.wndo.wcolor[0] = CONFIG_NXWM_NXTERM_WCOLOR;
g_nxtermvars.wndo.fcolor[0] = CONFIG_NXWM_NXTERM_FONTCOLOR;
g_nxtermvars.wndo.fontid = CONFIG_NXWM_NXTERM_FONTID;
m_minor = g_nxtermvars.minor;
window->getSize(&g_nxtermvars.wndo.wsize);
g_nxtermvars.console = (FAR void *)this;
g_nxtermvars.result = false;
g_nxtermvars.nxterm = 0;
sched_lock();
m_pid = task_create("NxTerm", CONFIG_NXWM_NXTERM_PRIO,
CONFIG_NXWM_NXTERM_STACKSIZE, nxterm,
(FAR char * const *)0);
bool result = true;
if (m_pid < 0)
{
gerr("ERROR: Failed to create the NxTerm task\n");
result = false;
}
else
{
struct timespec abstime;
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_sec += 2;
int ret = sem_timedwait(&g_nxtermvars.waitSem, &abstime);
sched_unlock();
if (ret == OK && g_nxtermvars.result)
{
DEBUGASSERT(g_nxtermvars.nxterm != 0);
#ifdef CONFIG_NXTERM_NXKBDIN
window->redirectNxTerm(g_nxtermvars.nxterm);
#endif
m_nxterm = g_nxtermvars.nxterm;
}
else
{
gerr("ERROR: Failed start the NxTerm task\n");
stop();
result = false;
}
}
sem_post(&g_nxtermvars.exclSem);
return result;
}
* Stop the application.
*/
void CNxTerm::stop(void)
{
if (m_pid >= 0)
{
pid_t pid = m_pid;
m_pid = -1;
task_delete(pid);
}
if (m_nxterm)
{
#ifdef CONFIG_NXTERM_NXKBDIN
NXWidgets::INxWindow *window = m_window->getWindow();
window->redirectNxTerm((NXTERM)0);
#endif
char devname[32];
snprintf(devname, sizeof(devname), "/dev/nxterm%d", m_minor);
unlink(devname);
m_nxterm = 0;
}
}
* Destroy the application and free all of its resources. This method
* will initiate blocking of messages from the NX server. The server
* will flush the window message queue and reply with the blocked
* message. When the block message is received by CWindowMessenger,
* it will send the destroy message to the start window task which
* will, finally, safely delete the application.
*/
void CNxTerm::destroy(void)
{
m_window->block(this);
stop();
}
* The application window is hidden (either it is minimized or it is
* maximized, but not at the top of the hierarchy
*/
void CNxTerm::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 CNxTerm::redraw(void)
{
NXWidgets::INxWindow *window = m_window->getWindow();
struct nxgl_size_s windowSize;
window->getSize(&windowSize);
struct boardioc_nxterm_ioctl_s iocargs;
struct nxtermioc_redraw_s redraw;
redraw.handle = m_nxterm;
redraw.rect.pt1.x = 0;
redraw.rect.pt1.y = 0;
redraw.rect.pt2.x = windowSize.w - 1;
redraw.rect.pt2.y = windowSize.h - 1;
redraw.more = false;
iocargs.cmd = NXTERMIOC_NXTERM_REDRAW;
iocargs.arg = (uintptr_t)&redraw;
boardctl(BOARDIOC_NXTERM_IOCTL, (uintptr_t)&iocargs);
}
* Report of this is a "normal" window or a full screen window. The
* primary purpose of this method is so that window manager will know
* whether or not it show draw the task bar.
*
* @return True if this is a full screen window.
*/
bool CNxTerm::isFullScreen(void) const
{
return m_window->isFullScreen();
}
* This is the NxTerm task. This function first redirects output to the
* console window then calls to start the NSH logic.
*/
int CNxTerm::nxterm(int argc, char *argv[])
{
int fd = -1;
int ret = OK;
if (on_exit(exitHandler, g_nxtermvars.console) != 0)
{
gerr("ERROR: on_exit failed\n");
goto errout;
}
struct boardioc_nxterm_create_s nxcreate;
nxcreate.nxterm = (FAR void *)0;
nxcreate.hwnd = g_nxtermvars.hwnd;
nxcreate.wndo = g_nxtermvars.wndo;
nxcreate.type = BOARDIOC_XTERM_FRAMED;
nxcreate.minor = g_nxtermvars.minor;
ret = boardctl(BOARDIOC_NXTERM, (uintptr_t)&nxcreate);
if (ret < 0)
{
gerr("ERROR: boardctl(BOARDIOC_NXTERM) failed: %d\n", errno);
goto errout;
}
g_nxtermvars.nxterm = nxcreate.nxterm;
DEBUGASSERT(g_nxtermvars.nxterm != NULL);
char devname[32];
snprintf(devname, sizeof(devname), "/dev/nxterm%d", g_nxtermvars.minor);
g_nxtermvars.minor++;
#ifdef CONFIG_NXTERM_NXKBDIN
fd = open(devname, O_RDWR);
#else
fd = open(devname, O_WRONLY);
#endif
if (fd < 0)
{
gerr("ERROR: Failed open the console device\n");
unlink(devname);
goto errout;
}
std::fflush(stdout);
std::fflush(stderr);
#ifdef CONFIG_NXTERM_NXKBDIN
dup2(fd, 0);
#endif
dup2(fd, 1);
dup2(fd, 2);
if (fd > 2)
{
::close(fd);
}
g_nxtermvars.result = true;
sem_post(&g_nxtermvars.waitSem);
#ifdef CONFIG_NSH_CONSOLE
nsh_consolemain(argc, argv);
#endif
return EXIT_SUCCESS;
errout:
g_nxtermvars.nxterm = 0;
g_nxtermvars.result = false;
sem_post(&g_nxtermvars.waitSem);
return EXIT_FAILURE;
}
* This is the NxTerm task exit handler. It registered with on_exit()
* and called automatically when the nxterm task exits.
*/
void CNxTerm::exitHandler(int code, FAR void *arg)
{
CNxTerm *This = (CNxTerm *)arg;
if (This->m_pid >= 0)
{
This->m_pid = -1;
This->m_taskbar->stopApplication(This);
}
}
* Called when the window minimize button is pressed.
*/
void CNxTerm::minimize(void)
{
m_taskbar->minimizeApplication(static_cast<IApplication*>(this));
}
* Called when the window close button is pressed.
*/
void CNxTerm::close(void)
{
m_taskbar->stopApplication(static_cast<IApplication*>(this));
}
* CNxTermFactory Constructor
*
* @param taskbar. The taskbar instance used to terminate the console
*/
CNxTermFactory::CNxTermFactory(CTaskbar *taskbar)
{
m_taskbar = taskbar;
}
* Create a new instance of an CNxTerm (as IApplication).
*/
IApplication *CNxTermFactory::create(void)
{
CApplicationWindow *window = m_taskbar->openApplicationWindow();
if (!window)
{
gerr("ERROR: Failed to create CApplicationWindow\n");
return (IApplication *)0;
}
if (!window->open())
{
gerr("ERROR: Failed to open CApplicationWindow\n");
delete window;
return (IApplication *)0;
}
CNxTerm *nxterm = new CNxTerm(m_taskbar, window);
if (!nxterm)
{
gerr("ERROR: Failed to instantiate CNxTerm\n");
delete window;
return (IApplication *)0;
}
return static_cast<IApplication*>(nxterm);
}
* 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 *CNxTermFactory::getIcon(void)
{
NXWidgets::CRlePaletteBitmap *bitmap =
new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_NXTERM_ICON);
return bitmap;
}
* 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 NxWM::nshlibInitialize(void)
{
sem_init(&g_nxtermvars.exclSem, 0, 1);
sem_init(&g_nxtermvars.waitSem, 0, 0);
nsh_initialize();
return true;
}