NxWidgets/NxWM updates from Petteri Aimonen (Patches 0007-0013)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5689 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
a96a12751a
commit
804bd95e05
@ -280,4 +280,50 @@
|
|||||||
it works with indexed input images.
|
it works with indexed input images.
|
||||||
* NxWidgets::CLabel: Fix backward conditional compilation in the
|
* NxWidgets::CLabel: Fix backward conditional compilation in the
|
||||||
"flicker free" logic.
|
"flicker free" logic.
|
||||||
|
* NxWidgets::CNxTimer: Previously repeated timers were re-enabled after
|
||||||
|
the timer action event. Consequently, if the action event handler tried
|
||||||
|
to stop the timer, the request would be ignored. Changes the order
|
||||||
|
so that the timer is re-enabled before the callback. There is still
|
||||||
|
no risk of re-entrancy, because everything executes on the USRWORK work
|
||||||
|
queue. From Petteri Aimonen.
|
||||||
|
* NxWidgets::CMultiLineTestBox: Fix text placement error. From Petteri
|
||||||
|
Aimonen.
|
||||||
|
* NxWidgets::CWidgetControl: Added another semaphore, boundssem, which
|
||||||
|
is set as soon as the screen bounds are known. This corrects two
|
||||||
|
problems:
|
||||||
|
1) Due to the way nxgl_rectsize computes the size, it will never
|
||||||
|
be 0,0 like CWidgetControl expects. Therefore the size is considered
|
||||||
|
valid even though it has not been set yet.
|
||||||
|
2) After the check is fixed to test for > 1, NxWM window creation will
|
||||||
|
hang. This is due to the fact that it uses the screen bounds for
|
||||||
|
determining window size. This was being blocked on geosem, which
|
||||||
|
is only posted after the size has been set.
|
||||||
|
From Petteri Aimonen.
|
||||||
|
* NxWidgets::CImage: Two enhancements:
|
||||||
|
1) Allow changing the bitmap even after the control has been created.
|
||||||
|
2) Allow giving 'null' to have the control draw no image at all.
|
||||||
|
From Petteri Aimonen.
|
||||||
|
* NxWM::CTaskBar: Allow windows with null icon. This makes sense for e.g.
|
||||||
|
full screen windows. From Petteri Aimonen.
|
||||||
|
* NxWM::CApplicationWindow: Add config options to override NxWM
|
||||||
|
stop/minimize icons. From Petteri Aimonen.
|
||||||
|
* NwWM::CStartWindow, NxWM::CWindowMessenger: Get rid of the start window
|
||||||
|
thread. Instead, handle all events through the USRWORK work queue.
|
||||||
|
For me, this was necessary because I would open some files in button
|
||||||
|
handlers and close them in NxTimer handlers. If these belonged to
|
||||||
|
different tasks, the close operation would fail. Further benefits:
|
||||||
|
+ Gets rid of one task and message queue.
|
||||||
|
+ Reduces the amount of code required
|
||||||
|
+ Decouples CStartWindow from everything else - now it is just a window
|
||||||
|
with application icons, not an integral part of the event logic.
|
||||||
|
+ All events come from the same thread, which reduces the possibility of
|
||||||
|
multithreading errors in user code.
|
||||||
|
+ The user code can also send events to USRWORK, so that everything gets
|
||||||
|
serialized nicely without having to use so many mutexes.
|
||||||
|
Drawbacks:
|
||||||
|
- Currently the work state structure is malloc()ed, causing one allocation
|
||||||
|
and free per each input event. Could add a memory pool for these later, but
|
||||||
|
the speed difference doesn't seem noticeable.
|
||||||
|
- The work queue will add ~50 ms latency to input events. This is however
|
||||||
|
configurable, and the delay is anyway short enough that it is unnoticeable.
|
||||||
|
From Petteri Aimonen.
|
||||||
|
24
Kconfig
24
Kconfig
@ -463,6 +463,30 @@ config NXWM_BACKGROUND_IMAGE
|
|||||||
The name of the image to use in the background window. Default:
|
The name of the image to use in the background window. Default:
|
||||||
NXWidgets::g_nuttxBitmap
|
NXWidgets::g_nuttxBitmap
|
||||||
|
|
||||||
|
comment "Application Window Configuration"
|
||||||
|
|
||||||
|
config NXWM_CUSTOM_APPWINDOW_ICONS
|
||||||
|
bool "Custom Start/Stop Application Window Icons"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Select to override the default Application Window Stop and Minimize Icons.
|
||||||
|
|
||||||
|
if NXWM_CUSTOM_APPWINDOW_ICONS
|
||||||
|
|
||||||
|
config NXWM_STOP_BITMAP
|
||||||
|
string "Stop Icon"
|
||||||
|
default "NxWM::g_stopBitmap"
|
||||||
|
---help---
|
||||||
|
The glyph to use as the Stop icon. Default: NxWM::g_stopBitmap
|
||||||
|
|
||||||
|
config NXWM_MINIMIZE_BITMAP
|
||||||
|
string "Minimize Icon"
|
||||||
|
default "NxWM::g_minimizeBitmap"
|
||||||
|
---help---
|
||||||
|
The glyph to use as the Minimize icon. Default: NxWM::g_minimizeBitmap
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
comment "Start Window Configuration"
|
comment "Start Window Configuration"
|
||||||
|
|
||||||
comment "Horizontal and vertical spacing of icons in the task bar"
|
comment "Horizontal and vertical spacing of icons in the task bar"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NxWidgets/libnxwidgets/include/cimage.hxx
|
* NxWidgets/libnxwidgets/include/cimage.hxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -207,6 +207,12 @@ namespace NXWidgets
|
|||||||
|
|
||||||
inline FAR IBitmap *getBitmap() const { return m_bitmap; }
|
inline FAR IBitmap *getBitmap() const { return m_bitmap; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the bitmap that this image contains.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void setBitmap(FAR IBitmap *bitmap) { m_bitmap = bitmap; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert the dimensions that this widget wants to have into the rect
|
* Insert the dimensions that this widget wants to have into the rect
|
||||||
* passed in as a parameter. All coordinates are relative to the
|
* passed in as a parameter. All coordinates are relative to the
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx
|
* NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -203,6 +204,7 @@ namespace NXWidgets
|
|||||||
struct nxgl_rect_s m_bounds; /**< Size of the display */
|
struct nxgl_rect_s m_bounds; /**< Size of the display */
|
||||||
#ifdef CONFIG_NX_MULTIUSER
|
#ifdef CONFIG_NX_MULTIUSER
|
||||||
sem_t m_geoSem; /**< Posted when geometry is valid */
|
sem_t m_geoSem; /**< Posted when geometry is valid */
|
||||||
|
sem_t m_boundsSem; /**< Posted when bounds are valid */
|
||||||
#endif
|
#endif
|
||||||
CWindowEventHandlerList m_eventHandlers; /**< List of event handlers. */
|
CWindowEventHandlerList m_eventHandlers; /**< List of event handlers. */
|
||||||
|
|
||||||
@ -324,6 +326,37 @@ namespace NXWidgets
|
|||||||
giveGeoSem();
|
giveGeoSem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take the bounds semaphore (handling signal interruptions)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NX_MULTIUSER
|
||||||
|
void takeBoundsSem(void);
|
||||||
|
#else
|
||||||
|
inline void takeBoundsSem(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the bounds semaphore
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void giveBoundsSem(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NX_MULTIUSER
|
||||||
|
sem_post(&m_boundsSem);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for bounds data
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void waitBoundsData(void)
|
||||||
|
{
|
||||||
|
takeBoundsSem();
|
||||||
|
giveBoundsSem();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all mouse events
|
* Clear all mouse events
|
||||||
*/
|
*/
|
||||||
@ -639,21 +672,21 @@ namespace NXWidgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the window bounding box in physical display coordinated. This
|
* Get the window bounding box in physical display coordinates. This
|
||||||
* method may need to wait until geometry data is available.
|
* method may need to wait until bounds data is available.
|
||||||
*
|
*
|
||||||
* @return This function returns the window handle.
|
* @return This function returns the window handle.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline CRect getWindowBoundingBox(void)
|
inline CRect getWindowBoundingBox(void)
|
||||||
{
|
{
|
||||||
waitGeoData();
|
waitBoundsData();
|
||||||
return CRect(&m_bounds);
|
return CRect(&m_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void getWindowBoundingBox(FAR struct nxgl_rect_s *bounds)
|
inline void getWindowBoundingBox(FAR struct nxgl_rect_s *bounds)
|
||||||
{
|
{
|
||||||
waitGeoData();
|
waitBoundsData();
|
||||||
nxgl_rectcopy(bounds, &m_bounds);
|
nxgl_rectcopy(bounds, &m_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NxWidgets/libnxwidgets/include/cimage.cxx
|
* NxWidgets/libnxwidgets/include/cimage.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -163,6 +163,13 @@ void CImage::getPreferredDimensions(CRect &rect) const
|
|||||||
|
|
||||||
void CImage::drawContents(CGraphicsPort *port)
|
void CImage::drawContents(CGraphicsPort *port)
|
||||||
{
|
{
|
||||||
|
if (!m_bitmap)
|
||||||
|
{
|
||||||
|
// No image to draw
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the the drawable region
|
// Get the the drawable region
|
||||||
|
|
||||||
CRect rect;
|
CRect rect;
|
||||||
|
@ -1261,8 +1261,8 @@ void CMultiLineTextBox::drawRow(CGraphicsPort *port, int row)
|
|||||||
uint8_t rowLength = m_text->getLineTrimmedLength(row);
|
uint8_t rowLength = m_text->getLineTrimmedLength(row);
|
||||||
|
|
||||||
struct nxgl_point_s pos;
|
struct nxgl_point_s pos;
|
||||||
pos.x = getRowX(row) + m_canvasX;
|
pos.x = getRowX(row) + m_canvasX + rect.getX();
|
||||||
pos.y = getRowY(row) + m_canvasY;
|
pos.y = getRowY(row) + m_canvasY + rect.getY();
|
||||||
|
|
||||||
// Determine the background and text color
|
// Determine the background and text color
|
||||||
|
|
||||||
|
@ -193,16 +193,16 @@ void CNxTimer::workQueueCallback(FAR void *arg)
|
|||||||
|
|
||||||
This->m_isRunning = false;
|
This->m_isRunning = false;
|
||||||
|
|
||||||
// Raise the action event.
|
|
||||||
|
|
||||||
This->m_widgetEventHandlers->raiseActionEvent();
|
|
||||||
|
|
||||||
// Restart the timer if this is a repeating timer
|
// Restart the timer if this is a repeating timer
|
||||||
|
|
||||||
if (This->m_isRepeater)
|
if (This->m_isRepeater)
|
||||||
{
|
{
|
||||||
This->start();
|
This->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Raise the action event.
|
||||||
|
|
||||||
|
This->m_widgetEventHandlers->raiseActionEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx
|
* NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -117,6 +117,7 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style)
|
|||||||
sem_init(&m_waitSem, 0, 0);
|
sem_init(&m_waitSem, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_NX_MULTIUSER
|
#ifdef CONFIG_NX_MULTIUSER
|
||||||
|
sem_init(&m_boundsSem, 0, 0);
|
||||||
sem_init(&m_geoSem, 0, 0);
|
sem_init(&m_geoSem, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -136,7 +137,6 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
*/
|
*/
|
||||||
@ -397,15 +397,16 @@ void CWidgetControl::geometryEvent(NXHANDLE hWindow,
|
|||||||
|
|
||||||
m_hWindow = hWindow;
|
m_hWindow = hWindow;
|
||||||
nxgl_rectcopy(&m_bounds, bounds);
|
nxgl_rectcopy(&m_bounds, bounds);
|
||||||
|
giveBoundsSem();
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the normal start up sequence, the window is created with zero size
|
// In the normal start up sequence, the window is created with zero size
|
||||||
// at position 0,0. The safe thing to do is to set the position (still
|
// at position 0,0. The safe thing to do is to set the position (still
|
||||||
// with size 0, then then set the size. Assuming that is what is being
|
// with size 0, then then set the size. Assuming that is what is being
|
||||||
// done, we will not report that we have valid geometry until the size
|
// done, we will not report that we have valid geometry until the size
|
||||||
// becomes nonzero.
|
// becomes nonzero (or actually over 1).
|
||||||
|
|
||||||
if (!m_haveGeometry && size->h > 0 && size->w > 0)
|
if (!m_haveGeometry && size->h > 1 && size->w > 1)
|
||||||
{
|
{
|
||||||
// Wake up any threads waiting for initial position information.
|
// Wake up any threads waiting for initial position information.
|
||||||
// REVISIT: If the window is moved or repositioned, then the
|
// REVISIT: If the window is moved or repositioned, then the
|
||||||
@ -916,6 +917,25 @@ void CWidgetControl::takeGeoSem(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take the bounds semaphore (handling signal interruptions)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NX_MULTIUSER
|
||||||
|
void CWidgetControl::takeBoundsSem(void)
|
||||||
|
{
|
||||||
|
// Take the bounds semaphore. Retry is an error occurs (only if
|
||||||
|
// the error is due to a signal interruption).
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = sem_wait(&m_boundsSem);
|
||||||
|
}
|
||||||
|
while (ret < 0 && errno == EINTR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all mouse events
|
* Clear all mouse events
|
||||||
*/
|
*/
|
||||||
|
@ -119,7 +119,6 @@ namespace NxWM
|
|||||||
CApplicationWindow *m_window; /**< Reference to the application window */
|
CApplicationWindow *m_window; /**< Reference to the application window */
|
||||||
TNxArray<struct SStartWindowSlot> m_slots; /**< List of apps in the start window */
|
TNxArray<struct SStartWindowSlot> m_slots; /**< List of apps in the start window */
|
||||||
struct nxgl_size_s m_iconSize; /**< A box big enough to hold the largest icon */
|
struct nxgl_size_s m_iconSize; /**< A box big enough to hold the largest icon */
|
||||||
pid_t m_taskId; /**< ID of the start window task */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the start window task. This function receives window events from
|
* This is the start window task. This function receives window events from
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NxWidgets/nxwm/include/cwindowmessenger.hxx
|
* NxWidgets/nxwm/include/cwindowmessenger.hxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -43,8 +43,8 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <mqueue.h>
|
|
||||||
|
|
||||||
|
#include <nuttx/wqueue.h>
|
||||||
#include <nuttx/nx/nxtk.h>
|
#include <nuttx/nx/nxtk.h>
|
||||||
#include <nuttx/nx/nxconsole.h>
|
#include <nuttx/nx/nxconsole.h>
|
||||||
|
|
||||||
@ -83,8 +83,19 @@ namespace NxWM
|
|||||||
public NXWidgets::CWidgetControl
|
public NXWidgets::CWidgetControl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
mqd_t m_mqd; /**< Message queue descriptor used to commincate with the
|
/** Structure that stores data for the work queue callback. */
|
||||||
** start window thread. */
|
|
||||||
|
struct work_state_t
|
||||||
|
{
|
||||||
|
work_s work;
|
||||||
|
CWindowMessenger *windowMessenger;
|
||||||
|
void *instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Work queue callback functions */
|
||||||
|
|
||||||
|
static void inputWorkCallback(FAR void *arg);
|
||||||
|
static void destroyWorkCallback(FAR void *arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an NX window mouse input event.
|
* Handle an NX window mouse input event.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* NxWidgets/nxwm/src/capplicationwindow.cxx
|
* NxWidgets/nxwm/src/capplicationwindow.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -54,6 +54,18 @@
|
|||||||
* Pre-Processor Definitions
|
* Pre-Processor Definitions
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NXWM_STOP_BITMAP
|
||||||
|
extern const struct NXWidgets::SRlePaletteBitmap CONFIG_NXWM_STOP_BITMAP;
|
||||||
|
#else
|
||||||
|
# define CONFIG_NXWM_STOP_BITMAP g_stopBitmap
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_NXWM_MINIMIZE_BITMAP
|
||||||
|
extern const struct NXWidgets::SRlePaletteBitmap CONFIG_NXWM_MINIMIZE_BITMAP;
|
||||||
|
#else
|
||||||
|
# define CONFIG_NXWM_MINIMIZE_BITMAP g_minimizeBitmap
|
||||||
|
#endif
|
||||||
|
|
||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* CApplicationWindow Method Implementations
|
* CApplicationWindow Method Implementations
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
@ -192,7 +204,7 @@ bool CApplicationWindow::open(void)
|
|||||||
{
|
{
|
||||||
// Create STOP bitmap container
|
// Create STOP bitmap container
|
||||||
|
|
||||||
m_stopBitmap = new NXWidgets::CRlePaletteBitmap(&g_stopBitmap);
|
m_stopBitmap = new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_STOP_BITMAP);
|
||||||
if (!m_stopBitmap)
|
if (!m_stopBitmap)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -244,7 +256,7 @@ bool CApplicationWindow::open(void)
|
|||||||
#ifndef CONFIG_NXWM_DISABLE_MINIMIZE
|
#ifndef CONFIG_NXWM_DISABLE_MINIMIZE
|
||||||
// Create MINIMIZE application bitmap container
|
// Create MINIMIZE application bitmap container
|
||||||
|
|
||||||
m_minimizeBitmap = new NXWidgets::CRlePaletteBitmap(&g_minimizeBitmap);
|
m_minimizeBitmap = new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_MINIMIZE_BITMAP);
|
||||||
if (!m_minimizeBitmap)
|
if (!m_minimizeBitmap)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* NxWidgets/nxwm/src/cstartwindow.cxx
|
* NxWidgets/nxwm/src/cstartwindow.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -44,8 +44,6 @@
|
|||||||
#include <csched>
|
#include <csched>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
|
||||||
#include <mqueue.h>
|
|
||||||
|
|
||||||
#include "cwidgetcontrol.hxx"
|
#include "cwidgetcontrol.hxx"
|
||||||
|
|
||||||
#include "nxwmconfig.hxx"
|
#include "nxwmconfig.hxx"
|
||||||
@ -89,10 +87,6 @@ CStartWindow::CStartWindow(CTaskbar *taskbar, CApplicationWindow *window)
|
|||||||
m_taskbar = taskbar;
|
m_taskbar = taskbar;
|
||||||
m_window = window;
|
m_window = window;
|
||||||
|
|
||||||
// The start window task is not running
|
|
||||||
|
|
||||||
m_taskId = -1;
|
|
||||||
|
|
||||||
// Add our personalized window label
|
// Add our personalized window label
|
||||||
|
|
||||||
NXWidgets::CNxString myName = getName();
|
NXWidgets::CNxString myName = getName();
|
||||||
@ -169,24 +163,7 @@ NXWidgets::CNxString CStartWindow::getName(void)
|
|||||||
|
|
||||||
bool CStartWindow::run(void)
|
bool CStartWindow::run(void)
|
||||||
{
|
{
|
||||||
// Some sanity checking
|
return true;
|
||||||
|
|
||||||
if (m_taskId >= 0)
|
|
||||||
{
|
|
||||||
// The start window task is already running???
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the start window task
|
|
||||||
|
|
||||||
m_taskId = TASK_CREATE("StartWindow", CONFIG_NXWM_STARTWINDOW_PRIO,
|
|
||||||
CONFIG_NXWM_STARTWINDOW_STACKSIZE, startWindow,
|
|
||||||
(FAR char * const *)0);
|
|
||||||
|
|
||||||
// Did we successfully start the NxConsole task?
|
|
||||||
|
|
||||||
return m_taskId >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,21 +172,8 @@ bool CStartWindow::run(void)
|
|||||||
|
|
||||||
void CStartWindow::stop(void)
|
void CStartWindow::stop(void)
|
||||||
{
|
{
|
||||||
// Delete the start window task --- what are we doing? This should never
|
|
||||||
// happen because the start window task is persistent!
|
|
||||||
|
|
||||||
if (m_taskId >= 0)
|
|
||||||
{
|
|
||||||
// Call task_delete(), possibly stranding resources
|
|
||||||
|
|
||||||
pid_t pid = m_taskId;
|
|
||||||
m_taskId = -1;
|
|
||||||
|
|
||||||
// Then delete the NSH task
|
|
||||||
|
|
||||||
task_delete(pid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the application and free all of its resources. This method
|
* Destroy the application and free all of its resources. This method
|
||||||
* will initiate blocking of messages from the NX server. The server
|
* will initiate blocking of messages from the NX server. The server
|
||||||
@ -596,108 +560,3 @@ void CStartWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the start window task. This function receives window events from
|
|
||||||
* the NX listener threads indirectly through this sequence:
|
|
||||||
*
|
|
||||||
* 1. NX listener thread receives a windows event. This may be a
|
|
||||||
* positional change notification, a redraw request, or mouse or
|
|
||||||
* keyboard input.
|
|
||||||
* 2. The NX listener thread performs the callback by calling a
|
|
||||||
* NXWidgets::CCallback method associated with the window.
|
|
||||||
* 3. NXWidgets::CCallback calls into NXWidgets::CWidgetControl to process
|
|
||||||
* the event.
|
|
||||||
* 4. NXWidgets::CWidgetControl records the new state data and raises a
|
|
||||||
* window event.
|
|
||||||
* 5. NXWidgets::CWindowEventHandlerList will give the event to
|
|
||||||
* NxWM::CWindowMessenger.
|
|
||||||
* 6. NxWM::CWindowMessenger will send the a message on a well-known message
|
|
||||||
* queue.
|
|
||||||
* 7. This CStartWindow::startWindow task will receive and process that
|
|
||||||
* message.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int CStartWindow::startWindow(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
/* Open a well-known message queue for reading */
|
|
||||||
|
|
||||||
struct mq_attr attr;
|
|
||||||
attr.mq_maxmsg = CONFIG_NXWM_STARTWINDOW_MXMSGS;
|
|
||||||
attr.mq_msgsize = sizeof(struct SStartWindowMessage);
|
|
||||||
attr.mq_flags = 0;
|
|
||||||
|
|
||||||
mqd_t mqd = mq_open(g_startWindowMqName, O_RDONLY|O_CREAT, 0666, &attr);
|
|
||||||
if (mqd == (mqd_t)-1)
|
|
||||||
{
|
|
||||||
gdbg("ERROR: mq_open(%s) failed: %d\n", g_startWindowMqName, errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now loop forever, receiving and processing messages. Ultimately, all
|
|
||||||
// widget driven events (button presses, etc.) are driven by this logic
|
|
||||||
// on this thread.
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// Receive the next message
|
|
||||||
|
|
||||||
struct SStartWindowMessage msg;
|
|
||||||
ssize_t nbytes = mq_receive(mqd, &msg, sizeof(struct SStartWindowMessage), 0);
|
|
||||||
if (nbytes < 0)
|
|
||||||
{
|
|
||||||
int errval = errno;
|
|
||||||
|
|
||||||
// EINTR is not an error. The wait was interrupted by a signal and
|
|
||||||
// we just need to try reading again.
|
|
||||||
|
|
||||||
if (errval != EINTR)
|
|
||||||
{
|
|
||||||
gdbg("ERROR: mq_receive failed: %d\n", errval);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdbg("mq_receive interrupted by signal\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gvdbg("Received msgid=%d nbytes=%d\n", msg.msgId, nbytes);
|
|
||||||
DEBUGASSERT(nbytes = sizeof(struct SStartWindowMessage) && msg.instance);
|
|
||||||
|
|
||||||
// Dispatch the message to the appropriate CWidgetControl and to the
|
|
||||||
// appropriate CWidgetControl method
|
|
||||||
|
|
||||||
switch (msg.msgId)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MSGID_MOUSE_INPUT: // New mouse input is available
|
|
||||||
case MSGID_KEYBOARD_INPUT: // New keyboard input is available
|
|
||||||
{
|
|
||||||
// Handle all new window input events by calling the CWidgetControl::pollEvents() method
|
|
||||||
|
|
||||||
NXWidgets::CWidgetControl *control = (NXWidgets::CWidgetControl *)msg.instance;
|
|
||||||
control->pollEvents();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MSGID_DESTROY_APP: // Destroy the application
|
|
||||||
{
|
|
||||||
// Handle all destroy application events
|
|
||||||
|
|
||||||
gdbg("Deleting app=%p\n", msg.instance);
|
|
||||||
IApplication *app = (IApplication *)msg.instance;
|
|
||||||
delete app;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MSGID_POSITIONAL_CHANGE: // Change in window positional data (not used)
|
|
||||||
case MSGID_REDRAW_REQUEST: // Request to redraw a portion of the window (not used)
|
|
||||||
default:
|
|
||||||
gdbg("ERROR: Unrecognized or unsupported msgId: %d\n", (int)msg.msgId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* NxWidgets/nxwm/src/ctaskbar.cxx
|
* NxWidgets/nxwm/src/ctaskbar.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -456,11 +456,21 @@ bool CTaskbar::startApplication(IApplication *app, bool minimized)
|
|||||||
|
|
||||||
NXWidgets::IBitmap *bitmap = app->getIcon();
|
NXWidgets::IBitmap *bitmap = app->getIcon();
|
||||||
|
|
||||||
// Create a CImage instance to manage the applications icon
|
// Create a CImage instance to manage the applications icon. Assume the
|
||||||
|
// minimum size in case no bitmap is provided (bitmap == NULL)
|
||||||
|
|
||||||
|
int w = 1;
|
||||||
|
int h = 1;
|
||||||
|
|
||||||
|
if (bitmap)
|
||||||
|
{
|
||||||
|
w = bitmap->getWidth();
|
||||||
|
h = bitmap->getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
NXWidgets::CImage *image =
|
NXWidgets::CImage *image =
|
||||||
new NXWidgets::CImage(control, 0, 0, bitmap->getWidth(),
|
new NXWidgets::CImage(control, 0, 0, w, h, bitmap, 0);
|
||||||
bitmap->getHeight(), bitmap, 0);
|
|
||||||
if (!image)
|
if (!image)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* NxWidgets/nxwm/src/cwindowmessenger.cxx
|
* NxWidgets/nxwm/src/cwindowmessenger.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -69,20 +69,6 @@ using namespace NxWM;
|
|||||||
CWindowMessenger::CWindowMessenger(FAR const NXWidgets::CWidgetStyle *style)
|
CWindowMessenger::CWindowMessenger(FAR const NXWidgets::CWidgetStyle *style)
|
||||||
: NXWidgets::CWidgetControl(style)
|
: NXWidgets::CWidgetControl(style)
|
||||||
{
|
{
|
||||||
// Open a message queue to communicate with the start window task. We need to create
|
|
||||||
// the message queue if it does not exist.
|
|
||||||
|
|
||||||
struct mq_attr attr;
|
|
||||||
attr.mq_maxmsg = CONFIG_NXWM_STARTWINDOW_MXMSGS;
|
|
||||||
attr.mq_msgsize = sizeof(struct SStartWindowMessage);
|
|
||||||
attr.mq_flags = 0;
|
|
||||||
|
|
||||||
m_mqd = mq_open(g_startWindowMqName, O_WRONLY|O_CREAT, 0666, &attr);
|
|
||||||
if (m_mqd == (mqd_t)-1)
|
|
||||||
{
|
|
||||||
gdbg("ERROR: mq_open(%s) failed: %d\n", g_startWindowMqName, errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add ourself to the list of window event handlers
|
// Add ourself to the list of window event handlers
|
||||||
|
|
||||||
addWindowEventHandler(this);
|
addWindowEventHandler(this);
|
||||||
@ -97,10 +83,6 @@ CWindowMessenger::~CWindowMessenger(void)
|
|||||||
// Remove ourself from the list of the window event handlers
|
// Remove ourself from the list of the window event handlers
|
||||||
|
|
||||||
removeWindowEventHandler(this);
|
removeWindowEventHandler(this);
|
||||||
|
|
||||||
// Close the message queue
|
|
||||||
|
|
||||||
(void)mq_close(m_mqd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,8 +102,8 @@ void CWindowMessenger::handleMouseEvent(void)
|
|||||||
// 3. The NX server will determine which window gets the mouse input
|
// 3. The NX server will determine which window gets the mouse input
|
||||||
// and send a window event message to the NX listener thread.
|
// and send a window event message to the NX listener thread.
|
||||||
// 4. The NX listener thread receives a windows event. The NX listener thread
|
// 4. The NX listener thread receives a windows event. The NX listener thread
|
||||||
// which is part of CTaskBar and was created when NX server connection was
|
// is part of CTaskBar and was created when NX server connection was
|
||||||
// established). This event may be a positional change notification, a
|
// established. This event may be a positional change notification, a
|
||||||
// redraw request, or mouse or keyboard input. In this case, mouse input.
|
// redraw request, or mouse or keyboard input. In this case, mouse input.
|
||||||
// 5. The NX listener thread handles the message by calling nx_eventhandler().
|
// 5. The NX listener thread handles the message by calling nx_eventhandler().
|
||||||
// nx_eventhandler() dispatches the message by calling a method in the
|
// nx_eventhandler() dispatches the message by calling a method in the
|
||||||
@ -133,20 +115,18 @@ void CWindowMessenger::handleMouseEvent(void)
|
|||||||
// window event.
|
// window event.
|
||||||
// 8. NXWidgets::CWindowEventHandlerList will give the event to this method
|
// 8. NXWidgets::CWindowEventHandlerList will give the event to this method
|
||||||
// NxWM::CWindowMessenger.
|
// NxWM::CWindowMessenger.
|
||||||
// 9. This NxWM::CWindowMessenger method will send the a message on a well-
|
// 9. This NxWM::CWindowMessenger method will schedule an entry on the work
|
||||||
// known message queue.
|
// queue.
|
||||||
// 10. This CStartWindow::startWindow task will receive and process that
|
// 10. The work queue callback will finally call pollEvents() to execute whatever
|
||||||
// message by calling CWidgetControl::pollEvents()
|
// actions the input event should trigger.
|
||||||
|
|
||||||
struct SStartWindowMessage outmsg;
|
work_state_t *state = new work_state_t;
|
||||||
outmsg.msgId = MSGID_MOUSE_INPUT;
|
state->windowMessenger = this;
|
||||||
outmsg.instance = (FAR void *)static_cast<CWidgetControl*>(this);
|
|
||||||
|
|
||||||
int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage),
|
int ret = work_queue(USRWORK, &state->work, &inputWorkCallback, state, 0);
|
||||||
CONFIG_NXWM_STARTWINDOW_MXMPRIO);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
gdbg("ERROR: mq_send failed: %d\n", errno);
|
gdbg("ERROR: work_queue failed: %d\n", ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -158,41 +138,13 @@ void CWindowMessenger::handleMouseEvent(void)
|
|||||||
#ifdef CONFIG_NX_KBD
|
#ifdef CONFIG_NX_KBD
|
||||||
void CWindowMessenger::handleKeyboardEvent(void)
|
void CWindowMessenger::handleKeyboardEvent(void)
|
||||||
{
|
{
|
||||||
// The logic path here is tortuous but flexible:
|
work_state_t *state = new work_state_t;
|
||||||
//
|
state->windowMessenger = this;
|
||||||
// 1. A listener thread receives keyboard input and injects that into NX
|
|
||||||
// via nx_kbdin.
|
|
||||||
// 2. In the multi-user mode, this will send a message to the NX server
|
|
||||||
// 3. The NX server will determine which window gets the keyboard input
|
|
||||||
// and send a window event message to the NX listener thread.
|
|
||||||
// 4. The NX listener thread receives a windows event. The NX listener thread
|
|
||||||
// which is part of CTaskBar and was created when NX server connection was
|
|
||||||
// established). This event may be a positional change notification, a
|
|
||||||
// redraw request, or mouse or keyboard input. In this case, keyboard input.
|
|
||||||
// 5. The NX listener thread handles the message by calling nx_eventhandler().
|
|
||||||
// nx_eventhandler() dispatches the message by calling a method in the
|
|
||||||
// NXWidgets::CCallback instance associated with the window.
|
|
||||||
// NXWidgets::CCallback is a part of the CWidgetControl.
|
|
||||||
// 6. NXWidgets::CCallback calls into NXWidgets::CWidgetControl to process
|
|
||||||
// the event.
|
|
||||||
// 7. NXWidgets::CWidgetControl records the new state data and raises a
|
|
||||||
// window event.
|
|
||||||
// 8. NXWidgets::CWindowEventHandlerList will give the event to this method
|
|
||||||
// NxWM::CWindowMessenger.
|
|
||||||
// 9. This NxWM::CWindowMessenger method will send the a message on a well-
|
|
||||||
// known message queue.
|
|
||||||
// 10. This CStartWindow::startWindow task will receive and process that
|
|
||||||
// message by calling CWidgetControl::pollEvents()
|
|
||||||
|
|
||||||
struct SStartWindowMessage outmsg;
|
int ret = work_queue(USRWORK, &state->work, &inputWorkCallback, state, 0);
|
||||||
outmsg.msgId = MSGID_KEYBOARD_INPUT;
|
|
||||||
outmsg.instance = (FAR void *)static_cast<CWidgetControl*>(this);
|
|
||||||
|
|
||||||
int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage),
|
|
||||||
CONFIG_NXWM_STARTWINDOW_MXMPRIO);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
gdbg("ERROR: mq_send failed: %d\n", errno);
|
gdbg("ERROR: work_queue failed: %d\n", ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -213,18 +165,40 @@ void CWindowMessenger::handleKeyboardEvent(void)
|
|||||||
|
|
||||||
void CWindowMessenger::handleBlockedEvent(FAR void *arg)
|
void CWindowMessenger::handleBlockedEvent(FAR void *arg)
|
||||||
{
|
{
|
||||||
// Send a message to destroy the window isntance at a later time
|
// Send a message to destroy the window instance.
|
||||||
|
|
||||||
struct SStartWindowMessage outmsg;
|
work_state_t *state = new work_state_t;
|
||||||
outmsg.msgId = MSGID_DESTROY_APP;
|
state->windowMessenger = this;
|
||||||
outmsg.instance = arg;
|
state->instance = arg;
|
||||||
|
|
||||||
gdbg("Sending MSGID_DESTROY_APP with instance=%p\n", arg);
|
int ret = work_queue(USRWORK, &state->work, &destroyWorkCallback, state, 0);
|
||||||
int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage),
|
|
||||||
CONFIG_NXWM_STARTWINDOW_MXMPRIO);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
gdbg("ERROR: mq_send failed: %d\n", errno);
|
gdbg("ERROR: work_queue failed: %d\n", ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Work queue callback functions */
|
||||||
|
|
||||||
|
void CWindowMessenger::inputWorkCallback(FAR void *arg)
|
||||||
|
{
|
||||||
|
work_state_t *state = (work_state_t*)arg;
|
||||||
|
state->windowMessenger->pollEvents();
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindowMessenger::destroyWorkCallback(FAR void *arg)
|
||||||
|
{
|
||||||
|
work_state_t *state = (work_state_t*)arg;
|
||||||
|
|
||||||
|
// First make sure any pending input events have been handled.
|
||||||
|
|
||||||
|
state->windowMessenger->pollEvents();
|
||||||
|
|
||||||
|
// Then release the memory.
|
||||||
|
|
||||||
|
gdbg("Deleting app=%p\n", state->instance);
|
||||||
|
IApplication *app = (IApplication *)state->instance;
|
||||||
|
delete app;
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user