Squashed commit of the following:

apps/graphics/twm4nx:  Additional redesign.  Window draggin now sort of works in an unreliable hurky-gurky way.  More to be done.

    apps/graphics/twm4nx:  First cut at redesigned dragging logic
This commit is contained in:
Gregory Nutt 2019-05-07 16:16:47 -06:00
parent b0d39372fb
commit d244b7a11d
17 changed files with 403 additions and 160 deletions

View File

@ -1,7 +1,7 @@
/****************************************************************************
* apps/graphics/nxwidgets/src/cwidgetcontrol.cxx
*
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012-2013, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -566,9 +566,9 @@ void CWidgetControl::newMouseEvent(FAR const struct nxgl_point_s *pos, uint8_t b
}
#endif
// Notify any external logic that a keyboard event has occurred
// Notify any external logic that a mouse event has occurred
m_eventHandlers.raiseMouseEvent();
m_eventHandlers.raiseMouseEvent(pos, buttons);
#ifdef CONFIG_NXWIDGET_EVENTWAIT
// Then wake up logic that may be waiting for a window event

View File

@ -137,11 +137,12 @@ void CWindowEventHandlerList::raiseGeometryEvent(void)
* Raise an NX mouse window input event.
*/
void CWindowEventHandlerList::raiseMouseEvent(void)
void CWindowEventHandlerList::raiseMouseEvent(FAR const struct nxgl_point_s *pos,
uint8_t buttons)
{
for (int i = 0; i < m_eventHandlers.size(); ++i)
{
m_eventHandlers.at(i)->handleMouseEvent();
m_eventHandlers.at(i)->handleMouseEvent(pos, buttons);
}
}
#endif

View File

@ -90,7 +90,8 @@ CWindowMessenger::~CWindowMessenger(void)
* Handle an NX window mouse input event.
*/
void CWindowMessenger::handleMouseEvent(void)
void CWindowMessenger::handleMouseEvent(FAR const struct nxgl_point_s *pos,
uint8_t buttons)
{
// The logic path here is tortuous but flexible:
//

View File

@ -823,8 +823,6 @@ void CIconMgr::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
struct SEventMsg msg;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.context = EVENT_CONTEXT_ICONMGR;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)swin->cwin;

View File

