Squashed commit of the following:
apps/graphics/twm4nx: Add logic to detect collisions with reserved regions in the backgroud or with other icons when moving an icon on the desktop. apps/graphics/twm4nx: When moving icons, erase the old icon image before drawing the new one.
This commit is contained in:
parent
75fc1a2dd3
commit
eeb5d4433c
@ -190,8 +190,8 @@ bool CBackground::checkCollision(FAR const struct nxgl_rect_s &bounds,
|
||||
|
||||
collision.pt1.x = imagePos.x;
|
||||
collision.pt1.y = imagePos.y;
|
||||
collision.pt1.x = imagePos.x + imageSize.w - 1;
|
||||
collision.pt1.y = imagePos.y + imageSize.h - 1;
|
||||
collision.pt2.x = imagePos.x + imageSize.w - 1;
|
||||
collision.pt2.y = imagePos.y + imageSize.h - 1;
|
||||
|
||||
return nxgl_intersecting(&bounds, &collision);
|
||||
}
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "graphics/twm4nx/ctwm4nx.hxx"
|
||||
#include "graphics/twm4nx/cfonts.hxx"
|
||||
#include "graphics/twm4nx/cwindow.hxx"
|
||||
#include "graphics/twm4nx/cwindowfactory.hxx"
|
||||
#include "graphics/twm4nx/cbackground.hxx"
|
||||
#include "graphics/twm4nx/ciconwidget.hxx"
|
||||
#include "graphics/twm4nx/twm4nx_widgetevents.hxx"
|
||||
#include "graphics/twm4nx/twm4nx_cursor.hxx"
|
||||
@ -636,18 +638,18 @@ bool CIconWidget::iconGrab(FAR struct SEventMsg *eventmsg)
|
||||
// Indicate that dragging has started but the icon has not
|
||||
// yet been moved.
|
||||
|
||||
m_dragging = true;
|
||||
m_moved = false;
|
||||
m_dragging = true;
|
||||
m_moved = false;
|
||||
m_collision = false;
|
||||
|
||||
// Get the icon position.
|
||||
|
||||
struct nxgl_point_s widgetPos;
|
||||
getPos(widgetPos);
|
||||
getPos(m_dragPos);
|
||||
|
||||
// Determine the relative position of the icon and the mouse
|
||||
|
||||
m_dragOffset.x = widgetPos.x - eventmsg->pos.x;
|
||||
m_dragOffset.y = widgetPos.y - eventmsg->pos.y;
|
||||
m_dragOffset.x = m_dragPos.x - eventmsg->pos.x;
|
||||
m_dragOffset.y = m_dragPos.y - eventmsg->pos.y;
|
||||
|
||||
#ifdef CONFIG_TWM4NX_MOUSE
|
||||
// Select the grab cursor image
|
||||
@ -655,7 +657,8 @@ bool CIconWidget::iconGrab(FAR struct SEventMsg *eventmsg)
|
||||
m_twm4nx->setCursorImage(&CONFIG_TWM4NX_GBCURSOR_IMAGE);
|
||||
#endif
|
||||
|
||||
// Remember the grab cursor size
|
||||
// Remember the grab cursor size. This, of course, makes
|
||||
// little since if we are using a touchscreen.
|
||||
|
||||
m_dragCSize.w = CONFIG_TWM4NX_GBCURSOR_IMAGE.size.w;
|
||||
m_dragCSize.h = CONFIG_TWM4NX_GBCURSOR_IMAGE.size.h;
|
||||
@ -712,14 +715,83 @@ bool CIconWidget::iconDrag(FAR struct SEventMsg *eventmsg)
|
||||
|
||||
if (oldpos.x != newpos.x || oldpos.y != newpos.y)
|
||||
{
|
||||
// Set the new window position
|
||||
// Re-draw the widget at the new background window position.
|
||||
// NOTE that this is done before moving erasing the old position which
|
||||
// probably overlaps the new position.
|
||||
|
||||
disableDrawing();
|
||||
if (!moveTo(newpos.x, newpos.y))
|
||||
{
|
||||
twmerr("ERROR: moveTo() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Redraw the background window in the rectangle previously occupied by
|
||||
// the widget.
|
||||
|
||||
struct nxgl_size_s widgetSize;
|
||||
getSize(widgetSize);
|
||||
|
||||
struct nxgl_rect_s bounds;
|
||||
bounds.pt1.x = oldpos.x;
|
||||
bounds.pt1.y = oldpos.y;
|
||||
bounds.pt2.x = oldpos.x + widgetSize.w - 1;
|
||||
bounds.pt2.y = oldpos.y + widgetSize.h - 1;
|
||||
|
||||
FAR CBackground *backgd = m_twm4nx->getBackground();
|
||||
if (!backgd->redrawBackgroundWindow(&bounds, false))
|
||||
{
|
||||
twmerr("ERROR: redrawBackgroundWindow() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now redraw the icon in its new position
|
||||
|
||||
enableDrawing();
|
||||
redraw();
|
||||
|
||||
// Check if the icon at this position intersects any reserved
|
||||
// region on the background. If not, check if some other icon is
|
||||
// already occupying this position
|
||||
|
||||
|
||||
bounds.pt1.x = newpos.x;
|
||||
bounds.pt1.y = newpos.y;
|
||||
bounds.pt2.x = newpos.x + widgetSize.w - 1;
|
||||
bounds.pt2.y = newpos.y + widgetSize.h - 1;
|
||||
|
||||
struct nxgl_rect_s collision;
|
||||
if (backgd->checkCollision(bounds, collision))
|
||||
{
|
||||
// Yes.. Remember that we are at a colliding position when
|
||||
// the if the icon is ungrabbed.
|
||||
|
||||
m_collision = true;
|
||||
}
|
||||
|
||||
// No.. Check if some other icon is already occupying this
|
||||
// position
|
||||
|
||||
else
|
||||
{
|
||||
FAR CWindowFactory *factory = m_twm4nx->getWindowFactory();
|
||||
if (factory->checkCollision(m_parent, bounds, collision))
|
||||
{
|
||||
// Yes.. Remember that we are at a colliding position when
|
||||
// the if the icon is ungrabbed.
|
||||
|
||||
m_collision = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No collision.. Remember the last good position
|
||||
|
||||
m_dragPos.x = newpos.x;
|
||||
m_dragPos.y = newpos.y;
|
||||
m_collision = false;
|
||||
}
|
||||
}
|
||||
|
||||
// The icon was moved... we are really dragging!
|
||||
|
||||
m_moved = true;
|
||||
@ -755,6 +827,8 @@ bool CIconWidget::iconUngrab(FAR struct SEventMsg *eventmsg)
|
||||
m_twm4nx->setCursorImage(&CONFIG_TWM4NX_CURSOR_IMAGE);
|
||||
#endif
|
||||
|
||||
bool success = true;
|
||||
|
||||
// There are two possibilities: (1) The icon was moved. In this case, we
|
||||
// leave the icon up and in its new position. Or (2) the icon was simply
|
||||
// clicked in which case we need to de-iconify the window. We also check
|
||||
@ -766,10 +840,60 @@ bool CIconWidget::iconUngrab(FAR struct SEventMsg *eventmsg)
|
||||
m_parent->deIconify();
|
||||
}
|
||||
|
||||
// Another possibility is that the icon was drug into a position that
|
||||
// collides with a reserved area on the background or that overlaps another
|
||||
// icon. In that case, we need to revert to last known good position.
|
||||
|
||||
else if (m_dragging && m_collision)
|
||||
{
|
||||
// Get the current, colliding position.
|
||||
|
||||
struct nxgl_point_s oldpos;
|
||||
getPos(oldpos);
|
||||
|
||||
// Move the widget to the last known good position.
|
||||
// NOTE that this is done before moving erasing the old position which
|
||||
// probably overlaps the new position.
|
||||
|
||||
disableDrawing();
|
||||
if (!moveTo(m_dragPos.x, m_dragPos.y))
|
||||
{
|
||||
twmerr("ERROR: moveTo() failed\n");
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Redraw the background window in the rectangle previously occupied
|
||||
// by the widget.
|
||||
|
||||
struct nxgl_size_s widgetSize;
|
||||
getSize(widgetSize);
|
||||
|
||||
struct nxgl_rect_s bounds;
|
||||
bounds.pt1.x = oldpos.x;
|
||||
bounds.pt1.y = oldpos.y;
|
||||
bounds.pt2.x = oldpos.x + widgetSize.w - 1;
|
||||
bounds.pt2.y = oldpos.y + widgetSize.h - 1;
|
||||
|
||||
FAR CBackground *backgd = m_twm4nx->getBackground();
|
||||
if (!backgd->redrawBackgroundWindow(&bounds, false))
|
||||
{
|
||||
twmerr("ERROR: redrawBackgroundWindow() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now redraw the icon in its new position
|
||||
|
||||
enableDrawing();
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate no longer dragging
|
||||
|
||||
m_dragging = false;
|
||||
m_moved = false;
|
||||
m_dragging = false;
|
||||
m_collision = false;
|
||||
m_moved = false;
|
||||
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ bool CWindowFactory::placeIcon(FAR CWindow *cwin,
|
||||
iconBounds.pt2.y = tmppos.y + iconSize.h - 1;
|
||||
|
||||
// Check if this box intersects any reserved region on the background.
|
||||
// If nt, check if so other icon is already occupying this position
|
||||
// If not, check if some other icon is already occupying this position
|
||||
|
||||
struct nxgl_rect_s collision;
|
||||
if (!backgd->checkCollision(iconBounds, collision) &&
|
||||
@ -435,6 +435,60 @@ void CWindowFactory::redrawIcons(FAR const nxgl_rect_s *nxRect)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the icon within iconBounds collides with any other icon on the
|
||||
* desktop.
|
||||
*
|
||||
* @param cwin The window containing the Icon of interest
|
||||
* @param iconBounds The candidate Icon bounding box
|
||||
* @param collision The bounding box of the icon that the candidate collides
|
||||
* with
|
||||
* @return Returns true if there is a collision
|
||||
*/
|
||||
|
||||
bool CWindowFactory::checkCollision(FAR CWindow *cwin,
|
||||
FAR const struct nxgl_rect_s &iconBounds,
|
||||
FAR struct nxgl_rect_s &collision)
|
||||
{
|
||||
// Try every window
|
||||
|
||||
for (FAR struct SWindow *win = m_windowHead;
|
||||
win != (FAR struct SWindow *)0;
|
||||
win = win->flink)
|
||||
{
|
||||
// Ignore 'this' window, any windows that are not iconified, and any
|
||||
// windows that have no icons.
|
||||
|
||||
if (win->cwin != cwin && win->cwin->hasIcon() &&
|
||||
win->cwin->isIconified())
|
||||
{
|
||||
// Create a bounding box for the icon
|
||||
|
||||
struct nxgl_size_s iconSize;
|
||||
(void)win->cwin->getIconWidgetSize(iconSize);
|
||||
|
||||
struct nxgl_point_s iconPos;
|
||||
(void)win->cwin->getIconWidgetPosition(iconPos);
|
||||
|
||||
collision.pt1.x = iconPos.x;
|
||||
collision.pt1.y = iconPos.y;
|
||||
collision.pt2.x = iconPos.x + iconSize.w - 1;
|
||||
collision.pt2.y = iconPos.y + iconSize.h - 1;
|
||||
|
||||
// Return true if there is an intersection
|
||||
|
||||
if (nxgl_intersecting(&iconBounds, &collision))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No collision
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle WINDOW events.
|
||||
*
|
||||
@ -552,60 +606,6 @@ FAR struct SWindow *CWindowFactory::findWindow(FAR CWindow *cwin)
|
||||
return (FAR struct SWindow *)0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the icon within iconBounds collides with any other icon on the
|
||||
* desktop.
|
||||
*
|
||||
* @param cwin The window containing the Icon of interest
|
||||
* @param iconBounds The candidate Icon bounding box
|
||||
* @param collision The bounding box of the icon that the candidate collides
|
||||
* with
|
||||
* @return Returns true if there is a collision
|
||||
*/
|
||||
|
||||
bool CWindowFactory::checkCollision(FAR CWindow *cwin,
|
||||
FAR const struct nxgl_rect_s &iconBounds,
|
||||
FAR struct nxgl_rect_s &collision)
|
||||
{
|
||||
// Try every window
|
||||
|
||||
for (FAR struct SWindow *win = m_windowHead;
|
||||
win != (FAR struct SWindow *)0;
|
||||
win = win->flink)
|
||||
{
|
||||
// Ignore 'this' window, any windows that are not iconified, and any
|
||||
// windows that have no icons.
|
||||
|
||||
if (win->cwin != cwin && win->cwin->hasIcon() &&
|
||||
win->cwin->isIconified())
|
||||
{
|
||||
// Create a bounding box for the icon
|
||||
|
||||
struct nxgl_size_s iconSize;
|
||||
(void)win->cwin->getIconWidgetSize(iconSize);
|
||||
|
||||
struct nxgl_point_s iconPos;
|
||||
(void)win->cwin->getIconWidgetPosition(iconPos);
|
||||
|
||||
collision.pt1.x = iconPos.x;
|
||||
collision.pt1.y = iconPos.y;
|
||||
collision.pt2.x = iconPos.x + iconSize.w - 1;
|
||||
collision.pt2.y = iconPos.y + iconSize.h - 1;
|
||||
|
||||
// Return true if there is an intersection
|
||||
|
||||
if (nxgl_intersecting(&iconBounds, &collision))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No collision
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the function that responds to the EVENT_WINDOW_DESKTOP. It
|
||||
* iconifies all windows so that the desktop is visible.
|
||||
|
@ -179,10 +179,11 @@ namespace Twm4Nx
|
||||
|
||||
// Dragging
|
||||
|
||||
struct nxgl_point_s m_dragPos; /**< Last mouse position */
|
||||
struct nxgl_point_s m_dragPos; /**< Last good icon position */
|
||||
struct nxgl_point_s m_dragOffset; /**< Offset from mouse to window origin */
|
||||
struct nxgl_size_s m_dragCSize; /**< The grab cursor size */
|
||||
bool m_dragging; /**< Drag in-progress */
|
||||
bool m_collision; /**< Current position collides */
|
||||
bool m_moved; /**< Icon has been moved */
|
||||
|
||||
/**
|
||||
|
@ -179,21 +179,6 @@ namespace Twm4Nx
|
||||
|
||||
FAR struct SWindow *findWindow(FAR CWindow *cwin);
|
||||
|
||||
/**
|
||||
* Check if the icon within iconBounds collides with any other icon on
|
||||
* the desktop.
|
||||
*
|
||||
* @param cwin The window containing the Icon of interest
|
||||
* @param iconBounds The candidate Icon bounding box
|
||||
* @param collision The bounding box of the icon that the candidate
|
||||
* collides with
|
||||
* @return Returns true if there is a collision
|
||||
*/
|
||||
|
||||
bool checkCollision(FAR CWindow *cwin,
|
||||
FAR const struct nxgl_rect_s &iconBounds,
|
||||
FAR struct nxgl_rect_s &collision);
|
||||
|
||||
/**
|
||||
* This is the function that responds to the EVENT_WINDOW_DESKTOP. It
|
||||
* iconifies all windows so that the desktop is visible.
|
||||
@ -295,6 +280,21 @@ namespace Twm4Nx
|
||||
|
||||
void redrawIcons(FAR const nxgl_rect_s *nxRect);
|
||||
|
||||
/**
|
||||
* Check if the icon within iconBounds collides with any other icon on
|
||||
* the desktop.
|
||||
*
|
||||
* @param cwin The window containing the Icon of interest
|
||||
* @param iconBounds The candidate Icon bounding box
|
||||
* @param collision The bounding box of the icon that the candidate
|
||||
* collides with
|
||||
* @return Returns true if there is a collision
|
||||
*/
|
||||
|
||||
bool checkCollision(FAR CWindow *cwin,
|
||||
FAR const struct nxgl_rect_s &iconBounds,
|
||||
FAR struct nxgl_rect_s &collision);
|
||||
|
||||
/**
|
||||
* Handle WINDOW events.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user