diff --git a/examples/pwfb/.gitignore b/examples/pwfb/.gitignore
new file mode 100644
index 000000000..fa1ec7579
--- /dev/null
+++ b/examples/pwfb/.gitignore
@@ -0,0 +1,11 @@
+/Make.dep
+/.depend
+/.built
+/*.asm
+/*.obj
+/*.rel
+/*.lst
+/*.sym
+/*.adb
+/*.lib
+/*.src
diff --git a/examples/pwfb/Kconfig b/examples/pwfb/Kconfig
new file mode 100644
index 000000000..1957ba3f7
--- /dev/null
+++ b/examples/pwfb/Kconfig
@@ -0,0 +1,93 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config EXAMPLES_PWFB
+	tristate "NX Per-Window Framebuffer Example"
+	default n
+	depends on NX
+	select LIB_BOARDCTL
+	select NX_RAMBACKED
+	---help---
+		Enable the NX per-window framebuffer example
+
+if EXAMPLES_PWFB
+
+config EXAMPLES_PWFB_DEFAULT_COLORS
+	bool "Use Default Colors"
+	default y
+
+if !EXAMPLES_PWFB_DEFAULT_COLORS
+
+config EXAMPLES_PWFB_BGCOLOR
+	hex "Background Color"
+	---help---
+		The color of the background.  Default depends on config EXAMPLES_PWFB_BPP.
+
+config EXAMPLES_PWFB_COLOR1
+	hex "Color of Window 1"
+	---help---
+		The color of window 1. Default depends on config EXAMPLES_PWFB_BPP.
+
+config EXAMPLES_PWFB_COLOR2
+	hex "Color of Window 2"
+	---help---
+		The color of window 2. Default depends on config EXAMPLES_PWFB_BPP.
+
+config EXAMPLES_PWFB_COLOR3
+	hex "Color of Window 3"
+	---help---
+		The color of window 3. Default depends on config EXAMPLES_PWFB_BPP.
+
+config EXAMPLES_PWFB_FONTCOLOR
+	hex "Font Color"
+	---help---
+		The color of the fonts. Default depends on config EXAMPLES_PWFB_BPP.
+
+endif
+
+config EXAMPLES_PWFB_DEFAULT_FONT
+	bool "Use Default Font"
+	default y
+
+config EXAMPLES_PWFB_FONTID
+	int "Font ID"
+	depends on !EXAMPLES_PWFB_DEFAULT_FONT
+	---help---
+		Selects the font (see font ID numbers in include/nuttx/nx/nxfonts.h)
+
+config EXAMPLES_PWFB_BPP
+	int "Bits-Per-Pixel"
+	default 32
+	---help---
+		Pixels per pixel to use.  Valid options include 2, 4, 8, 16, 24,
+		and 32.  Default is 32.
+
+comment "NX Server Options"
+
+config EXAMPLES_PWFB_STACKSIZE
+	int "NX Server Stack Size"
+	default 2048
+	---help---
+		The stacksize to use when creating the NX server.  Default 2048
+
+config EXAMPLES_PWFB_CLIENTPRIO
+	int "Client Priority"
+	default 100
+	---help---
+		The client priority.  Default: 100
+
+config EXAMPLES_PWFB_SERVERPRIO
+	int "Server Priority"
+	default 120
+	---help---
+		The server priority.  Default: 120
+
+config EXAMPLES_PWFB_LISTENERPRIO
+	int "Listener Priority"
+	default 80
+	---help---
+		The priority of the event listener thread. Default 80.
+
+endif
diff --git a/examples/pwfb/Make.defs b/examples/pwfb/Make.defs
new file mode 100644
index 000000000..45272d628
--- /dev/null
+++ b/examples/pwfb/Make.defs
@@ -0,0 +1,39 @@
+############################################################################
+# apps/examples/pwfb/Make.defs
+# Adds selected applications to apps/ build
+#
+#   Copyright (C) 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.
+#
+############################################################################
+
+ifneq ($(CONFIG_EXAMPLES_PWFB),)
+CONFIGURED_APPS += examples/pwfb
+endif
diff --git a/examples/pwfb/Makefile b/examples/pwfb/Makefile
new file mode 100644
index 000000000..c73a0ecdd
--- /dev/null
+++ b/examples/pwfb/Makefile
@@ -0,0 +1,55 @@
+############################################################################
+# apps/examples/pwfb/Makefile
+#
+#   Copyright (C) 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.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+
+# NuttX NX Graphics Example.
+
+ASRCS =
+CSRCS = pwfb_events.c pwfb_motion.c
+MAINSRC = pwfb_main.c
+
+CONFIG_PWFB_PROGNAME ?= pwfb$(EXEEXT)
+PROGNAME = $(CONFIG_PWFB_PROGNAME)
+
+# NX built-in application info
+
+APPNAME = pwfb
+PRIORITY = SCHED_PRIORITY_DEFAULT
+STACKSIZE = 2048
+
+MODULE = CONFIG_EXAMPLES_PWFB
+
+include $(APPDIR)/Application.mk
diff --git a/examples/pwfb/pwfb_events.c b/examples/pwfb/pwfb_events.c
new file mode 100644
index 000000000..46b30a5f0
--- /dev/null
+++ b/examples/pwfb/pwfb_events.c
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * examples/pwfb/pwfb_events.c
+ *
+ *   Copyright (C) 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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <semaphore.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxtk.h>
+#include "pwfb_internal.h"
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void pwfb_redraw(NXTKWINDOW hwnd, FAR const struct nxgl_rect_s *rect,
+                        bool morem, FAR void *arg);
+static void pwfb_position(NXTKWINDOW hwnd, FAR const struct nxgl_size_s *size,
+                          FAR const struct nxgl_point_s *pos,
+                          FAR const struct nxgl_rect_s *bounds,
+                          FAR void *arg);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct nx_callback_s g_pwfb_cb =
+{
+  pwfb_redraw,   /* redraw */
+  pwfb_position  /* position */
+#ifdef CONFIG_NX_XYINPUT
+  , NULL         /* mousein */
+#endif
+#ifdef CONFIG_NX_KBD
+  , NULL         /* kbdin */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwfb_redraw
+ ****************************************************************************/
+
+static void pwfb_redraw(NXTKWINDOW hwnd, FAR const struct nxgl_rect_s *rect,
+                        bool more, FAR void *arg)
+{
+  /* There should be no redraw requests when using per-window framebuffers */
+
+  printf("pwfb_redraw: hwnd=%p rect={(%d,%d),(%d,%d)} more=%s\n",
+         hwnd,
+         rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y,
+         more ? "true" : "false");
+}
+
+/****************************************************************************
+ * Name: pwfb_position
+ ****************************************************************************/
+
+static void pwfb_position(NXTKWINDOW hwnd, FAR const struct nxgl_size_s *size,
+                          FAR const struct nxgl_point_s *pos,
+                          FAR const struct nxgl_rect_s *bounds,
+                          FAR void *arg)
+{
+  FAR struct pwfb_state_s *st = (FAR struct pwfb_state_s *)arg;
+
+  /* Report the position */
+
+  printf("pwfb_position: hwnd=%p size=(%d,%d) pos=(%d,%d) "
+         "bounds={(%d,%d),(%d,%d)}\n",
+         hwnd, size->w, size->h, pos->x, pos->y,
+         bounds->pt1.x, bounds->pt1.y, bounds->pt2.x, bounds->pt2.y);
+
+  /* Have we picked off the window bounds yet? */
+
+  if (!st->haveres)
+    {
+      /* Save the window limits (these should be the same for all places and
+       * all windows.
+       */
+
+      st->xres = bounds->pt2.x + 1;
+      st->yres = bounds->pt2.y + 1;
+
+      st->haveres = true;
+      sem_post(&st->semevent);
+
+      printf("pwfb_position2: Have xres=%d yres=%d\n", st->xres, st->yres);
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwfb_listener
+ ****************************************************************************/
+
+FAR void *pwfb_listener(FAR void *arg)
+{
+  FAR struct pwfb_state_s *st = (FAR struct pwfb_state_s *)arg;
+  int ret;
+
+  /* Process events forever */
+
+  for (; ; )
+    {
+      /* Handle the next event.  If we were configured blocking, then
+       * we will stay right here until the next event is received.  Since
+       * we have dedicated a while thread to servicing events, it would
+       * be most natural to also select CONFIG_NX_BLOCKING -- if not, the
+       * following would be a tight infinite loop (unless we added addition
+       * logic with nx_eventnotify and sigwait to pace it).
+       */
+
+      ret = nx_eventhandler(st->hnx);
+      if (ret < 0)
+        {
+          /* An error occurred... assume that we have lost connection with
+           * the server.
+           */
+
+          printf("pwfb_listener: Lost server connection: %d\n", errno);
+          pthread_exit(NULL);
+        }
+
+      /* If we received a message, we must be connected */
+
+      if (!st->connected)
+        {
+          st->connected = true;
+          sem_post(&st->semevent);
+          printf("pwfb_listener: Connected\n");
+        }
+    }
+}
diff --git a/examples/pwfb/pwfb_internal.h b/examples/pwfb/pwfb_internal.h
new file mode 100644
index 000000000..5ee4111d8
--- /dev/null
+++ b/examples/pwfb/pwfb_internal.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+ * examples/pwfb/pwfb_internal.h
+ *
+ *   Copyright (C) 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.
+ *
+ ****************************************************************************/
+
+#ifndef __EXAMPLES_PWFB_PWFB_INTERNAL_H
+#define __EXAMPLES_PWFB_PWFB_INTERNAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <fixedmath.h>
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxtk.h>
+#include <nuttx/nx/nxfonts.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* Required NX Server Settings */
+
+#ifndef CONFIG_NX
+#  error "NX is not enabled (CONFIG_NX)"
+#endif
+#ifdef CONFIG_DISABLE_MQUEUE
+#  error "The multi-threaded example requires MQ support (CONFIG_DISABLE_MQUEUE=n)"
+#endif
+#ifdef CONFIG_DISABLE_PTHREAD
+#  error "This example requires pthread support (CONFIG_DISABLE_PTHREAD=n)"
+#endif
+#ifndef CONFIG_NX_BLOCKING
+#  error "This example depends on CONFIG_NX_BLOCKING"
+#endif
+
+/* Default colors */
+
+#ifndef CONFIG_EXAMPLES_PWFB_BGCOLOR
+#  if CONFIG_EXAMPLES_PWFB_BPP == 24 || CONFIG_EXAMPLES_PWFB_BPP == 32
+#    define CONFIG_EXAMPLES_PWFB_BGCOLOR 0x007b68ee
+#  elif CONFIG_EXAMPLES_PWFB_BPP == 16
+#    define CONFIG_EXAMPLES_PWFB_BGCOLOR 0x7b5d
+#  else
+#    define CONFIG_EXAMPLES_PWFB_BGCOLOR ' '
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWFB_COLOR1
+#  if CONFIG_EXAMPLES_PWFB_BPP == 24 || CONFIG_EXAMPLES_PWFB_BPP == 32
+#    define CONFIG_EXAMPLES_PWFB_COLOR1 0x00e6e6fa
+#  elif CONFIG_EXAMPLES_PWFB_BPP == 16
+#    define CONFIG_EXAMPLES_PWFB_COLOR1 0xe73f
+#  else
+#    define CONFIG_EXAMPLES_PWFB_COLOR1 '1'
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWFB_COLOR2
+#  if CONFIG_EXAMPLES_PWFB_BPP == 24 || CONFIG_EXAMPLES_PWFB_BPP == 32
+#    define CONFIG_EXAMPLES_PWFB_COLOR2 0x00dcdcdc
+#  elif CONFIG_EXAMPLES_PWFB_BPP == 16
+#    define CONFIG_EXAMPLES_PWFB_COLOR2 0xdefb
+#  else
+#    define CONFIG_EXAMPLES_PWFB_COLOR2 '2'
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWFB_COLOR3
+#  if CONFIG_EXAMPLES_PWFB_BPP == 24 || CONFIG_EXAMPLES_PWFB_BPP == 32
+#    define CONFIG_EXAMPLES_PWFB_COLOR2 0x00ffecb3
+#  elif CONFIG_EXAMPLES_PWFB_BPP == 16
+#    define CONFIG_EXAMPLES_PWFB_COLOR2 0xff76
+#  else
+#    define CONFIG_EXAMPLES_PWFB_COLOR2 '3'
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWFB_FONTCOLOR
+#  if CONFIG_EXAMPLES_PWFB_BPP == 24 || CONFIG_EXAMPLES_PWFB_BPP == 32
+#    define CONFIG_EXAMPLES_PWFB_FONTCOLOR 0x00000000
+#  elif CONFIG_EXAMPLES_PWFB_BPP == 16
+#    define CONFIG_EXAMPLES_PWFB_FONTCOLOR 0x0000
+#  else
+#    define CONFIG_EXAMPLES_PWFB_FONTCOLOR 'F'
+#  endif
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Describes the unique state of one window */
+
+struct pwfb_window_s
+{
+  NXTKWINDOW hwnd;                         /* Window handle */
+  nxgl_mxpixel_t color[CONFIG_NX_NPLANES]; /* Window color */
+  FCACHE fcache;                           /* Font cache handle */
+  b32_t xmax;                              /* Max X position */
+  b32_t ymax;                              /* Max Y position */
+  b32_t xpos;                              /* Current X position */
+  b32_t ypos;                              /* Current Y position */
+  b32_t deltax;                            /* Current X speed */
+  b32_t deltay;                            /* Current Y speed */
+};
+
+/* Describes the overall state of the example */
+
+struct pwfb_state_s
+{
+  /* NX server */
+
+  volatile bool haveres;                   /* True:  Have screen resolution */
+  volatile bool connected;                 /* True:  Connected to server */
+  sem_t semevent;                          /* Event wait semaphore */
+  NXHANDLE hnx;                            /* Connection handle */
+
+  /* Font */
+
+  NXHANDLE hfont;                          /* The font handle */
+
+  /* Graphics hardware */
+
+  nxgl_coord_t xres;                       /* Horizontal resolution */
+  nxgl_coord_t yres;                       /* Vertical resolution */
+
+  /* Font properties */
+
+  uint8_t fheight;                         /* Max height of a font in pixels */
+  uint8_t fwidth;                          /* Max width of a font in pixels */
+  uint8_t spwidth;                         /* The width of a space */
+
+  /* Window-specific state */
+
+  struct pwfb_window_s wndo[3];
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* NX callback vtables */
+
+extern const struct nx_callback_s g_pwfb_cb;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+FAR void *pwfb_listener(FAR void *arg);
+bool pwfb_motion(FAR struct pwfb_state_s *st);
+
+#endif /* __EXAMPLES_PWFB_PWFB_INTERNAL_H */
diff --git a/examples/pwfb/pwfb_main.c b/examples/pwfb/pwfb_main.c
new file mode 100644
index 000000000..afff641c7
--- /dev/null
+++ b/examples/pwfb/pwfb_main.c
@@ -0,0 +1,685 @@
+/****************************************************************************
+ * examples/pwfb/pwfb_main.c
+ *
+ *   Copyright (C) 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 <sys/types.h>
+#include <sys/boardctl.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <pthread.h>
+#include <fixedmath.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/board.h>
+
+#ifdef CONFIG_VNCSERVER
+#  include <nuttx/video/vnc.h>
+#endif
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxtk.h>
+#include <nuttx/nx/nxbe.h>
+#include <nuttx/nx/nxfonts.h>
+
+#include "pwfb_internal.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const char g_wndomsg1[] = "NuttX is cool!";
+static const char g_wndomsg2[] = "NuttX is fun!";
+static const char g_wndomsg3[] = "NuttX is groovy!";
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwfb_server_initialize
+ ****************************************************************************/
+
+static bool pwfb_server_initialize(FAR struct pwfb_state_s *st)
+{
+  struct sched_param param;
+  int ret;
+
+  /* Set the client task priority */
+
+  param.sched_priority = CONFIG_EXAMPLES_PWFB_CLIENTPRIO;
+  ret = sched_setparam(0, &param);
+  if (ret < 0)
+    {
+      printf("pwfb_server_initialize: ERROR: "
+             "sched_setparam failed: %d\n" ,
+             ret);
+      return false;
+    }
+
+  /* Start the NX server kernel thread */
+
+  ret = boardctl(BOARDIOC_NX_START, 0);
+  if (ret < 0)
+    {
+      printf("pwfb_server_initialize: ERROR: "
+             "Failed to start the NX server: %d\n",
+             errno);
+      return false;
+    }
+
+  /* Connect to the server */
+
+  st->hnx = nx_connect();
+  if (st->hnx)
+    {
+#ifdef CONFIG_VNCSERVER
+      /* Setup the VNC server to support keyboard/mouse inputs */
+
+      ret = vnc_default_fbinitialize(0, st->hnx);
+      if (ret < 0)
+        {
+          printf("pwfb_server_initialize: ERROR: "
+                 "vnc_default_fbinitialize failed: %d\n",
+                 ret);
+          nx_disconnect(st->hnx);
+          return false;
+        }
+#endif
+    }
+  else
+    {
+      printf("pwfb_server_initialize: ERROR: "
+             "nx_connect failed: %d\n",
+             errno);
+      return false;
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: pwfb_listener_initialize
+ ****************************************************************************/
+
+static bool pwfb_listener_initialize(FAR struct pwfb_state_s *st)
+{
+  struct sched_param param;
+  pthread_attr_t attr;
+  pthread_t thread;
+  int ret;
+
+  /* Start a separate thread to listen for server events.  This is probably
+   * the least efficient way to do this, but it makes this example flow more
+   * smoothly.
+   */
+
+  (void)pthread_attr_init(&attr);
+  param.sched_priority = CONFIG_EXAMPLES_PWFB_LISTENERPRIO;
+  (void)pthread_attr_setschedparam(&attr, &param);
+  (void)pthread_attr_setstacksize(&attr, CONFIG_EXAMPLES_PWFB_STACKSIZE);
+
+  ret = pthread_create(&thread, &attr, pwfb_listener, st);
+  if (ret != 0)
+    {
+       printf("pwfb_listener_initialize: ERROR: "
+              "pthread_create failed: %d\n",
+              ret);
+       return false;
+    }
+
+  /* Don't return until we are connected to the server */
+
+  while (!st->connected)
+    {
+      /* Wait for the listener thread to wake us up when we really
+       * are connected.
+       */
+
+      (void)sem_wait(&st->semevent);
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: pwfb_state_initialize
+ ****************************************************************************/
+
+static bool pwfb_state_initialize(FAR struct pwfb_state_s *st)
+{
+  FAR const struct nx_font_s *fontset;
+
+  /* Initialize semaphores */
+
+  sem_init(&st->semevent, 0, 0);
+
+  /* Initialize color information */
+
+  st->wndo[0].color[0] = CONFIG_EXAMPLES_PWFB_COLOR1;
+  st->wndo[1].color[0] = CONFIG_EXAMPLES_PWFB_COLOR2;
+  st->wndo[2].color[0] = CONFIG_EXAMPLES_PWFB_COLOR3;
+
+  /* Connect each widnow to the font cache.  They cannot share the
+   * font cache becuse of the differing background colors.
+   */
+
+  st->wndo[0].fcache = nxf_cache_connect(CONFIG_EXAMPLES_PWFB_FONTID,
+                                         CONFIG_EXAMPLES_PWFB_FONTCOLOR,
+                                         CONFIG_EXAMPLES_PWFB_COLOR1,
+                                         CONFIG_EXAMPLES_PWFB_BPP, 8);
+  if (st->wndo[0].fcache == NULL)
+    {
+      printf("pwfb_state_initialize: ERROR: "
+             "Failed to connect to font cache for window 1,"
+             "font ID %d: %d\n",
+             CONFIG_EXAMPLES_PWFB_FONTID, errno);
+      return false;
+    }
+
+  st->wndo[1].fcache = nxf_cache_connect(CONFIG_EXAMPLES_PWFB_FONTID,
+                                         CONFIG_EXAMPLES_PWFB_FONTCOLOR,
+                                         CONFIG_EXAMPLES_PWFB_COLOR2,
+                                         CONFIG_EXAMPLES_PWFB_BPP, 8);
+  if (st->wndo[1].fcache == NULL)
+    {
+      printf("pwfb_state_initialize: ERROR: "
+             "Failed to connect to font cache for window 2,"
+             "font ID %d: %d\n",
+             CONFIG_EXAMPLES_PWFB_FONTID, errno);
+      goto errout_with_fcache1;
+    }
+
+  st->wndo[2].fcache = nxf_cache_connect(CONFIG_EXAMPLES_PWFB_FONTID,
+                                         CONFIG_EXAMPLES_PWFB_FONTCOLOR,
+                                         CONFIG_EXAMPLES_PWFB_COLOR3,
+                                         CONFIG_EXAMPLES_PWFB_BPP, 8);
+  if (st->wndo[2].fcache == NULL)
+    {
+      printf("pwfb_state_initialize: ERROR: "
+             "Failed to connect to font cache for window 3,"
+             "font ID %d: %d\n",
+             CONFIG_EXAMPLES_PWFB_FONTID, errno);
+      goto errout_with_fcache2;
+    }
+
+  /* Get the handle of the font managed by the font caches.  Since the
+   * font is used, the same font handle can be shared.
+   */
+
+  st->hfont = nxf_cache_getfonthandle(st->wndo[0].fcache);
+  if (st->hfont == NULL)
+    {
+      printf("pwfb_state_initialize: ERROR: "
+             "Failed to get handle for font ID %d: %d\n",
+             CONFIG_EXAMPLES_PWFB_FONTID, errno);
+      goto errout_with_fcache3;
+    }
+
+  /* Get information about the font set being used and save this in the
+   * state structure
+   */
+
+  fontset      = nxf_getfontset(st->hfont);
+  st->fheight  = fontset->mxheight;
+  st->fwidth   = fontset->mxwidth;
+  st->spwidth  = fontset->spwidth;
+
+  return true;
+
+errout_with_fcache3:
+  nxf_cache_disconnect(st->wndo[2].fcache);
+
+errout_with_fcache2:
+  nxf_cache_disconnect(st->wndo[1].fcache);
+
+errout_with_fcache1:
+  nxf_cache_disconnect(st->wndo[0].fcache);
+  return false;
+}
+
+/****************************************************************************
+ * Name: pwfb_putc
+ ****************************************************************************/
+
+static bool pwfb_putc(FAR struct pwfb_state_s *st,
+                      FAR struct pwfb_window_s *wndo,
+                      FAR struct nxgl_point_s *fpos,
+                      uint8_t ch)
+{
+  FAR const struct nxfonts_glyph_s *glyph;
+  FAR const struct nx_fontbitmap_s *fbm;
+  struct nxgl_rect_s bounds;
+  struct nxgl_size_s fsize;
+  FAR const void *src;
+  int ret;
+
+  /* Find (or create) the matching glyph */
+
+  glyph = nxf_cache_getglyph(wndo->fcache, ch);
+  if (glyph == NULL)
+    {
+      /* No, there is no font for this code.  Treat it like a space. */
+
+      fpos->x += st->spwidth;
+      return true;
+    }
+
+  /* Get information about the glyph? */
+
+  fbm = nxf_getbitmap(st->hfont, ch);
+  if (fbm == NULL)
+    {
+      /* Should not happen ceause we already know that the character has a
+       * glyph.
+       */
+
+      fpos->x += st->spwidth;
+      return true;
+    }
+
+  /* Get the font size */
+
+  fsize.w = fbm->metric.width + fbm->metric.xoffset;
+  fsize.h = fbm->metric.height + fbm->metric.yoffset;
+
+  /* Construct a bounding box for the glyph */
+
+  bounds.pt1.x = fpos->x;
+  bounds.pt1.y = fpos->y;
+  bounds.pt2.x = fpos->x + fsize.w - 1;
+  bounds.pt2.y = fpos->y + fsize.h - 1;
+
+  /* Render the glyph into the window */
+
+  src = (FAR const void *)glyph->bitmap;
+  ret =  nxtk_bitmapwindow(wndo->hwnd, &bounds, &src,
+                           fpos, (unsigned int)glyph->stride);
+  if (ret < 0)
+    {
+      printf("pwfb_putc: ERROR: "
+             "nxtk_bitmapwindow failed: %d\n",
+             errno);
+      return false;
+    }
+
+  /* Set up the next character position */
+
+  fpos->x += glyph->width;
+  return true;
+}
+
+/****************************************************************************
+ * Name: pwfb_configure_window
+ ****************************************************************************/
+
+static bool pwfb_configure_window(FAR struct pwfb_state_s *st, int wndx,
+                                  FAR struct nxgl_size_s *size,
+                                  FAR struct nxgl_point_s *pos,
+                                  FAR const char *text,
+                                  double deltax, double deltay)
+{
+  FAR struct pwfb_window_s *wndo = &st->wndo[wndx];
+  FAR const char *ptr;
+  struct nxgl_rect_s rect;
+  struct nxgl_point_s textpos;
+  int ret;
+
+  /* Set the size of the window */
+
+  printf("pwfb_configure_window: Set window %d size to (%d,%d)\n",
+         wndx + 1, size->w, size->h);
+
+  ret = nxtk_setsize(wndo->hwnd, size);
+  if (ret < 0)
+    {
+      printf("pwfb_configure_window: ERROR: "
+             "nx_setsize failed: %d\n", errno);
+      goto errout_with_hwnd;
+    }
+
+  /* Set the position of window */
+
+  printf("pwfb_configure_window: Set window %d position to (%d,%d)\n",
+         wndx + 1, pos->x, pos->y);
+
+  ret = nxtk_setposition(wndo->hwnd, pos);
+  if (ret < 0)
+    {
+      printf("pwfb_configure_window: ERROR: "
+             "nxtk_setposition failed: %d\n",
+             errno);
+      goto errout_with_hwnd;
+    }
+
+  /* Create a bounding box.  This is actually too large because it does not
+   * account for the boarder widths.  However, NX should clip the fill to
+   * stay within the frame.
+   */
+
+  rect.pt1.x = 0;
+  rect.pt1.y = 0;
+  rect.pt2.x = size->w - 1;
+  rect.pt2.y = size->h - 1;
+
+  /* Fill the window with the selected color */
+
+  ret = nxtk_fillwindow(wndo->hwnd, &rect, wndo->color);
+  if (ret < 0)
+    {
+      printf("pwfb_configure_window: ERROR: "
+             "nxtk_fillwindow failed: %d\n",
+             errno);
+      goto errout_with_hwnd;
+    }
+
+  /* Add the text to the display, character at a time */
+
+  textpos.x = st->spwidth;
+  textpos.y = st->fheight;
+
+  for (ptr = text; *ptr != '\0'; ptr++)
+    {
+      if (!pwfb_putc(st, wndo, &textpos, (uint8_t)*ptr))
+        {
+          printf("pwfb_configure_window: ERROR: "
+                 "pwfb_putc failed\n");
+          goto errout_with_hwnd;
+        }
+    }
+
+  /* Set up for motion */
+
+  wndo->xmax   = itob32(st->xres - size->w - 1);
+  wndo->ymax   = itob32(st->yres - size->h - 1);
+  wndo->ypos   = itob32(pos->y);
+  wndo->xpos   = itob32(pos->x);
+  wndo->deltax = dtob32(deltax);
+  wndo->deltay = dtob32(deltay);
+
+  return true;
+
+errout_with_hwnd:
+  printf("pwfb_configure_window: Close window %d\n", wndx + 1);
+
+  ret = nxtk_closewindow(wndo->hwnd);
+  if (ret < 0)
+    {
+      printf("pwfb_configure_window: ERROR: "
+             "nxtk_closewindow failed: %d\n",
+             errno);
+    }
+
+  return false;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwfb_main
+ ****************************************************************************/
+
+#ifdef BUILD_MODULE
+int main(int argc, FAR char *argv[])
+#else
+int pwfb_main(int argc, char *argv[])
+#endif
+{
+  struct pwfb_state_s wstate;
+  struct nxgl_size_s size;
+  struct nxgl_point_s pos;
+  nxgl_mxpixel_t color;
+  int errcode = EXIT_SUCCESS;
+  int ret;
+
+  /* Connect to the NX server */
+
+  memset(&wstate, 0, sizeof(struct pwfb_state_s));
+  if (!pwfb_server_initialize(&wstate) || wstate.hnx == NULL)
+    {
+      printf("pwfb_main: ERROR: "
+             "Failed to get NX handle\n");
+      goto errout;
+    }
+
+  printf("pwfb_main: NX handle=%p\n", wstate.hnx);
+
+  /* Start the listener thread */
+
+  if (!pwfb_listener_initialize(&wstate))
+    {
+      printf("pwfb_main: ERROR: "
+             "pwfb_listener_initialize failed\n");
+      goto errout_with_nx;
+    }
+
+  /* Initialize the window state, colors, font cache, etc. */
+
+  if (!pwfb_state_initialize(&wstate))
+    {
+      printf("pwfb_main: ERROR: "
+             "pwfb_state_initialize failed\n");
+      goto errout_with_nx;
+    }
+
+  /* Set the background to the configured background color */
+
+  printf("pwfb_main: Set background color=%d\n",
+         CONFIG_EXAMPLES_PWFB_BGCOLOR);
+
+  color = CONFIG_EXAMPLES_PWFB_BGCOLOR;
+  ret = nx_setbgcolor(wstate.hnx, &color);
+  if (ret < 0)
+    {
+      printf("pwfb_main: nx_setbgcolor failed: %d\n", errno);
+      goto errout_with_fontcache;
+    }
+
+  /* Open window 1 */
+
+  printf("pwfb_main: Open window 1\n");
+
+  wstate.wndo[0].hwnd = nxtk_openwindow(wstate.hnx, NXBE_WINDOW_RAMBACKED,
+                                        &g_pwfb_cb, (FAR void *)&wstate);
+  if (wstate.wndo[0].hwnd == NULL)
+    {
+      printf("pwfb_main: ERROR: "
+             "nxtk_openwindow failed: %d\n",
+             errno);
+      goto errout_with_fontcache;
+    }
+
+  printf("pwfb_main: hwnd1=%p\n", wstate.wndo[0].hwnd);
+
+  /* Wait until we receive the screen resolution from the server.  We only
+   * need to do this once after opening the first window.
+   */
+
+  while (!wstate.haveres)
+    {
+      (void)sem_wait(&wstate.semevent);
+    }
+
+  printf("pwfb_main: Screen resolution (%d,%d)\n",
+         wstate.xres, wstate.yres);
+
+  /* Configure window 1 */
+
+  size.w = wstate.xres / 2;
+  size.h = wstate.yres / 2;
+
+  pos.x  = wstate.xres / 4;
+  pos.y  = wstate.yres / 4;
+
+  if (!pwfb_configure_window(&wstate, 0, &size, &pos, g_wndomsg1, 1.58, 4.5))
+    {
+      printf("pwfb_main: ERROR: "
+             "pwfb_configure_window failed for window 1\n");
+      goto errout_with_fontcache;
+    }
+
+  /* Open window 2 */
+
+  printf("pwfb_main: Open window 2\n");
+
+  wstate.wndo[1].hwnd = nxtk_openwindow(wstate.hnx, NXBE_WINDOW_RAMBACKED,
+                                        &g_pwfb_cb, (FAR void *)&wstate);
+  if (wstate.wndo[1].hwnd == NULL)
+    {
+      printf("pwfb_main: ERROR: "
+             "nxtk_openwindow failed: %d\n",
+             errno);
+      goto errout_with_hwnd1;
+    }
+
+  printf("pwfb_main: hwnd1=%p\n", wstate.wndo[1].hwnd);
+
+  /* Configure window 2 (same size) */
+
+  pos.x  = wstate.xres / 4;
+  pos.y  = wstate.yres / 4;
+
+  if (!pwfb_configure_window(&wstate, 1, &size, &pos, g_wndomsg2, -1.13, 5.0))
+    {
+      printf("pwfb_main: ERROR: "
+             "pwfb_configure_window failed for window 2\n");
+      goto errout_with_hwnd2;
+    }
+
+  /* Open window 3 */
+
+  printf("pwfb_main: Open window 3\n");
+
+  wstate.wndo[2].hwnd = nxtk_openwindow(wstate.hnx, NXBE_WINDOW_RAMBACKED,
+                                        &g_pwfb_cb, (FAR void *)&wstate);
+  if (wstate.wndo[2].hwnd == NULL)
+    {
+      printf("pwfb_main: ERROR: "
+             "nxtk_openwindow failed: %d\n",
+             errno);
+      goto errout_with_hwnd2;
+    }
+
+  printf("pwfb_main: hwnd2=%p\n", wstate.wndo[2].hwnd);
+
+  /* Configure window 3 (same size) */
+
+  pos.x = (3 * wstate.xres) / 8;
+  pos.y = (3 * wstate.yres) / 8;
+
+  if (!pwfb_configure_window(&wstate, 2, &size, &pos, g_wndomsg3, -1.13, 5.0))
+    {
+      printf("pwfb_main: ERROR: "
+             "pwfb_configure_window failed for window 2\n");
+      goto errout_with_hwnd3;
+    }
+
+  /* Now loop animating the windows */
+
+  for (; ; )
+    {
+      if (!pwfb_motion(&wstate))
+        {
+          printf("pwfb_main: ERROR:"
+                 "pwfb_motion failed\n");
+          goto errout_with_hwnd3;
+        }
+    }
+
+  errcode = EXIT_SUCCESS;
+
+  /* Close window 3 */
+
+errout_with_hwnd3:
+  printf("pwfb_main: Close window #2\n");
+
+  ret = nxtk_closewindow(wstate.wndo[2].hwnd);
+  if (ret < 0)
+    {
+      printf("pwfb_main: ERROR: nxtk_closewindow failed: %d\n", errno);
+    }
+
+  /* Close window 2 */
+
+errout_with_hwnd2:
+  printf("pwfb_main: Close window #2\n");
+
+  ret = nxtk_closewindow(wstate.wndo[1].hwnd);
+  if (ret < 0)
+    {
+      printf("pwfb_main: ERROR: nxtk_closewindow failed: %d\n", errno);
+    }
+
+  /* Close window1 */
+
+errout_with_hwnd1:
+  printf("pwfb_main: Close window #1\n");
+
+  ret = nxtk_closewindow(wstate.wndo[0].hwnd);
+  if (ret < 0)
+    {
+      printf("pwfb_main: ERROR: nxtk_closewindow failed: %d\n", errno);
+    }
+
+errout_with_fontcache:
+  /* Release the font cache */
+
+  nxf_cache_disconnect(wstate.wndo[0].fcache);
+  nxf_cache_disconnect(wstate.wndo[1].fcache);
+  nxf_cache_disconnect(wstate.wndo[2].fcache);
+
+errout_with_nx:
+  /* Disconnect from the server */
+
+  printf("pwfb_main: Disconnect from the server\n");
+  nx_disconnect(wstate.hnx);
+
+errout:
+  return errcode;
+}
diff --git a/examples/pwfb/pwfb_motion.c b/examples/pwfb/pwfb_motion.c
new file mode 100644
index 000000000..6febd30a2
--- /dev/null
+++ b/examples/pwfb/pwfb_motion.c
@@ -0,0 +1,165 @@
+/****************************************************************************
+ * examples/pwfb/pwfb_motion.c
+ *
+ *   Copyright (C) 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 <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <nuttx/nx/nxglib.h>
+#include <nuttx/nx/nxtk.h>
+
+#include "pwfb_internal.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwfb_move_window
+ ****************************************************************************/
+
+static inline bool pwfb_move_window(FAR struct pwfb_state_s *st, int wndx)
+{
+  FAR struct pwfb_window_s *wndo = &st->wndo[wndx];
+  FAR struct nxgl_point_s pos;
+  b32_t newx;
+  b32_t newy;
+  bool hit = false;
+  int ret;
+
+  /* Update X position */
+
+  newx             = wndo->xpos + wndo->deltax;
+
+  /* Check for collision with left or right side */
+
+  if (newx <= 0)
+    {
+      newx         = 0;
+      wndo->deltax = -wndo->deltax;
+      hit          = true;
+    }
+  else if (newx >= wndo->xmax)
+    {
+      newx         = wndo->xmax;
+      wndo->deltax = -wndo->deltax;
+      hit          = true;
+    }
+
+  wndo->xpos       = newx;
+
+  /* Update Y position */
+
+  newy             = wndo->ypos + wndo->deltay;
+
+  /* Check for collision with top or bottom side */
+
+  if (newy <= 0)
+    {
+      newy         = 0;
+      wndo->deltay = -wndo->deltay;
+      hit          = true;
+    }
+  else if (newy >= wndo->ymax)
+    {
+      newy         = wndo->ymax;
+      wndo->deltay = -wndo->deltay;
+      hit          = true;
+    }
+
+  wndo->ypos       = newy;
+
+  /* Set the new window position */
+
+  pos.x            = b32toi(newx);
+  pos.y            = b32toi(newy);
+  ret              = nxtk_setposition(wndo->hwnd, &pos);
+  if (ret < 0)
+    {
+      printf("pwfb_move_window: ERROR:"
+             "nxtk_setposition failed: %d\n",
+             errno);
+      return false;
+    }
+
+  /* If we hit an edge, the raise the window */
+
+  if (hit)
+    {
+      ret          = nxtk_raise(wndo->hwnd);
+      if (ret < 0)
+        {
+          printf("pwfb_move_window: ERROR:"
+                 "nxtk_raise failed: %d\n",
+                 errno);
+          return false;
+        }
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwfb_motion
+ ****************************************************************************/
+
+bool pwfb_motion(FAR struct pwfb_state_s *st)
+{
+  int wndx;
+
+  /* Move each window */
+
+  for (wndx = 0; wndx < 3; wndx++)
+    {
+      if (!pwfb_move_window(st, wndx))
+        {
+          printf("pwfb_motion: ERROR:"
+                 "pwfb_move_window failed for window %d\n",
+                 wndx + 1);
+        }
+    }
+
+  return true;
+}