@ -107,7 +107,8 @@ CIconWidget::CIconWidget(FAR CTwm4Nx *twm4nx,
// Configure the widget
m_flags.borderless = true; // The widget is borless (and transparent)
m_flags.borderless = true; // The widget is borderless (and transparent)
m_flags.draggable = true; // This widget may be dragged
}
/**
@ -461,8 +462,6 @@ void CIconWidget::handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e)
msg.eventID = EVENT_ICONWIDGET_UNGRAB;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.context = EVENT_CONTEXT_ICON;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
@ -490,8 +489,8 @@ void CIconWidget::handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e)
void CIconWidget::handleDragEvent(const NXWidgets::CWidgetEventArgs &e)
{
// We don't care which widget is being dragged, only that we are in the
// dragging state.
// We don't care which component of the icon widget was clicked only that
// we are not currently being dragged
if (m_drag)
{
@ -501,8 +500,6 @@ void CIconWidget::handleDragEvent(const NXWidgets::CWidgetEventArgs &e)
msg.eventID = EVENT_ICONWIDGET_DRAG;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = e.getVX();
msg.delta.y = e.getVY();
msg.context = EVENT_CONTEXT_ICON;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
@ -562,8 +559,6 @@ void CIconWidget::handleClickEvent(const NXWidgets::CWidgetEventArgs &e)
msg.eventID = EVENT_ICONWIDGET_GRAB;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.context = EVENT_CONTEXT_ICON;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;

View File

@ -48,6 +48,7 @@
#include <pthread.h>
#include <assert.h>
#include <nuttx/semaphore.h>
#include <nuttx/nx/nxglib.h>
#include <nuttx/input/mouse.h>
@ -95,6 +96,8 @@ using namespace Twm4Nx;
CInput::CInput(CTwm4Nx *twm4nx)
{
// Session
m_twm4nx = twm4nx; // Save the NX server
#ifndef CONFIG_TWM4NX_NOKEYBOARD
m_kbdFd = -1; // Keyboard driver is not opened
@ -102,14 +105,21 @@ CInput::CInput(CTwm4Nx *twm4nx)
#ifndef CONFIG_TWM4NX_NOMOUSE
m_mouseFd = -1; // Mouse/touchscreen driver is not opened
#endif
// Listener
m_state = LISTENER_NOTRUNNING; // The listener thread is not running yet
#ifdef CONFIG_TWM4NX_TOUCHSCREEN
m_calib = false; // Use raw touches until calibrated
#endif
// Initialize the semaphore used to synchronize with the listener thread
sem_init(&m_waitSem, 0, 0);
sem_setprotocol(&m_waitSem, SEM_PRIO_NONE);
#ifdef CONFIG_TWM4NX_TOUCHSCREEN
// Calibration
m_calib = false; // Use raw touches until calibrated
#endif
}
/**

View File

@ -180,8 +180,7 @@ bool CMenus::initialize(FAR NXWidgets::CNxString &name)
bool CMenus::addMenuItem(FAR NXWidgets::CNxString &text, FAR CMenus *subMenu,
FAR CTwm4NxEvent *handler, uint16_t event)
{
twminfo("Adding menu text=\"%s\", subMenu=%p, event=%04x\n",
text->getCharArray(), subMenu, event);
twminfo("Adding: subMenu=%p, event=%04x\n", subMenu, event);
// Allocate a new menu item entry
@ -317,8 +316,6 @@ bool CMenus::event(FAR struct SEventMsg *eventmsg)
newmsg.eventID = item->event;
newmsg.pos.x = eventmsg->pos.x;
newmsg.pos.y = eventmsg->pos.y;
newmsg.delta.x = 0;
newmsg.delta.y = 0;
newmsg.context = eventmsg->context;
newmsg.handler = item->handler;
newmsg.obj = eventmsg->obj;
@ -862,8 +859,6 @@ void CMenus::handleValueChangeEvent(const NXWidgets::CWidgetEventArgs &e)
msg.eventID = item->event;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.context = EVENT_CONTEXT_TOOLBAR;
msg.handler = item->handler;
msg.obj = (FAR void *)this;

View File

@ -161,8 +161,8 @@ CWindow::CWindow(CTwm4Nx *twm4nx)
// Dragging
m_drag = false;
m_dragOffset.x = 0;
m_dragOffset.y = 0;
m_dragPos.x = 0;
m_dragPos.y = 0;
m_dragCSize.w = 0;
m_dragCSize.h = 0;
@ -675,6 +675,8 @@ bool CWindow::createMainWindow(FAR const nxgl_size_s *winsize,
// 3. Create a Widget control instance for the window using the default
// style for now. CWindowEvent derives from CWidgetControl.
// Setup the the CWindowEvent instance to use our inherited drag event
// handler
FAR CWindowEvent *control = new CWindowEvent(m_twm4nx, (FAR void *)this);
@ -767,6 +769,7 @@ bool CWindow::createToolbar(void)
// style for now. CWindowEvent derives from CWidgetControl.
FAR CWindowEvent *control = new CWindowEvent(m_twm4nx, (FAR void *)this);
control->registerDragEventHandler(this);
// 3. Get the toolbar sub-window from the framed window
@ -1145,19 +1148,18 @@ bool CWindow::createToolbarTitle(FAR const char *name)
* virtual event handling methods. It just combines some common event-
* handling logic.
*
* @param e The event data.
* @param x The mouse/touch X position.
* @param y The mouse/touch y position.
*/
void CWindow::handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e)
void CWindow::handleUngrabEvent(nxgl_coord_t x, nxgl_coord_t y)
{
// Generate the un-grab event
struct SEventMsg msg;
msg.eventID = EVENT_TOOLBAR_UNGRAB;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.pos.x = x;
msg.pos.y = y;
msg.context = EVENT_CONTEXT_TOOLBAR;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
@ -1177,70 +1179,6 @@ void CWindow::handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e)
}
}
/**
* Override the mouse button drag event.
*
* @param e The event data.
*/
void CWindow::handleDragEvent(const NXWidgets::CWidgetEventArgs &e)
{
// We are interested only the the drag event on the title box while we are
// in the dragging state.
if (m_drag && m_tbTitle->isBeingDragged())
{
// Generate the event
struct SEventMsg msg;
msg.eventID = EVENT_WINDOW_DRAG;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = e.getVX();
msg.delta.y = e.getVY();
msg.context = EVENT_CONTEXT_TOOLBAR;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
// NOTE that we cannot block because we are on the same thread
// as the message reader. If the event queue becomes full then
// we have no other option but to lose events.
//
// I suppose we could recurse and call Twm4Nx::dispatchEvent at
// the risk of runaway stack usage.
int ret = mq_send(m_eventq, (FAR const char *)&msg,
sizeof(struct SEventMsg), 100);
if (ret < 0)
{
twmerr("ERROR: mq_send failed: %d\n", ret);
}
}
}
/**
* Override a drop event, triggered when the widget has been dragged-and-dropped.
*
* @param e The event data.
*/
void CWindow::handleDropEvent(const NXWidgets::CWidgetEventArgs &e)
{
// We are interested only the the drag drop event on the title box while we
// are in the dragging state.
//
// When the Drop Event is received, both isClicked and isBeingDragged()
// will return false. It is sufficient to verify that the isClicked() is
// not true to exit the drag.
if (m_drag && !m_tbTitle->isClicked())
{
// Yes.. handle the drop event
handleUngrabEvent(e);
}
}
/**
* Handle a mouse click event.
*
@ -1260,8 +1198,6 @@ void CWindow::handleClickEvent(const NXWidgets::CWidgetEventArgs &e)
msg.eventID = EVENT_TOOLBAR_GRAB;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.context = EVENT_CONTEXT_TOOLBAR;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
@ -1303,7 +1239,7 @@ void CWindow::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
// Handle the non-drag drop event
handleUngrabEvent(e);
handleUngrabEvent(e.getX(), e.getY());
}
}
@ -1334,8 +1270,6 @@ void CWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
msg.eventID = GToolBarInfo[btindex].event;
msg.pos.x = e.getX();
msg.pos.y = e.getY();
msg.delta.x = 0;
msg.delta.y = 0;
msg.context = EVENT_CONTEXT_TOOLBAR;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
@ -1357,6 +1291,95 @@ void CWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
}
}
/**
* This function is called when there is any moved of the mouse or
* touch position that would indicate that the object is being moved.
*
* This function overrides the virtual IDragEvent::dragEvent method.
*
* @param pos The current mouse/touch X/Y position in toolbar relative
* coordinates.
* @return True: if the drage event was processed; false it is was
* ignored. The event should be ignored if there is not actually
* a drag event in progress
*/
bool CWindow::dragEvent(FAR const struct nxgl_point_s &pos)
{
twminfo("m_drag=%u pos=(%d,%d)\n", m_drag, pos.x, pos.y);
// We are interested only the drag event while we are in the dragging
// state.
if (m_drag)
{
// Conver the
// Generate the event
struct SEventMsg msg;
msg.eventID = EVENT_WINDOW_DRAG;
msg.pos.x = pos.x;
msg.pos.y = pos.y;
msg.context = EVENT_CONTEXT_TOOLBAR;
msg.handler = (FAR CTwm4NxEvent *)0;
msg.obj = (FAR void *)this;
// NOTE that we cannot block because we are on the same thread
// as the message reader. If the event queue becomes full then
// we have no other option but to lose events.
//
// I suppose we could recurse and call Twm4Nx::dispatchEvent at
// the risk of runaway stack usage.
int ret = mq_send(m_eventq, (FAR const char *)&msg,
sizeof(struct SEventMsg), 100);
if (ret < 0)
{
twmerr("ERROR: mq_send failed: %d\n", ret);
}
return true;
}
return false;
}
/**
* This function is called if the mouse left button is released or
* if the touchscrreen touch is lost. This indicates that the
* dragging sequence is complete.
*
* This function overrides the virtual IDragEvent::dropEvent method.
*
* @param pos The last mouse/touch X/Y position in toolbar relative
* coordinates.
* @return True: if the drage event was processed; false it is was
* ignored. The event should be ignored if there is not actually
* a drag event in progress
*/
bool CWindow::dropEvent(FAR const struct nxgl_point_s &pos)
{
twminfo("m_drag=%u pos=(%d,%d)\n", m_drag, pos.x, pos.y);
// We are interested only the the drag drop event on the title box while we
// are in the dragging state.
//
// When the Drop Event is received, both isClicked and isBeingDragged()
// will return false. It is sufficient to verify that the isClicked() is
// not true to exit the drag.
if (m_drag)
{
// Yes.. handle the drop event
handleUngrabEvent(pos.x, pos.y);
return true;
}
return false;
}
/**
* Handle the TOOLBAR_GRAB event. That corresponds to a left
* mouse click on the title widget in the toolbar
@ -1368,6 +1391,8 @@ void CWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
bool CWindow::toolbarGrab(FAR struct SEventMsg *eventmsg)
{
twminfo("GRAB (%d,%d)\n", eventmsg->pos.x, eventmsg->pos.y);
// Promote the window to a modal window
m_modal = true;
@ -1382,19 +1407,25 @@ bool CWindow::toolbarGrab(FAR struct SEventMsg *eventmsg)
struct nxgl_point_s framePos;
getFramePosition(&framePos);
// Determine the relative position of the frame and the mouse
twminfo("Position (%d,%d)\n", framePos.x, framePos.y);
m_dragOffset.x = framePos.x - eventmsg->pos.x;
m_dragOffset.y = framePos.y - eventmsg->pos.y;
// Save the toolbar-relative mouse position in order to detect the amount
// of movement in the next drag event.
m_dragPos.x = eventmsg->pos.x;
m_dragPos.y = eventmsg->pos.y;
#ifdef CONFIG_TWM4NX_MOUSE
// Select the grab cursor image
m_twm4nx->setCursorImage(&CONFIG_TWM4NX_GBCURSOR_IMAGE);
#endif
// Remember the grab cursor size
m_dragCSize.w = CONFIG_TWM4NX_GBCURSOR_IMAGE.size.w;
m_dragCSize.h = CONFIG_TWM4NX_GBCURSOR_IMAGE.size.h;
return true;
}
@ -1409,13 +1440,31 @@ bool CWindow::toolbarGrab(FAR struct SEventMsg *eventmsg)
bool CWindow::windowDrag(FAR struct SEventMsg *eventmsg)
{
twminfo("DRAG (%d,%d)\n", eventmsg->pos.x, eventmsg->pos.y);
if (m_drag)
{
// Calculate the new Window position
// The coordinates in the eventmsg or relative to the origin
// of the toolbar.
struct nxgl_point_s newpos;
newpos.x = eventmsg->pos.x + m_dragOffset.x;
newpos.y = eventmsg->pos.y + m_dragOffset.y;
struct nxgl_point_s oldPos;
if (!getFramePosition(&oldPos))
{
gerr("ERROR: getFramePosition() failed\n") ;
return false;
}
// We want to set the new frame position so that it has the same
// relative mouse position as when we grabbed the toolbar.
struct nxgl_point_s newPos;
newPos.x = oldPos.x + eventmsg->pos.x - m_dragPos.x;
newPos.y = oldPos.y + eventmsg->pos.y - m_dragPos.y;
// Save the new mouse position
m_dragPos.x = eventmsg->pos.x;
m_dragPos.y = eventmsg->pos.y;
// Keep the window on the display (at least enough of it so that we
// can still grab it)
@ -1423,27 +1472,41 @@ bool CWindow::windowDrag(FAR struct SEventMsg *eventmsg)
struct nxgl_size_s displaySize;
m_twm4nx->getDisplaySize(&displaySize);
if (newpos.x < 0)
if (newPos.x < 0)
{
newpos.x = 0;
newPos.x = 0;
}
else if (newpos.x + m_dragCSize.w > displaySize.w)
else if (newPos.x + m_dragCSize.w > displaySize.w)
{
newpos.x = displaySize.w - m_dragCSize.w;
newPos.x = displaySize.w - m_dragCSize.w;
}
if (newpos.y < 0)
if (newPos.y < 0)
{
newpos.y = 0;
newPos.y = 0;
}
else if (newpos.y + m_dragCSize.h > displaySize.h)
else if (newPos.y + m_dragCSize.h > displaySize.h)
{
newpos.y = displaySize.h - m_dragCSize.h;
newPos.y = displaySize.h - m_dragCSize.h;
}
// Set the new window position
// Set the new window position if it has changed
return setFramePosition(&newpos);
twminfo("Position (%d,%d)->(%d,%d)\n",
oldPos.x, oldPos.y, newPos.x, newPos.y);
if (newPos.x != oldPos.x || newPos.y != oldPos.y)
{
if (!setFramePosition(&newPos))
{
gerr("ERROR: setFramePosition failed\n");
return false;
}
m_nxWin->synchronize();
}
return true;
}
return false;
@ -1453,13 +1516,16 @@ bool CWindow::windowDrag(FAR struct SEventMsg *eventmsg)
* Handle the TOOLBAR_UNGRAB event. The corresponds to a mouse
* left button release while in the grabbed state
*
* @param eventmsg. The received NxWidget event message.
* @param eventmsg. The received NxWidget event message in window relative
* coordinates.
* @return True if the message was properly handled. false is
* return on any failure.
*/
bool CWindow::toolbarUngrab(FAR struct SEventMsg *eventmsg)
{
twminfo("UNGRAB (%d,%d)\n", eventmsg->pos.x, eventmsg->pos.y);
// One last position update
if (!windowDrag(eventmsg))
@ -1476,9 +1542,11 @@ bool CWindow::toolbarUngrab(FAR struct SEventMsg *eventmsg)
m_modal = false;
m_nxWin->modal(false);
#ifdef CONFIG_TWM4NX_MOUSE
// Restore the normal cursor image
m_twm4nx->setCursorImage(&CONFIG_TWM4NX_CURSOR_IMAGE);
#endif
return true;
}

