Converserely, when the icon is clicked, the icon needs to be hidden on the backgound and the window needs to be restored in its current state (which may be different than the state of the window at the time it was iconified. Squashed commit of the following: graphics/: Add checks in all places that I can think to avoid doing something stupid with hidden windows Improve some naming Add a new file missing in last commit. graphics/: Initial, incomplete support for hiding windows.
479 lines
14 KiB
C
479 lines
14 KiB
C
/****************************************************************************
|
|
* graphics/nxbe/nxbe_move.c
|
|
*
|
|
* Copyright (C) 2008-2009, 2011-2012, 2016, 2019 Gregory Nutt. All rights
|
|
* reserved.
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdint.h>
|
|
#include <assert.h>
|
|
|
|
#include <nuttx/nx/nxglib.h>
|
|
|
|
#include "nxbe.h"
|
|
#include "nxmu.h"
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
struct nxbe_move_s
|
|
{
|
|
struct nxbe_clipops_s cops;
|
|
struct nxgl_point_s offset;
|
|
FAR struct nxbe_window_s *wnd;
|
|
struct nxgl_rect_s srcrect;
|
|
uint8_t order;
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: nxbe_clipmovesrc
|
|
*
|
|
* Description:
|
|
* Called from nxbe_clipper() to performed the move operation on visible regions
|
|
* of the rectangle.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void nxbe_clipmovesrc(FAR struct nxbe_clipops_s *cops,
|
|
FAR struct nxbe_plane_s *plane,
|
|
FAR const struct nxgl_rect_s *rect)
|
|
{
|
|
struct nxbe_move_s *info = (struct nxbe_move_s *)cops;
|
|
struct nxgl_point_s offset;
|
|
#ifdef CONFIG_NX_UPDATE
|
|
FAR struct nxbe_window_s *wnd;
|
|
struct nxgl_rect_s update;
|
|
#endif
|
|
|
|
if (info->offset.x != 0 || info->offset.y != 0)
|
|
{
|
|
/* Offset is the destination position of the moved rectangle */
|
|
|
|
offset.x = rect->pt1.x + info->offset.x;
|
|
offset.y = rect->pt1.y + info->offset.y;
|
|
|
|
/* Move the source rectangle to the destination position in the device */
|
|
|
|
plane->dev.moverectangle(&plane->pinfo, rect, &offset);
|
|
|
|
#ifdef CONFIG_NX_UPDATE
|
|
/* Move the source rectangle back to window relative coordinates and
|
|
* apply the offset.
|
|
*/
|
|
|
|
wnd = info->wnd;
|
|
nxgl_rectoffset(&update, rect, offset.x - wnd->bounds.pt1.x,
|
|
offset.y - wnd->bounds.pt1.y);
|
|
|
|
/* Notify any listeners that the graphic content in the update
|
|
* rectangle has changed.
|
|
*/
|
|
|
|
nx_notify_rectangle(&plane->pinfo, &update);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: nxbe_clipmoveobscured
|
|
*
|
|
* Description:
|
|
* Called from nxbe_clipper() to performed the move operation on obsrured regions
|
|
* of the rectangle.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void nxbe_clipmoveobscured(FAR struct nxbe_clipops_s *cops,
|
|
FAR struct nxbe_plane_s *plane,
|
|
FAR const struct nxgl_rect_s *rect)
|
|
{
|
|
struct nxbe_move_s *info = (struct nxbe_move_s *)cops;
|
|
struct nxgl_rect_s dst;
|
|
|
|
nxgl_rectoffset(&dst, rect, info->offset.x, info->offset.y);
|
|
nxmu_redrawreq(info->wnd, &dst);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: nxbe_clipmovedest
|
|
*
|
|
* Description:
|
|
* Called from nxbe_clipper() to performed the move operation on visible
|
|
* regions of the source rectangle.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void nxbe_clipmovedest(FAR struct nxbe_clipops_s *cops,
|
|
FAR struct nxbe_plane_s *plane,
|
|
FAR const struct nxgl_rect_s *rect)
|
|
{
|
|
struct nxbe_move_s *dstdata = (struct nxbe_move_s *)cops;
|
|
struct nxbe_window_s *wnd = dstdata->wnd;
|
|
struct nxgl_point_s offset = dstdata->offset;
|
|
struct nxgl_rect_s src;
|
|
struct nxgl_rect_s tmprect1;
|
|
struct nxgl_rect_s tmprect2;
|
|
struct nxgl_rect_s nonintersecting[4];
|
|
int i;
|
|
|
|
/* Redraw dest regions where the source is outside of the bounds of the
|
|
* background window
|
|
*/
|
|
|
|
nxgl_rectoffset(&tmprect1, &dstdata->srcrect, offset.x, offset.y);
|
|
nxgl_rectintersect(&tmprect2, &tmprect1, &wnd->be->bkgd.bounds);
|
|
nxgl_nonintersecting(nonintersecting, rect, &tmprect2);
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (!nxgl_nullrect(&nonintersecting[i]))
|
|
{
|
|
nxmu_redrawreq(dstdata->wnd, &nonintersecting[i]);
|
|
}
|
|
}
|
|
|
|
/* Clip to determine what is inside the bounds */
|
|
|
|
nxgl_rectintersect(&src, rect, &dstdata->srcrect);
|
|
|
|
if (!nxgl_nullrect(&src))
|
|
{
|
|
struct nxbe_move_s srcinfo;
|
|
|
|
/* Move the visible part of window */
|
|
|
|
srcinfo.cops.visible = nxbe_clipmovesrc;
|
|
srcinfo.cops.obscured = nxbe_clipmoveobscured;
|
|
srcinfo.offset = offset;
|
|
srcinfo.wnd = wnd;
|
|
|
|
nxbe_clipper(dstdata->wnd->above, &src, dstdata->order,
|
|
&srcinfo.cops, plane);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: nxbe_move_dev
|
|
*
|
|
* Description:
|
|
* Move a rectangular region within the window
|
|
*
|
|
* Input Parameters:
|
|
* wnd - The window within which the move is to be done
|
|
* rect - Describes the rectangular region to move (absolute device
|
|
* positions)
|
|
* offset - The offset to move the region
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
static inline void nxbe_move_dev(FAR struct nxbe_window_s *wnd,
|
|
FAR const struct nxgl_rect_s *rect,
|
|
FAR const struct nxgl_point_s *offset)
|
|
{
|
|
struct nxbe_move_s info;
|
|
#ifdef CONFIG_NX_SWCURSOR
|
|
struct nxgl_rect_s dest;
|
|
#endif
|
|
int i;
|
|
|
|
info.cops.visible = nxbe_clipmovedest;
|
|
info.cops.obscured = nxbe_clipnull;
|
|
info.offset.x = offset->x;
|
|
info.offset.y = offset->y;
|
|
info.wnd = wnd;
|
|
|
|
nxgl_rectcopy(&info.srcrect, rect);
|
|
|
|
/* The clip order depends up the direction that the rectangle is being
|
|
* moved.
|
|
*/
|
|
|
|
if (offset->y < 0)
|
|
{
|
|
/* Moving rectangle up */
|
|
|
|
if (offset->x < 0)
|
|
{
|
|
/* Moving to upper-left */
|
|
|
|
info.order = NX_CLIPORDER_TLRB; /* Top-left-right-bottom */
|
|
}
|
|
else
|
|
{
|
|
/* Moving to upper-right (or just up) */
|
|
|
|
info.order = NX_CLIPORDER_TRLB; /* Top-right-left-bottom */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Moving rectangle down (or just left/right) */
|
|
|
|
if (offset->x < 0)
|
|
{
|
|
/* Moving to lower-left */
|
|
|
|
info.order = NX_CLIPORDER_BLRT; /* Bottom-left-right-top */
|
|
}
|
|
else
|
|
{
|
|
/* Moving to lower-right */
|
|
|
|
info.order = NX_CLIPORDER_BRLT; /* Bottom-right-left-top */
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_NX_SWCURSOR
|
|
/* Apply the offsets to the source window to get the destination window */
|
|
|
|
nxgl_rectoffset(&dest, rect, offset->x, offset->y);
|
|
#endif
|
|
|
|
/* Then perform the move */
|
|
|
|
#if CONFIG_NX_NPLANES > 1
|
|
for (i = 0; i < wnd->be->vinfo.nplanes; i++)
|
|
#else
|
|
i = 0;
|
|
#endif
|
|
{
|
|
#ifdef CONFIG_NX_SWCURSOR
|
|
/* Is the cursor visible? */
|
|
|
|
if (wnd->be->cursor.visible)
|
|
{
|
|
/* Remove the cursor from the source region */
|
|
|
|
wnd->be->plane[i].cursor.erase(wnd->be, rect, i);
|
|
}
|
|
#endif
|
|
|
|
nxbe_clipper(wnd->above, &info.srcrect, info.order,
|
|
&info.cops, &wnd->be->plane[i]);
|
|
|
|
#ifdef CONFIG_NX_SWCURSOR
|
|
/* Backup and redraw the cursor in the modified region.
|
|
*
|
|
* REVISIT: This and the following logic belongs in the function
|
|
* nxbe_clipfill(). It is here only because the struct nxbe_state_s
|
|
* (wnd->be) is not available at that point. This may result in an
|
|
* excessive number of cursor updates.
|
|
*/
|
|
|
|
nxbe_cursor_backupdraw_dev(wnd->be, &dest, i);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: nxbe_move_pwfb
|
|
*
|
|
* Description:
|
|
* Move a rectangular region within the window
|
|
*
|
|
* Input Parameters:
|
|
* wnd - The window within which the move is to be done
|
|
* rect - Describes the rectangular region to move (absolute positions)
|
|
* offset - The offset to move the region
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_NX_RAMBACKED
|
|
static inline void nxbe_move_pwfb(FAR struct nxbe_window_s *wnd,
|
|
FAR const struct nxgl_rect_s *rect,
|
|
FAR const struct nxgl_point_s *offset)
|
|
{
|
|
FAR const void *src[CONFIG_NX_NPLANES];
|
|
struct nxgl_point_s destpos;
|
|
struct nxgl_point_s origin;
|
|
struct nxgl_rect_s srcrect;
|
|
struct nxgl_rect_s destrect;
|
|
unsigned int bpp;
|
|
|
|
/* The rectangle that we receive here is in abolute device coordinates. We
|
|
* need to restore this to windows relative coordinates.
|
|
*/
|
|
|
|
nxgl_rectoffset(&srcrect, rect, -wnd->bounds.pt1.x, -wnd->bounds.pt1.y);
|
|
|
|
/* Offset is the destination position of the moved rectangle */
|
|
|
|
destpos.x = srcrect.pt1.x + offset->x;
|
|
destpos.y = srcrect.pt1.y + offset->y;
|
|
|
|
/* Move the source rectangle to the destination position in the
|
|
* frambebuffer.
|
|
* REVISIT: Assumes a single color plane.
|
|
*/
|
|
|
|
DEBUGASSERT(wnd->be->plane[0].pwfb.moverectangle != NULL);
|
|
wnd->be->plane[0].pwfb.moverectangle(wnd, &srcrect, &destpos);
|
|
|
|
/* Construct the destination bounding box in relative window
|
|
* coordinates. This derives from the source bounding box with
|
|
* an offset distination.
|
|
*/
|
|
|
|
nxgl_rectoffset(&destrect, &srcrect, offset->x, offset->y);
|
|
|
|
/* Get the source of address of the moved rectangle in the framebuffer. */
|
|
|
|
bpp = wnd->be->plane[0].pinfo.bpp;
|
|
src[0] = (FAR const void *)
|
|
((FAR uint8_t *)wnd->fbmem +
|
|
destrect.pt1.y * wnd->stride +
|
|
((bpp * destrect.pt1.x) >> 3));
|
|
|
|
/* For resolutions less than 8-bits, the starting pixel will be contained
|
|
* in the byte pointed to by src[0]but may not be properly aligned for
|
|
* the transfer. We fix this by modifying the origin.
|
|
*/
|
|
|
|
origin.x = destrect.pt1.x;
|
|
origin.y = destrect.pt1.y;
|
|
|
|
switch (bpp)
|
|
{
|
|
#ifndef CONFIG_NX_DISABLE_1BPP
|
|
case 1: /* 1 bit per pixel */
|
|
{
|
|
origin.x &= ~7;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#ifndef CONFIG_NX_DISABLE_2BPP
|
|
case 2: /* 2 bits per pixel */
|
|
{
|
|
origin.x &= ~3;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#ifndef CONFIG_NX_DISABLE_4BPP
|
|
case 4: /* 4 bits per pixel */
|
|
{
|
|
origin.x &= ~1;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Update the physical device by just copying the rectangle from the
|
|
* framebuffer to the destination rectangle device graphics memory.
|
|
*/
|
|
|
|
nxbe_flush(wnd, &destrect, src, &origin, wnd->stride);
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: nxbe_move
|
|
*
|
|
* Description:
|
|
* Move a rectangular region within the window
|
|
*
|
|
* Input Parameters:
|
|
* wnd - The window within which the move is to be done
|
|
* rect - Describes the rectangular region to move (window relative)
|
|
* offset - The offset to move the region
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
void nxbe_move(FAR struct nxbe_window_s *wnd,
|
|
FAR const struct nxgl_rect_s *rect,
|
|
FAR const struct nxgl_point_s *offset)
|
|
{
|
|
struct nxgl_rect_s srcrect;
|
|
|
|
DEBUGASSERT(wnd != NULL && rect != NULL && offset != 0);
|
|
if (offset->x != 0 || offset->y != 0)
|
|
{
|
|
/* Offset the rectangle by the window origin to create a bounding box */
|
|
|
|
nxgl_rectoffset(&srcrect, rect, wnd->bounds.pt1.x, wnd->bounds.pt1.y);
|
|
|
|
/* Clip to the limits of the window and of the background screen */
|
|
|
|
nxgl_rectintersect(&srcrect, &srcrect, &wnd->bounds);
|
|
nxgl_rectintersect(&srcrect, &srcrect, &wnd->be->bkgd.bounds);
|
|
|
|
if (!nxgl_nullrect(&srcrect))
|
|
{
|
|
#ifdef CONFIG_NX_RAMBACKED
|
|
/* Update the pre-window framebuffer first, then the device memory. */
|
|
|
|
if (NXBE_ISRAMBACKED(wnd))
|
|
{
|
|
nxbe_move_pwfb(wnd, &srcrect, offset);
|
|
}
|
|
else
|
|
#endif
|
|
/* Don't update hidden windows */
|
|
|
|
if (!NXBE_ISHIDDEN(wnd))
|
|
{
|
|
/* Update only the graphics device memory. */
|
|
|
|
nxbe_move_dev(wnd, &srcrect, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|