diff --git a/examples/pwfb/Makefile b/examples/pwfb/Makefile index 12b2daa98..395618fc1 100644 --- a/examples/pwfb/Makefile +++ b/examples/pwfb/Makefile @@ -35,7 +35,10 @@ -include $(TOPDIR)/Make.defs -# NuttX NX Graphics Example. +# NuttX per-window frame buffer graphics example. + +NXGLYPHS = $(APPDIR)$(DELIM)graphics$(DELIM)nxglyphs +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(NXGLYPHS)$(DELIM)include"} ASRCS = CSRCS = pwfb_events.c pwfb_motion.c @@ -44,7 +47,7 @@ MAINSRC = pwfb_main.c CONFIG_EXAMPLES_PWFB_PROGNAME ?= pwfb$(EXEEXT) PROGNAME = $(CONFIG_EXAMPLES_PWFB_PROGNAME) -# NX built-in application info +# Per-Window frame buffer built-in application info CONFIG_EXAMPLES_PWFB_CLIENT_PRIO ?= SCHED_PRIORITY_DEFAULT CONFIG_EXAMPLES_PWFB_CLIENT_STACKSIZE ?= 2048 diff --git a/examples/pwfb/pwfb_internal.h b/examples/pwfb/pwfb_internal.h index dadd6f8b6..bf1c8a213 100644 --- a/examples/pwfb/pwfb_internal.h +++ b/examples/pwfb/pwfb_internal.h @@ -148,6 +148,20 @@ # endif #endif +/* Cursor timing */ + +#if CONFIG_EXAMPLES_PWFB_RATECONTROL > 0 +# define CURSOR_MOVING_DELAY (3000 / CONFIG_EXAMPLES_PWFB_RATECONTROL) +# define CURSOR_STATIONARY_DELAY (2000 / CONFIG_EXAMPLES_PWFB_RATECONTROL) +# define CURSOR_BLINKING_DELAY (5000 / CONFIG_EXAMPLES_PWFB_RATECONTROL) +# define CURSOR_BLINK_DELAY ( 500 / CONFIG_EXAMPLES_PWFB_RATECONTROL) +#else +# define CURSOR_MOVING_DELAY (0) +# define CURSOR_STATIONARY_DELAY (0) +# define CURSOR_BLINKING_DELAY (0) +# define CURSOR_BLINK_DELAY (0) +#endif + /**************************************************************************** * Public Types ****************************************************************************/ @@ -167,6 +181,37 @@ struct pwfb_window_s b16_t deltay; /* Current Y speed */ }; +#ifdef CONFIG_NX_SWCURSOR +/* We will run the cursor in 3 different states: + * + * 1. Moving + * 2. Stationary + * 3. Enabling/disabling + */ + +enum pfwb_cursor_state_s +{ + PFWB_CURSOR_MOVING = 0, + PFWB_CURSOR_STATIONARY, + PFWB_CURSOR_BLINKING +}; + +/* Describes the unique state of the cursor */ + +struct pwfb_cursor_s +{ + enum pfwb_cursor_state_s state; /* Current cursor state */ + bool visible; /* True: The cursor is visible */ + int countdown; /* Countdown until next state */ + int blinktime; /* Time remaining enabled/disabled */ + b16_t xmax; /* Max X position */ + b16_t ymax; /* Max Y position */ + b16_t xpos; /* Current X position */ + b16_t ypos; /* Current Y position */ + b16_t deltax; /* Current X speed */ + b16_t deltay; /* Current Y speed */ +}; +#endif /* Describes the overall state of the example */ struct pwfb_state_s @@ -197,6 +242,12 @@ struct pwfb_state_s uint8_t fwidth; /* Max width of a font in pixels */ uint8_t spwidth; /* The width of a space */ +#ifdef CONFIG_NX_SWCURSOR + /* Cursor-specific state */ + + struct pwfb_cursor_s cursor; +#endif + /* Window-specific state */ struct pwfb_window_s wndo[3]; diff --git a/examples/pwfb/pwfb_main.c b/examples/pwfb/pwfb_main.c index c029ce47f..a6689ac0b 100644 --- a/examples/pwfb/pwfb_main.c +++ b/examples/pwfb/pwfb_main.c @@ -62,6 +62,12 @@ #include <nuttx/nx/nxbe.h> #include <nuttx/nx/nxfonts.h> +#ifdef CONFIG_NX_SWCURSOR +# undef CONFIG_NXWIDGETS_BPP +# define CONFIG_NXWIDGETS_BPP CONFIG_EXAMPLES_PWFB_BPP +# include "cursor-arrow1-30x30.h" +#endif + #include "pwfb_internal.h" /**************************************************************************** @@ -492,6 +498,64 @@ errout_with_hwnd: return false; } +/**************************************************************************** + * Name: pwfb_configure_cursor + ****************************************************************************/ + +#ifdef CONFIG_NX_SWCURSOR +static bool pwfb_configure_cursor(FAR struct pwfb_state_s *st, + FAR struct nxgl_point_s *pos, + double deltax, double deltay) +{ + int ret; + + /* Initialize the data structure */ + + st->cursor.state = PFWB_CURSOR_MOVING; + st->cursor.countdown = CURSOR_MOVING_DELAY; + st->cursor.blinktime = 0; + st->cursor.xpos = pos->x; + st->cursor.ypos = pos->y; + st->cursor.deltax = deltax; + st->cursor.deltay = deltay; + + /* Set the cursor image */ + + ret = nxcursor_setimage(st->hnx, &g_arrow1Cursor); + if (ret < 0) + { + printf("pwfb_configure_cursor: ERROR: " + "nxcursor_setimage failed: %d\n", + errno); + return false; + } + + /* Set the cursor position */ + + ret = nxcursor_setposition(st->hnx, pos); + if (ret < 0) + { + printf("pwfb_configure_cursor: ERROR: " + "nxcursor_setposition failed: %d\n", + errno); + return false; + } + + /* Enable the cursor */ + + ret = nxcursor_enable(st->hnx, false); + if (ret < 0) + { + printf("pwfb_configure_cursor: ERROR: " + "nxcursor_enable failed: %d\n", + errno); + return false; + } + + return true; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -655,6 +719,20 @@ int pwfb_main(int argc, char *argv[]) goto errout_with_hwnd3; } +#ifdef CONFIG_NX_SWCURSOR + /* Configure the software cursor */ + + pos.x = wstate.xres / 2; + pos.x = wstate.yres / 2; + + if (!pwfb_configure_cursor(&wstate, &pos, 2.900, -5.253)) + { + printf("pwfb_main: ERROR: " + "pwfb_configure_cursor failed for window 2\n"); + goto errout_with_hwnd3; + } +#endif + /* Now loop animating the windows */ for (; ; ) @@ -664,12 +742,19 @@ int pwfb_main(int argc, char *argv[]) { printf("pwfb_main: ERROR:" "pwfb_motion failed\n"); - goto errout_with_hwnd3; + goto errout_with_cursor; } } errcode = EXIT_SUCCESS; +errout_with_cursor: +#ifdef CONFIG_NX_SWCURSOR + /* Disable the cursor */ + + (void)nxcursor_enable(wstate.hnx, false); +#endif + /* Close window 3 */ errout_with_hwnd3: diff --git a/examples/pwfb/pwfb_motion.c b/examples/pwfb/pwfb_motion.c index 53df607b5..1433f8d5b 100644 --- a/examples/pwfb/pwfb_motion.c +++ b/examples/pwfb/pwfb_motion.c @@ -44,6 +44,7 @@ #include <errno.h> #include <nuttx/nx/nxglib.h> +#include <nuttx/nx/nxcursor.h> #include <nuttx/nx/nxtk.h> #include "pwfb_internal.h" @@ -174,6 +175,155 @@ static inline bool pwfb_move_window(FAR struct pwfb_state_s *st, int wndx) return true; } +/**************************************************************************** + * Name: pwfb_move_cursor + ****************************************************************************/ + +#ifdef CONFIG_NX_SWCURSOR +static inline bool pwfb_move_cursor(FAR struct pwfb_state_s *st) +{ + FAR struct nxgl_point_s pos; + b16_t newx; + b16_t newy; + int ret; + +#ifdef CONFIG_EXAMPLES_PWFB_VERBOSE + printf("pwfb_move_cursor: State: %u countdown: %u blinktime: %u\n", + (unsigned int)st->cursor.state, (unsigned int)st->cursor.countdown, + (unsigned int)st->cursor.blinktime; + printf("pwfb_move_cursor: Velocity: (%lx.%04lx,%lx.%04lx)\n", + (unsigned long)st->cursor.deltax >> 16, + (unsigned long)st->cursor.deltax & 0xffff, + (unsigned long)st->cursor.deltay >> 16, + (unsigned long)st->cursor.deltay & 0xffff); +#endif + + /* Handle the update based on cursor state */ + /* If the state is not PFWB_CURSOR_STATIONARY, then update the cursor + * position. + */ + + if (st->cursor.state != PFWB_CURSOR_STATIONARY) + { + /* Update X position */ + + newx = st->cursor.xpos + st->cursor.deltax; + + /* Check for collision with left or right side */ + + if (newx <= 0) + { + newx = 0; + st->cursor.deltax = -st->cursor.deltax; + } + else if (newx >= st->cursor.xmax) + { + newx = st->cursor.xmax; + st->cursor.deltax = -st->cursor.deltax; + } + + /* Update Y position */ + + newy = st->cursor.ypos + st->cursor.deltay; + + /* Check for collision with top or bottom side */ + + if (newy <= 0) + { + newy = 0; + st->cursor.deltay = -st->cursor.deltay; + } + else if (newy >= st->cursor.ymax) + { + newy = st->cursor.ymax; + st->cursor.deltay = -st->cursor.deltay; + } + +#ifdef CONFIG_EXAMPLES_PWFB_VERBOSE + printf("pwfb_move_cursor: Old pos: (%lx.%04lx,%lx.%04lx) " + "New pos: (%lx.%04lx,%lx.%04lx)\n", + (unsigned long)st->cursor.xpos >> 16, + (unsigned long)st->cursor.xpos & 0xffff, + (unsigned long)st->cursor.ypos >> 16, + (unsigned long)st->cursor.ypos & 0xffff, + (unsigned long)newx >> 16, + (unsigned long)newx & 0xffff, + (unsigned long)newy >> 16, + (unsigned long)newy & 0xffff); +#endif + + /* Set the new cursor position */ + + st->cursor.xpos = newx; + st->cursor.ypos = newy; + + pos.x = b16toi(newx); + pos.y = b16toi(newy); + + printf("pwfb_move_cursor: Set position (%d,%d)\n", pos.x, pos.y); + + ret = nxcursor_setposition(st->hnx, &pos); + if (ret < 0) + { + printf("nxcursor_setposition: ERROR:" + "nxcursor_setposition failed: %d\n", + errno); + + return false; + } + } + + /* Check for state changes */ + + switch (st->cursor.state) + { + case PFWB_CURSOR_MOVING: + if (--st->cursor.countdown <= 0) + { + /* Set up for the the STATIONARY state next */ + + st->cursor.state = PFWB_CURSOR_STATIONARY; + st->cursor.countdown = CURSOR_STATIONARY_DELAY; + } + + break; + + case PFWB_CURSOR_STATIONARY: + if (--st->cursor.countdown <= 0) + { + /* Set up for the the BLINKING state next */ + + st->cursor.state = PFWB_CURSOR_BLINKING; + st->cursor.countdown = CURSOR_BLINKING_DELAY; + st->cursor.blinktime = CURSOR_BLINK_DELAY; + } + + break; + + case PFWB_CURSOR_BLINKING: + if (--st->cursor.countdown <= 0) + { + /* Set up for the the MOVING state next */ + + st->cursor.state = PFWB_CURSOR_MOVING; + st->cursor.countdown = CURSOR_MOVING_DELAY; + st->cursor.visible = true; + nxcursor_enable(st->hnx, true); + } + else if (--st->cursor.blinktime <= 0) + { + /* Toggle visibility */ + + st->cursor.blinktime = CURSOR_BLINK_DELAY; + st->cursor.visible = !st->cursor.visible; + nxcursor_enable(st->hnx, st->cursor.visible); + } + } + + return true; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -198,5 +348,14 @@ bool pwfb_motion(FAR struct pwfb_state_s *st) } } +#ifdef CONFIG_NX_SWCURSOR + /* Move the cursor */ + + if (!pwfb_move_cursor(st)) + { + printf("pwfb_motion: ERROR: pwfb_move_cursor failed\n"); + } +#endif + return true; } diff --git a/include/graphics/nxwidgets/cnxtkwindow.hxx b/include/graphics/nxwidgets/cnxtkwindow.hxx index cf1648b11..e4a4e8af0 100644 --- a/include/graphics/nxwidgets/cnxtkwindow.hxx +++ b/include/graphics/nxwidgets/cnxtkwindow.hxx @@ -386,4 +386,3 @@ namespace NXWidgets #endif // __cplusplus #endif // __APPS_INCLUDE_GRAPHICS_NXWIDGETS_CNXTKWINDOW_HXX -