View File

@ -42,8 +42,11 @@
#include <cfcntl>
#include <cerrno>
#include <semaphore.h>
#include <mqueue.h>
#include <nuttx/input/mouse.h>
#include "graphics/nxwidgets/cwidgetcontrol.hxx"
#include "graphics/twm4nx/twm4nx_config.hxx"
@ -72,9 +75,14 @@ CWindowEvent::CWindowEvent(FAR CTwm4Nx *twm4nx, FAR void *obj,
FAR const NXWidgets::CWidgetStyle *style)
: NXWidgets::CWidgetControl(style)
{
m_twm4nx = twm4nx; // Cache the Twm4Nx session
m_object = obj; // Used for event message construction
m_isBackground = isBackground; // Background window?
m_twm4nx = twm4nx; // Cache the Twm4Nx session
m_object = obj; // Used for event message construction
m_isBackground = isBackground; // Background window?
// Dragging
m_dragHandler = (FAR IDragEvent *)0; // No drag handler callbacks
m_dragging = false; // Not dragging
// Open a message queue to send raw NX events. This cannot fail!
@ -208,9 +216,84 @@ void CWindowEvent::handleRedrawEvent(FAR const nxgl_rect_s *nxRect,
* Handle an NX window mouse input event.
*/
void CWindowEvent::handleMouseEvent(void)
void CWindowEvent::handleMouseEvent(FAR const struct nxgl_point_s *pos,
uint8_t buttons)
{
twminfo("Mouse input...\n");
twminfo("Mouse input: m_dragging=%u\n", m_dragging);
// Check if are dragging
//
// STATE LEFT BUTTON ACTION
// dragging clicked dragEvent
// dragging released dropEvent
// NOT dragging clicked May be detected as a grab
// NOT dragging released None
if (m_dragging)
{
// Save the new drag position in window relative display coordinates
m_dragPos.x = pos->x;
m_dragPos.y = pos->y;
// Is the left button still pressed?
if ((buttons & MOUSE_BUTTON_1) != 0)
{
twminfo("Continue dragging (%d,%d) buttons=%02x m_dragHandler=%p\n",
m_dragPos.x, m_dragPos.y, buttons, m_dragHandler);
// Yes.. generate a drag event if we have a drag event handler
if (m_dragHandler != (FAR IDragEvent *)0 &&
m_dragHandler->dragEvent(m_dragPos))
{
// Skip the input poll until the drag completes
return;
}
}
else
{
twminfo("Stop dragging (%d,%d) buttons=%02x m_dragHandler=%p\n",
m_dragPos.x, m_dragPos.y, buttons, m_dragHandler);
// No.. then we are no longer dragging
m_dragging = false;
// Generate a dropEvent
if (m_dragHandler != (FAR IDragEvent *)0 &&
m_dragHandler->dropEvent(m_dragPos))
{
// If the drop event was processed then skip the
// input poll until AFTER the drag completes
return;
}
}
}
// If we are not currently dragging but the left button is pressed, then
// start the drag event
else if ((buttons & MOUSE_BUTTON_1) != 0)
{
// Indicate that we are (or may be) dragging
m_dragging = true;
// Save the initial drag position
m_dragPos.x = pos->x;
m_dragPos.y = pos->y;
twminfo("Start dragging (%d,%d) buttons=%02x m_dragHandler=%p\n",
m_dragPos.x, m_dragPos.y, buttons, m_dragHandler);
// But take no other actions until the window recognizes the grab
}
// Stimulate an input poll

View File

@ -249,6 +249,7 @@ void CWindowFactory::destroyWindow(FAR CWindow *cwin)
bool CWindowFactory::event(FAR struct SEventMsg *eventmsg)
{
twminfo("eventID: %d\n", eventmsg->eventID);
bool success = true;
switch (eventmsg->eventID)

View File

@ -98,7 +98,10 @@ namespace NXWidgets
* Handle an NX window mouse input event.
*/
virtual void handleMouseEvent(void) { }
virtual void handleMouseEvent(FAR const struct nxgl_point_s *pos,
uint8_t buttons)
{
}
#endif
#ifdef CONFIG_NX_KBD

View File

@ -153,7 +153,8 @@ namespace NXWidgets
* Raise an NX mouse window input event.
*/
void raiseMouseEvent(void);
void raiseMouseEvent(FAR const struct nxgl_point_s *pos,
uint8_t buttons);
#endif
#ifdef CONFIG_NX_KBD

View File

@ -104,7 +104,7 @@ namespace NxWM
* Handle an NX window mouse input event.
*/
void handleMouseEvent(void);
void handleMouseEvent(FAR const struct nxgl_point_s *pos, uint8_t buttons);
#endif
#ifdef CONFIG_NX_KBD

View File

@ -124,6 +124,8 @@ namespace Twm4Nx
* CInput state data
*/
// Session
CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */
#ifndef CONFIG_TWM4NX_NOKEYBOARD
int m_kbdFd; /**< File descriptor of the opened keyboard device */
@ -131,15 +133,21 @@ namespace Twm4Nx
#ifndef CONFIG_TWM4NX_NOMOUSE
int m_mouseFd; /**< File descriptor of the opened mouse device */
#endif
// Listener
pthread_t m_thread; /**< The listener thread ID */
volatile enum EListenerState m_state; /**< The state of the listener thread */
sem_t m_waitSem; /**< Used to synchronize with the listener thread */
#ifdef CONFIG_TWM4NX_TOUCHSCREEN
// Calibration
bool m_calib; /**< False: Use raw, uncalibrated touches */
struct SCalibrationData m_calData; /**< Touchscreen calibration data */
#endif
#ifndef CONFIG_TWM4NX_NOKEYBOARD
/**
* Open the keyboard device. Not very interesting for the case of
@ -278,7 +286,7 @@ namespace Twm4Nx
#endif
/**
* Start the keyboard listener thread.
* Start the keyboard/mouse listener thread.
*
* @return True if the keyboard listener thread was correctly started.
*/

View File

@ -57,6 +57,7 @@
#include "graphics/nxwidgets/cwidgeteventhandler.hxx"
#include "graphics/nxwidgets/cwidgeteventargs.hxx"
#include "graphics/twm4nx/cwindowevent.hxx"
#include "graphics/twm4nx/ciconwidget.hxx"
#include "graphics/twm4nx/ctwm4nxevent.hxx"
@ -128,7 +129,9 @@ namespace Twm4Nx
// The CWindow class implements a standard, framed window with a toolbar
// containing the standard buttons and the window title.
class CWindow : protected NXWidgets::CWidgetEventHandler, public CTwm4NxEvent
class CWindow : protected NXWidgets::CWidgetEventHandler,
protected IDragEvent,
public CTwm4NxEvent
{
private:
CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session */
@ -166,7 +169,7 @@ namespace Twm4Nx
// Dragging
struct nxgl_point_s m_dragOffset; /**< Offset from mouse to window origin */
struct nxgl_point_s m_dragPos; /**< Last reported mouse position */
struct nxgl_size_s m_dragCSize; /**< The grab cursor size */
bool m_drag; /**< Drag in-progress */
@ -239,26 +242,11 @@ namespace Twm4Nx
* virtual event handling methods. It just combines some common event-
* handling logic.
*
* @param e The event data.
* @param x The mouse/touch X position.
* @param y The mouse/touch y position.
*/
void handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e);
/**
* Override the mouse button drag event.
*
* @param e The event data.
*/
void handleDragEvent(const NXWidgets::CWidgetEventArgs &e);
/**
* Override a drop event, triggered when the widget has been dragged-and-dropped.
*
* @param e The event data.
*/
void handleDropEvent(const NXWidgets::CWidgetEventArgs &e);
void handleUngrabEvent(nxgl_coord_t x, nxgl_coord_t y);
/**
* Handle a mouse click event.
@ -289,6 +277,34 @@ namespace Twm4Nx
void handleActionEvent(const NXWidgets::CWidgetEventArgs &e);
/**
* This function is called when there is any moved of the mouse or
* touch position that would indicate that the object is being moved.
*
* This function overrides the virtual IDragEvent::dragEvent method.
*
* @param pos The current mouse/touch X/Y position.
* @return True: if the drage event was processed; false it is was
* ignored. The event should be ignored if there is not actually
* a drag event in progress
*/
bool dragEvent(FAR const struct nxgl_point_s &pos);
/**
* This function is called if the mouse left button is released or
* if the touchscrreen touch is lost. This indicates that the
* dragging sequence is complete.
*
* This function overrides the virtual IDragEvent::dropEvent method.
*
* @return True: if the drage event was processed; false it is was
* ignored. The event should be ignored if there is not actually
* a drag event in progress
*/
bool dropEvent(FAR const struct nxgl_point_s &pos);
/**
* Handle the TOOLBAR_GRAB event. That corresponds to a left
* mouse click on the toolbar (other than on an icon)

View File

@ -57,10 +57,53 @@
// Implementation Classes
/////////////////////////////////////////////////////////////////////////////
#if defined(__cplusplus)
namespace Twm4Nx
{
/**
* This abstract base class provides add on methods to support dragging
* of a window.
*/
class IDragEvent
{
public:
/**
* A virtual destructor is required in order to override the ITextBox
* destructor. We do this because if we delete ITextBox, we want the
* destructor of the class that inherits from ITextBox to run, not this
* one.
*/
virtual ~IDragEvent(void) { }
/**
* This function is called when there is any moved of the mouse or
* touch position that would indicate that the object is being moved.
*
* @param pos The current mouse/touch X/Y position in toolbar relative
* coordinates.
* @return True: if the drage event was processed; false it is was
* ignored. The event should be ignored if there is not actually
* a drag event in progress
*/
virtual bool dragEvent(FAR const struct nxgl_point_s &pos) = 0;
/**
* This function is called if the mouse left button is released or
* if the touchscrreen touch is lost. This indicates that the
* dragging sequence is complete.
*
* @param pos The last mouse/touch X/Y position in toolbar relative
* coordinates.
* @return True: if the drage event was processed; false it is was
* ignored. The event should be ignored if there is not actually
* a drag event in progress
*/
virtual bool dropEvent(FAR const struct nxgl_point_s &pos) = 0;
};
/**
* The class CWindowEvent integrates the widget control with some special
* handling of mouse and keyboard inputs needs by NxWM. It use used
@ -74,10 +117,16 @@ namespace Twm4Nx
public NXWidgets::CWidgetControl
{
private:
FAR CTwm4Nx *m_twm4nx; /**< Cached instance of CTwm4Nx */
mqd_t m_eventq; /**< NxWidget event message queue */
FAR void *m_object; /**< Window object (context specific) */
bool m_isBackground; /**< True if this serves the background window */
FAR CTwm4Nx *m_twm4nx; /**< Cached instance of CTwm4Nx */
mqd_t m_eventq; /**< NxWidget event message queue */
FAR void *m_object; /**< Window object (context specific) */
bool m_isBackground; /**< True if this serves the background window */
// Dragging
FAR IDragEvent *m_dragHandler; /**< Drag event handlers (may be NULL) */
bool m_dragging; /**< True: dragging */
struct nxgl_point_s m_dragPos; /**< Last mouse/touch position */
/**
* Send the EVENT_MSG_POLL input event message to the Twm4Nx event loop.
@ -101,7 +150,8 @@ namespace Twm4Nx
* Handle an NX window mouse input event.
*/
void handleMouseEvent(void);
void handleMouseEvent(FAR const struct nxgl_point_s *pos,
uint8_t buttons);
#endif
#ifdef CONFIG_NX_KBD
@ -142,9 +192,23 @@ namespace Twm4Nx
* CWindowEvent Destructor.
*/
~CWindowEvent(void);
~CWindowEvent(void);
/**
* Register an IDragEvent instance to provide callbacks when mouse
* movement is received. A mouse movement with the left button down
* or a touchscreen touch movement are treated as a drag event.
* Release of the mouse left button or loss of the touchscreen touch
* is treated as a drop event.
*
* @param cb A reference to the IDragEvent callback interface.
*/
inline void registerDragEventHandler(FAR IDragEvent *dragHandler)
{
m_dragHandler = dragHandler;
}
};
}
#endif // __cplusplus
#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWEVENT_HXX

View File

@ -197,7 +197,6 @@ namespace Twm4Nx
{
uint16_t eventID; /**< Encoded event ID */
struct nxgl_point_s pos; /**< X/Y position */
struct nxgl_point_s delta; /**< X/Y change (for dragging only) */
uint8_t context; /**< Button press context */
FAR CTwm4NxEvent *handler; /**< App event handler (APP recipient only) */
FAR void *obj; /**< Window object (CWindow or CIconWidget) */